diff options
285 files changed, 17006 insertions, 8875 deletions
diff --git a/binfilter/bf_sc/source/ui/docshell/sc_impex.cxx b/binfilter/bf_sc/source/ui/docshell/sc_impex.cxx index b958fdbd1..cf6da4d38 100644 --- a/binfilter/bf_sc/source/ui/docshell/sc_impex.cxx +++ b/binfilter/bf_sc/source/ui/docshell/sc_impex.cxx @@ -478,8 +478,7 @@ enum DoubledQuoteMode /*N*/ rStrm.Seek( STREAM_SEEK_TO_END ); /*N*/ ScProgress aProgress( pDocSh, ScGlobal::GetRscString( STR_LOAD_DOC ), rStrm.Tell() - nOldPos ); /*N*/ rStrm.Seek( nOldPos ); -/*N*/ if ( rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE ) -/*?*/ rStrm.StartReadingUnicodeText(); +/*?*/ rStrm.StartReadingUnicodeText( rStrm.GetStreamCharSet() ); /*N*/ /*N*/ BOOL bOld = ScColumn::bDoubleAlloc; /*N*/ ScColumn::bDoubleAlloc = TRUE; diff --git a/binfilter/bf_xmloff/source/forms/formcellbinding.hxx b/binfilter/bf_xmloff/source/forms/formcellbinding.hxx index c42b87554..41f6371f8 100644 --- a/binfilter/bf_xmloff/source/forms/formcellbinding.hxx +++ b/binfilter/bf_xmloff/source/forms/formcellbinding.hxx @@ -40,11 +40,13 @@ #ifndef _COM_SUN_STAR_TABLE_CELLRANGEADDRESS_HPP_ #include <com/sun/star/table/CellRangeAddress.hpp> #endif -#ifndef _DRAFTS_COM_SUN_STAR_FORM_XVALUEBINDING_HPP_ -#include <drafts/com/sun/star/form/XValueBinding.hpp> +#ifndef _COM_SUN_STAR_FORM_BINDING_XVALUEBINDING_HPP_ +//#include <drafts/com/sun/star/form/XValueBinding.hpp> +#include <com/sun/star/form/binding/XValueBinding.hpp> #endif -#ifndef _DRAFTS_COM_SUN_STAR_FORM_XLISTENTRYSOURCE_HPP_ -#include <drafts/com/sun/star/form/XListEntrySource.hpp> +#ifndef _COM_SUN_STAR_FORM_XLISTENTRYSOURCE_HPP_ +#include <com/sun/star/form/binding/XListEntrySource.hpp> +//#include <drafts/com/sun/star/form/XListEntrySource.hpp> #endif #ifndef _COM_SUN_STAR_FRAME_XMODEL_HPP_ #include <com/sun/star/frame/XModel.hpp> @@ -97,15 +99,19 @@ namespace xmloff @precond isCellBindingAllowed returns <TRUE/> */ - ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding > - createCellBindingFromStringAddress( +// ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding > + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > + createCellBindingFromStringAddress( + const ::rtl::OUString& _rAddress, bool _bUseIntegerBinding ) const; /** gets a cell range list source binding for the given address */ - ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource > + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > + + // ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource > createCellListSourceFromStringAddress( const ::rtl::OUString& _rAddress ) const; /** creates a string representation for the given value binding's address @@ -118,8 +124,10 @@ namespace xmloff @see isCellBinding */ ::rtl::OUString getStringAddressFromCellBinding( - const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding - ) const; +// const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + + ) const; /** creates a string representation for the given list source's range address @@ -132,18 +140,24 @@ namespace xmloff @see isCellRangeListSource */ ::rtl::OUString getStringAddressFromCellListSource( - const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource >& _rxSource - ) const; + // const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource >& _rxSource + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource + + ) const; /** returns the current binding of our control model, if any. */ - ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding > - getCurrentBinding( ) const; + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding > + //::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding > + + getCurrentBinding( ) const; /** returns the current external list source of the control model, if any */ - ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource > - getCurrentListSource( ) const; + //::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource > + ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource > + + getCurrentListSource( ) const; /** sets a new binding for our control model @precond @@ -151,8 +165,10 @@ namespace xmloff returning <TRUE/>) */ void setBinding( - const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding - ); +// const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + + ); /** sets a list source for our control model @precond @@ -160,8 +176,10 @@ namespace xmloff returning <TRUE/>) */ void setListSource( - const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource >& _rxSource - ); +// const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource >& _rxSource + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource + + ); /** checks whether it's possible to bind the control model to a spreadsheet cell */ @@ -188,21 +206,27 @@ namespace xmloff /** checks whether a given binding is a spreadsheet cell binding */ bool isCellBinding( - const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding + //const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding + + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding ) const; /** checks whether a given binding is a spreadsheet cell binding, exchanging integer values */ bool isCellIntegerBinding( - const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding - ) const; + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding + //const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XValueBinding >& _rxBinding + + ) const; /** checks whether a given list source is a spreadsheet cell list source */ bool isCellRangeListSource( - const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource >& _rxSource - ) const; +// const ::com::sun::star::uno::Reference< ::drafts::com::sun::star::form::XListEntrySource >& _rxSource + const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntrySource >& _rxSource + + ) const; protected: /** creates an address object from a string representation of a cell address diff --git a/binfilter/bf_xmloff/source/forms/xmloff_elementexport.cxx b/binfilter/bf_xmloff/source/forms/xmloff_elementexport.cxx index afa2061e4..5cd4a3f37 100644 --- a/binfilter/bf_xmloff/source/forms/xmloff_elementexport.cxx +++ b/binfilter/bf_xmloff/source/forms/xmloff_elementexport.cxx @@ -83,8 +83,11 @@ #include "formcellbinding.hxx" #endif +#include <com/sun/star/form/binding/XValueBinding.hpp> + #ifndef _DRAFTS_COM_SUN_STAR_FORM_XLISTENTRYSINK_HPP_ -#include <drafts/com/sun/star/form/XListEntrySink.hpp> +//#include <drafts/com/sun/star/form/XListEntrySink.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> #endif #include <algorithm> @@ -106,7 +109,7 @@ namespace xmloff using namespace ::com::sun::star::script; using namespace ::com::sun::star::io; using namespace ::com::sun::star::table; - using namespace ::drafts::com::sun::star::form; + using namespace ::com::sun::star::form::binding; //===================================================================== //= OElementExport diff --git a/binfilter/bf_xmloff/source/forms/xmloff_formcellbinding.cxx b/binfilter/bf_xmloff/source/forms/xmloff_formcellbinding.cxx index 57d6f70cc..928a8b3fa 100644 --- a/binfilter/bf_xmloff/source/forms/xmloff_formcellbinding.cxx +++ b/binfilter/bf_xmloff/source/forms/xmloff_formcellbinding.cxx @@ -29,11 +29,13 @@ #include "formcellbinding.hxx" #endif -#ifndef _DRAFTS_COM_SUN_STAR_FORM_XBINDABLEVALUE_HPP_ -#include <drafts/com/sun/star/form/XBindableValue.hpp> +#ifndef _COM_SUN_STAR_FORM_BINDING_XBINDABLEVALUE_HPP_ +//#include <drafts/com/sun/star/form/XBindableValue.hpp> +#include <com/sun/star/form/binding/XBindableValue.hpp> #endif -#ifndef _DRAFTS_COM_SUN_STAR_FORM_XLISTENTRYSINK_HPP_ -#include <drafts/com/sun/star/form/XListEntrySink.hpp> +#ifndef _COM_SUN_STAR_FORM_BINDING_XLISTENTRYSINK_HPP_ +//#include <drafts/com/sun/star/form/XListEntrySink.hpp> +#include <com/sun/star/form/binding/XListEntrySink.hpp> #endif #ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESUPPLIER_HPP_ #include <com/sun/star/drawing/XDrawPageSupplier.hpp> @@ -76,7 +78,7 @@ namespace xmloff using namespace ::com::sun::star::table; using namespace ::com::sun::star::form; using namespace ::com::sun::star::lang; - using namespace ::drafts::com::sun::star::form; + using namespace ::com::sun::star::form::binding; namespace { diff --git a/filter/prj/build.lst b/filter/prj/build.lst index c964e5fcf..b2182d762 100644 --- a/filter/prj/build.lst +++ b/filter/prj/build.lst @@ -1,4 +1,4 @@ -fl filter : l10n svtools unotools xmloff cppu tools cppuhelper sal svx javaunohelper XPDF:xpdf jvmaccess canvas SAXON:saxon LIBXSLT:libxslt basegfx NULL +fl filter : L10N:l10n svtools unotools xmloff cppu tools cppuhelper sal svx javaunohelper XPDF:xpdf jvmaccess canvas SAXON:saxon LIBXSLT:libxslt basegfx NULL fl filter usr1 - all fl_mkout NULL fl filter\prj get - all fl_prj NULL fl filter\inc nmake - all fl_inc NULL diff --git a/filter/source/docbook/sofftodocbookheadings.xsl b/filter/source/docbook/sofftodocbookheadings.xsl index cfddf901b..3fda55612 100644 --- a/filter/source/docbook/sofftodocbookheadings.xsl +++ b/filter/source/docbook/sofftodocbookheadings.xsl @@ -163,20 +163,20 @@ <!-- if the first heading is not of the section1 level --> <xsl:if test="generate-id(.) != generate-id($firstHeading)"> <!-- create an anonymous section1 and embrace all headings preceding the first real existent section1 --> - <xsl:text disable-output-escaping="yes"><sect1></xsl:text> - <title></title> - <!-- create sections for all the first section1 preluding headings --> - <xsl:for-each select="key('getHeadingsByOutline', $section1_OutlineLevel)[1]/preceding::text:h"> - <xsl:call-template name="make-section"> - <xsl:with-param name="previousSectionLevel" select="$section1_OutlineLevel"/> - <xsl:with-param name="currentSectionLevel"> - <xsl:call-template name="getSectionLevel"> - <xsl:with-param name="outlineLevel" select="@text:level"/> - </xsl:call-template> - </xsl:with-param> - </xsl:call-template> - </xsl:for-each> - <xsl:text disable-output-escaping="yes"></sect1></xsl:text> + <xsl:element name="sect1"> + <title></title> + <!-- create sections for all the first section1 preluding headings --> + <xsl:for-each select="key('getHeadingsByOutline', $section1_OutlineLevel)[1]/preceding::text:h"> + <xsl:call-template name="make-section"> + <xsl:with-param name="previousSectionLevel" select="$section1_OutlineLevel"/> + <xsl:with-param name="currentSectionLevel"> + <xsl:call-template name="getSectionLevel"> + <xsl:with-param name="outlineLevel" select="@text:level"/> + </xsl:call-template> + </xsl:with-param> + </xsl:call-template> + </xsl:for-each> + </xsl:element> </xsl:if> </xsl:for-each> <!-- match all headings, which are mapped to section1 to create a nested section structure used in docbook (see first comment after copyright) --> @@ -278,30 +278,22 @@ <xsl:choose> <!-- empty title as it is an empty section between two headings with an outline level difference higher than 1 --> <xsl:when test="$currentSectionLevel > $previousSectionLevel+1"> - <xsl:text disable-output-escaping="yes"><sect</xsl:text> - <xsl:value-of select="$previousSectionLevel +1"/> - <xsl:text disable-output-escaping="yes">></xsl:text> - <title></title> - <xsl:call-template name="make-section"> - <xsl:with-param name="currentSectionLevel" select="$currentSectionLevel"/> - <xsl:with-param name="previousSectionLevel" select="$previousSectionLevel +1"/> - </xsl:call-template> - <xsl:text disable-output-escaping="yes"></sect</xsl:text> - <xsl:value-of select="$previousSectionLevel +1"/> - <xsl:text disable-output-escaping="yes">></xsl:text> + <xsl:element name="{concat('sect', $previousSectionLevel + 1)}"> + <title></title> + <xsl:call-template name="make-section"> + <xsl:with-param name="currentSectionLevel" select="$currentSectionLevel"/> + <xsl:with-param name="previousSectionLevel" select="$previousSectionLevel +1"/> + </xsl:call-template> + </xsl:element> </xsl:when> <xsl:otherwise> - <xsl:text disable-output-escaping="yes"><sect</xsl:text> - <xsl:value-of select="$currentSectionLevel"/> - <xsl:text disable-output-escaping="yes">></xsl:text> - <title> - <xsl:apply-templates/> - </title> - <xsl:apply-templates select="key('nestedContent', generate-id())"/> - <xsl:apply-templates select="key('nestedHeadings', generate-id())" mode="recreateStructure"/> - <xsl:text disable-output-escaping="yes"></sect</xsl:text> - <xsl:value-of select="$currentSectionLevel"/> - <xsl:text disable-output-escaping="yes">></xsl:text> + <xsl:element name="{concat('sect', $currentSectionLevel)}"> + <title> + <xsl:apply-templates/> + </title> + <xsl:apply-templates select="key('nestedContent', generate-id())"/> + <xsl:apply-templates select="key('nestedHeadings', generate-id())" mode="recreateStructure"/> + </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:template> @@ -370,23 +362,12 @@ </appendix> </xsl:when> <xsl:otherwise> - <xsl:variable name="sectvar"> - <xsl:text>sect</xsl:text> - <xsl:value-of select="count(ancestor::text:section)+1"/> - </xsl:variable> - <xsl:variable name="idvar"> - <xsl:text> id="</xsl:text> - <xsl:value-of select="@text:name"/> - <xsl:text>"</xsl:text> - </xsl:variable> - <xsl:text disable-output-escaping="yes"><</xsl:text> - <xsl:value-of select="$sectvar"/> - <xsl:value-of select="$idvar"/> - <xsl:text disable-output-escaping="yes">></xsl:text> - <xsl:apply-templates/> - <xsl:text disable-output-escaping="yes"></</xsl:text> - <xsl:value-of select="$sectvar"/> - <xsl:text disable-output-escaping="yes">></xsl:text> + <xsl:element name="{concat('sect', count(ancestor::text:section) + 1)}"> + <xsl:attribute name="id"> + <xsl:value-of select="@text:name"/> + </xsl:attribute> + <xsl:apply-templates/> + </xsl:element> </xsl:otherwise> </xsl:choose> </xsl:template> diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx index 844724760..358e58907 100644 --- a/filter/source/pdf/impdialog.cxx +++ b/filter/source/pdf/impdialog.cxx @@ -473,6 +473,10 @@ ImpPDFTabGeneralPage::ImpPDFTabGeneralPage( Window* pParent, aNewPos.Y() -= nDelta; maCbEmbedStandardFonts.SetPosPixel( aNewPos ); } + + maEdPages.SetAccessibleName(maRbRange.GetText()); + maEdPages.SetAccessibleRelationLabeledBy(&maRbRange); + maCbExportEmptyPages.SetStyle( maCbExportEmptyPages.GetStyle() | WB_VCENTER ); } @@ -658,7 +662,8 @@ SfxTabPage* ImpPDFTabGeneralPage::Create( Window* pParent, IMPL_LINK( ImpPDFTabGeneralPage, TogglePagesHdl, void*, EMPTYARG ) { maEdPages.Enable( maRbRange.IsChecked() ); - maEdPages.SetReadOnly( !maRbRange.IsChecked() ); + //Sym2_5805, When the control is disabled, it is also readonly. So here, it is not necessary to set it as readonly. + //maEdPages.SetReadOnly( !maRbRange.IsChecked() ); return 0; } @@ -695,7 +700,8 @@ IMPL_LINK( ImpPDFTabGeneralPage, ToggleAddStreamHdl, void*, EMPTYARG ) maRbRange.Enable( sal_False ); maRbSelection.Enable( sal_False ); maEdPages.Enable( sal_False ); - maEdPages.SetReadOnly( sal_True ); + //Sym2_5805, When the control is disabled, it is also readonly. So here, it is not necessary to set it as readonly. + //maEdPages.SetReadOnly( sal_True ); maRbAll.Enable( sal_False ); } else @@ -711,9 +717,13 @@ IMPL_LINK( ImpPDFTabGeneralPage, ToggleAddStreamHdl, void*, EMPTYARG ) // ----------------------------------------------------------------------------- IMPL_LINK( ImpPDFTabGeneralPage, ToggleExportPDFAHdl, void*, EMPTYARG ) { + ImpPDFTabSecurityPage* pSecPage = NULL; //set the security page status (and its controls as well) if( mpaParent && mpaParent->GetTabPage( RID_PDF_TAB_SECURITY ) ) - ( ( ImpPDFTabSecurityPage* )mpaParent->GetTabPage( RID_PDF_TAB_SECURITY ) )->ImplPDFASecurityControl( !maCbPDFA1b.IsChecked() ); + { + pSecPage = static_cast<ImpPDFTabSecurityPage*>(mpaParent->GetTabPage( RID_PDF_TAB_SECURITY )); + pSecPage->ImplPDFASecurityControl( !maCbPDFA1b.IsChecked() ); + } //PDF/A-1 needs tagged PDF, so force disable the control, will be forced in pdfexport. sal_Bool bPDFA1Sel = maCbPDFA1b.IsChecked(); @@ -748,6 +758,13 @@ IMPL_LINK( ImpPDFTabGeneralPage, ToggleExportPDFAHdl, void*, EMPTYARG ) if( mpaParent && mpaParent->GetTabPage( RID_PDF_TAB_LINKS ) ) ( ( ImpPDFTabLinksPage* )mpaParent->GetTabPage( RID_PDF_TAB_LINKS ) )->ImplPDFALinkControl( !maCbPDFA1b.IsChecked() ); + // if a password was set, inform the user that this will not be used in PDF/A case + if( maCbPDFA1b.IsChecked() && pSecPage && pSecPage->hasPassword() ) + { + WarningBox aBox( this, PDFFilterResId( RID_PDF_WARNPDFAPASSWORD ) ); + aBox.Execute(); + } + return 0; } @@ -788,6 +805,8 @@ ImpPDFTabOpnFtrPage::ImpPDFTabOpnFtrPage( Window* pParent, maRbMagnFitWidth.SetToggleHdl( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) ); maRbMagnFitVisible.SetToggleHdl( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) ); maRbMagnZoom.SetToggleHdl( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) ); + maNumZoom.SetAccessibleName(maRbMagnZoom.GetText()); + maNumZoom.SetAccessibleRelationLabeledBy(&maRbMagnZoom); } // ----------------------------------------------------------------------------- @@ -910,9 +929,8 @@ void ImpPDFTabOpnFtrPage::SetFilterConfigItem( const ImpPDFTabDialog* paParent } } -IMPL_LINK( ImpPDFTabOpnFtrPage, ToggleRbPgLyContinueFacingHdl, void*, p ) +IMPL_LINK( ImpPDFTabOpnFtrPage, ToggleRbPgLyContinueFacingHdl, void*, EMPTYARG ) { - p = p; //for compiler warning maCbPgLyFirstOnLeft.Enable( maRbPgLyContinueFacing.IsChecked() ); return 0; } @@ -951,6 +969,8 @@ ImpPDFTabViewerPage::ImpPDFTabViewerPage( Window* pParent, FreeResource(); maRbAllBookmarkLevels.SetToggleHdl( LINK( this, ImpPDFTabViewerPage, ToggleRbBookmarksHdl ) ); maRbVisibleBookmarkLevels.SetToggleHdl( LINK( this, ImpPDFTabViewerPage, ToggleRbBookmarksHdl ) ); + maNumBookmarkLevels.SetAccessibleName(maRbVisibleBookmarkLevels.GetText()); + maNumBookmarkLevels.SetAccessibleRelationLabeledBy(&maRbVisibleBookmarkLevels); } // ----------------------------------------------------------------------------- @@ -1024,10 +1044,13 @@ ImpPDFTabSecurityPage::ImpPDFTabSecurityPage( Window* i_pParent, maFtUserPwd( this, PDFFilterResId( FT_USER_PWD ) ), maUserPwdSet( PDFFilterResId( STR_USER_PWD_SET ) ), maUserPwdUnset( PDFFilterResId( STR_USER_PWD_UNSET ) ), + maUserPwdPdfa( PDFFilterResId( STR_USER_PWD_PDFA ) ), + maStrSetPwd( PDFFilterResId( STR_SET_PWD ) ), maFtOwnerPwd( this, PDFFilterResId( FT_OWNER_PWD ) ), maOwnerPwdSet( PDFFilterResId( STR_OWNER_PWD_SET ) ), maOwnerPwdUnset( PDFFilterResId( STR_OWNER_PWD_UNSET ) ), + maOwnerPwdPdfa( PDFFilterResId( STR_OWNER_PWD_PDFA ) ), maFlPrintPermissions( this, PDFFilterResId( FL_PRINT_PERMISSIONS ) ), maRbPrintNone( this, PDFFilterResId( RB_PRINT_NONE ) ), @@ -1219,10 +1242,21 @@ IMPL_LINK( ImpPDFTabSecurityPage, ClickmaPbSetPwdHdl, void*, EMPTYARG ) void ImpPDFTabSecurityPage::enablePermissionControls() { - maFtUserPwd.SetText( (mbHaveUserPassword && IsEnabled()) ? maUserPwdSet : maUserPwdUnset ); + sal_Bool bIsPDFASel = sal_False; + ImpPDFTabDialog* pParent = static_cast<ImpPDFTabDialog*>(GetTabDialog()); + if( pParent && pParent->GetTabPage( RID_PDF_TAB_GENER ) ) + bIsPDFASel = ( ( ImpPDFTabGeneralPage* )pParent-> + GetTabPage( RID_PDF_TAB_GENER ) )->IsPdfaSelected(); + if( bIsPDFASel ) + maFtUserPwd.SetText( maUserPwdPdfa ); + else + maFtUserPwd.SetText( (mbHaveUserPassword && IsEnabled()) ? maUserPwdSet : maUserPwdUnset ); sal_Bool bLocalEnable = mbHaveOwnerPassword && IsEnabled(); - maFtOwnerPwd.SetText( bLocalEnable ? maOwnerPwdSet : maOwnerPwdUnset ); + if( bIsPDFASel ) + maFtOwnerPwd.SetText( maOwnerPwdPdfa ); + else + maFtOwnerPwd.SetText( bLocalEnable ? maOwnerPwdSet : maOwnerPwdUnset ); maFlPrintPermissions.Enable( bLocalEnable ); maRbPrintNone.Enable( bLocalEnable ); diff --git a/filter/source/pdf/impdialog.hrc b/filter/source/pdf/impdialog.hrc index 8ca94362d..e7ccbf621 100644 --- a/filter/source/pdf/impdialog.hrc +++ b/filter/source/pdf/impdialog.hrc @@ -33,6 +33,8 @@ #define RID_PDF_TAB_OPNFTR (RID_PDF_DIALOG_START + 3) #define RID_PDF_TAB_SECURITY (RID_PDF_DIALOG_START + 4) #define RID_PDF_TAB_LINKS (RID_PDF_DIALOG_START + 12) +#define RID_PDF_WARNPDFAPASSWORD (RID_PDF_DIALOG_START + 6) + //strings #define STR_PDF_EXPORT (RID_PDF_DIALOG_START + 5) @@ -152,12 +154,14 @@ #define STR_USER_PWD_UNSET 124 #define STR_USER_PWD_UNENC 125 #define STR_SET_PWD 126 +#define STR_USER_PWD_PDFA 127 #define FT_OWNER_PWD 128 #define STR_OWNER_PWD_SET 129 #define STR_OWNER_PWD_REST 130 #define STR_OWNER_PWD_UNSET 131 #define STR_OWNER_PWD_UNREST 132 +#define STR_OWNER_PWD_PDFA 133 #define FL_PRINT_PERMISSIONS 133 #define RB_PRINT_NONE 134 diff --git a/filter/source/pdf/impdialog.hxx b/filter/source/pdf/impdialog.hxx index 1b3a48866..33aa2f9f4 100644 --- a/filter/source/pdf/impdialog.hxx +++ b/filter/source/pdf/impdialog.hxx @@ -321,11 +321,13 @@ class ImpPDFTabSecurityPage : public SfxTabPage FixedText maFtUserPwd; String maUserPwdSet; String maUserPwdUnset; + String maUserPwdPdfa; String maStrSetPwd; FixedText maFtOwnerPwd; String maOwnerPwdSet; String maOwnerPwdUnset; + String maOwnerPwdPdfa; FixedLine maFlPrintPermissions; RadioButton maRbPrintNone; @@ -370,6 +372,7 @@ public: void GetFilterConfigItem( ImpPDFTabDialog* paParent); void SetFilterConfigItem( const ImpPDFTabDialog* paParent ); void ImplPDFASecurityControl( sal_Bool bEnableSecurity ); + bool hasPassword() const { return mbHaveOwnerPassword || mbHaveUserPassword; } }; //class to implement the relative link stuff diff --git a/filter/source/pdf/impdialog.src b/filter/source/pdf/impdialog.src index db8aaa118..5e6d6bf2b 100644 --- a/filter/source/pdf/impdialog.src +++ b/filter/source/pdf/impdialog.src @@ -265,6 +265,12 @@ TabPage RID_PDF_TAB_GENER }; }; +WarningBox RID_PDF_WARNPDFAPASSWORD +{ + Title[en-US] = "PDF/A Export"; + Message[ en-US ] = "PDF/A does not allow encryption. The exported PDF file will not be password protected."; +}; + //---------------------------------------------------------- //tab page for PDF Export, opening features TabPage RID_PDF_TAB_OPNFTR @@ -606,6 +612,11 @@ TabPage RID_PDF_TAB_SECURITY { Text [ en-US ] = "PDF document will not be encrypted"; }; + + String STR_USER_PWD_PDFA + { + Text [en-US] = "PDF doument will not be encrypted due to PDF/A export."; + }; FixedText FT_OWNER_PWD { @@ -633,6 +644,11 @@ TabPage RID_PDF_TAB_SECURITY Text [ en-US ] = "PDF document will be unrestricted"; }; + String STR_OWNER_PWD_PDFA + { + Text [en-US] = "PDF doument will not be restricted due to PDF/A export."; + }; + ////////////////////////////// FixedLine FL_PRINT_PERMISSIONS { diff --git a/filter/source/xslt/export/wordml/ooo2wordml_draw.xsl b/filter/source/xslt/export/wordml/ooo2wordml_draw.xsl index 40b146f14..2badb7cd6 100644 --- a/filter/source/xslt/export/wordml/ooo2wordml_draw.xsl +++ b/filter/source/xslt/export/wordml/ooo2wordml_draw.xsl @@ -27,7 +27,7 @@ --> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xalan="http://xml.apache.org/xalan" xmlns:oleextracter="MyOleExtracter" xmlns:ole="java:XSLTFilterOLEExtracter" xmlns:java="http://saxon.sf.net/java-type" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw xalan ole oleextracter java" extension-element-prefixes="oleextracter"> <xsl:include href="ooo2wordml_custom_draw.xsl"/> - <xsl:param name="oleExtractor" as="java:XSLTFilterOLEExtracter" select="ole:new()"/> + <xsl:param name="oleExtractor" as="java:com.sun.star.comp.xsltfilter.XSLTFilterOLEExtracter" select="ole:new()"/> <xsl:param name="XMultiServiceFactory" as="java:com.sun.star.lang.XMultiServiceFactory" select="ole:init($oleExtractor, 'uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager')"/> <xsl:key name="stroke-dash-style" match="draw:stroke-dash" use="@draw:name"/> @@ -1880,6 +1880,6 @@ </xsl:template> <xsl:template match="draw:object-ole"/> <xalan:component prefix="oleextracter" elements="init exit" functions="getByName insertByName"> - <xalan:script lang="javaclass" src="xalan://XSLTFilterOLEExtracter"/> + <xalan:script lang="javaclass" src="xalan://com.sun.star.comp.xsltfilter.XSLTFilterOLEExtracter"/> </xalan:component> </xsl:stylesheet> diff --git a/filter/source/xslt/import/wordml/wordml2ooo_draw.xsl b/filter/source/xslt/import/wordml/wordml2ooo_draw.xsl index e0737d137..0a1228779 100644 --- a/filter/source/xslt/import/wordml/wordml2ooo_draw.xsl +++ b/filter/source/xslt/import/wordml/wordml2ooo_draw.xsl @@ -28,7 +28,7 @@ <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xalan="http://xml.apache.org/xalan" xmlns:oleextracter="MyOleExtracter" xmlns:ole="java:XSLTFilterOLEExtracter" xmlns:java="http://saxon.sf.net/java-type" exclude-result-prefixes="w wx aml o dt v xalan ole oleextracter java" extension-element-prefixes="oleextracter"> <xsl:include href="wordml2ooo_custom_draw.xsl"/> <xsl:include href="wordml2ooo_path.xsl"/> - <xsl:param name="oleExtractor" as="java:XSLTFilterOLEExtracter" select="ole:new()"/> + <xsl:param name="oleExtractor" as="java:com.sun.star.comp.xsltfilter.XSLTFilterOLEExtracter" select="ole:new()"/> <xsl:param name="XMultiServiceFactory" as="java:com.sun.star.lang.XMultiServiceFactory" select="ole:init($oleExtractor, 'uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager')"/> @@ -2208,6 +2208,6 @@ </xsl:choose> </xsl:template> <xalan:component prefix="oleextracter" elements="init exit" functions="getByName insertByName"> - <xalan:script lang="javaclass" src="xalan://XSLTFilterOLEExtracter"/> + <xalan:script lang="javaclass" src="xalan://com.sun.star.comp.xsltfilter.XSLTFilterOLEExtracter"/> </xalan:component> </xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl b/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl index 2aa2fdc50..5f75027d3 100644 --- a/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl +++ b/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl @@ -1,6 +1,6 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
+<?xml version="1.0" encoding="UTF-8"?> +<!-- + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. Copyright 2000, 2010 Oracle and/or its affiliates. @@ -24,805 +24,805 @@ <http://www.openoffice.org/license.html> for a copy of the LGPLv3 License. --->
-<!--
- For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
--->
-<xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
- xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:dom="http://www.w3.org/2001/xml-events"
- xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
- xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
- xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
- xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
- xmlns:math="http://www.w3.org/1998/Math/MathML"
- xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
- xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
- xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
- xmlns:ooo="http://openoffice.org/2004/office"
- xmlns:oooc="http://openoffice.org/2004/calc"
- xmlns:ooow="http://openoffice.org/2004/writer"
- xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
- xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
- xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
- xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
- xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
- xmlns:xforms="http://www.w3.org/2002/xforms"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xt="http://www.jclark.com/xt"
- xmlns:common="http://exslt.org/common"
- xmlns:xalan="http://xml.apache.org/xalan"
- exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan">
-
-
-
- <!-- ***************************************** -->
- <!-- *** Gathering office style properties *** -->
- <!-- ***************************************** -->
-
- <!-- REASON FOR STYLESHEET:
- In the OpenOffice documents styles are represented by a hierarchy.
- (e.g. most styles are inherited from a default style).
- Many other languages (as XHTML/CSS) do not support inherited styles.
- The style inheritance have to be made flat/absolute for each style.
-
- A further reason was, that the earlier style collection mechanism
- had problems with CSS inline, which do not inherit from XML office defaults
- nor font:family defaults as the style header does
- (cp. stylesheet 'style_collector.xsl' and the 'write-default-styles' template)
-
- RESULT OF STYLESHEET:
- All styles will be returned in a variable containing styles with their inherited *:
-
- <all-styles>
- <style style:family="foo" style:name="x1">
- <* fo:padding-left="0cm" fo:margin-right="0cm" />
- </style>
- <style style:family="muh" style:name="x2" >
- <* fo:padding-left="3cm" ... />
- </style>
- ...
-
- </all-styles>
- -->
-
-
- <xsl:template name="collect-global-odf-properties">
- <!-- to access the variable as a node-set by XPATH expressions, it is necessary to convert it
- from a result-tree-fragment (RTF) to a node set by a in a XSLT 1.0 non standarized function -->
- <xsl:variable name="globalDataRTF">
- <xsl:call-template name="collect-document-links-RTF" />
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="function-available('common:node-set')">
- <xsl:call-template name="collect-style-properties">
- <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xalan:nodeset')">
- <xsl:call-template name="collect-style-properties">
- <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xt:node-set')">
- <xsl:call-template name="collect-style-properties">
- <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
-
-
- <xsl:template name="collect-style-properties">
- <xsl:param name="globalData" />
-
- <!-- Add the input file references to the new collected style properties -->
- <xsl:variable name="globalDataRTF">
- <xsl:copy-of select="$globalData" />
- <xsl:call-template name="collect-style-properties-RTF">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="function-available('common:node-set')">
- <xsl:call-template name="map-odf-style-properties">
- <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xalan:nodeset')">
- <xsl:call-template name="map-odf-style-properties">
- <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xt:node-set')">
- <xsl:call-template name="map-odf-style-properties">
- <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
-
- <xsl:template name="collect-document-links-RTF">
- <!-- works for zipped office files, unzipped office files as for flat filter single office file format as well -->
- <xsl:variable name="documentLinksRTF">
- <xsl:choose>
- <xsl:when test="office:document-content">
- <xsl:element name="styles-file" namespace="">
- <xsl:copy-of select="document(concat($sourceBaseURL, 'styles.xml'))" />
- </xsl:element>
- <xsl:element name="meta-file" namespace="">
- <xsl:copy-of select="document(concat($sourceBaseURL, 'meta.xml'))" />
- </xsl:element>
- </xsl:when>
- <xsl:otherwise>
- <xsl:element name="styles-file" namespace="">
- <xsl:copy-of select="/" />
- </xsl:element>
- <xsl:element name="meta-file" namespace="">
- <xsl:copy-of select="/" />
- </xsl:element>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="function-available('common:node-set')">
- <xsl:call-template name="collect-document-links">
- <xsl:with-param name="documentLinks" select="common:node-set($documentLinksRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xalan:nodeset')">
- <xsl:call-template name="collect-document-links">
- <xsl:with-param name="documentLinks" select="xalan:nodeset($documentLinksRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xt:node-set')">
- <xsl:call-template name="collect-document-links">
- <xsl:with-param name="documentLinks" select="xt:node-set($documentLinksRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
- </xsl:otherwise>
- </xsl:choose>
-
- </xsl:template>
-
-
- <xsl:template name="collect-document-links">
- <xsl:param name="documentLinks" />
-
- <xsl:element name="styles-file" namespace="">
- <xsl:copy-of select="$documentLinks/styles-file/*" />
- </xsl:element>
-
- <xsl:element name="meta-file" namespace="">
- <xsl:copy-of select="$documentLinks/meta-file/*" />
- </xsl:element>
-
- <xsl:copy-of select="$documentLinks/styles-file/*/office:styles" />
- <xsl:copy-of select="$documentLinks/styles-file/*/office:font-face-decls" />
-
- <!-- office:automatic-styles may be containted in two files (i.e. content.xml and styles.xml).
- Wild card necessary as top level element differs from flat office files ("SampleName.fsxw") -->
- <xsl:copy-of select="/*/office:automatic-styles" />
-
- </xsl:template>
-
-
- <xsl:template name="collect-style-properties-RTF">
- <xsl:param name="globalData" />
-
- <!--** DEFAULT STYLES: First adding some office defaults unwritten in XML -->
- <xsl:variable name="defaultOfficeStyle-RTF">
- <xsl:element name="style" namespace="">
- <xsl:element name="style:properties" />
- </xsl:element>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="function-available('common:node-set')">
- <xsl:call-template name="collect-properties-defaults">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="defaultOfficeStyle" select="common:node-set($defaultOfficeStyle-RTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xalan:nodeset')">
- <xsl:call-template name="collect-properties-defaults">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="defaultOfficeStyle" select="xalan:nodeset($defaultOfficeStyle-RTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xt:node-set')">
- <xsl:call-template name="collect-properties-defaults">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="defaultOfficeStyle" select="xt:node-set($defaultOfficeStyle-RTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">ERROR: Function not found: 'Nodeset'</xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
-
- <xsl:template name="collect-properties-defaults">
- <xsl:param name="globalData" />
- <xsl:param name="defaultOfficeStyle" />
-
- <!--** DEFAULT STYLES: Adding the default styles of a style:family, by adding each office:styles/style:default-style element **-->
- <xsl:variable name="defaultFamilyStyles-RTF">
- <xsl:for-each select="$globalData/office:styles/style:default-style">
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="@style:family" />
- <xsl:call-template name="create-inherited-style-properties">
- <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" />
- </xsl:call-template>
- </xsl:element>
- </xsl:for-each>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="function-available('common:node-set')">
- <xsl:call-template name="collect-properties">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" />
- <xsl:with-param name="defaultFamilyStyles" select="common:node-set($defaultFamilyStyles-RTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xalan:nodeset')">
- <xsl:call-template name="collect-properties">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" />
- <xsl:with-param name="defaultFamilyStyles" select="xalan:nodeset($defaultFamilyStyles-RTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xt:node-set')">
- <xsl:call-template name="collect-properties">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" />
- <xsl:with-param name="defaultFamilyStyles" select="xt:node-set($defaultFamilyStyles-RTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
-
- <xsl:template name="collect-properties">
- <xsl:param name="globalData" />
- <xsl:param name="defaultOfficeStyle" />
- <xsl:param name="defaultFamilyStyles" />
-
- <!--** traversee all style trees - branch after branch - collecting style properties **-->
- <xsl:element name="all-doc-styles" namespace="">
-
- <!-- Background Information:
-
- There are two different types of styles in the Office:
- 1) The office:styles from the user pre-defined style templates
- 2) The automatic:styles, which are created whenever a user uses explicit style formatting.
-
- The office:styles only have parent styles in the office:styles,
- but automatic:styles may inherit from both office:styles and themself.
- -->
-
- <!--** traversee all office:styles trees beginning with the top-level styles **-->
- <xsl:for-each select="$globalData/office:styles/style:style[not(@style:parent-style-name)]">
- <!-- Looking for parents from style:family
- <xsl:for-each select="$globalData/office:styles/style:style[@style:family=current()/@style:family][not(@style:parent-style-name)]"> -->
- <xsl:choose>
- <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]">
- <xsl:call-template name="inherit-style-for-self-and-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="inherit-style-for-self-and-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
- <!--** creates a style element with style:name and style:family attribute and
- an element representing the absolute style properties style:property ** -->
- </xsl:for-each>
-
- <!--** traversee all office:automatic-styles trees beginning with the top-level styles **-->
- <xsl:for-each select="$globalData/office:automatic-styles/style:style[not(@style:parent-style-name)]">
- <!--** creates a style element with style:name and style:family attribute and
- an element representing the absolute style properties style:property ** -->
- <xsl:choose>
- <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]">
- <xsl:call-template name="inherit-style-for-self-and-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:call-template name="inherit-style-for-self-and-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
-
- </xsl:for-each>
-
- </xsl:element>
- <!-- debug output in case only styles should be given out (regression test) -->
- <xsl:if test="$onlyStyleOutputEnabled">
- <xsl:element name="defaultOfficeStyle" namespace="">
- <xsl:copy-of select="$defaultOfficeStyle" />
- </xsl:element>
- <xsl:element name="defaultFamilyStyles" namespace="">
- <xsl:copy-of select="$defaultFamilyStyles" />
- </xsl:element>
- </xsl:if>
-
- </xsl:template>
-
-
- <xsl:template name="inherit-style-for-self-and-children">
- <xsl:param name="globalData" />
- <xsl:param name="inheritedStyleProperties" />
- <xsl:param name="searchOnlyInAutomaticStyles" />
-
- <!--** create an absolute style by inherting properties from the given parent properties **-->
- <xsl:variable name="newStyleProperties-RTF">
- <xsl:call-template name="create-inherited-style-properties">
- <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" />
- </xsl:call-template>
- </xsl:variable>
- <xsl:choose>
- <xsl:when test="function-available('common:node-set')">
- <xsl:variable name="newStyleProperties" select="common:node-set($newStyleProperties-RTF)" />
-
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="@style:family" />
- <xsl:copy-of select="@style:name" />
- <xsl:copy-of select="$newStyleProperties" />
- </xsl:element>
-
- <xsl:choose>
- <xsl:when test="$searchOnlyInAutomaticStyles">
- <xsl:call-template name="get-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
- <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <!--** for all automatic-children of the current office:styles **-->
- <xsl:call-template name="get-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
- <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:when>
- <xsl:when test="function-available('xalan:nodeset')">
- <xsl:variable name="newStyleProperties" select="xalan:nodeset($newStyleProperties-RTF)" />
-
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="@style:family" />
- <xsl:copy-of select="@style:name" />
- <xsl:copy-of select="$newStyleProperties" />
- </xsl:element>
-
- <xsl:choose>
- <xsl:when test="$searchOnlyInAutomaticStyles">
- <xsl:call-template name="get-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
- <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <!--** for all automatic-children of the current office:styles **-->
- <xsl:call-template name="get-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
- <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:when>
- <xsl:when test="function-available('xt:node-set')">
- <xsl:variable name="newStyleProperties" select="xt:node-set($newStyleProperties-RTF)" />
-
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="@style:family" />
- <xsl:copy-of select="@style:name" />
- <xsl:copy-of select="$newStyleProperties" />
- </xsl:element>
-
- <xsl:choose>
- <xsl:when test="$searchOnlyInAutomaticStyles">
- <xsl:call-template name="get-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
- <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <!--** for all automatic-children of the current office:styles **-->
- <xsl:call-template name="get-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
- <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
- </xsl:call-template>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
-
- <xsl:template name="get-children">
- <xsl:param name="globalData" />
- <xsl:param name="searchOnlyInAutomaticStyles" />
- <xsl:param name="inheritedStyleProperties" select="*" />
-
-<!-- QUESTION: Parent style is only unique by name and family, but what about cross family inheritance? -->
- <!-- For each child style (that is every style which has the given parentStyleName as style:parent-style-name and the same style:family -->
- <xsl:variable name="parentStyleFamily" select="@style:family" />
- <xsl:variable name="parentStyleName" select="@style:name" />
- <xsl:if test="not($searchOnlyInAutomaticStyles)">
- <xsl:for-each select="$globalData/office:styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]">
- <xsl:call-template name="inherit-style-for-self-and-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" />
- </xsl:call-template>
- </xsl:for-each>
- </xsl:if>
- <xsl:for-each select="$globalData/office:automatic-styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]">
- <xsl:call-template name="inherit-style-for-self-and-children">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" />
- <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" />
- </xsl:call-template>
- </xsl:for-each>
- </xsl:template>
-
-
- <xsl:template name="create-inherited-style-properties">
- <xsl:param name="inheritedStyleProperties" />
-
- <xsl:element name="style:properties">
- <!-- Writing all inherited style properties -->
- <xsl:for-each select="$inheritedStyleProperties/@*">
- <xsl:sort select="name()" />
- <xsl:copy-of select="." />
- </xsl:for-each>
-
- <!--All current attributes will override already inserted attributes of the same name
- XSLT Spec: "Adding an attribute to an element replaces any existing attribute of that element with the same expanded-name." -->
- <xsl:for-each select="*/@*[name() != 'style:font-size-rel']">
- <xsl:copy-of select="." />
- </xsl:for-each>
-
- <xsl:if test="*/@style:font-size-rel">
-<!--
- The intheritedStyleProperties should include a absolute Font Size, but
- <style:properties
- xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
- xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
- style:font-name="Courier New"
- fo:language="en"
- fo:country="US"
- style:font-name-asian=Courier New"
- style:font-name-complex="Courier New"/>
--->
- <xsl:variable name="fontSizeAbsolute">
- <xsl:call-template name="convert2pt">
- <xsl:with-param name="value" select="$inheritedStyleProperties/@fo:font-size" />
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:variable name="fontSizeRelative">
- <xsl:call-template name="convert2pt">
- <xsl:with-param name="value" select="*/@style:font-size-rel" />
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:attribute name="fo:font-size">
- <xsl:value-of select="$fontSizeAbsolute + $fontSizeRelative"/>
- <xsl:text>pt</xsl:text>
- </xsl:attribute>
- </xsl:if>
-
- <!-- providing tabulator indentation -->
- <xsl:copy-of select="$inheritedStyleProperties/style:tab-stops"/>
- <xsl:copy-of select="*/style:tab-stops"/>
- </xsl:element>
- </xsl:template>
-
- <!-- debugging & testing purpose -->
- <xsl:template name="write-collected-styles">
- <xsl:param name="globalData" />
-
- <xsl:message><all-doc-styles></xsl:message>
- <xsl:for-each select="$globalData/all-doc-styles/style">
- <xsl:message><style</xsl:message>
- <xsl:message>style:family="<xsl:value-of select="current()/@style:family" />"></xsl:message>
- <xsl:message>style:name="<xsl:value-of select="current()/@style:name" />" </xsl:message>
- <xsl:message> <*</xsl:message>
- <xsl:for-each select="*/@*">
- <xsl:message>
- <xsl:text></xsl:text>
- <xsl:value-of select="name()" />="<xsl:value-of select="." />"</xsl:message>
- </xsl:for-each>
- <xsl:message>/></xsl:message>
- <xsl:message></style></xsl:message>
- </xsl:for-each>
- <xsl:message></all-doc-styles></xsl:message>
- </xsl:template>
-
- <xsl:template name="map-odf-style-properties">
- <xsl:param name="globalData" />
-
- <xsl:choose>
- <!--+++++ DEBUG STYLE OUTPUT FOR REGRESSION TEST +++++-->
- <!-- create styles file from the style variable (testing switch) -->
- <xsl:when test="$onlyStyleOutputEnabled">
-
- <xsl:element name="debug-output" namespace="">
- <xsl:copy-of select="$globalData" />
- <xsl:call-template name="map-odf-properties">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:call-template>
- </xsl:element>
- </xsl:when>
-
- <!-- create XHTML file -->
- <xsl:otherwise>
- <!-- to access the variable like a node-set it is necessary to convert it
- from a result-tree-fragment (RTF) to a node set using the James Clark extension -->
- <xsl:variable name="globalDataRTF">
- <!-- raw properties still needed for table width attribute creation -->
- <xsl:copy-of select="$globalData" />
- <xsl:call-template name="map-odf-properties">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:call-template>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="function-available('common:node-set')">
- <xsl:call-template name="start-main">
- <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xalan:nodeset')">
- <xsl:call-template name="start-main">
- <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:when test="function-available('xt:node-set')">
- <xsl:call-template name="start-main">
- <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <!-- REASON FOR TEMPLATE:
- The OpenOffice style properities gathered in the variable 'globalData' have to be mapped to the CSS style format
- -->
- <xsl:template name="map-odf-properties">
- <xsl:param name="globalData" />
- <xsl:element name="all-styles" namespace="">
- <xsl:for-each select="$globalData/all-doc-styles/style">
- <xsl:sort select="@style:family" />
- <xsl:sort select="@style:name" />
-
- <xsl:call-template name="writeUsedStyles">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="style" select="."/>
- </xsl:call-template>
- </xsl:for-each>
- </xsl:element>
- </xsl:template>
-
- <xsl:key name="elementUsingStyle" match="/*/office:body//*" use="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name | @table:default-cell-style-name"/>
- <xsl:key name="listLabelStyleInStyles" match="/*/office:styles/text:list-style/* |
- /*/office:styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/>
-
- <xsl:key name="listLabelStyleInContent" match="/*/office:automatic-styles/text:list-style/* | /*/office:automatic-styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/>
-
-
- <xsl:variable name="documentRoot" select="/" />
- <xsl:template name="writeUsedStyles">
- <xsl:param name="globalData" />
- <xsl:param name="style"/>
-
- <!-- for-each changes the key environment from the previously globalData back to the document root -->
- <xsl:for-each select="$documentRoot">
- <!-- only styles, which are used in the content are written as CSS styles -->
- <xsl:choose>
- <xsl:when test="key('elementUsingStyle', $style/@style:name)/@* or key('listLabelStyleInContent', $style/@style:name)/@*">
- <xsl:call-template name="writeUsedStyles2">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="style" select="$style" />
- </xsl:call-template>
- </xsl:when>
- <xsl:otherwise>
- <xsl:choose>
- <xsl:when test="not(office:document-content)">
- <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]">
- <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border
- unless style:join-border="false" -->
- <xsl:call-template name="writeUsedStyles2">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="style" select="$style" />
- </xsl:call-template>
- </xsl:if>
- </xsl:when>
- <xsl:otherwise>
- <xsl:for-each select="document($stylesFileURL)">
- <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]">
- <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border
- unless style:join-border="false" -->
- <xsl:call-template name="writeUsedStyles2">
- <xsl:with-param name="globalData" select="$globalData" />
- <xsl:with-param name="style" select="$style" />
- </xsl:call-template>
- </xsl:if>
- </xsl:for-each>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:for-each>
- </xsl:template>
-
- <xsl:template name="writeUsedStyles2">
- <xsl:param name="globalData" />
- <xsl:param name="style"/>
- <xsl:choose>
- <xsl:when test="
- $style/@style:family='paragraph'
- and((
- (
- $style/*/@fo:border-top
- or $style/*/@fo:border-bottom
- or $style/*/@fo:border
- )
- and
- (
- not($style/*/@style:join-border)
- or $style/*/@style:join-border = 'true'
- )
- )
- or
- (
- (
- $style/*/@fo:margin-top
- or $style/*/@fo:margin-bottom
- or $style/*/@fo:margin
- )
- and
- ( $style/*/@fo:background-color
- and
- not($style/*/fo:background-color='transparent')
- )
- )
- )">
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="$style/@style:family" />
- <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderStart')" /></xsl:attribute>
- <xsl:element name="final-properties" namespace="">
- <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-bottom' or name() = 'fo:margin']">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- <xsl:text> border-bottom-style:none; </xsl:text>
- </xsl:element>
- </xsl:element>
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="$style/@style:family" />
- <xsl:copy-of select="$style/@style:name" />
- <xsl:attribute name="mergedBorders"><xsl:value-of select="true()" /></xsl:attribute>
- <xsl:element name="final-properties" namespace="">
- <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top') and not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-top') and not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-top') and not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin-bottom' or name() = 'fo:margin']">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- <xsl:text> border-top-style:none; border-bottom-style:none; </xsl:text>
- </xsl:element>
- </xsl:element>
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="$style/@style:family" />
- <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderEnd')" /></xsl:attribute>
- <xsl:element name="final-properties" namespace="">
- <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top')][not(name() = 'fo:padding-top')][not(name() = 'fo:margin-top')][not(name() = 'fo:margin')]">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin']">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- <xsl:text> border-top-style:none;</xsl:text>
- </xsl:element>
- </xsl:element>
- </xsl:when>
- <xsl:otherwise>
- <xsl:choose>
- <xsl:when test="not(key('listLabelStyleInStyles', $style/@style:name)/@*)">
- <xsl:element name="style" namespace="">
- <xsl:copy-of select="$style/@style:family" />
- <xsl:copy-of select="$style/@style:name" />
- <xsl:element name="final-properties" namespace="">
- <xsl:apply-templates select="$style/*/@*">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- </xsl:element>
- </xsl:element>
- </xsl:when>
- <xsl:otherwise>
- <xsl:element name="style" namespace="">
- <xsl:attribute name="style:family">none</xsl:attribute>
- <xsl:attribute name="style:name"><xsl:value-of select="$style/@style:name"/></xsl:attribute>
- <xsl:element name="final-properties" namespace="">
- <xsl:apply-templates select="$style/*/@*">
- <xsl:with-param name="globalData" select="$globalData" />
- </xsl:apply-templates>
- </xsl:element>
- </xsl:element>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <xsl:template mode="paragraphMerge" match="@fo:margin | @fo:margin-top | @fo:margin-bottom | @fo:margin-left | @fo:margin-right">
- <xsl:text>padding</xsl:text>
- <xsl:value-of select="substring-after(name(), 'fo:margin')"/>
- <xsl:text>:</xsl:text>
- <!-- Map once erroneusly used inch shortage 'inch' to CSS shortage 'in' -->
- <xsl:choose>
- <xsl:when test="contains(., 'inch')">
- <xsl:value-of select="substring-before(.,'ch')"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="."/>
- </xsl:otherwise>
- </xsl:choose>
- <xsl:text>; </xsl:text>
- </xsl:template>
-</xsl:stylesheet>
\ No newline at end of file +--> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xt="http://www.jclark.com/xt" + xmlns:common="http://exslt.org/common" + xmlns:xalan="http://xml.apache.org/xalan" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan"> + + + + <!-- ***************************************** --> + <!-- *** Gathering office style properties *** --> + <!-- ***************************************** --> + + <!-- REASON FOR STYLESHEET: + In the OpenOffice documents styles are represented by a hierarchy. + (e.g. most styles are inherited from a default style). + Many other languages (as XHTML/CSS) do not support inherited styles. + The style inheritance have to be made flat/absolute for each style. + + A further reason was, that the earlier style collection mechanism + had problems with CSS inline, which do not inherit from XML office defaults + nor font:family defaults as the style header does + (cp. stylesheet 'style_collector.xsl' and the 'write-default-styles' template) + + RESULT OF STYLESHEET: + All styles will be returned in a variable containing styles with their inherited *: + + <all-styles> + <style style:family="foo" style:name="x1"> + <* fo:padding-left="0cm" fo:margin-right="0cm" /> + </style> + <style style:family="muh" style:name="x2" > + <* fo:padding-left="3cm" ... /> + </style> + ... + + </all-styles> + --> + + + <xsl:template name="collect-global-odf-properties"> + <!-- to access the variable as a node-set by XPATH expressions, it is necessary to convert it + from a result-tree-fragment (RTF) to a node set by a in a XSLT 1.0 non standarized function --> + <xsl:variable name="globalDataRTF"> + <xsl:call-template name="collect-document-links-RTF" /> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-style-properties"> + <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-style-properties"> + <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-style-properties"> + <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + + <xsl:template name="collect-style-properties"> + <xsl:param name="globalData" /> + + <!-- Add the input file references to the new collected style properties --> + <xsl:variable name="globalDataRTF"> + <xsl:copy-of select="$globalData" /> + <xsl:call-template name="collect-style-properties-RTF"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="map-odf-style-properties"> + <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="map-odf-style-properties"> + <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="map-odf-style-properties"> + <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="collect-document-links-RTF"> + <!-- works for zipped office files, unzipped office files as for flat filter single office file format as well --> + <xsl:variable name="documentLinksRTF"> + <xsl:choose> + <xsl:when test="office:document-content"> + <xsl:element name="styles-file" namespace=""> + <xsl:copy-of select="document(concat($sourceBaseURL, 'styles.xml'), .)" /> + </xsl:element> + <xsl:element name="meta-file" namespace=""> + <xsl:copy-of select="document(concat($sourceBaseURL, 'meta.xml'), .)" /> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:element name="styles-file" namespace=""> + <xsl:copy-of select="/" /> + </xsl:element> + <xsl:element name="meta-file" namespace=""> + <xsl:copy-of select="/" /> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-document-links"> + <xsl:with-param name="documentLinks" select="common:node-set($documentLinksRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-document-links"> + <xsl:with-param name="documentLinks" select="xalan:nodeset($documentLinksRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-document-links"> + <xsl:with-param name="documentLinks" select="xt:node-set($documentLinksRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + + </xsl:template> + + + <xsl:template name="collect-document-links"> + <xsl:param name="documentLinks" /> + + <xsl:element name="styles-file" namespace=""> + <xsl:copy-of select="$documentLinks/styles-file/*" /> + </xsl:element> + + <xsl:element name="meta-file" namespace=""> + <xsl:copy-of select="$documentLinks/meta-file/*" /> + </xsl:element> + + <xsl:copy-of select="$documentLinks/styles-file/*/office:styles" /> + <xsl:copy-of select="$documentLinks/styles-file/*/office:font-face-decls" /> + + <!-- office:automatic-styles may be containted in two files (i.e. content.xml and styles.xml). + Wild card necessary as top level element differs from flat office files ("SampleName.fsxw") --> + <xsl:copy-of select="/*/office:automatic-styles" /> + + </xsl:template> + + + <xsl:template name="collect-style-properties-RTF"> + <xsl:param name="globalData" /> + + <!--** DEFAULT STYLES: First adding some office defaults unwritten in XML --> + <xsl:variable name="defaultOfficeStyle-RTF"> + <xsl:element name="style" namespace=""> + <xsl:element name="style:properties" /> + </xsl:element> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-properties-defaults"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="common:node-set($defaultOfficeStyle-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-properties-defaults"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="xalan:nodeset($defaultOfficeStyle-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-properties-defaults"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="xt:node-set($defaultOfficeStyle-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: 'Nodeset'</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="collect-properties-defaults"> + <xsl:param name="globalData" /> + <xsl:param name="defaultOfficeStyle" /> + + <!--** DEFAULT STYLES: Adding the default styles of a style:family, by adding each office:styles/style:default-style element **--> + <xsl:variable name="defaultFamilyStyles-RTF"> + <xsl:for-each select="$globalData/office:styles/style:default-style"> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:call-template name="create-inherited-style-properties"> + <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" /> + </xsl:call-template> + </xsl:element> + </xsl:for-each> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" /> + <xsl:with-param name="defaultFamilyStyles" select="common:node-set($defaultFamilyStyles-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" /> + <xsl:with-param name="defaultFamilyStyles" select="xalan:nodeset($defaultFamilyStyles-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" /> + <xsl:with-param name="defaultFamilyStyles" select="xt:node-set($defaultFamilyStyles-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="collect-properties"> + <xsl:param name="globalData" /> + <xsl:param name="defaultOfficeStyle" /> + <xsl:param name="defaultFamilyStyles" /> + + <!--** traversee all style trees - branch after branch - collecting style properties **--> + <xsl:element name="all-doc-styles" namespace=""> + + <!-- Background Information: + + There are two different types of styles in the Office: + 1) The office:styles from the user pre-defined style templates + 2) The automatic:styles, which are created whenever a user uses explicit style formatting. + + The office:styles only have parent styles in the office:styles, + but automatic:styles may inherit from both office:styles and themself. + --> + + <!--** traversee all office:styles trees beginning with the top-level styles **--> + <xsl:for-each select="$globalData/office:styles/style:style[not(@style:parent-style-name)]"> + <!-- Looking for parents from style:family + <xsl:for-each select="$globalData/office:styles/style:style[@style:family=current()/@style:family][not(@style:parent-style-name)]"> --> + <xsl:choose> + <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + <!--** creates a style element with style:name and style:family attribute and + an element representing the absolute style properties style:property ** --> + </xsl:for-each> + + <!--** traversee all office:automatic-styles trees beginning with the top-level styles **--> + <xsl:for-each select="$globalData/office:automatic-styles/style:style[not(@style:parent-style-name)]"> + <!--** creates a style element with style:name and style:family attribute and + an element representing the absolute style properties style:property ** --> + <xsl:choose> + <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + + </xsl:for-each> + + </xsl:element> + <!-- debug output in case only styles should be given out (regression test) --> + <xsl:if test="$onlyStyleOutputEnabled"> + <xsl:element name="defaultOfficeStyle" namespace=""> + <xsl:copy-of select="$defaultOfficeStyle" /> + </xsl:element> + <xsl:element name="defaultFamilyStyles" namespace=""> + <xsl:copy-of select="$defaultFamilyStyles" /> + </xsl:element> + </xsl:if> + + </xsl:template> + + + <xsl:template name="inherit-style-for-self-and-children"> + <xsl:param name="globalData" /> + <xsl:param name="inheritedStyleProperties" /> + <xsl:param name="searchOnlyInAutomaticStyles" /> + + <!--** create an absolute style by inherting properties from the given parent properties **--> + <xsl:variable name="newStyleProperties-RTF"> + <xsl:call-template name="create-inherited-style-properties"> + <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" /> + </xsl:call-template> + </xsl:variable> + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:variable name="newStyleProperties" select="common:node-set($newStyleProperties-RTF)" /> + + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:copy-of select="@style:name" /> + <xsl:copy-of select="$newStyleProperties" /> + </xsl:element> + + <xsl:choose> + <xsl:when test="$searchOnlyInAutomaticStyles"> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!--** for all automatic-children of the current office:styles **--> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:variable name="newStyleProperties" select="xalan:nodeset($newStyleProperties-RTF)" /> + + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:copy-of select="@style:name" /> + <xsl:copy-of select="$newStyleProperties" /> + </xsl:element> + + <xsl:choose> + <xsl:when test="$searchOnlyInAutomaticStyles"> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!--** for all automatic-children of the current office:styles **--> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:variable name="newStyleProperties" select="xt:node-set($newStyleProperties-RTF)" /> + + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:copy-of select="@style:name" /> + <xsl:copy-of select="$newStyleProperties" /> + </xsl:element> + + <xsl:choose> + <xsl:when test="$searchOnlyInAutomaticStyles"> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!--** for all automatic-children of the current office:styles **--> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="get-children"> + <xsl:param name="globalData" /> + <xsl:param name="searchOnlyInAutomaticStyles" /> + <xsl:param name="inheritedStyleProperties" select="*" /> + +<!-- QUESTION: Parent style is only unique by name and family, but what about cross family inheritance? --> + <!-- For each child style (that is every style which has the given parentStyleName as style:parent-style-name and the same style:family --> + <xsl:variable name="parentStyleFamily" select="@style:family" /> + <xsl:variable name="parentStyleName" select="@style:name" /> + <xsl:if test="not($searchOnlyInAutomaticStyles)"> + <xsl:for-each select="$globalData/office:styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" /> + </xsl:call-template> + </xsl:for-each> + </xsl:if> + <xsl:for-each select="$globalData/office:automatic-styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" /> + </xsl:call-template> + </xsl:for-each> + </xsl:template> + + + <xsl:template name="create-inherited-style-properties"> + <xsl:param name="inheritedStyleProperties" /> + + <xsl:element name="style:properties"> + <!-- Writing all inherited style properties --> + <xsl:for-each select="$inheritedStyleProperties/@*"> + <xsl:sort select="name()" /> + <xsl:copy-of select="." /> + </xsl:for-each> + + <!--All current attributes will override already inserted attributes of the same name + XSLT Spec: "Adding an attribute to an element replaces any existing attribute of that element with the same expanded-name." --> + <xsl:for-each select="*/@*[name() != 'style:font-size-rel']"> + <xsl:copy-of select="." /> + </xsl:for-each> + + <xsl:if test="*/@style:font-size-rel"> +<!-- + The intheritedStyleProperties should include a absolute Font Size, but + <style:properties + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + style:font-name="Courier New" + fo:language="en" + fo:country="US" + style:font-name-asian=Courier New" + style:font-name-complex="Courier New"/> +--> + <xsl:variable name="fontSizeAbsolute"> + <xsl:call-template name="convert2pt"> + <xsl:with-param name="value" select="$inheritedStyleProperties/@fo:font-size" /> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="fontSizeRelative"> + <xsl:call-template name="convert2pt"> + <xsl:with-param name="value" select="*/@style:font-size-rel" /> + </xsl:call-template> + </xsl:variable> + + <xsl:attribute name="fo:font-size"> + <xsl:value-of select="$fontSizeAbsolute + $fontSizeRelative"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + </xsl:if> + + <!-- providing tabulator indentation --> + <xsl:copy-of select="$inheritedStyleProperties/style:tab-stops"/> + <xsl:copy-of select="*/style:tab-stops"/> + </xsl:element> + </xsl:template> + + <!-- debugging & testing purpose --> + <xsl:template name="write-collected-styles"> + <xsl:param name="globalData" /> + + <xsl:message><all-doc-styles></xsl:message> + <xsl:for-each select="$globalData/all-doc-styles/style"> + <xsl:message><style</xsl:message> + <xsl:message>style:family="<xsl:value-of select="current()/@style:family" />"></xsl:message> + <xsl:message>style:name="<xsl:value-of select="current()/@style:name" />" </xsl:message> + <xsl:message> <*</xsl:message> + <xsl:for-each select="*/@*"> + <xsl:message> + <xsl:text></xsl:text> + <xsl:value-of select="name()" />="<xsl:value-of select="." />"</xsl:message> + </xsl:for-each> + <xsl:message>/></xsl:message> + <xsl:message></style></xsl:message> + </xsl:for-each> + <xsl:message></all-doc-styles></xsl:message> + </xsl:template> + + <xsl:template name="map-odf-style-properties"> + <xsl:param name="globalData" /> + + <xsl:choose> + <!--+++++ DEBUG STYLE OUTPUT FOR REGRESSION TEST +++++--> + <!-- create styles file from the style variable (testing switch) --> + <xsl:when test="$onlyStyleOutputEnabled"> + + <xsl:element name="debug-output" namespace=""> + <xsl:copy-of select="$globalData" /> + <xsl:call-template name="map-odf-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:element> + </xsl:when> + + <!-- create XHTML file --> + <xsl:otherwise> + <!-- to access the variable like a node-set it is necessary to convert it + from a result-tree-fragment (RTF) to a node set using the James Clark extension --> + <xsl:variable name="globalDataRTF"> + <!-- raw properties still needed for table width attribute creation --> + <xsl:copy-of select="$globalData" /> + <xsl:call-template name="map-odf-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="start-main"> + <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="start-main"> + <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="start-main"> + <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- REASON FOR TEMPLATE: + The OpenOffice style properities gathered in the variable 'globalData' have to be mapped to the CSS style format + --> + <xsl:template name="map-odf-properties"> + <xsl:param name="globalData" /> + <xsl:element name="all-styles" namespace=""> + <xsl:for-each select="$globalData/all-doc-styles/style"> + <xsl:sort select="@style:family" /> + <xsl:sort select="@style:name" /> + + <xsl:call-template name="writeUsedStyles"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="."/> + </xsl:call-template> + </xsl:for-each> + </xsl:element> + </xsl:template> + + <xsl:key name="elementUsingStyle" match="*" use="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name | @table:default-cell-style-name"/> + <xsl:key name="listLabelStyleInStyles" match="/*/office:styles/text:list-style/* | + /*/office:styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/> + + <xsl:key name="listLabelStyleInContent" match="/*/office:automatic-styles/text:list-style/* | /*/office:automatic-styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/> + + + <xsl:variable name="documentRoot" select="/" /> + <xsl:template name="writeUsedStyles"> + <xsl:param name="globalData" /> + <xsl:param name="style"/> + + <!-- for-each changes the key environment from the previously globalData back to the document root --> + <xsl:for-each select="$documentRoot"> + <!-- only styles, which are used in the content are written as CSS styles --> + <xsl:choose> + <xsl:when test="key('elementUsingStyle', $style/@style:name)/@* or key('listLabelStyleInContent', $style/@style:name)/@*"> + <xsl:call-template name="writeUsedStyles2"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="$style" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="not(office:document-content)"> + <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]"> + <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border + unless style:join-border="false" --> + <xsl:call-template name="writeUsedStyles2"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="$style" /> + </xsl:call-template> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:for-each select="document($stylesFileURL)"> + <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]"> + <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border + unless style:join-border="false" --> + <xsl:call-template name="writeUsedStyles2"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="$style" /> + </xsl:call-template> + </xsl:if> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:template> + + <xsl:template name="writeUsedStyles2"> + <xsl:param name="globalData" /> + <xsl:param name="style"/> + <xsl:choose> + <xsl:when test=" + $style/@style:family='paragraph' + and(( + ( + $style/*/@fo:border-top + or $style/*/@fo:border-bottom + or $style/*/@fo:border + ) + and + ( + not($style/*/@style:join-border) + or $style/*/@style:join-border = 'true' + ) + ) + or + ( + ( + $style/*/@fo:margin-top + or $style/*/@fo:margin-bottom + or $style/*/@fo:margin + ) + and + ( $style/*/@fo:background-color + and + not($style/*/fo:background-color='transparent') + ) + ) + )"> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderStart')" /></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-bottom' or name() = 'fo:margin']"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:text> border-bottom-style:none; </xsl:text> + </xsl:element> + </xsl:element> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:copy-of select="$style/@style:name" /> + <xsl:attribute name="mergedBorders"><xsl:value-of select="true()" /></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top') and not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-top') and not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-top') and not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin-bottom' or name() = 'fo:margin']"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:text> border-top-style:none; border-bottom-style:none; </xsl:text> + </xsl:element> + </xsl:element> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderEnd')" /></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top')][not(name() = 'fo:padding-top')][not(name() = 'fo:margin-top')][not(name() = 'fo:margin')]"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin']"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:text> border-top-style:none;</xsl:text> + </xsl:element> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="not(key('listLabelStyleInStyles', $style/@style:name)/@*)"> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:copy-of select="$style/@style:name" /> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + </xsl:element> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:element name="style" namespace=""> + <xsl:attribute name="style:family">none</xsl:attribute> + <xsl:attribute name="style:name"><xsl:value-of select="$style/@style:name"/></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + </xsl:element> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template mode="paragraphMerge" match="@fo:margin | @fo:margin-top | @fo:margin-bottom | @fo:margin-left | @fo:margin-right"> + <xsl:text>padding</xsl:text> + <xsl:value-of select="substring-after(name(), 'fo:margin')"/> + <xsl:text>:</xsl:text> + <!-- Map once erroneusly used inch shortage 'inch' to CSS shortage 'in' --> + <xsl:choose> + <xsl:when test="contains(., 'inch')"> + <xsl:value-of select="substring-before(.,'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="."/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + </xsl:template> +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl index 5934e2e3a..acdc3dd04 100644 --- a/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl +++ b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl @@ -2,23 +2,23 @@ <!-- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - + Copyright 2000, 2010 Oracle and/or its affiliates. - + OpenOffice.org - a multi-platform office productivity suite - + This file is part of OpenOffice.org. - + OpenOffice.org is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 only, as published by the Free Software Foundation. - + OpenOffice.org is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License version 3 for more details (a copy is included in the LICENSE file that accompanied this code). - + You should have received a copy of the GNU Lesser General Public License version 3 along with OpenOffice.org. If not, see <http://www.openoffice.org/license.html> @@ -50,7 +50,7 @@ <xsl:param name="globalData"/> <xsl:choose> - <xsl:when test="*/text:tab[1] or */*/text:tab[1]"> + <xsl:when test="parent::table-of-content and */text:tab[1] or */*/text:tab[1]"> <xsl:call-template name="createIndexBodyTable"> <xsl:with-param name="globalData" select="$globalData"/> </xsl:call-template> @@ -93,18 +93,18 @@ <xsl:attribute name="border">0</xsl:attribute> <xsl:attribute name="cellspacing">0</xsl:attribute> <xsl:attribute name="cellpadding">0</xsl:attribute> - <xsl:if test="parent::*/@text:style-name"> + <xsl:if test="parent::*/@text:style-name"> <!-- parent as index:body has no style --> - <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/parent::*/@text:style-name]/*/@style:rel-width"/> - <xsl:if test="$value"> - <xsl:attribute name="width"> - <xsl:value-of select="$value"/> - </xsl:attribute> - </xsl:if> - <xsl:attribute name="class"> - <xsl:value-of select="translate(parent::*/@text:style-name, '.,;: %()[]/\+', '_____________')"/> - </xsl:attribute> - </xsl:if> + <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/parent::*/@text:style-name]/*/@style:rel-width"/> + <xsl:if test="$value"> + <xsl:attribute name="width"> + <xsl:value-of select="$value"/> + </xsl:attribute> + </xsl:if> + <xsl:attribute name="class"> + <xsl:value-of select="translate(parent::*/@text:style-name, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:if> <xsl:element namespace="{$namespace}" name="colgroup"> <xsl:choose> @@ -489,32 +489,66 @@ Scenarios unmatched: <!-- CREATION OF A CONTENT TABLE LINK --> <!-- ************************************** --> + <xsl:key name="bookmark" match="text:bookmark | text:bookmark-start" use="@text:name"/> <!-- content table link --> <xsl:template match="text:a" mode="content-table"> <xsl:param name="globalData"/> - <xsl:variable name="text"> - <xsl:choose> - <!-- heuristic assumption that first in a content table row, there is numbering (if at all) and than the text, - furthermore that a tab will separate the to be neglected page number --> - <xsl:when test="text:tab"> - <xsl:value-of select="text()[1]"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="text()"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <!-- REFERENCE HANDLING - HREF --> - <xsl:element namespace="{$namespace}" name="a"> - <xsl:attribute name="href"> - <xsl:text>#</xsl:text> - <xsl:value-of select='concat("a_", translate(normalize-space($text), "
&<>.,;: %()[]/\+", "_______________________________"))'/> - </xsl:attribute> - <xsl:value-of select="$text"/> - </xsl:element> + <xsl:variable name="name" select="substring(@xlink:href,2)"/> + + <xsl:variable name="text"> + <xsl:choose> + <!-- heuristic assumption that first in a content table row, there is numbering (if at all) and than the text, + furthermore that a tab will separate the to be neglected page number --> + <xsl:when test="text:tab"> + <xsl:call-template name="write-text-without-line-numbers"> + <xsl:with-param name="textCount" select="count(text())"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="text()"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <!-- REFERENCE HANDLING - HREF --> + <xsl:element namespace="{$namespace}" name="a"> + <xsl:attribute name="href"> + <xsl:text>#</xsl:text> + <xsl:choose> + <xsl:when test="key('bookmark',$name)"> + <xsl:value-of select="$name"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select='concat("a_", translate(normalize-space($text), "
&<>.,;: %()[]/\+", "_______________________________"))'/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:value-of select="$text"/> + </xsl:element> + </xsl:template> + + <!-- Heuristic: write out text separated by elements, leaving the last number out (mostly text number) --> + <xsl:template name="write-text-without-line-numbers"> + <xsl:param name="textCount"/> + <xsl:param name="textNodeNumber" select="1"/> + + <xsl:choose> + <xsl:when test="$textCount > $textNodeNumber"> + <xsl:value-of select="text()[$textNodeNumber]"/> + <xsl:call-template name="write-text-without-line-numbers"> + <xsl:with-param name="textCount" select="$textCount"/> + <xsl:with-param name="textNodeNumber" select="$textNodeNumber + 1"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:if test="not(number(text()[$textNodeNumber]) > -1)"> + <xsl:value-of select="text()[$textNodeNumber]"/> + </xsl:if> + </xsl:otherwise> + </xsl:choose> + </xsl:template> <xsl:template match="text:s" mode="content-table"> @@ -542,13 +576,13 @@ Scenarios unmatched: </xsl:element> </xsl:if> </xsl:template> - + <xsl:template match="text()" mode="content-table"> - <!-- Heuristic to remove page numbers (useless in HTML) in the content table + <!-- Heuristic to remove page numbers (useless in HTML) in the content table usually after a tab --> <xsl:if test="name(preceding-sibling::*[1]) != 'text:tab' and not(number() > -1)"> <xsl:value-of select="."/> </xsl:if> </xsl:template> - + </xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl index 1c47b8f25..99c2b45d1 100644 --- a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl +++ b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl @@ -57,7 +57,6 @@ <xsl:key match="style:master-page" name="masterPageElements" use="@style:name"/> <xsl:key match="style:page-layout" name="pageLayoutElements" use="@style:name"/> <xsl:key name="writingModeStyles" match="/*/office:styles/style:style/style:paragraph-properties/@style:writing-mode | /*/office:automatic-styles/style:style/style:paragraph-properties/@style:writing-mode" use="'test'"/> - <xsl:template name="create-body"> <xsl:param name="globalData"/> <xsl:call-template name="create-body.collect-page-properties"> @@ -76,7 +75,8 @@ <xsl:if test="key('elementUsingStyle', ../@style:name)"> <!-- Check every master-page-name if it is not emtpy and return as ';' separated list --> <xsl:if test="string-length(../@style:master-page-name) > 0"> - <xsl:value-of select="../@style:master-page-name"/>;</xsl:if> + <xsl:value-of select="../@style:master-page-name"/>; + </xsl:if> </xsl:if> </xsl:for-each> </xsl:variable> @@ -86,7 +86,7 @@ <xsl:variable name="pagePropertiesRTF"> <xsl:choose> <xsl:when test="not($pageLayoutName) or $pageLayoutName = ''"> - <xsl:value-of select="$globalData/styles-file/*/office:automatic-styles/style:page-layout[1]/style:page-layout-properties"/> + <xsl:copy-of select="$globalData/styles-file/*/office:automatic-styles/style:page-layout[1]/style:page-layout-properties"/> </xsl:when> <xsl:otherwise> <!-- Find the according style:page-layout and store the properties in a variable --> @@ -404,7 +404,7 @@   is an unbreakable whitespace to give conent to the element and force a browser not to ignore the element --> <div style="clear:both; line-height:0; width:0; height:0; margin:0; padding:0;"> </div> </xsl:when> - <xsl:when test="text:tab"> + <xsl:when test="text:tab and not(ancestor::text:index-body)"> <!-- If there is a tabulator (ie. text:tab) within a paragraph, a heuristic for ODF tabulators creates a span for every text:tab embracing the following text nodes aligning them according to the tabulator. A line break or another text:tab starts a new text:span, line break even the tab counter for the line. @@ -511,8 +511,9 @@ <!-- every frame sibling have to be incapuslated within a div with left indent --> <xsl:element name="span"> <xsl:choose> - <xsl:when test="count($tabStops/style:tab-stop) < 3"> + <xsl:when test="count($tabStops/style:tab-stop) > 0 and count($tabStops/style:tab-stop) < 3"> <!-- only allow the heuristic when the style has less than 3 TABS --> + <!-- ignore heuristics if no TABS are defined --> <xsl:attribute name="style"> <xsl:call-template name="createTabIndent"> <xsl:with-param name="globalData" select="$globalData"/> @@ -615,6 +616,11 @@ </xsl:otherwise> </xsl:choose> </xsl:variable> + <!--<xsl:message>TAB: tabCount= + <xsl:value-of select="$tabCount"/>, tabPosition= + <xsl:value-of select="$tabPosition"/>, tabIndent= + <xsl:value-of select="$tabIndent"/> + </xsl:message>--> <xsl:choose> <xsl:when test="$tabIndent='NaN'"> <xsl:variable name="tabPositionTmp"> @@ -785,7 +791,7 @@ <xsl:with-param name="globalData" select="$globalData"/> <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/> <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/> - <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> </xsl:call-template> <!-- next elements will be called after the creation with the new indent (plus width of frame) --> </xsl:when> @@ -891,7 +897,9 @@ <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/> </xsl:call-template> <!-- after the last draw:frame sibling the CSS float is disabled --> - <div style="clear:both; line-height:0; width:0; height:0; margin:0; padding:0;"> </div> + <xsl:if test="@text:anchor-type!='as-char'"> + <div style="clear:both; line-height:0; width:0; height:0; margin:0; padding:0;"> </div> + </xsl:if> </xsl:template> <xsl:template name="getPageMarginLeft"> @@ -903,7 +911,8 @@ <xsl:if test="key('elementUsingStyle', ../@style:name)"> <!-- Check every master-page-name if it is not emtpy and return as ';' separated list --> <xsl:if test="string-length(../@style:master-page-name) > 0"> - <xsl:value-of select="../@style:master-page-name"/>;</xsl:if> + <xsl:value-of select="../@style:master-page-name"/>; + </xsl:if> </xsl:if> </xsl:for-each> </xsl:variable> @@ -1030,21 +1039,21 @@ </xsl:apply-templates> </xsl:when> <xsl:otherwise>--> - <xsl:call-template name="createDrawFrame2"> - <xsl:with-param name="globalData" select="$globalData"/> - <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/> - <xsl:with-param name="parentMarginLeftNew" select="$parentMarginLeftNew"/> - <xsl:with-param name="leftPosition" select="$leftPosition"/> - <xsl:with-param name="svgY" select="$svgY"/> - </xsl:call-template> - <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating"> - <xsl:with-param name="globalData" select="$globalData"/> - <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/> - <xsl:with-param name="parentMarginLeft" select="$parentMarginLeftNew"/> - <xsl:with-param name="leftPosition" select="$leftPosition"/> - <xsl:with-param name="createDiv" select="true()"/> - <xsl:with-param name="noDivBefore" select="false()"/> - </xsl:apply-templates> + <xsl:call-template name="createDrawFrame2"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/> + <xsl:with-param name="parentMarginLeftNew" select="$parentMarginLeftNew"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="svgY" select="$svgY"/> + </xsl:call-template> + <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeftNew"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="createDiv" select="true()"/> + <xsl:with-param name="noDivBefore" select="false()"/> + </xsl:apply-templates> <!-- </xsl:otherwise> @@ -1058,20 +1067,31 @@ <xsl:param name="leftPosition" /> <xsl:param name="svgY" /> - <xsl:comment>Next 'div' is a draw:frame.</xsl:comment> - <xsl:element name="div"> + <xsl:variable name="elem-name"> + <xsl:choose> + <xsl:when test="@text:anchor-type='as-char'">span</xsl:when> + <xsl:otherwise>div</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:comment>Next ' + <xsl:value-of select="$elem-name"/>' is a draw:frame. + </xsl:comment> + <xsl:element name="{$elem-name}"> <xsl:attribute name="style"> <xsl:call-template name="widthAndHeight"/> - - <!-- all images float (CSS float reltaive) with a left position calculated by svg:x - parentMarginLeft - previousFrameWidths --> - <xsl:text> float:left; padding:0; position:relative; left:</xsl:text> - <xsl:value-of select="$leftPosition"/> - <xsl:text>cm; </xsl:text> - <!-- if the frame is anchored on a char --> - <xsl:if test="@text:anchor-type='char'"> - <xsl:text>top:</xsl:text> - <xsl:value-of select="$svgY"/> + <!-- MIB --> + <xsl:text> padding:0; </xsl:text> + <xsl:if test="@text:anchor-type!='as-char'"> + <!-- all images float (CSS float reltaive) with a left position calculated by svg:x - parentMarginLeft - previousFrameWidths --> + <xsl:text> float:left; position:relative; left:</xsl:text> + <xsl:value-of select="$leftPosition"/> <xsl:text>cm; </xsl:text> + <!-- if the frame is anchored on a char --> + <xsl:if test="@text:anchor-type='char'"> + <xsl:text>top:</xsl:text> + <xsl:value-of select="$svgY"/> + <xsl:text>cm; </xsl:text> + </xsl:if> </xsl:if> </xsl:attribute> <xsl:apply-templates select="@*"> @@ -1083,6 +1103,8 @@ </xsl:element> </xsl:template> + <xsl:template match="svg:desc"/> + <xsl:template name="widthAndHeight"> <xsl:if test="@svg:height | @svg:width"> <xsl:choose> @@ -1498,7 +1520,9 @@ <xsl:message> Accessibility Warning: No alternate text ('svg:desc' element) set for - image '<xsl:value-of select="@xlink:href"/>'!</xsl:message> + image ' + <xsl:value-of select="@xlink:href"/>'! + </xsl:message> </xsl:otherwise> </xsl:choose> </xsl:attribute> @@ -1926,7 +1950,6 @@ <xsl:when test="$isEmptyList or $isListHeader"> <xsl:apply-templates> <xsl:with-param name="globalData" select="$globalData"/> - <xsl:with-param name="isNextLevelNumberingReset" select="$isListHeader or $isNextLevelNumberingReset"/> <xsl:with-param name="itemLabel" select="$itemLabelNew"/> <xsl:with-param name="listLevel" select="$listLevel + 1"/> <xsl:with-param name="listStyleName" select="$listStyleName"/> @@ -2206,7 +2229,7 @@ <xsl:when test="$currentListLevel < $listLevel"> <xsl:choose> <!-- if it has content the counting is ended --> - <xsl:when test="not($isEmptyList or $isListHeader)"> + <xsl:when test="*[name() = 'text:h' or name() = 'text:p'] or $isListHeader"> <!-- 2DO: Perhaps the children still have to be processed --> <xsl:value-of select="$itemNumber + $pseudoLevel"/> </xsl:when> @@ -2261,7 +2284,7 @@ <xsl:with-param name="pseudoLevel"> <xsl:choose> <!-- empty list item does not count --> - <xsl:when test="$isEmptyList or $isListHeader"> + <xsl:when test="not(*[name() = 'text:h' or name() = 'text:p']) or $isListHeader"> <xsl:value-of select="$pseudoLevel"/> </xsl:when> <xsl:otherwise>1</xsl:otherwise> @@ -2853,6 +2876,20 @@ </xsl:apply-templates> </xsl:template> + <!-- ***************** --> + <!-- *** Bookmarks *** --> + <!-- ***************** --> + + <xsl:template match="text:bookmark|text:bookmark-start"> + <xsl:element name="a"> + <xsl:attribute name="name"> + <xsl:value-of select="@text:name"/> + </xsl:attribute> + </xsl:element> + </xsl:template> + + <xsl:template match="text:bookmark-end"/> + <!-- DISABLING this tab handling as the tab width is only relative <xsl:template match="text:tab"> <xsl:param name="globalData"/> diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl index ab2c9bbaa..7e834862c 100644 --- a/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl +++ b/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl @@ -441,15 +441,16 @@ <link rel="transformation" href="http://xml.openoffice.org/odf2xhtml/rdf-extract.xsl" /> --> - <!-- base URL of document for resolving relative links --> + <!-- base URL of document for resolving relative links + NOTE: CHROME has a problem, with relative references as from content table, referencing to root directory instead of document <xsl:element name="base"> - <xsl:attribute name="href"> + <xsl:attribute name="href">--> <!-- earlier 'targetURL' was used for an absoulte reference of base provided by the Office (file URL) <xsl:value-of select="$targetURL" /> now '.' let relative links work, even if document has been moved --> - <xsl:text>.</xsl:text> + <!--<xsl:text>.</xsl:text> </xsl:attribute> - </xsl:element> + </xsl:element>--> </xsl:template> <!-- generic template for adding common meta tags --> diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl index f0ac642a0..3d2cd7881 100644 --- a/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl +++ b/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl @@ -79,7 +79,7 @@ indent = "no" omit-xml-declaration = "no" doctype-public = "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" - doctype-system = "http://www.w3.org/TR/MathML2/dtd/xhtml-math11-f.dtd" /> + doctype-system = "http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd" /> diff --git a/filter/source/xsltdialog/xmlfilterjar.cxx b/filter/source/xsltdialog/xmlfilterjar.cxx index 8605b1412..c12f59d9d 100644 --- a/filter/source/xsltdialog/xmlfilterjar.cxx +++ b/filter/source/xsltdialog/xmlfilterjar.cxx @@ -389,8 +389,20 @@ bool XMLFilterJarHelper::copyFile( Reference< XHierarchicalNameAccess > xIfc, OU if( !createDirectory( rURL ) ) return false; - SvFileStream aOutputStream(rURL, STREAM_WRITE ); - Reference< XOutputStream > xOS( new utl::OOutputStreamWrapper( aOutputStream ) ); + ::osl::File file(rURL); + ::osl::FileBase::RC rc = + file.open(OpenFlag_Write|OpenFlag_Create); + if (::osl::FileBase::E_EXIST == rc) { + rc = file.open(OpenFlag_Write); + if (::osl::FileBase::E_None == rc) { + file.setSize(0); // #i97170# truncate + } + } + if (::osl::FileBase::E_None != rc) { + throw RuntimeException(); + } + Reference< XOutputStream > const xOS( + new comphelper::OSLOutputStreamWrapper(file)); return copyStreams( xIS, xOS ); } diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx index e0c1c7f44..d12d0550d 100644 --- a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx +++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx @@ -91,6 +91,8 @@ XMLFilterSettingsDialog::XMLFilterSettingsDialog( Window* pParent, ResMgr& rResM mpFilterListBox->SetSelectHdl( LINK( this, XMLFilterSettingsDialog, SelectionChangedHdl_Impl ) ); mpFilterListBox->SetDeselectHdl( LINK( this, XMLFilterSettingsDialog, SelectionChangedHdl_Impl ) ); mpFilterListBox->SetDoubleClickHdl( LINK( this, XMLFilterSettingsDialog, DoubleClickHdl_Impl ) ); + mpFilterListBox->SetAccessibleName(String( RESID( STR_XML_FILTER_LISTBOX ))); + maCtrlFilterList.SetAccessibleName(String( RESID( STR_XML_FILTER_LISTBOX ))); mpFilterListBox->SetHelpId( HID_XML_FILTER_LIST ); maPBNew.SetClickHdl(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) ); diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.hrc b/filter/source/xsltdialog/xmlfiltersettingsdialog.hrc index 02022d050..20b4ba5c9 100644 --- a/filter/source/xsltdialog/xmlfiltersettingsdialog.hrc +++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.hrc @@ -39,5 +39,5 @@ #define PB_XML_FILTER_OPEN 7 #define BTN_XML_FILTER_HELP 8 #define PB_XML_FILTER_CLOSE 9 - +#define STR_XML_FILTER_LISTBOX 10 #endif diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.src b/filter/source/xsltdialog/xmlfiltersettingsdialog.src index a40259acc..5e4f402d3 100644 --- a/filter/source/xsltdialog/xmlfiltersettingsdialog.src +++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.src @@ -126,6 +126,11 @@ WorkWindow DLG_XML_FILTER_SETTINGS_DIALOG }; +String STR_XML_FILTER_LISTBOX +{ + Text [ en-US ] = "XML Filter List"; +}; + diff --git a/filter/source/xsltfilter/Manifest b/filter/source/xsltfilter/Manifest index b189662d3..e20aea34d 100644 --- a/filter/source/xsltfilter/Manifest +++ b/filter/source/xsltfilter/Manifest @@ -1,3 +1,3 @@ -RegistrationClassName: XSLTransformer +RegistrationClassName: com.sun.star.comp.xsltfilter.XSLTransformer Class-Path: saxon9.jar UNO-Type-Path: diff --git a/filter/source/xsltfilter/Base64.java b/filter/source/xsltfilter/com/sun/star/comp/xsltfilter/Base64.java index 2196aa0bc..d98132607 100644 --- a/filter/source/xsltfilter/Base64.java +++ b/filter/source/xsltfilter/com/sun/star/comp/xsltfilter/Base64.java @@ -1,3 +1,5 @@ +package com.sun.star.comp.xsltfilter; + /************************************************************************ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/filter/source/xsltfilter/XSLTFilterOLEExtracter.java b/filter/source/xsltfilter/com/sun/star/comp/xsltfilter/XSLTFilterOLEExtracter.java index 686032437..9508e98f8 100644 --- a/filter/source/xsltfilter/XSLTFilterOLEExtracter.java +++ b/filter/source/xsltfilter/com/sun/star/comp/xsltfilter/XSLTFilterOLEExtracter.java @@ -1,3 +1,5 @@ +package com.sun.star.comp.xsltfilter; + /************************************************************************ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/filter/source/xsltfilter/XSLTransformer.java b/filter/source/xsltfilter/com/sun/star/comp/xsltfilter/XSLTransformer.java index e6e67bd21..b738a6534 100644 --- a/filter/source/xsltfilter/XSLTransformer.java +++ b/filter/source/xsltfilter/com/sun/star/comp/xsltfilter/XSLTransformer.java @@ -1,3 +1,5 @@ +package com.sun.star.comp.xsltfilter; + /************************************************************************ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -77,6 +79,7 @@ import com.sun.star.uno.UnoRuntime; //Uno to java Adaptor import com.sun.star.lib.uno.adapter.XInputStreamToInputStreamAdapter; import com.sun.star.lib.uno.adapter.XOutputStreamToOutputStreamAdapter; +import javax.xml.transform.Templates; import net.sf.saxon.FeatureKeys; @@ -97,7 +100,6 @@ public class XSLTransformer */ private XInputStream m_xis; private XOutputStream m_xos; // private static HashMap templatecache; - private static final int STREAM_BUFFER_SIZE = 4000; private static final String STATSPROP = "XSLTransformer.statsfile"; private static PrintStream statsp; private String stylesheeturl; @@ -110,11 +112,11 @@ public class XSLTransformer private Thread t; // listeners private Vector listeners = new Vector(); // private XMultiServiceFactory svcfactory; // cache for transformations by stylesheet - private static Hashtable transformers = new Hashtable(); + private static Hashtable xsltReferences = new Hashtable(); // struct for cached stylesheets private static class Transformation { - public Transformer transformer; + public Templates cachedXSLT; public long lastmod; } // Resolve URIs to an empty source @@ -259,9 +261,10 @@ public class XSLTransformer // in order to help performance and to remedy a a possible memory // leak in xalan, where it seems, that Transformer instances cannot // be reclaimed though they are no longer referenced here, we use - // a cache of weak references to transformers created for specific + // a cache of weak references (ie. xsltReferences) created for specific // style sheet URLs see also #i48384# + Templates xsltTemplate = null; Transformer transformer = null; Transformation transformation = null; // File stylefile = new File(new URI(stylesheeturl)); @@ -278,36 +281,37 @@ public class XSLTransformer } } - synchronized (transformers) { + synchronized (xsltReferences) { java.lang.ref.WeakReference ref = null; - // try to get the transformer reference from the cache - if ((ref = (java.lang.ref.WeakReference) transformers.get(stylesheeturl)) == null || + // try to get the xsltTemplate reference from the cache + if ((ref = (java.lang.ref.WeakReference) xsltReferences.get(stylesheeturl)) == null || (transformation = ((Transformation) ref.get())) == null || ((Transformation) ref.get()).lastmod < lastmod) { // we cannot find a valid reference for this stylesheet // or the stylsheet was updated if (ref != null) { - transformers.remove(stylesheeturl); + xsltReferences.remove(stylesheeturl); } - // create new transformer for this stylesheet + // create new xsltTemplate for this stylesheet TransformerFactory tfactory = TransformerFactory.newInstance(); debug("TransformerFactory is '" + tfactory.getClass().getName() + "'"); // some external saxons (Debian, Ubuntu, ...) have this disabled // per default tfactory.setAttribute(FeatureKeys.ALLOW_EXTERNAL_FUNCTIONS, new Boolean(true)); - transformer = tfactory.newTransformer(new StreamSource(stylesheeturl)); - transformer.setOutputProperty("encoding", "UTF-8"); - // transformer.setURIResolver(XSLTransformer.this); + xsltTemplate = tfactory.newTemplates(new StreamSource(stylesheeturl)); // store the transformation into the cache transformation = new Transformation(); transformation.lastmod = lastmod; - transformation.transformer = transformer; + transformation.cachedXSLT = xsltTemplate; ref = new java.lang.ref.WeakReference(transformation); - transformers.put(stylesheeturl, ref); + xsltReferences.put(stylesheeturl, ref); } } - transformer = transformation.transformer; + xsltTemplate = transformation.cachedXSLT; + transformer = xsltTemplate.newTransformer(); + transformer.setOutputProperty("encoding", "UTF-8"); + // transformer.setURIResolver(XSLTransformer.this); // invalid to set 'null' as parameter as 'null' is not a valid Java object if (sourceurl != null) { @@ -356,12 +360,33 @@ public class XSLTransformer if (is != null) { is.close(); } + } catch (java.lang.Throwable ex) { + if (statsp != null) { + statsp.println(ex.getClass().getName() + ": " + ex.getMessage()); + ex.printStackTrace(statsp); + } + } + try { if (os != null) { os.close(); } + } catch (java.lang.Throwable ex) { + if (statsp != null) { + statsp.println(ex.getClass().getName() + ": " + ex.getMessage()); + ex.printStackTrace(statsp); + } + } + try { if (m_xis != null) { m_xis.closeInput(); } + } catch (java.lang.Throwable ex) { + if (statsp != null) { + statsp.println(ex.getClass().getName() + ": " + ex.getMessage()); + ex.printStackTrace(statsp); + } + } + try { if (m_xos != null) { m_xos.closeOutput(); } @@ -469,7 +494,7 @@ public class XSLTransformer public static XSingleServiceFactory __getServiceFactory( String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) { XSingleServiceFactory xSingleServiceFactory = null; - if (implName.equals(XSLTransformer.class.getName())) { + if (implName.indexOf("XSLTransformer") != -1) { xSingleServiceFactory = FactoryHelper.getServiceFactory(XSLTransformer.class, _serviceName, multiFactory, regKey); } diff --git a/filter/source/xsltfilter/makefile.mk b/filter/source/xsltfilter/makefile.mk index f96534df4..b275a1c5f 100644 --- a/filter/source/xsltfilter/makefile.mk +++ b/filter/source/xsltfilter/makefile.mk @@ -26,7 +26,7 @@ #************************************************************************* PRJ = ..$/.. PRJNAME = filter -#PACKAGE = com$/sun$/star$/documentconversion$/XSLTFilter +PACKAGE = com/sun/star/comp/xsltfilter TARGET =XSLTFilter ENABLE_EXCEPTIONS=TRUE LIBTARGET=NO @@ -62,7 +62,7 @@ JAVAFILES = $(subst,$(CLASSDIR)$/, $(subst,.class,.java $(JAVACLASSFILES))) CUSTOMMANIFESTFILE = Manifest JARCOMPRESS = TRUE -JARCLASSDIRS = XSLTransformer*.class XSLTFilterOLEExtracter*.class +JARCLASSDIRS = com/sun/star/comp/xsltfilter JARTARGET = $(TARGET).jar .IF "$(SYSTEM_SAXON)" == "YES" @@ -72,7 +72,11 @@ JARFILES += saxon9.jar .ENDIF # --- Files -------------------------------------------------------- -JAVACLASSFILES=$(CLASSDIR)$/XSLTransformer.class $(CLASSDIR)$/XSLTFilterOLEExtracter.class +JAVACLASSFILES= \ + $(CLASSDIR)/com/sun/star/comp/xsltfilter/XSLTransformer.class \ + $(CLASSDIR)/com/sun/star/comp/xsltfilter/XSLTFilterOLEExtracter.class \ + $(CLASSDIR)/com/sun/star/comp/xsltfilter/Base64.class \ + .ENDIF # --- Targets ------------------------------------------------------ diff --git a/oox/inc/oox/core/contexthandler.hxx b/oox/inc/oox/core/contexthandler.hxx index b09f405d4..ce15394ce 100644 --- a/oox/inc/oox/core/contexthandler.hxx +++ b/oox/inc/oox/core/contexthandler.hxx @@ -57,9 +57,9 @@ typedef ::rtl::Reference< ContextHandler > ContextHandlerRef; struct FragmentBaseData; typedef ::boost::shared_ptr< FragmentBaseData > FragmentBaseDataRef; -typedef ::cppu::WeakImplHelper1< ::com::sun::star::xml::sax::XFastContextHandler > ContextHandlerImplBase; +typedef ::cppu::WeakImplHelper1< ::com::sun::star::xml::sax::XFastContextHandler > ContextHandler_BASE; -class ContextHandler : public ContextHandlerImplBase +class ContextHandler : public ContextHandler_BASE { public: explicit ContextHandler( ContextHandler& rParent ); diff --git a/oox/inc/oox/core/fasttokenhandler.hxx b/oox/inc/oox/core/fasttokenhandler.hxx index 54d729c21..ad1746d37 100644 --- a/oox/inc/oox/core/fasttokenhandler.hxx +++ b/oox/inc/oox/core/fasttokenhandler.hxx @@ -39,12 +39,12 @@ namespace core { // ============================================================================ -typedef ::cppu::WeakImplHelper2< ::com::sun::star::lang::XServiceInfo, ::com::sun::star::xml::sax::XFastTokenHandler > FastTokenHandlerBase; +typedef ::cppu::WeakImplHelper2< ::com::sun::star::lang::XServiceInfo, ::com::sun::star::xml::sax::XFastTokenHandler > FastTokenHandler_BASE; /** Wrapper implementing the com.sun.star.xml.sax.XFastTokenHandler API interface that provides access to the tokens generated from the internal token name list. */ -class FastTokenHandler : public FastTokenHandlerBase +class FastTokenHandler : public FastTokenHandler_BASE { public: explicit FastTokenHandler(); diff --git a/oox/inc/oox/core/filterbase.hxx b/oox/inc/oox/core/filterbase.hxx index aa52fa33a..409152f9c 100644 --- a/oox/inc/oox/core/filterbase.hxx +++ b/oox/inc/oox/core/filterbase.hxx @@ -87,9 +87,9 @@ typedef ::cppu::WeakImplHelper5< ::com::sun::star::document::XImporter, ::com::sun::star::document::XExporter, ::com::sun::star::document::XFilter > - FilterBaseBase; + FilterBase_BASE; -class OOX_DLLPUBLIC FilterBase : public FilterBaseBase, public ::cppu::BaseMutex +class OOX_DLLPUBLIC FilterBase : public FilterBase_BASE, public ::cppu::BaseMutex { public: explicit FilterBase( diff --git a/oox/inc/oox/core/fragmenthandler.hxx b/oox/inc/oox/core/fragmenthandler.hxx index dbdcd417b..3ee6c244c 100644 --- a/oox/inc/oox/core/fragmenthandler.hxx +++ b/oox/inc/oox/core/fragmenthandler.hxx @@ -81,9 +81,9 @@ struct RecordInfo // ============================================================================ -typedef ::cppu::ImplInheritanceHelper1< ContextHandler, ::com::sun::star::xml::sax::XFastDocumentHandler > FragmentHandlerImplBase; +typedef ::cppu::ImplInheritanceHelper1< ContextHandler, ::com::sun::star::xml::sax::XFastDocumentHandler > FragmentHandler_BASE; -class FragmentHandler : public FragmentHandlerImplBase +class FragmentHandler : public FragmentHandler_BASE { public: explicit FragmentHandler( XmlFilterBase& rFilter, const ::rtl::OUString& rFragmentPath ); diff --git a/oox/inc/oox/core/relations.hxx b/oox/inc/oox/core/relations.hxx index 50627149c..138faa3fe 100755 --- a/oox/inc/oox/core/relations.hxx +++ b/oox/inc/oox/core/relations.hxx @@ -25,8 +25,8 @@ * ************************************************************************/ -#ifndef OOX_CORE_RELATIONS -#define OOX_CORE_RELATIONS +#ifndef OOX_CORE_RELATIONS_HXX +#define OOX_CORE_RELATIONS_HXX #include <map> #include <boost/shared_ptr.hpp> @@ -105,4 +105,4 @@ private: } // namespace core } // namespace oox -#endif // OOX_CORE_RELATIONS +#endif diff --git a/oox/inc/oox/core/relationshandler.hxx b/oox/inc/oox/core/relationshandler.hxx index 3bca23b76..4d813e498 100644 --- a/oox/inc/oox/core/relationshandler.hxx +++ b/oox/inc/oox/core/relationshandler.hxx @@ -25,8 +25,8 @@ * ************************************************************************/ -#ifndef OOX_CORE_RELATIONSHANDLER -#define OOX_CORE_RELATIONSHANDLER +#ifndef OOX_CORE_RELATIONSHANDLER_HXX +#define OOX_CORE_RELATIONSHANDLER_HXX #include "oox/core/fragmenthandler.hxx" @@ -57,4 +57,4 @@ private: } // namespace core } // namespace oox -#endif // OOX_CORE_RELATIONSHANDLER +#endif diff --git a/oox/inc/oox/drawingml/chart/chartdrawingfragment.hxx b/oox/inc/oox/drawingml/chart/chartdrawingfragment.hxx index 3ff545cda..9b495c723 100644 --- a/oox/inc/oox/drawingml/chart/chartdrawingfragment.hxx +++ b/oox/inc/oox/drawingml/chart/chartdrawingfragment.hxx @@ -72,8 +72,7 @@ public: void setPos( sal_Int32 nElement, sal_Int32 nParentContext, const ::rtl::OUString& rValue ); /** Calculates the resulting shape anchor in EMUs. */ - ::com::sun::star::awt::Rectangle - calcEmuLocation( const EmuRectangle& rEmuChartRect ) const; + EmuRectangle calcAnchorRectEmu( const EmuRectangle& rChartRect ) const; private: AnchorPosModel maFrom; /// Top-left position relative to chart object. @@ -109,7 +108,7 @@ private: mxDrawPage; /// Drawing page of this sheet. ::oox::drawingml::ShapePtr mxShape; /// Current top-level shape. ShapeAnchorRef mxAnchor; /// Current anchor of top-level shape. - EmuRectangle maEmuChartRect; /// Position and size of the chart object for embedded shapes (in EMUs). + EmuRectangle maChartRectEmu; /// Position and size of the chart object for embedded shapes (in EMUs). bool mbOleSupport; /// True = allow to insert OLE objects into the drawing page. }; diff --git a/oox/inc/oox/drawingml/chart/converterbase.hxx b/oox/inc/oox/drawingml/chart/converterbase.hxx index feaa6ecbd..af4530e20 100644 --- a/oox/inc/oox/drawingml/chart/converterbase.hxx +++ b/oox/inc/oox/drawingml/chart/converterbase.hxx @@ -34,7 +34,6 @@ namespace com { namespace sun { namespace star { namespace awt { struct Rectangle; } namespace awt { struct Size; } - namespace lang { class XMultiServiceFactory; } namespace chart2 { class XChartDocument; } namespace chart2 { class XTitle; } namespace drawing { class XShape; } @@ -138,9 +137,10 @@ public: OOXML layout model. Returns true, if returned rectangle is valid. */ bool calcAbsRectangle( ::com::sun::star::awt::Rectangle& orRect ) const; - /** Tries to set the position from the contained OOXML layout model. - Returns true, if a manual position could be calculated. */ + /** Tries to set the position and size from the contained OOXML layout model. + Returns true, if a manual position and size could be calculated. */ bool convertFromModel( PropertySet& rPropSet ); + /** Tries to set the position from the contained OOXML layout model. Returns true, if a manual position could be calculated. */ bool convertFromModel( diff --git a/oox/inc/oox/drawingml/color.hxx b/oox/inc/oox/drawingml/color.hxx index 099841899..ba69156b4 100644 --- a/oox/inc/oox/drawingml/color.hxx +++ b/oox/inc/oox/drawingml/color.hxx @@ -92,10 +92,10 @@ public: @param nPhClr Actual color for the phClr placeholder color used in theme style lists. */ sal_Int32 getColor( const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr = API_RGB_TRANSPARENT ) const; - /** Returns true, if the color has a transparence set. */ - bool hasTransparence() const; - /** Returns the transparence of the color (0 = opaque, 100 = full transparent). */ - sal_Int16 getTransparence() const; + /** Returns true, if the color is transparent. */ + bool hasTransparency() const; + /** Returns the transparency of the color (0 = opaque, 100 = full transparent). */ + sal_Int16 getTransparency() const; private: /** Internal helper for getColor(). */ diff --git a/oox/inc/oox/drawingml/drawingmltypes.hxx b/oox/inc/oox/drawingml/drawingmltypes.hxx index c513446e9..89e47e8f7 100644 --- a/oox/inc/oox/drawingml/drawingmltypes.hxx +++ b/oox/inc/oox/drawingml/drawingmltypes.hxx @@ -35,6 +35,7 @@ #include <com/sun/star/awt/Point.hpp> #include <com/sun/star/awt/Size.hpp> #include <com/sun/star/xml/sax/XFastAttributeList.hpp> +#include "oox/helper/helper.hxx" namespace oox { namespace drawingml { @@ -150,6 +151,23 @@ IndexRange GetIndexRange( const ::com::sun::star::uno::Reference< ::com::sun::st // ============================================================================ +const sal_Int32 EMU_PER_HMM = 360; /// 360 EMUs per 1/100 mm. + +/** Converts the passed 32-bit integer value from 1/100 mm to EMUs. */ +inline sal_Int64 convertHmmToEmu( sal_Int32 nValue ) +{ + return static_cast< sal_Int64 >( nValue ) * EMU_PER_HMM; +} + +/** Converts the passed 64-bit integer value from EMUs to 1/100 mm. */ +inline sal_Int32 convertEmuToHmm( sal_Int64 nValue ) +{ + return getLimitedValue< sal_Int32, sal_Int64 >( (nValue + EMU_PER_HMM / 2) / EMU_PER_HMM, 0, SAL_MAX_INT32 ); +} + +// ============================================================================ + +/** A structure for a point with 64-bit interger components. */ struct EmuPoint { sal_Int64 X; @@ -161,6 +179,7 @@ struct EmuPoint // ============================================================================ +/** A structure for a size with 64-bit interger components. */ struct EmuSize { sal_Int64 Width; @@ -172,11 +191,15 @@ struct EmuSize // ============================================================================ +/** A structure for a rectangle with 64-bit interger components. */ struct EmuRectangle : public EmuPoint, public EmuSize { inline explicit EmuRectangle() {} inline explicit EmuRectangle( const EmuPoint& rPos, const EmuSize& rSize ) : EmuPoint( rPos ), EmuSize( rSize ) {} inline explicit EmuRectangle( sal_Int64 nX, sal_Int64 nY, sal_Int64 nWidth, sal_Int64 nHeight ) : EmuPoint( nX, nY ), EmuSize( nWidth, nHeight ) {} + + inline void setPos( const EmuPoint& rPos ) { static_cast< EmuPoint& >( *this ) = rPos; } + inline void setSize( const EmuSize& rSize ) { static_cast< EmuSize& >( *this ) = rSize; } }; // ============================================================================ diff --git a/oox/inc/oox/drawingml/fillproperties.hxx b/oox/inc/oox/drawingml/fillproperties.hxx index 7ae00a976..9525abde4 100644 --- a/oox/inc/oox/drawingml/fillproperties.hxx +++ b/oox/inc/oox/drawingml/fillproperties.hxx @@ -36,7 +36,6 @@ namespace oox { class GraphicHelper; - class ModelObjectHelper; class PropertyMap; class PropertySet; } @@ -44,38 +43,7 @@ namespace oox { namespace oox { namespace drawingml { -// ============================================================================ - -enum FillPropertyId -{ - FillStyleId, - FillColorId, - FillTransparenceId, - FillGradientId, - FillBitmapUrlId, - FillBitmapModeId, - FillBitmapSizeXId, - FillBitmapSizeYId, - FillBitmapOffsetXId, - FillBitmapOffsetYId, - FillBitmapRectanglePointId, - FillId_END -}; - -struct FillPropertyIds -{ - const sal_Int32* mpnPropertyIds; - bool mbNamedFillGradient; - bool mbNamedFillBitmap; - - explicit FillPropertyIds( - const sal_Int32* pnPropertyIds, - bool bNamedFillGradient, - bool bNamedFillBitmap ); - - inline bool has( FillPropertyId ePropId ) const { return mpnPropertyIds[ ePropId ] >= 0; } - inline sal_Int32 operator[]( FillPropertyId ePropId ) const { return mpnPropertyIds[ ePropId ]; } -}; +class ShapePropertyMap; // ============================================================================ @@ -147,8 +115,6 @@ struct FillProperties PatternFillProperties maPatternProps; /// Properties for pattern fills. BlipFillProperties maBlipProps; /// Properties for bitmap fills. - static FillPropertyIds DEFAULT_IDS; /// Default fill property identifiers for shape fill. - /** Overwrites all members that are explicitly set in rSourceProps. */ void assignUsed( const FillProperties& rSourceProps ); @@ -158,19 +124,8 @@ struct FillProperties /** Writes the properties to the passed property map. */ void pushToPropMap( - PropertyMap& rPropMap, - ModelObjectHelper& rModelObjHelper, + ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper, - const FillPropertyIds& rPropIds = DEFAULT_IDS, - sal_Int32 nShapeRotation = 0, - sal_Int32 nPhClr = API_RGB_TRANSPARENT ) const; - - /** Writes the properties to the passed property set. */ - void pushToPropSet( - PropertySet& rPropSet, - ModelObjectHelper& rModelObjHelper, - const GraphicHelper& rGraphicHelper, - const FillPropertyIds& rPropIds = DEFAULT_IDS, sal_Int32 nShapeRotation = 0, sal_Int32 nPhClr = API_RGB_TRANSPARENT ) const; }; @@ -189,12 +144,6 @@ struct GraphicProperties PropertyMap& rPropMap, const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr = API_RGB_TRANSPARENT ) const; - - /** Writes the properties to the passed property set. */ - void pushToPropSet( - PropertySet& rPropSet, - const GraphicHelper& rGraphicHelper, - sal_Int32 nPhClr = API_RGB_TRANSPARENT ) const; }; // ============================================================================ diff --git a/oox/inc/oox/drawingml/lineproperties.hxx b/oox/inc/oox/drawingml/lineproperties.hxx index e7e3170f1..c1e6d5364 100644 --- a/oox/inc/oox/drawingml/lineproperties.hxx +++ b/oox/inc/oox/drawingml/lineproperties.hxx @@ -35,40 +35,6 @@ namespace drawingml { // ============================================================================ -enum LinePropertyId -{ - LineStyleId, - LineWidthId, - LineColorId, - LineTransparenceId, - LineDashId, - LineJointId, - LineStartId, - LineStartWidthId, - LineStartCenterId, - LineEndId, - LineEndWidthId, - LineEndCenterId, - LineId_END -}; - -struct LinePropertyIds -{ - const sal_Int32* mpnPropertyIds; - bool mbNamedLineDash; - bool mbNamedLineMarker; - - explicit LinePropertyIds( - const sal_Int32* pnPropertyIds, - bool bNamedLineDash, - bool bNamedLineMarker ); - - inline bool has( LinePropertyId ePropId ) const { return mpnPropertyIds[ ePropId ] >= 0; } - inline sal_Int32 operator[]( LinePropertyId ePropId ) const { return mpnPropertyIds[ ePropId ]; } -}; - -// ============================================================================ - struct LineArrowProperties { OptValue< sal_Int32 > moArrowType; @@ -96,25 +62,13 @@ struct LineProperties OptValue< sal_Int32 > moLineCap; /// Line cap (OOXML token). OptValue< sal_Int32 > moLineJoint; /// Line joint type (OOXML token). - static LinePropertyIds DEFAULT_IDS; /// Default line property identifiers. - /** Overwrites all members that are explicitly set in rSourceProps. */ void assignUsed( const LineProperties& rSourceProps ); /** Writes the properties to the passed property map. */ void pushToPropMap( - PropertyMap& rPropMap, - ModelObjectHelper& rModelObjHelper, - const GraphicHelper& rGraphicHelper, - const LinePropertyIds& rPropIds = DEFAULT_IDS, - sal_Int32 nPhClr = API_RGB_TRANSPARENT ) const; - - /** Writes the properties to the passed property map. */ - void pushToPropSet( - PropertySet& rPropSet, - ModelObjectHelper& rModelObjHelper, + ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper, - const LinePropertyIds& rPropIds = DEFAULT_IDS, sal_Int32 nPhClr = API_RGB_TRANSPARENT ) const; }; diff --git a/oox/inc/oox/drawingml/shapepropertymap.hxx b/oox/inc/oox/drawingml/shapepropertymap.hxx new file mode 100755 index 000000000..096724a67 --- /dev/null +++ b/oox/inc/oox/drawingml/shapepropertymap.hxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef OOX_DRAWINGML_SHAPEPROPERTYMAP_HXX +#define OOX_DRAWINGML_SHAPEPROPERTYMAP_HXX + +#include "oox/helper/propertymap.hxx" + +namespace oox { class ModelObjectHelper; } + +namespace oox { +namespace drawingml { + +// ============================================================================ + +/** Enumeration for various properties related to drawing shape formatting. + + This is an abstraction for shape formatting properties that have different + names in various implementations, e.g. drawing shapes vs. chart objects. + */ +enum ShapePropertyId +{ + SHAPEPROP_LineStyle, + SHAPEPROP_LineWidth, + SHAPEPROP_LineColor, + SHAPEPROP_LineTransparency, + SHAPEPROP_LineDash, /// Explicit line dash or name of a line dash stored in a global container. + SHAPEPROP_LineJoint, + SHAPEPROP_LineStart, /// Explicit line start marker or name of a line marker stored in a global container. + SHAPEPROP_LineStartWidth, + SHAPEPROP_LineStartCenter, + SHAPEPROP_LineEnd, /// Explicit line end marker or name of a line marker stored in a global container. + SHAPEPROP_LineEndWidth, + SHAPEPROP_LineEndCenter, + SHAPEPROP_FillStyle, + SHAPEPROP_FillColor, + SHAPEPROP_FillTransparency, + SHAPEPROP_FillGradient, /// Explicit fill gradient or name of a fill gradient stored in a global container. + SHAPEPROP_FillBitmapUrl, /// Explicit fill bitmap URL or name of a fill bitmap URL stored in a global container. + SHAPEPROP_FillBitmapMode, + SHAPEPROP_FillBitmapSizeX, + SHAPEPROP_FillBitmapSizeY, + SHAPEPROP_FillBitmapOffsetX, + SHAPEPROP_FillBitmapOffsetY, + SHAPEPROP_FillBitmapRectanglePoint, + SHAPEPROP_END +}; + +// ============================================================================ + +struct ShapePropertyInfo +{ + const sal_Int32* mpnPropertyIds; /// Pointer to array of property identifiers for all SHAPEPROP properties. + bool mbNamedLineMarker; /// True = use named line marker instead of explicit line marker. + bool mbNamedLineDash; /// True = use named line dash instead of explicit line dash. + bool mbNamedFillGradient; /// True = use named fill gradient instead of explicit fill gradient. + bool mbNamedFillBitmapUrl; /// True = use named fill bitmap URL instead of explicit fill bitmap URL. + + static ShapePropertyInfo DEFAULT; /// Default property info (used as default parameter of other methods). + + explicit ShapePropertyInfo( + const sal_Int32* pnPropertyIds, + bool bNamedLineMarker, + bool bNamedLineDash, + bool bNamedFillGradient, + bool bNamedFillBitmapUrl ); + + inline bool has( ShapePropertyId ePropId ) const { return mpnPropertyIds[ ePropId ] >= 0; } + inline sal_Int32 operator[]( ShapePropertyId ePropId ) const { return mpnPropertyIds[ ePropId ]; } +}; + +// ============================================================================ + +class ShapePropertyMap : public PropertyMap +{ +public: + explicit ShapePropertyMap( + ModelObjectHelper& rModelObjHelper, + const ShapePropertyInfo& rShapePropInfo = ShapePropertyInfo::DEFAULT ); + + /** Returns true, if the specified property is supported. */ + bool supportsProperty( ShapePropertyId ePropId ) const; + + /** Returns true, if named line markers are supported, and the specified + line marker has already been inserted into the marker table. */ + bool hasNamedLineMarkerInTable( const ::rtl::OUString& rMarkerName ) const; + + /** Sets the specified shape property to the passed value. */ + bool setAnyProperty( ShapePropertyId ePropId, const ::com::sun::star::uno::Any& rValue ); + + /** Sets the specified shape property to the passed value. */ + template< typename Type > + inline bool setProperty( ShapePropertyId ePropId, const Type& rValue ) + { return setAnyProperty( ePropId, ::com::sun::star::uno::Any( rValue ) ); } + + using PropertyMap::setAnyProperty; + using PropertyMap::setProperty; + using PropertyMap::operator[]; + +private: + /** Sets an explicit line marker, or creates a named line marker. */ + bool setLineMarker( sal_Int32 nPropId, const ::com::sun::star::uno::Any& rValue ); + /** Sets an explicit line dash, or creates a named line dash. */ + bool setLineDash( sal_Int32 nPropId, const ::com::sun::star::uno::Any& rValue ); + /** Sets an explicit fill gradient, or creates a named fill gradient. */ + bool setFillGradient( sal_Int32 nPropId, const ::com::sun::star::uno::Any& rValue ); + /** Sets an explicit fill bitmap URL, or creates a named fill bitmap URL. */ + bool setFillBitmapUrl( sal_Int32 nPropId, const ::com::sun::star::uno::Any& rValue ); + + // not implemented, to prevent implicit conversion from enum to int + ::com::sun::star::uno::Any& operator[]( ShapePropertyId ePropId ); + const ::com::sun::star::uno::Any& operator[]( ShapePropertyId ePropId ) const; + +private: + ModelObjectHelper& mrModelObjHelper; + ShapePropertyInfo maShapePropInfo; +}; + +// ============================================================================ + +} // namespace drawingml +} // namespace oox + +#endif diff --git a/oox/inc/oox/dump/biffdumper.hxx b/oox/inc/oox/dump/biffdumper.hxx index 56a7a0b63..5f3ee55c0 100644 --- a/oox/inc/oox/dump/biffdumper.hxx +++ b/oox/inc/oox/dump/biffdumper.hxx @@ -530,7 +530,7 @@ public: protected: virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -554,7 +554,7 @@ public: explicit Dumper( const ::oox::core::FilterBase& rFilter ); explicit Dumper( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, const ::rtl::OUString& rSysFileName ); @@ -571,4 +571,3 @@ protected: #endif #endif - diff --git a/oox/inc/oox/dump/dffdumper.hxx b/oox/inc/oox/dump/dffdumper.hxx index 8d8a000b8..6000ef23e 100644 --- a/oox/inc/oox/dump/dffdumper.hxx +++ b/oox/inc/oox/dump/dffdumper.hxx @@ -79,4 +79,3 @@ private: #endif #endif - diff --git a/oox/inc/oox/dump/dumperbase.hxx b/oox/inc/oox/dump/dumperbase.hxx index 5cdb8c147..f5f4f6227 100644 --- a/oox/inc/oox/dump/dumperbase.hxx +++ b/oox/inc/oox/dump/dumperbase.hxx @@ -49,10 +49,9 @@ namespace com { namespace sun { namespace star { namespace io { class XInputStream; } - namespace io { class XTextInputStream; } namespace io { class XOutputStream; } namespace io { class XTextOutputStream; } - namespace lang { class XMultiServiceFactory; } + namespace uno { class XComponentContext; } } } } namespace comphelper { @@ -124,43 +123,46 @@ public: // input streams ---------------------------------------------------------- static ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > - getXInputStream( BinaryInputStream& rStrm ); - - static ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > openInputStream( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::rtl::OUString& rFileName ); - static ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextInputStream > - openTextInputStream( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, - const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, - const ::rtl::OUString& rEncoding ); - - static ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextInputStream > - openTextInputStream( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, - const ::rtl::OUString& rFileName, - const ::rtl::OUString& rEncoding ); - // output streams --------------------------------------------------------- static ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > openOutputStream( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::rtl::OUString& rFileName ); static ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextOutputStream > openTextOutputStream( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rxOutStrm, - const ::rtl::OUString& rEncoding ); + rtl_TextEncoding eTextEnc ); static ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextOutputStream > openTextOutputStream( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::rtl::OUString& rFileName, - const ::rtl::OUString& rEncoding ); + rtl_TextEncoding eTextEnc ); +}; + +// ============================================================================ + +class BinaryInputStreamRef : public ::oox::BinaryInputStreamRef +{ +public: + inline BinaryInputStreamRef() {} + + inline /*implicit*/ BinaryInputStreamRef( BinaryInputStream* pInStrm ) : + ::oox::BinaryInputStreamRef( pInStrm ) {} + + inline /*implicit*/ BinaryInputStreamRef( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm ) : + ::oox::BinaryInputStreamRef( new BinaryXInputStream( rxInStrm, true ) ) {} + + template< typename StreamType > + inline /*implicit*/ BinaryInputStreamRef( const ::boost::shared_ptr< StreamType >& rxInStrm ) : + ::oox::BinaryInputStreamRef( rxInStrm ) {} }; // ============================================================================ @@ -550,7 +552,9 @@ typedef ::boost::shared_ptr< Base > BaseRef; | | | +----> BinaryStreamObject | | - | +----> TextStreamObject + | +----> TextStreamObjectBase + | | | + | | +----> TextStreamObject | | | | | +----> XmlStreamObject | | @@ -890,14 +894,14 @@ class SharedConfigData : public Base, public ConfigItemBase public: explicit SharedConfigData( const ::rtl::OUString& rFileName, - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const StorageRef& rxRootStrg, const ::rtl::OUString& rSysFileName, ::comphelper::MediaDescriptor& rMediaDesc ); virtual ~SharedConfigData(); - inline const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& getFactory() const { return mxFactory; } + inline const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& getContext() const { return mxContext; } inline const StorageRef& getRootStorage() const { return mxRootStrg; } inline const ::rtl::OUString& getSysFileName() const { return maSysFileName; } @@ -932,7 +936,7 @@ private: typedef ::std::map< ::rtl::OUString, ::rtl::OUString > ConfigDataMap; typedef ::std::map< ::rtl::OUString, NameListRef > NameListMap; - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxFactory; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxContext; StorageRef mxRootStrg; ::rtl::OUString maSysFileName; ::comphelper::MediaDescriptor& mrMediaDesc; @@ -977,14 +981,14 @@ public: const ::oox::core::FilterBase& rFilter ); explicit Config( const sal_Char* pcEnvVar, - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const StorageRef& rxRootStrg, const ::rtl::OUString& rSysFileName, ::comphelper::MediaDescriptor& rMediaDesc ); virtual ~Config(); - inline const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& getFactory() const { return mxCfgData->getFactory(); } + inline const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& getContext() const { return mxCfgData->getContext(); } inline const StorageRef& getRootStorage() const { return mxCfgData->getRootStorage(); } inline const ::rtl::OUString& getSysFileName() const { return mxCfgData->getSysFileName(); } @@ -1022,7 +1026,7 @@ protected: const ::oox::core::FilterBase& rFilter ); void construct( const sal_Char* pcEnvVar, - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const StorageRef& rxRootStrg, const ::rtl::OUString& rSysFileName, ::comphelper::MediaDescriptor& rMediaDesc ); @@ -1076,10 +1080,7 @@ class Output : public Base { public: explicit Output( - const ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextOutputStream >& rxStrm ); - - explicit Output( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::rtl::OUString& rFileName ); // ------------------------------------------------------------------------ @@ -1152,8 +1153,6 @@ public: // ------------------------------------------------------------------------ protected: - void construct( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextOutputStream >& rxStrm ); - virtual bool implIsValid() const; private: @@ -1279,8 +1278,8 @@ class ObjectBase : public Base public: virtual ~ObjectBase(); - inline const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& - getFactory() const { return mxConfig->getFactory(); } + inline const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& + getContext() const { return mxConfig->getContext(); } void dump(); @@ -1323,7 +1322,7 @@ protected: virtual void implDump(); virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -1394,7 +1393,6 @@ protected: using ObjectBase::construct; void construct( const ObjectBase& rParent, const ::rtl::OUString& rSysFileName ); - void construct( const ObjectBase& rParent, const OutputRef& rxOut ); void construct( const OutputObjectBase& rParent ); virtual bool implIsValid() const; @@ -1453,6 +1451,7 @@ protected: protected: OutputRef mxOut; + ::rtl::OUString maSysFileName; }; typedef ::boost::shared_ptr< OutputObjectBase > OutputObjectRef; @@ -1578,7 +1577,6 @@ protected: using OutputObjectBase::construct; void construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const ::rtl::OUString& rSysFileName ); - void construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OutputRef& rxOut ); void construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm ); void construct( const InputObjectBase& rParent ); @@ -1805,46 +1803,76 @@ protected: }; // ============================================================================ +// ============================================================================ -class TextStreamObject : public InputObjectBase +class TextStreamObjectBase : public InputObjectBase { -public: - explicit TextStreamObject( +protected: + inline TextStreamObjectBase() {} + + using InputObjectBase::construct; + void construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const ::rtl::OUString& rSysFileName ); - - explicit TextStreamObject( + void construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc ); + void construct( + const InputObjectBase& rParent, + rtl_TextEncoding eTextEnc ); -protected: virtual bool implIsValid() const; virtual void implDump(); - virtual void implDumpLine( const ::rtl::OUString& rLine, sal_uInt32 nLine ); + + virtual void implDumpText( TextInputStream& rTextStrm ) = 0; private: + void constructTextStrmObj( rtl_TextEncoding eTextEnc ); + +protected: ::boost::shared_ptr< TextInputStream > mxTextStrm; }; // ============================================================================ -class XmlStreamObject : public TextStreamObject +class TextLineStreamObject : public TextStreamObjectBase { public: - explicit XmlStreamObject( + explicit TextLineStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, + rtl_TextEncoding eTextEnc, const ::rtl::OUString& rSysFileName ); + explicit TextLineStreamObject( + const OutputObjectBase& rParent, + const BinaryInputStreamRef& rxStrm, + rtl_TextEncoding eTextEnc ); + protected: - virtual void implDump(); + virtual void implDumpText( TextInputStream& rTextStrm ); virtual void implDumpLine( const ::rtl::OUString& rLine, sal_uInt32 nLine ); +}; -private: - ::rtl::OUString maIncompleteLine; +// ============================================================================ + +class XmlStreamObject : public TextStreamObjectBase +{ +public: + explicit XmlStreamObject( + const ObjectBase& rParent, + const BinaryInputStreamRef& rxStrm, + const ::rtl::OUString& rSysFileName ); + + explicit XmlStreamObject( + const OutputObjectBase& rParent, + const BinaryInputStreamRef& rxStrm ); + +protected: + virtual void implDumpText( TextInputStream& rTextStrm ); }; // ============================================================================ @@ -1976,4 +2004,3 @@ do { \ #endif // OOX_INCLUDE_DUMPER #endif - diff --git a/oox/inc/oox/dump/oledumper.hxx b/oox/inc/oox/dump/oledumper.hxx index 137f48698..a186d434d 100644 --- a/oox/inc/oox/dump/oledumper.hxx +++ b/oox/inc/oox/dump/oledumper.hxx @@ -180,7 +180,7 @@ protected: void construct( const ObjectBase& rParent ); virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -762,7 +762,7 @@ public: protected: virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -857,7 +857,7 @@ public: protected: virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -879,7 +879,7 @@ public: protected: virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -897,7 +897,7 @@ public: protected: virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -936,4 +936,3 @@ protected: #endif #endif - diff --git a/oox/inc/oox/dump/pptxdumper.hxx b/oox/inc/oox/dump/pptxdumper.hxx index 135d59930..309ea8eeb 100644 --- a/oox/inc/oox/dump/pptxdumper.hxx +++ b/oox/inc/oox/dump/pptxdumper.hxx @@ -45,7 +45,7 @@ public: protected: virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -59,7 +59,7 @@ public: explicit Dumper( const ::oox::core::FilterBase& rFilter ); explicit Dumper( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, const ::rtl::OUString& rSysFileName ); @@ -75,4 +75,3 @@ protected: #endif #endif - diff --git a/oox/inc/oox/dump/xlsbdumper.hxx b/oox/inc/oox/dump/xlsbdumper.hxx index de822419f..bfd0fbbcf 100644 --- a/oox/inc/oox/dump/xlsbdumper.hxx +++ b/oox/inc/oox/dump/xlsbdumper.hxx @@ -225,7 +225,7 @@ public: protected: virtual void implDumpStream( - const BinaryInputStreamRef& rxStrm, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxStrm, const ::rtl::OUString& rStrgPath, const ::rtl::OUString& rStrmName, const ::rtl::OUString& rSysFileName ); @@ -239,7 +239,7 @@ public: explicit Dumper( const ::oox::core::FilterBase& rFilter ); explicit Dumper( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, const ::rtl::OUString& rSysFileName ); diff --git a/oox/inc/oox/helper/binaryinputstream.hxx b/oox/inc/oox/helper/binaryinputstream.hxx index 27fbae439..062ff6b1e 100644 --- a/oox/inc/oox/helper/binaryinputstream.hxx +++ b/oox/inc/oox/helper/binaryinputstream.hxx @@ -28,10 +28,14 @@ #ifndef OOX_HELPER_BINARYINPUTSTREAM_HXX #define OOX_HELPER_BINARYINPUTSTREAM_HXX -#include <boost/shared_ptr.hpp> +#include <vector> #include <com/sun/star/io/XInputStream.hpp> #include "oox/helper/binarystreambase.hxx" +namespace com { namespace sun { namespace star { + namespace io { class XInputStream; } +} } } + namespace oox { class BinaryOutputStream; @@ -46,24 +50,51 @@ class BinaryInputStream : public virtual BinaryStreamBase { public: /** Derived classes implement reading nBytes bytes to the passed sequence. - @return Number of bytes really read. */ - virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes ) = 0; - /** Derived classes implement reading nBytes bytes to the (existing) buffer opMem. - @return Number of bytes really read. */ - virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes ) = 0; + The sequence will be reallocated internally. + + @param nAtomSize + The size of the elements in the memory block, if available. Derived + classes may be interested in this information. + + @return + Number of bytes really read. + */ + virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ) = 0; + + /** Derived classes implement reading nBytes bytes to the (preallocated!) + memory buffer opMem. + + @param nAtomSize + The size of the elements in the memory block, if available. Derived + classes may be interested in this information. + + @return + Number of bytes really read. + */ + virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ) = 0; + /** Derived classes implement seeking the stream forward by the passed - number of bytes. This should work for non-seekable streams too. */ - virtual void skip( sal_Int32 nBytes ) = 0; + number of bytes. This should work for non-seekable streams too. + + @param nAtomSize + The size of the elements in the memory block, if available. Derived + classes may be interested in this information. + */ + virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ) = 0; /** Reads a value from the stream and converts it to platform byte order. - Supported types: SAL integers (8 to 64 bit), float, double. */ + All data types supported by the ByteOrderConverter class can be used. + */ template< typename Type > void readValue( Type& ornValue ); + /** Reads a value from the stream and converts it to platform byte order. - Supported types: SAL integers (8 to 64 bit), float, double. */ + All data types supported by the ByteOrderConverter class can be used. + */ template< typename Type > inline Type readValue() { Type nValue; readValue( nValue ); return nValue; } - /** Stream operator for integral and floating-point types. */ + + /** Stream operator for all data types supported by the readValue() function. */ template< typename Type > inline BinaryInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; } @@ -78,46 +109,135 @@ public: inline float readFloat() { return readValue< float >(); } inline double readDouble() { return readValue< double >(); } - /** Reads a NUL-terminated byte character array and returns the string. */ + /** Reads a (preallocated!) C array of values from the stream. + + Converts all values in the array to platform byte order. All data types + supported by the ByteOrderConverter class can be used. + + @param nElemCount + Number of array elements to read (NOT byte count). + + @return + Number of array elements really read (NOT byte count). + */ + template< typename Type > + sal_Int32 readArray( Type* opnArray, sal_Int32 nElemCount ); + + /** Reads a sequence of values from the stream. + + The sequence will be reallocated internally. Converts all values in the + array to platform byte order. All data types supported by the + ByteOrderConverter class can be used. + + @param nElemCount + Number of elements to put into the sequence (NOT byte count). + + @return + Number of sequence elements really read (NOT byte count). + */ + template< typename Type > + sal_Int32 readArray( ::com::sun::star::uno::Sequence< Type >& orSequence, sal_Int32 nElemCount ); + + /** Reads a vector of values from the stream. + + The vector will be resized internally. Converts all values in the + vector to platform byte order. All data types supported by the + ByteOrderConverter class can be used. + + @param nElemCount + Number of elements to put into the vector (NOT byte count). + + @return + Number of vector elements really read (NOT byte count). + */ + template< typename Type > + sal_Int32 readArray( ::std::vector< Type >& orVector, sal_Int32 nElemCount ); + + /** Skips an array of values of a certain type in the stream. + + All data types supported by the ByteOrderConverter class can be used. + + @param nElemCount + Number of array elements to skip (NOT byte count). + */ + template< typename Type > + void skipArray( sal_Int32 nElemCount ); + + /** Reads a NUL-terminated byte character array and returns the string. + */ ::rtl::OString readNulCharArray(); /** Reads a NUL-terminated byte character array and returns a Unicode string. - @param eTextEnc The text encoding used to create the Unicode string. */ + + @param eTextEnc + The text encoding used to create the Unicode string. + */ ::rtl::OUString readNulCharArrayUC( rtl_TextEncoding eTextEnc ); - /** Reads a NUL-terminated Unicode character array and returns the string. */ + /** Reads a NUL-terminated Unicode character array and returns the string. + */ ::rtl::OUString readNulUnicodeArray(); - /** Reads nChar byte characters and returns the string. - @param nChars Number of characters (bytes) to read from the stream. + /** Reads a byte character array and returns the string. + + @param nChars + Number of characters (bytes) to read from the stream. + @param bAllowNulChars True = NUL characters are inserted into the imported string. - False = NUL characters are replaced by question marks (default). */ + False = NUL characters are replaced by question marks (default). + */ ::rtl::OString readCharArray( sal_Int32 nChars, bool bAllowNulChars = false ); - /** Reads nChar byte characters and returns a Unicode string. - @param nChars Number of characters (bytes) to read from the stream. - @param eTextEnc The text encoding used to create the Unicode string. + /** Reads a byte character array and returns a Unicode string. + + @param nChars + Number of characters (bytes) to read from the stream. + + @param eTextEnc + The text encoding used to create the Unicode string. + @param bAllowNulChars True = NUL characters are inserted into the imported string. - False = NUL characters are replaced by question marks (default). */ + False = NUL characters are replaced by question marks (default). + */ ::rtl::OUString readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars = false ); - /** Reads nChars Unicode characters and returns the string. - @param nChars Number of 16-bit characters to read from the stream. + /** Reads a Unicode character array and returns the string. + + @param nChars + Number of 16-bit characters to read from the stream. + @param bAllowNulChars True = NUL characters are inserted into the imported string. - False = NUL characters are replaced by question marks (default). */ + False = NUL characters are replaced by question marks (default). + */ ::rtl::OUString readUnicodeArray( sal_Int32 nChars, bool bAllowNulChars = false ); - /** Copies nBytes bytes from the current position to the passed output stream. */ - void copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes = SAL_MAX_INT64 ); + /** Reads a Unicode character array (may be compressed) and returns the + string. -private: - /** Used by the readValue() template functions to read built-in types. - @descr Derived classes may overwrite this default implementation which - simply calls readMemory() with something own. */ - virtual void readAtom( void* opMem, sal_uInt8 nSize ); + @param nChars + Number of 8-bit or 16-bit characters to read from the stream. + + @param bCompressed + True = Character array is compressed (stored as 8-bit characters). + False = Character array is not compressed (stored as 16-bit characters). + + @param bAllowNulChars + True = NUL characters are inserted into the imported string. + False = NUL characters are replaced by question marks (default). + */ + ::rtl::OUString readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed, bool bAllowNulChars = false ); + + /** Copies nBytes bytes from the current position to the passed output stream. + */ + void copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes = SAL_MAX_INT64, sal_Int32 nAtomSize = 1 ); + +protected: + /** This dummy default c'tor will never call the c'tor of the virtual base + class BinaryStreamBase as this class cannot be instanciated directly. */ + inline explicit BinaryInputStream() : BinaryStreamBase( false ) {} }; typedef ::boost::shared_ptr< BinaryInputStream > BinaryInputStreamRef; @@ -127,14 +247,47 @@ typedef ::boost::shared_ptr< BinaryInputStream > BinaryInputStreamRef; template< typename Type > void BinaryInputStream::readValue( Type& ornValue ) { - // can be instanciated for all types supported in class ByteOrderConverter - readAtom( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ) ); + readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) ); ByteOrderConverter::convertLittleEndian( ornValue ); } +template< typename Type > +sal_Int32 BinaryInputStream::readArray( Type* opnArray, sal_Int32 nElemCount ) +{ + sal_Int32 nRet = 0; + if( !mbEof ) + { + sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nElemCount, 0, SAL_MAX_INT32 / sizeof( Type ) ) * sizeof( Type ); + nRet = readMemory( opnArray, nReadSize, sizeof( Type ) ) / sizeof( Type ); + ByteOrderConverter::convertLittleEndianArray( opnArray, static_cast< size_t >( nRet ) ); + } + return nRet; +} + +template< typename Type > +sal_Int32 BinaryInputStream::readArray( ::com::sun::star::uno::Sequence< Type >& orSequence, sal_Int32 nElemCount ) +{ + orSequence.reallocate( nElemCount ); + return orSequence.hasElements() ? readArray( orSequence.getArray(), nElemCount ) : 0; +} + +template< typename Type > +sal_Int32 BinaryInputStream::readArray( ::std::vector< Type >& orVector, sal_Int32 nElemCount ) +{ + orVector.resize( static_cast< size_t >( nElemCount ) ); + return orVector.empty() ? 0 : readArray( &orVector.front(), nElemCount ); +} + +template< typename Type > +void BinaryInputStream::skipArray( sal_Int32 nElemCount ) +{ + sal_Int32 nSkipSize = getLimitedValue< sal_Int32, sal_Int32 >( nElemCount, 0, SAL_MAX_INT32 / sizeof( Type ) ) * sizeof( Type ); + skip( nSkipSize, sizeof( Type ) ); +} + // ============================================================================ -/** Wraps a com.sun.star.io.XInputStream and provides convenient access functions. +/** Wraps a UNO input stream and provides convenient access functions. The binary data in the stream is assumed to be in little-endian format. */ @@ -143,10 +296,13 @@ class BinaryXInputStream : public BinaryXSeekableStream, public BinaryInputStrea public: /** Constructs the wrapper object for the passed input stream. - @param rxInStream The com.sun.star.io.XInputStream interface of the - input stream to be wrapped. - @param bAutoClose True = automatically close the wrapped input stream - on destruction of this wrapper. + @param rxInStream + The com.sun.star.io.XInputStream interface of the UNO input stream + to be wrapped. + + @param bAutoClose + True = automatically close the wrapped input stream on destruction + of this wrapper or when close() is called. */ explicit BinaryXInputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, @@ -154,26 +310,26 @@ public: virtual ~BinaryXInputStream(); + /** Closes the input stream. Does also close the wrapped UNO input stream + if bAutoClose has been set to true in the constructor. */ + virtual void close(); + /** Reads nBytes bytes to the passed sequence. @return Number of bytes really read. */ - virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes ); + virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ); + /** Reads nBytes bytes to the (existing) buffer opMem. @return Number of bytes really read. */ - virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes ); + virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); + /** Seeks the stream forward by the passed number of bytes. This works for non-seekable streams too. */ - virtual void skip( sal_Int32 nBytes ); + virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ); - /** Stream operator for integral and floating-point types. */ + /** Stream operator for all data types supported by the readValue() function. */ template< typename Type > inline BinaryXInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; } - /** Returns the XInputStream interface of the wrapped input stream. */ - inline ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > - getXInputStream() const { return mxInStrm; } - /** Closes the wrapped XInputStream. */ - void close(); - private: StreamDataSequence maBuffer; /// Data buffer used in readMemory() function. ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > @@ -181,8 +337,6 @@ private: bool mbAutoClose; /// True = automatically close stream on destruction. }; -typedef ::boost::shared_ptr< BinaryXInputStream > BinaryXInputStreamRef; - // ============================================================================ /** Wraps a StreamDataSequence and provides convenient access functions. @@ -203,86 +357,97 @@ public: /** Reads nBytes bytes to the passed sequence. @return Number of bytes really read. */ - virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes ); + virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ); + /** Reads nBytes bytes to the (existing) buffer opMem. @return Number of bytes really read. */ - virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes ); + virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); + /** Seeks the stream forward by the passed number of bytes. This works for non-seekable streams too. */ - virtual void skip( sal_Int32 nBytes ); + virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ); - /** Stream operator for integral and floating-point types. */ + /** Stream operator for all data types supported by the readValue() function. */ template< typename Type > inline SequenceInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; } -}; -typedef ::boost::shared_ptr< SequenceInputStream > SequenceInputStreamRef; +private: + /** Returns the number of bytes available in the sequence for the passed byte count. */ + inline sal_Int32 getMaxBytes( sal_Int32 nBytes ) const + { return getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, mpData->getLength() - mnPos ); } +}; // ============================================================================ /** Wraps a BinaryInputStream and provides access to a specific part of the stream data. - @descr - Provides access to the stream data block starting at the current - position of the stream, and with a specific length. If the wrapped - stream is seekable, this wrapper will treat the position the wrapped - has at construction time as position "0" (therefore the class name). + Provides access to the stream data block starting at the current position + of the stream, and with a specific length. If the wrapped stream is + seekable, this wrapper will treat the position of the wrapped stream at + construction time as position "0" (therefore the class name). + + The passed input stream MUST live at least as long as this stream wrapper. + The stream MUST NOT be changed from outside as long as this stream wrapper + is used to read from it. */ class RelativeInputStream : public BinaryInputStream { public: /** Constructs the wrapper object for the passed stream. - @attention - The passed input stream MUST live at least as long as this stream - wrapper. The stream MUST NOT be changed from outside as long as - this stream wrapper is used to read from it. - - @param nLength + @param nSize If specified, restricts the amount of data that can be read from the passed input stream. */ explicit RelativeInputStream( BinaryInputStream& rInStrm, - sal_Int64 nLength = SAL_MAX_INT64 ); + sal_Int64 nSize = SAL_MAX_INT64 ); - /** Returns whether the wrapped stream is seekable. */ - virtual bool isSeekable() const; /** Returns the size of the data block in the wrapped stream offered by this wrapper. */ - virtual sal_Int64 getLength() const; + virtual sal_Int64 size() const; + /** Returns the current relative stream position. */ virtual sal_Int64 tell() const; + /** Seeks the stream to the passed relative position, if the wrapped stream is seekable. */ virtual void seek( sal_Int64 nPos ); + /** Closes the input stream but not the wrapped stream. */ + virtual void close(); + /** Reads nBytes bytes to the passed sequence. Does not read out of the data block whose size has been specified on construction. @return Number of bytes really read. */ - virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes ); + virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ); + /** Reads nBytes bytes to the (existing) buffer opMem. Does not read out of the data block whose size has been specified on construction. @return Number of bytes really read. */ - virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes ); + virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); + /** Seeks the stream forward by the passed number of bytes. This works for non-seekable streams too. Does not seek out of the data block. */ - virtual void skip( sal_Int32 nBytes ); + virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ); - /** Stream operator for integral and floating-point types. */ + /** Stream operator for all data types supported by the readValue() function. */ template< typename Type > inline RelativeInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; } private: - BinaryInputStream& mrInStrm; + /** Returns the number of bytes available in the sequence for the passed byte count. */ + inline sal_Int32 getMaxBytes( sal_Int32 nBytes ) const + { return getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, mnSize - mnRelPos ); } + +private: + BinaryInputStream* mpInStrm; sal_Int64 mnStartPos; sal_Int64 mnRelPos; - sal_Int64 mnLength; + sal_Int64 mnSize; }; -typedef ::boost::shared_ptr< RelativeInputStream > RelativeInputStreamRef; - // ============================================================================ } // namespace oox diff --git a/oox/inc/oox/helper/binaryoutputstream.hxx b/oox/inc/oox/helper/binaryoutputstream.hxx index 441504171..8fd5ca4bc 100644 --- a/oox/inc/oox/helper/binaryoutputstream.hxx +++ b/oox/inc/oox/helper/binaryoutputstream.hxx @@ -28,10 +28,12 @@ #ifndef OOX_HELPER_BINARYOUTPUTSTREAM_HXX #define OOX_HELPER_BINARYOUTPUTSTREAM_HXX -#include <boost/shared_ptr.hpp> -#include <com/sun/star/io/XOutputStream.hpp> #include "oox/helper/binarystreambase.hxx" +namespace com { namespace sun { namespace star { + namespace io { class XOutputStream; } +} } } + namespace oox { // ============================================================================ @@ -43,24 +45,38 @@ namespace oox { class BinaryOutputStream : public virtual BinaryStreamBase { public: - /** Derived classes implement writing the passed data sequence. */ - virtual void writeData( const StreamDataSequence& rData ) = 0; - /** Derived classes implement writing from the (existing) buffer pMem. */ - virtual void writeMemory( const void* pMem, sal_Int32 nBytes ) = 0; + /** Derived classes implement writing the contents of the passed data + sequence. + + @param nAtomSize + The size of the elements in the memory block, if available. Derived + classes may be interested in this information. + */ + virtual void writeData( const StreamDataSequence& rData, size_t nAtomSize = 1 ) = 0; + + /** Derived classes implement writing the contents of the (preallocated!) + memory buffer pMem. + + @param nAtomSize + The size of the elements in the memory block, if available. Derived + classes may be interested in this information. + */ + virtual void writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize = 1 ) = 0; /** Writes a value to the stream and converts it to platform byte order. - Supported types: SAL integers (8 to 64 bit), float, double. */ + All data types supported by the ByteOrderConverter class can be used. + */ template< typename Type > void writeValue( Type nValue ); - /** Stream operator for integral and floating-point types. */ + + /** Stream operator for all data types supported by the writeValue() function. */ template< typename Type > inline BinaryOutputStream& operator<<( Type nValue ) { writeValue( nValue ); return *this; } -private: - /** Used by the writeValue() template function to write built-in types. - @descr Derived classes may overwrite this default implementation which - simply calls writeMemory() with something own. */ - virtual void writeAtom( const void* pMem, sal_uInt8 nSize ); +protected: + /** This dummy default c'tor will never call the c'tor of the virtual base + class BinaryStreamBase as this class cannot be instanciated directly. */ + inline explicit BinaryOutputStream() : BinaryStreamBase( false ) {} }; typedef ::boost::shared_ptr< BinaryOutputStream > BinaryOutputStreamRef; @@ -70,14 +86,13 @@ typedef ::boost::shared_ptr< BinaryOutputStream > BinaryOutputStreamRef; template< typename Type > void BinaryOutputStream::writeValue( Type nValue ) { - // can be instanciated for all types supported in class ByteOrderConverter ByteOrderConverter::convertLittleEndian( nValue ); - writeMemory( &nValue, static_cast< sal_Int32 >( sizeof( Type ) ) ); + writeMemory( &nValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) ); } // ============================================================================ -/** Wraps a com.sun.star.io.XOutputStream and provides convenient access functions. +/** Wraps a UNO output stream and provides convenient access functions. The binary data in the stream is written in little-endian format. */ @@ -86,10 +101,13 @@ class BinaryXOutputStream : public BinaryXSeekableStream, public BinaryOutputStr public: /** Constructs the wrapper object for the passed output stream. - @param rxOutStream The com.sun.star.io.XOutputStream interface of the - output stream to be wrapped. - @param bAutoClose True = automatically close the wrapped output stream - on destruction of this wrapper. + @param rxOutStream + The com.sun.star.io.XOutputStream interface of the output stream to + be wrapped. + + @param bAutoClose + True = automatically close the wrapped output stream on destruction + of this wrapper or when close() is called. */ explicit BinaryXOutputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream >& rxOutStrm, @@ -97,20 +115,23 @@ public: virtual ~BinaryXOutputStream(); + /** Flushes and closes the output stream. Does also close the wrapped UNO + output stream if bAutoClose has been set to true in the constructor. */ + void close(); + /** Writes the passed data sequence. */ - virtual void writeData( const StreamDataSequence& rData ); - /** Write nBytes bytes from the (existing) buffer pMem. */ - virtual void writeMemory( const void* pMem, sal_Int32 nBytes ); + virtual void writeData( const StreamDataSequence& rData, size_t nAtomSize = 1 ); + + /** Write nBytes bytes from the (preallocated!) buffer pMem. */ + virtual void writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); - /** Stream operator for integral and floating-point types. */ + /** Stream operator for all data types supported by the writeValue() function. */ template< typename Type > inline BinaryXOutputStream& operator<<( Type nValue ) { writeValue( nValue ); return *this; } /** Returns the XOutputStream interface of the wrapped output stream. */ inline ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > getXOutputStream() const { return mxOutStrm; } - /** Flushes and closes the wrapped XOutputStream. */ - void close(); private: StreamDataSequence maBuffer; /// Data buffer used in writeMemory() function. @@ -119,8 +140,6 @@ private: bool mbAutoClose; /// True = automatically close stream on destruction. }; -typedef ::boost::shared_ptr< BinaryXOutputStream > BinaryXOutputStreamRef; - // ============================================================================ /** Wraps a StreamDataSequence and provides convenient access functions. @@ -142,17 +161,16 @@ public: explicit SequenceOutputStream( StreamDataSequence& rData ); /** Writes the passed data sequence. */ - virtual void writeData( const StreamDataSequence& rData ); - /** Write nBytes bytes from the (existing) buffer pMem. */ - virtual void writeMemory( const void* pMem, sal_Int32 nBytes ); + virtual void writeData( const StreamDataSequence& rData, size_t nAtomSize = 1 ); - /** Stream operator for integral and floating-point types. */ + /** Write nBytes bytes from the (preallocated!) buffer pMem. */ + virtual void writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); + + /** Stream operator for all data types supported by the writeValue() function. */ template< typename Type > inline SequenceOutputStream& operator<<( Type nValue ) { writeValue( nValue ); return *this; } }; -typedef ::boost::shared_ptr< SequenceOutputStream > SequenceOutputStreamRef; - // ============================================================================ } // namespace oox diff --git a/oox/inc/oox/helper/binarystreambase.hxx b/oox/inc/oox/helper/binarystreambase.hxx index 0a8b362ab..2573f69c5 100644 --- a/oox/inc/oox/helper/binarystreambase.hxx +++ b/oox/inc/oox/helper/binarystreambase.hxx @@ -29,75 +29,123 @@ #define OOX_HELPER_BINARYSTREAMBASE_HXX #include <com/sun/star/uno/Sequence.hxx> -#include <com/sun/star/io/XSeekable.hpp> +#include <boost/shared_ptr.hpp> #include "oox/helper/helper.hxx" +namespace com { namespace sun { namespace star { + namespace io { class XSeekable; } +} } } + namespace oox { typedef ::com::sun::star::uno::Sequence< sal_Int8 > StreamDataSequence; // ============================================================================ -/** Base interface for binary stream classes. Implemenetations may or may not - support seeking the stream. */ +/** Base class for binary stream classes. + */ class BinaryStreamBase { public: virtual ~BinaryStreamBase(); + + /** Implementations return the size of the stream, if possible. - /** Derived classes return whether the stream is seekable. Default: false. */ - virtual bool isSeekable() const; - /** Derived classes return the size of the stream, if possible, - otherwise/default: -1. May return something for unseekable streams. */ - virtual sal_Int64 getLength() const; - /** Derived classes return the current stream position, if possible, - otherwise/default: -1. May return something for unseekable streams. */ - virtual sal_Int64 tell() const; - /** Derived classes implement seeking the stream to the passed position, if - the stream is seekable. */ - virtual void seek( sal_Int64 nPos ); + This function may be implemented for some types of unseekable streams, + and MUST be implemented for all seekable streams. + + @return + The size of the stream in bytes, or -1, if not implemented. + */ + virtual sal_Int64 size() const = 0; + + /** Implementations return the current stream position, if possible. + + This function may be implemented for some types of unseekable streams, + and MUST be implemented for all seekable streams. + + @return + The current position in the stream, or -1, if not implemented. + */ + virtual sal_Int64 tell() const = 0; + + /** Implementations seek the stream to the passed position, if + the stream is seekable. + */ + virtual void seek( sal_Int64 nPos ) = 0; + + /** Implementations close the stream. + */ + virtual void close() = 0; + + /** Returns true, if the implementation supports the seek() operation. + + Implementations may still implement size() and tell() even if the + stream is not seekable. + */ + inline bool isSeekable() const { return mbSeekable; } /** Returns true, if the stream position is invalid (EOF). This flag turns - true *after* the first attempt to seek/read beyond the stream end. */ + true *after* the first attempt to seek/read beyond the stream end. + */ inline bool isEof() const { return mbEof; } - /** Returns the size of the remaining data, if stream is seekable, otherwise -1. */ + /** Returns the size of the remaining data available in the stream, if + stream supports size() and tell(), otherwise -1. + */ sal_Int64 getRemaining() const; - /** Seeks the stream to the beginning, if stream is seekable. */ + + /** Seeks the stream to the beginning, if stream is seekable. + */ inline void seekToStart() { seek( 0 ); } - /** Seeks the stream to the end, if stream is seekable. */ - inline void seekToEnd() { seek( getLength() ); } + + /** Seeks the stream to the end, if stream is seekable. + */ + inline void seekToEnd() { seek( size() ); } + /** Seeks the stream forward to a position that is a multiple of the passed - block size, relative to the passed stream position, if stream is seekable. */ + block size, if stream is seekable. + + @param nBlockSize + The size of the data blocks the streams needs to be aligned to. + + @param nAnchorPos + Position in the stream the data blocks are aligned to. + */ void alignToBlock( sal_Int32 nBlockSize, sal_Int64 nAnchorPos = 0 ); protected: - inline explicit BinaryStreamBase() : mbEof( false ) {} + inline explicit BinaryStreamBase( bool bSeekable ) : mbEof( false ), mbSeekable( bSeekable ) {} private: BinaryStreamBase( const BinaryStreamBase& ); BinaryStreamBase& operator=( const BinaryStreamBase& ); protected: - bool mbEof; + bool mbEof; /// End of stream flag. + +private: + const bool mbSeekable; /// True = implementation supports seeking. }; // ============================================================================ -/** Base class for binary input and output streams wrapping an API stream, +/** Base class for binary input and output streams wrapping a UNO stream, seekable via the com.sun.star.io.XSeekable interface. */ class BinaryXSeekableStream : public virtual BinaryStreamBase { public: - /** Returns true, if the wrapped stream is seekable. */ - virtual bool isSeekable() const; - /** Returns the size of the stream, if stream is seekable, otherwise -1. */ - virtual sal_Int64 getLength() const; - /** Returns the current stream position, if stream is seekable, otherwise -1. */ + virtual ~BinaryXSeekableStream(); + + /** Returns the size of the stream, if wrapped stream is seekable, otherwise -1. */ + virtual sal_Int64 size() const; + /** Returns the current stream position, if wrapped stream is seekable, otherwise -1. */ virtual sal_Int64 tell() const; - /** Seeks the stream to the passed position, if stream is seekable. */ + /** Seeks the stream to the passed position, if wrapped stream is seekable. */ virtual void seek( sal_Int64 nPos ); + /** Releases the reference to the UNO XSeekable interface. */ + virtual void close(); protected: explicit BinaryXSeekableStream( @@ -111,31 +159,29 @@ private: // ============================================================================ /** Base class for binary input and output streams wrapping a - StreamDataSequence, which is always seekable. */ + StreamDataSequence, which is always seekable. + + The wrapped data sequence MUST live at least as long as this stream + wrapper. The data sequence MUST NOT be changed from outside as long as this + stream wrapper is used to modify it. + */ class SequenceSeekableStream : public virtual BinaryStreamBase { public: - /** Returns true (data sequence streams are always seekable). */ - virtual bool isSeekable() const; /** Returns the size of the wrapped data sequence. */ - virtual sal_Int64 getLength() const; + virtual sal_Int64 size() const; /** Returns the current stream position. */ virtual sal_Int64 tell() const; /** Seeks the stream to the passed position. */ virtual void seek( sal_Int64 nPos ); + /** Releases the reference to the data sequence. */ + virtual void close(); protected: - /** Constructs the wrapper object for the passed data sequence. - - @attention - The passed data sequence MUST live at least as long as this stream - wrapper. The data sequence MUST NOT be changed from outside as long - as this stream wrapper is used to modify it. - */ - inline explicit SequenceSeekableStream( const StreamDataSequence& rData ) : mrData( rData ), mnPos( 0 ) {} + explicit SequenceSeekableStream( const StreamDataSequence& rData ); protected: - const StreamDataSequence& mrData; /// Wrapped data sequence. + const StreamDataSequence* mpData; /// Wrapped data sequence. sal_Int32 mnPos; /// Current position in the sequence. }; diff --git a/oox/inc/oox/helper/containerhelper.hxx b/oox/inc/oox/helper/containerhelper.hxx index 262cb6036..559777096 100644 --- a/oox/inc/oox/helper/containerhelper.hxx +++ b/oox/inc/oox/helper/containerhelper.hxx @@ -28,8 +28,8 @@ #ifndef OOX_HELPER_CONTAINERHELPER_HXX #define OOX_HELPER_CONTAINERHELPER_HXX -#include <vector> #include <map> +#include <vector> #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> @@ -40,13 +40,59 @@ namespace com { namespace sun { namespace star { namespace container { class XIndexContainer; } namespace container { class XNameAccess; } namespace container { class XNameContainer; } - namespace lang { class XMultiServiceFactory; } + namespace uno { class XComponentContext; } } } } namespace oox { // ============================================================================ +/** A range of signed 32-bit integer values. */ +struct ValueRange +{ + sal_Int32 mnFirst; + sal_Int32 mnLast; + + inline explicit ValueRange( sal_Int32 nValue = 0 ) : mnFirst( nValue ), mnLast( nValue ) {} + inline explicit ValueRange( sal_Int32 nFirst, sal_Int32 nLast ) : mnFirst( nFirst ), mnLast( nLast ) {} + + inline bool operator==( const ValueRange& rRange ) const { return (mnFirst == rRange.mnFirst) && (mnLast == rRange.mnLast); } + inline bool operator!=( const ValueRange& rRange ) const { return !(*this == rRange); } + inline bool contains( sal_Int32 nValue ) const { return (mnFirst <= nValue) && (nValue <= mnLast); } + inline bool contains( const ValueRange& rRange ) const { return (mnFirst <= rRange.mnFirst) && (rRange.mnLast <= mnLast); } + inline bool intersects( const ValueRange& rRange ) const { return (mnFirst <= rRange.mnLast) && (rRange.mnFirst <= mnLast); } +}; + +// ---------------------------------------------------------------------------- + +typedef ::std::vector< ValueRange > ValueRangeVector; + +// ---------------------------------------------------------------------------- + +/** An ordered list of value ranges. The insertion operation will merge + consecutive value ranges. + */ +class ValueRangeSet +{ +public: + inline explicit ValueRangeSet() {} + + /** Inserts the passed value into the range list. */ + inline void insert( sal_Int32 nValue ) { insert( ValueRange( nValue ) ); } + /** Inserts the passed value range into the range list. */ + void insert( const ValueRange& rRange ); + + /** Returns the ordered list of all value ranges. */ + inline const ValueRangeVector& getRanges() const { return maRanges; } + /** Returns an intersection of the range list and the passed range. */ + ValueRangeVector getIntersection( const ValueRange& rRange ) const; + +private: + ValueRangeVector maRanges; +}; + +// ============================================================================ + /** Template for a 2-dimensional array of objects. This class template provides a similar interface to the ::std::vector @@ -124,7 +170,7 @@ public: /** Creates a new index container object from scratch. */ static ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > - createIndexContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory ); + createIndexContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext ); /** Inserts an object into an indexed container. @@ -146,7 +192,7 @@ public: /** Creates a new name container object from scratch. */ static ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > - createNameContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory ); + createNameContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext ); /** Returns a name that is not used in the passed name container. diff --git a/oox/inc/oox/helper/graphichelper.hxx b/oox/inc/oox/helper/graphichelper.hxx index 93c723325..bc245cf02 100644 --- a/oox/inc/oox/helper/graphichelper.hxx +++ b/oox/inc/oox/helper/graphichelper.hxx @@ -157,7 +157,7 @@ private: typedef ::std::deque< ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphicObject > > GraphicObjectDeque; typedef ::std::map< ::rtl::OUString, ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > > EmbeddedGraphicMap; - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxCompContext; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxContext; ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphicProvider > mxGraphicProvider; ::com::sun::star::uno::Reference< ::com::sun::star::awt::XUnitConversion > mxUnitConversion; ::com::sun::star::awt::DeviceInfo maDeviceInfo; /// Current output device info. diff --git a/oox/inc/oox/helper/helper.hxx b/oox/inc/oox/helper/helper.hxx index 5eef06fe6..0431ec99f 100644 --- a/oox/inc/oox/helper/helper.hxx +++ b/oox/inc/oox/helper/helper.hxx @@ -236,9 +236,9 @@ private: class ByteOrderConverter { public: +#ifdef OSL_BIGENDIAN inline static void convertLittleEndian( sal_Int8& ) {} // present for usage in templates inline static void convertLittleEndian( sal_uInt8& ) {} // present for usage in templates -#ifdef OSL_BIGENDIAN inline static void convertLittleEndian( sal_Int16& rnValue ) { swap2( reinterpret_cast< sal_uInt8* >( &rnValue ) ); } inline static void convertLittleEndian( sal_uInt16& rnValue ) { swap2( reinterpret_cast< sal_uInt8* >( &rnValue ) ); } inline static void convertLittleEndian( sal_Int32& rnValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rnValue ) ); } @@ -247,15 +247,20 @@ public: inline static void convertLittleEndian( sal_uInt64& rnValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rnValue ) ); } inline static void convertLittleEndian( float& rfValue ) { swap4( reinterpret_cast< sal_uInt8* >( &rfValue ) ); } inline static void convertLittleEndian( double& rfValue ) { swap8( reinterpret_cast< sal_uInt8* >( &rfValue ) ); } + + template< typename Type > + inline static void convertLittleEndianArray( Type* pnArray, size_t nElemCount ); + + inline static void convertLittleEndianArray( sal_Int8*, size_t ) {} + inline static void convertLittleEndianArray( sal_uInt8*, size_t ) {} + #else - inline static void convertLittleEndian( sal_Int16& ) {} - inline static void convertLittleEndian( sal_uInt16& ) {} - inline static void convertLittleEndian( sal_Int32& ) {} - inline static void convertLittleEndian( sal_uInt32& ) {} - inline static void convertLittleEndian( sal_Int64& ) {} - inline static void convertLittleEndian( sal_uInt64& ) {} - inline static void convertLittleEndian( float& ) {} - inline static void convertLittleEndian( double& ) {} + template< typename Type > + inline static void convertLittleEndian( Type& ) {} + + template< typename Type > + inline static void convertLittleEndianArray( Type*, size_t ) {} + #endif /** Reads a value from memory, assuming memory buffer in little-endian. @@ -297,6 +302,13 @@ inline void ByteOrderConverter::writeLittleEndian( void* pDstBuffer, Type nValue } #ifdef OSL_BIGENDIAN +template< typename Type > +inline void ByteOrderConverter::convertLittleEndianArray( Type* pnArray, size_t nElemCount ) +{ + for( Type* pnArrayEnd = pnArray + nElemCount; pnArray != pnArrayEnd; ++pnArray ) + convertLittleEndian( *pnArray ); +} + inline void ByteOrderConverter::swap2( sal_uInt8* pnData ) { ::std::swap( pnData[ 0 ], pnData[ 1 ] ); diff --git a/oox/inc/oox/helper/modelobjecthelper.hxx b/oox/inc/oox/helper/modelobjecthelper.hxx index a48a059e1..86729f38c 100644 --- a/oox/inc/oox/helper/modelobjecthelper.hxx +++ b/oox/inc/oox/helper/modelobjecthelper.hxx @@ -48,7 +48,7 @@ class ObjectContainer { public: explicit ObjectContainer( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxModelFactory, const ::rtl::OUString& rServiceName ); ~ObjectContainer(); @@ -68,8 +68,8 @@ private: void createContainer() const; private: - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > - mxFactory; /// Factory to create the container. + mutable ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > + mxModelFactory; /// Factory to create the container. mutable ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > mxContainer; /// Container for the objects. ::rtl::OUString maServiceName; /// Service name to create the container. @@ -81,9 +81,9 @@ private: /** Contains tables for named drawing objects for a document model. Contains tables for named line markers, line dashes, fill gradients, and - fill bitmaps. The class is needed to handle different document models in - the same filter (e.g. embedded charts) which carry their own drawing object - tables. + fill bitmap URLs. The class is needed to handle different document models + in the same filter (e.g. embedded charts) which carry their own drawing + object tables. */ class ModelObjectHelper { @@ -108,18 +108,18 @@ public: an internal constant name with a new unused index appended. */ ::rtl::OUString insertFillGradient( const ::com::sun::star::awt::Gradient& rGradient ); - /** Inserts a new named fill bitmap, returns the bitmap name, based on an - internal constant name with a new unused index appended. */ - ::rtl::OUString insertFillBitmap( const ::rtl::OUString& rGraphicUrl ); + /** Inserts a new named fill bitmap URL, returns the bitmap name, based on + an internal constant name with a new unused index appended. */ + ::rtl::OUString insertFillBitmapUrl( const ::rtl::OUString& rGraphicUrl ); private: ObjectContainer maMarkerContainer; /// Contains all named line markers (line end polygons). ObjectContainer maDashContainer; /// Contains all named line dsahes. ObjectContainer maGradientContainer; /// Contains all named fill gradients. - ObjectContainer maBitmapContainer; /// Contains all named fill bitmaps. + ObjectContainer maBitmapUrlContainer; /// Contains all named fill bitmap URLs. const ::rtl::OUString maDashNameBase; /// Base name for all named line dashes. const ::rtl::OUString maGradientNameBase; /// Base name for all named fill gradients. - const ::rtl::OUString maBitmapNameBase; /// Base name for all named fill bitmaps. + const ::rtl::OUString maBitmapUrlNameBase; /// Base name for all named fill bitmap URLs. }; // ============================================================================ diff --git a/oox/inc/oox/helper/propertymap.hxx b/oox/inc/oox/helper/propertymap.hxx index d5f9ab526..064c4e09f 100644 --- a/oox/inc/oox/helper/propertymap.hxx +++ b/oox/inc/oox/helper/propertymap.hxx @@ -59,7 +59,6 @@ class PropertyMap : public PropertyMapBase { public: explicit PropertyMap(); - ~PropertyMap(); /** Returns the name of the passed property identifier. */ static const ::rtl::OUString& getPropertyName( sal_Int32 nPropId ); @@ -73,9 +72,18 @@ public: /** Sets the specified property to the passed value. Does nothing, if the identifier is invalid. */ + inline bool setAnyProperty( sal_Int32 nPropId, const ::com::sun::star::uno::Any& rValue ) + { if( nPropId < 0 ) return false; (*this)[ nPropId ] = rValue; return true; } + + /** Sets the specified property to the passed value. Does nothing, if the + identifier is invalid. */ template< typename Type > - inline void setProperty( sal_Int32 nPropId, const Type& rValue ) - { if( nPropId >= 0 ) (*this)[ nPropId ] <<= rValue; } + inline bool setProperty( sal_Int32 nPropId, const Type& rValue ) + { if( nPropId < 0 ) return false; (*this)[ nPropId ] <<= rValue; return true; } + + /** Inserts all properties contained in the passed property map. */ + inline void assignUsed( const PropertyMap& rPropMap ) + { insert( rPropMap.begin(), rPropMap.end() ); } /** Returns a sequence of property values, filled with all contained properties. */ ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > @@ -86,7 +94,7 @@ public: ::com::sun::star::uno::Sequence< ::rtl::OUString >& rNames, ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& rValues ) const; - /** Creates and fills a new instance supporting the XPropertySet interface. */ + /** Creates a property set supporting the XPropertySet interface and inserts all properties. */ ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > makePropertySet() const; diff --git a/oox/inc/oox/helper/propertyset.hxx b/oox/inc/oox/helper/propertyset.hxx index 9ff5afb9a..22c78fe58 100644 --- a/oox/inc/oox/helper/propertyset.hxx +++ b/oox/inc/oox/helper/propertyset.hxx @@ -28,8 +28,9 @@ #ifndef OOX_HELPER_PROPERTYSET_HXX #define OOX_HELPER_PROPERTYSET_HXX -#include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/XMultiPropertySet.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertySetInfo.hpp> #include "oox/token/properties.hxx" namespace oox { @@ -82,24 +83,25 @@ public: inline ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > getXPropertySet() const { return mxPropSet; } + /** Returns true, if the specified property is supported by the property set. */ + bool hasProperty( sal_Int32 nPropId ) const; + // Get properties --------------------------------------------------------- /** Gets the specified property from the property set. - @return true, if the any could be filled with the property value. */ - bool getAnyProperty( ::com::sun::star::uno::Any& orValue, sal_Int32 nPropId ) const; + @return the property value, or an empty Any, if the property is missing. */ + ::com::sun::star::uno::Any getAnyProperty( sal_Int32 nPropId ) const; /** Gets the specified property from the property set. @return true, if the passed variable could be filled with the property value. */ template< typename Type > - inline bool getProperty( Type& orValue, sal_Int32 nPropId ) const; - - /** Gets the specified property from the property set. - @return the property value, or an empty Any, if the property is missing. */ - ::com::sun::star::uno::Any getAnyProperty( sal_Int32 nPropId ) const; + inline bool getProperty( Type& orValue, sal_Int32 nPropId ) const + { return getAnyProperty( nPropId ) >>= orValue; } /** Gets the specified boolean property from the property set. @return true = property contains true; false = property contains false or error occured. */ - bool getBoolProperty( sal_Int32 nPropId ) const; + inline bool getBoolProperty( sal_Int32 nPropId ) const + { bool bValue = false; return getProperty( bValue, nPropId ) && bValue; } /** Gets the specified properties from the property set. Tries to use the XMultiPropertySet interface. @param orValues (out-parameter) The related property values. @@ -111,11 +113,12 @@ public: // Set properties --------------------------------------------------------- /** Puts the passed any into the property set. */ - void setAnyProperty( sal_Int32 nPropId, const ::com::sun::star::uno::Any& rValue ); + bool setAnyProperty( sal_Int32 nPropId, const ::com::sun::star::uno::Any& rValue ); /** Puts the passed value into the property set. */ template< typename Type > - inline void setProperty( sal_Int32 nPropId, const Type& rValue ); + inline bool setProperty( sal_Int32 nPropId, const Type& rValue ) + { return setAnyProperty( nPropId, ::com::sun::star::uno::Any( rValue ) ); } /** Puts the passed properties into the property set. Tries to use the XMultiPropertySet interface. @param rPropNames The property names. MUST be ordered alphabetically. @@ -132,33 +135,20 @@ public: private: /** Gets the specified property from the property set. @return true, if the any could be filled with the property value. */ - bool getAnyProperty( ::com::sun::star::uno::Any& orValue, const ::rtl::OUString& rPropName ) const; + bool implGetPropertyValue( ::com::sun::star::uno::Any& orValue, const ::rtl::OUString& rPropName ) const; /** Puts the passed any into the property set. */ - void setAnyProperty( const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rValue ); + bool implSetPropertyValue( const ::rtl::OUString& rPropName, const ::com::sun::star::uno::Any& rValue ); private: ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > mxPropSet; /// The mandatory property set interface. ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet > mxMultiPropSet; /// The optional multi property set interface. + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > + mxPropSetInfo; /// Property information. }; -// ---------------------------------------------------------------------------- - -template< typename Type > -inline bool PropertySet::getProperty( Type& orValue, sal_Int32 nPropId ) const -{ - ::com::sun::star::uno::Any aAny; - return getAnyProperty( aAny, nPropId ) && (aAny >>= orValue); -} - -template< typename Type > -inline void PropertySet::setProperty( sal_Int32 nPropId, const Type& rValue ) -{ - setAnyProperty( nPropId, ::com::sun::star::uno::Any( rValue ) ); -} - // ============================================================================ } // namespace oox diff --git a/oox/inc/oox/helper/textinputstream.hxx b/oox/inc/oox/helper/textinputstream.hxx index 2e98d3fc8..e4358a8bd 100755 --- a/oox/inc/oox/helper/textinputstream.hxx +++ b/oox/inc/oox/helper/textinputstream.hxx @@ -25,29 +25,100 @@ * ************************************************************************/ -#ifndef OOX_HELPER_RECORDINPUTSTREAM_HXX -#define OOX_HELPER_RECORDINPUTSTREAM_HXX +#ifndef OOX_HELPER_TEXTINPUTSTREAM_HXX +#define OOX_HELPER_TEXTINPUTSTREAM_HXX -#include "oox/helper/binaryinputstream.hxx" +#include <com/sun/star/uno/Reference.hxx> +#include <rtl/ustring.hxx> + +namespace com { namespace sun { namespace star { + namespace io { class XInputStream; } + namespace io { class XTextInputStream; } + namespace uno { class XComponentContext; } +} } } namespace oox { +class BinaryInputStream; + // ============================================================================ class TextInputStream { public: - explicit TextInputStream( BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc ); + explicit TextInputStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, + rtl_TextEncoding eTextEnc ); + + explicit TextInputStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, + BinaryInputStream& rInStrm, + rtl_TextEncoding eTextEnc ); + + ~TextInputStream(); - /** Returns true, if the wrapped input stream is in EOF state. */ + /** Returns true, if no more text is available in the stream. + */ bool isEof() const; - /** Reads a text line from the stream. */ + + /** Reads a text line from the stream. + + If the last line in the stream is not terminated with line-end + character(s), the stream will immediately go into EOF state and return + the text line. Otherwise, if the last character in the stream is a + line-end character, the next call to this function will turn the stream + into EOF state and return an empty string. + */ ::rtl::OUString readLine(); + /** Reads a text portion from the stream until the specified character is + found. + + If the end of the stream is not terminated with the specified + character, the stream will immediately go into EOF state and return the + remaining text portion. Otherwise, if the last character in the stream + is the specified character (and caller specifies to read and return it, + see parameter bIncludeChar), the next call to this function will turn + the stream into EOF state and return an empty string. + + @param cChar + The separator character to be read to. + + @param bIncludeChar + True = if found, the specified character will be read from stream + and included in the returned string. + False = the specified character will neither be read from the + stream nor included in the returned string, but will be + returned as first character in the next call of this function + or readLine(). + */ + ::rtl::OUString readToChar( sal_Unicode cChar, bool bIncludeChar ); + + // ------------------------------------------------------------------------ + + /** Creates a UNO text input stream object from the passed UNO input stream. + */ + static ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextInputStream > + createXTextInputStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, + rtl_TextEncoding eTextEnc ); + + // ------------------------------------------------------------------------ +private: + void init( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm, + rtl_TextEncoding eTextEnc ); + + /** Adds the pending character in front of the passed string, if existing. */ + ::rtl::OUString createFinalString( const ::rtl::OUString& rString ); + private: - BinaryInputStream& mrInStrm; - rtl_TextEncoding meTextEnc; - sal_Unicode mcLastEolChar; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextInputStream > + mxTextStrm; + sal_Unicode mcPendingChar; }; // ============================================================================ diff --git a/oox/inc/oox/helper/zipstorage.hxx b/oox/inc/oox/helper/zipstorage.hxx index 55dd454ff..62a8eb5a2 100644 --- a/oox/inc/oox/helper/zipstorage.hxx +++ b/oox/inc/oox/helper/zipstorage.hxx @@ -31,7 +31,7 @@ #include "oox/helper/storagebase.hxx" namespace com { namespace sun { namespace star { - namespace lang { class XMultiServiceFactory; } + namespace uno { class XComponentContext; } } } } namespace oox { @@ -43,11 +43,11 @@ class ZipStorage : public StorageBase { public: explicit ZipStorage( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream ); explicit ZipStorage( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxStream ); virtual ~ZipStorage(); @@ -83,9 +83,8 @@ private: virtual void implCommit() const; private: - typedef ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > XStorageRef; - - XStorageRef mxStorage; /// Storage based on input or output stream. + ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage > + mxStorage; /// Storage based on input or output stream. }; // ============================================================================ diff --git a/oox/inc/oox/ole/axbinaryreader.hxx b/oox/inc/oox/ole/axbinaryreader.hxx index e9f26c990..732262484 100644 --- a/oox/inc/oox/ole/axbinaryreader.hxx +++ b/oox/inc/oox/ole/axbinaryreader.hxx @@ -40,7 +40,7 @@ namespace ole { /** A wrapper for a binary input stream that supports aligned read operations. The implementation does not support seeking back the wrapped stream. All - seeking operations (tell, seek, align) are performed relative to the + seeking operations (tell, seekTo, align) are performed relative to the position of the wrapped stream at construction time of this wrapper. It is possible to construct this wrapper with an unseekable input stream without loosing any functionality. @@ -50,21 +50,26 @@ class AxAlignedInputStream : public BinaryInputStream public: explicit AxAlignedInputStream( BinaryInputStream& rInStrm ); + /** Returns the size of the data this stream represents, if the wrapped + stream supports the size() operation. */ + virtual sal_Int64 size() const; /** Return the current relative stream position (relative to position of the wrapped stream at construction time). */ virtual sal_Int64 tell() const; /** Seeks the stream to the passed relative position, if it is behind the current position. */ virtual void seek( sal_Int64 nPos ); + /** Closes the input stream but not the wrapped stream. */ + virtual void close(); /** Reads nBytes bytes to the passed sequence. @return Number of bytes really read. */ - virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes ); + virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Reads nBytes bytes to the (existing) buffer opMem. @return Number of bytes really read. */ - virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes ); + virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Seeks the stream forward by the passed number of bytes. */ - virtual void skip( sal_Int32 nBytes ); + virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Aligns the stream to a multiple of the passed size (relative to the position of the wrapped stream at construction time). */ @@ -78,8 +83,9 @@ public: inline void skipAligned() { align( sizeof( Type ) ); skip( sizeof( Type ) ); } private: - BinaryInputStream& mrInStrm; /// The wrapped input stream. + BinaryInputStream* mpInStrm; /// The wrapped input stream. sal_Int64 mnStrmPos; /// Tracks relative position in the stream. + sal_Int64 mnStrmSize; /// Size of the wrapped stream data. }; // ============================================================================ diff --git a/oox/inc/oox/ole/oleobjecthelper.hxx b/oox/inc/oox/ole/oleobjecthelper.hxx index d4835a907..17c0a3916 100644 --- a/oox/inc/oox/ole/oleobjecthelper.hxx +++ b/oox/inc/oox/ole/oleobjecthelper.hxx @@ -63,7 +63,7 @@ class OleObjectHelper { public: explicit OleObjectHelper( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory ); + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxModelFactory ); ~OleObjectHelper(); bool importOleObject( diff --git a/oox/inc/oox/ole/olestorage.hxx b/oox/inc/oox/ole/olestorage.hxx index 171ad7676..f3ffaec91 100644..100755 --- a/oox/inc/oox/ole/olestorage.hxx +++ b/oox/inc/oox/ole/olestorage.hxx @@ -32,7 +32,7 @@ namespace com { namespace sun { namespace star { namespace container { class XNameContainer; } - namespace lang { class XMultiServiceFactory; } + namespace uno { class XComponentContext; } } } } namespace oox { @@ -45,12 +45,12 @@ class OleStorage : public StorageBase { public: explicit OleStorage( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStream, bool bBaseStreamAccess ); explicit OleStorage( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStream >& rxOutStream, bool bBaseStreamAccess ); @@ -101,8 +101,8 @@ private: virtual void implCommit() const; private: - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > - mxFactory; /// Factory for storage/stream creation. + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > + mxContext; /// Component context with service manager. ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > mxStorage; /// Access to elements of this sub storage. const OleStorage* mpParentStorage; /// Parent OLE storage that contains this storage. diff --git a/oox/inc/oox/ole/vbacontrol.hxx b/oox/inc/oox/ole/vbacontrol.hxx index 8d10966fc..9adf20440 100755..100644 --- a/oox/inc/oox/ole/vbacontrol.hxx +++ b/oox/inc/oox/ole/vbacontrol.hxx @@ -206,7 +206,7 @@ public: rtl_TextEncoding eTextEnc ); private: - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxCompContext; + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > mxContext; ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > mxDocModel; ControlConverter maConverter; }; diff --git a/oox/inc/oox/ole/vbainputstream.hxx b/oox/inc/oox/ole/vbainputstream.hxx index 88a40cbca..6b40d6c7a 100644 --- a/oox/inc/oox/ole/vbainputstream.hxx +++ b/oox/inc/oox/ole/vbainputstream.hxx @@ -42,14 +42,23 @@ class VbaInputStream : public BinaryInputStream public: explicit VbaInputStream( BinaryInputStream& rInStrm ); + /** Returns -1, stream size is not determinable. */ + virtual sal_Int64 size() const; + /** Returns -1, stream position is not tracked. */ + virtual sal_Int64 tell() const; + /** Does nothing, stream is not seekable. */ + virtual void seek( sal_Int64 nPos ); + /** Closes the input stream but not the wrapped stream. */ + virtual void close(); + /** Reads nBytes bytes to the passed sequence. @return Number of bytes really read. */ - virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes ); + virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Reads nBytes bytes to the (existing) buffer opMem. @return Number of bytes really read. */ - virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes ); + virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Seeks the stream forward by the passed number of bytes. */ - virtual void skip( sal_Int32 nBytes ); + virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ); private: /** If no data left in chunk buffer, reads the next chunk from stream. */ @@ -58,7 +67,7 @@ private: private: typedef ::std::vector< sal_uInt8 > ChunkBuffer; - BinaryInputStream& mrInStrm; + BinaryInputStream* mpInStrm; ChunkBuffer maChunk; size_t mnChunkPos; }; diff --git a/oox/inc/oox/ole/vbamodule.hxx b/oox/inc/oox/ole/vbamodule.hxx index 52b2261e5..57a1de316 100644..100755 --- a/oox/inc/oox/ole/vbamodule.hxx +++ b/oox/inc/oox/ole/vbamodule.hxx @@ -35,6 +35,7 @@ namespace com { namespace sun { namespace star { namespace container { class XNameAccess; } namespace container { class XNameContainer; } namespace frame { class XModel; } + namespace uno { class XComponentContext; } } } } namespace oox { @@ -51,6 +52,7 @@ class VbaModule { public: explicit VbaModule( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& rxDocModel, const ::rtl::OUString& rName, rtl_TextEncoding eTextEnc, @@ -90,6 +92,8 @@ private: const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameAccess >& rxDocObjectNA ) const; private: + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > + mxContext; /// Component context with service manager. ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > mxDocModel; /// Document model used to import/export the VBA project. ::rtl::OUString maName; diff --git a/oox/inc/oox/ole/vbaproject.hxx b/oox/inc/oox/ole/vbaproject.hxx index 8c494f7f9..9e6e6b951 100644 --- a/oox/inc/oox/ole/vbaproject.hxx +++ b/oox/inc/oox/ole/vbaproject.hxx @@ -189,7 +189,7 @@ private: typedef ::std::map< ::rtl::OUString, sal_Int32 > DummyModuleMap; ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > - mxCompContext; /// Component context with service manager. + mxContext; /// Component context with service manager. ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > mxDocModel; /// Document model used to import/export the VBA project. ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > diff --git a/oox/inc/oox/ppt/slidepersist.hxx b/oox/inc/oox/ppt/slidepersist.hxx index f147e88b3..25f40d15c 100644 --- a/oox/inc/oox/ppt/slidepersist.hxx +++ b/oox/inc/oox/ppt/slidepersist.hxx @@ -90,7 +90,7 @@ public: void setBackgroundProperties( const oox::drawingml::FillPropertiesPtr pFillPropertiesPtr ){ mpBackgroundPropertiesPtr = pFillPropertiesPtr; } oox::drawingml::FillPropertiesPtr getBackgroundProperties() const { return mpBackgroundPropertiesPtr; } - oox::drawingml::Color& getBackgroundColorRef() { return maBackgroundColorRef; } + oox::drawingml::Color& getBackgroundColor() { return maBackgroundColor; } sal_Bool isMasterPage() const { return mbMaster; } sal_Bool isNotesPage() const { return mbNotes; } @@ -130,7 +130,7 @@ private: SlidePersistPtr mpMasterPagePtr; oox::drawingml::ShapePtr maShapesPtr; - oox::drawingml::Color maBackgroundColorRef; + oox::drawingml::Color maBackgroundColor; oox::drawingml::FillPropertiesPtr mpBackgroundPropertiesPtr; ::std::list< boost::shared_ptr< TimeNode > > maTimeNodeList; diff --git a/oox/inc/oox/vml/vmldrawing.hxx b/oox/inc/oox/vml/vmldrawing.hxx index 11f810420..af5b196c2 100644 --- a/oox/inc/oox/vml/vmldrawing.hxx +++ b/oox/inc/oox/vml/vmldrawing.hxx @@ -132,7 +132,7 @@ public: /** Final processing after import of the fragment. */ void finalizeFragmentImport(); - /** Creates and inserts all UNO shapes into the passed container. The virtual + /** Creates and inserts all UNO shapes into the draw page. The virtual function notifyXShapeInserted() will be called for each new shape. */ void convertAndInsert() const; diff --git a/oox/inc/oox/vml/vmlformatting.hxx b/oox/inc/oox/vml/vmlformatting.hxx index 173f15eb4..b85ec9c18 100644 --- a/oox/inc/oox/vml/vmlformatting.hxx +++ b/oox/inc/oox/vml/vmlformatting.hxx @@ -32,9 +32,8 @@ namespace oox { class GraphicHelper; - class ModelObjectHelper; - class PropertyMap; namespace drawingml { class Color; } + namespace drawingml { class ShapePropertyMap; } } namespace oox { @@ -91,7 +90,7 @@ public: @param bDefaultAsPixel Set to true if omitted measure unit means pixel. Set to false if omitted measure unit means EMU. */ - static sal_Int32 decodeMeasureToEmu( + static sal_Int64 decodeMeasureToEmu( const GraphicHelper& rGraphicHelper, const ::rtl::OUString& rValue, sal_Int32 nRefValue, @@ -179,8 +178,7 @@ struct StrokeModel /** Writes the properties to the passed property map. */ void pushToPropMap( - PropertyMap& rPropMap, - ModelObjectHelper& rModelObjectHelper, + ::oox::drawingml::ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper ) const; }; @@ -206,8 +204,7 @@ struct FillModel /** Writes the properties to the passed property map. */ void pushToPropMap( - PropertyMap& rPropMap, - ModelObjectHelper& rModelObjectHelper, + ::oox::drawingml::ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper ) const; }; diff --git a/oox/inc/oox/vml/vmlinputstream.hxx b/oox/inc/oox/vml/vmlinputstream.hxx index 5d5bbdf04..415b8c30c 100644 --- a/oox/inc/oox/vml/vmlinputstream.hxx +++ b/oox/inc/oox/vml/vmlinputstream.hxx @@ -28,36 +28,72 @@ #ifndef OOX_VML_VMLINPUTSTREAM_HXX #define OOX_VML_VMLINPUTSTREAM_HXX -#include <comphelper/seqstream.hxx> +#include <com/sun/star/io/XInputStream.hpp> +#include <cppuhelper/implbase1.hxx> +#include <rtl/string.hxx> + +namespace com { namespace sun { namespace star { + namespace io { class XTextInputStream; } + namespace uno { class XComponentContext; } +} } } namespace oox { namespace vml { // ============================================================================ -struct StreamDataContainer -{ - ::comphelper::ByteSequence maDataSeq; +typedef ::cppu::WeakImplHelper1< ::com::sun::star::io::XInputStream > InputStream_BASE; - explicit StreamDataContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm ); -}; - -// ============================================================================ +/** An input stream class for VML streams, implementing the UNO interface + com.sun.star.io.XInputStream needed by the Expat XML parsers. -/** An input stream class for VML streams. + This stream reads the data from the input stream passed to the constructor, + and parses all XML elements for features unsupported by the current Expat + XML parser: - This stream reads the entire data from the input stream passed to the - constructor, and parses all XML elements for features unsupported by the - current Expat parser. - - All elements that have the form '<![inst]>' where 'inst' is any string not - containing the characters '<' and '>' are stripped from the input stream. + 1) All elements that have the form '<![inst]>' where 'inst' is any string + not containing the characters '<' and '>' are stripped from the input + stream. + + 2) Multiple occurences of the same attribute in an element but the last + are removed. + + 3) Line breaks represented by a single <br> element (without matching + </br> element) are replaced by a literal LF character. */ -class InputStream : private StreamDataContainer, public ::comphelper::SequenceInputStream +class InputStream : public InputStream_BASE { public: - explicit InputStream( const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm ); + explicit InputStream( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, + const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm ); virtual ~InputStream(); + + virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) + throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) + throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL available() + throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL closeInput() + throw (::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + +private: + void updateBuffer() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + ::rtl::OString readToElementBegin() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + ::rtl::OString readToElementEnd() throw (::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + +private: + ::com::sun::star::uno::Reference< ::com::sun::star::io::XTextInputStream > + mxTextStrm; + ::com::sun::star::uno::Sequence< sal_Unicode > maOpeningBracket; + ::com::sun::star::uno::Sequence< sal_Unicode > maClosingBracket; + const ::rtl::OString maOpeningCData; + const ::rtl::OString maClosingCData; + ::rtl::OString maBuffer; + sal_Int32 mnBufferPos; }; // ============================================================================ diff --git a/oox/inc/oox/xls/biffhelper.hxx b/oox/inc/oox/xls/biffhelper.hxx index 5141bd74f..5ed0180c8 100644 --- a/oox/inc/oox/xls/biffhelper.hxx +++ b/oox/inc/oox/xls/biffhelper.hxx @@ -442,6 +442,7 @@ const sal_uInt16 BIFF_ID_MTHREADSETTINGS = 0x089A; const sal_uInt16 BIFF_ID_MULTBLANK = 0x00BE; const sal_uInt16 BIFF_ID_MULTRK = 0x00BD; const sal_uInt16 BIFF_ID_NOTE = 0x001C; +const sal_uInt16 BIFF_ID_NOTESOUND = 0x0096; const sal_uInt16 BIFF2_ID_NUMBER = 0x0003; const sal_uInt16 BIFF3_ID_NUMBER = 0x0203; const sal_uInt16 BIFF_ID_OBJ = 0x005D; @@ -620,7 +621,7 @@ public: // BIFF12 import ---------------------------------------------------------- /** Reads a BIFF12 string with leading 16-bit or 32-bit length field. */ - static ::rtl::OUString readString( SequenceInputStream& rStrm, bool b32BitLen = true ); + static ::rtl::OUString readString( SequenceInputStream& rStrm, bool b32BitLen = true, bool bAllowNulChars = false ); // BIFF2-BIFF8 import ----------------------------------------------------- diff --git a/oox/inc/oox/xls/biffinputstream.hxx b/oox/inc/oox/xls/biffinputstream.hxx index c94a1e39c..078f7823b 100644 --- a/oox/inc/oox/xls/biffinputstream.hxx +++ b/oox/inc/oox/xls/biffinputstream.hxx @@ -242,30 +242,30 @@ public: // BinaryStreamBase interface (seeking) ----------------------------------- - /** Returns true, as the BIFF input stream is required to be seekable. */ - virtual bool isSeekable() const; + /** Returns the data size of the whole record without record headers. */ + virtual sal_Int64 size() const; /** Returns the position inside of the whole record content. */ virtual sal_Int64 tell() const; - /** Returns the data size of the whole record without record headers. */ - virtual sal_Int64 getLength() const; /** Seeks in record content to the specified position. */ virtual void seek( sal_Int64 nRecPos ); + /** Closes the input stream but not the wrapped stream. */ + virtual void close(); /** Returns the absolute position in the wrapped binary stream. */ sal_Int64 tellBase() const; /** Returns the total size of the wrapped binary stream. */ - sal_Int64 getBaseLength() const; + sal_Int64 sizeBase() const; // BinaryInputStream interface (stream read access) ----------------------- /** Reads nBytes bytes to the passed sequence. @return Number of bytes really read. */ - virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes ); + virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Reads nBytes bytes and copies them to the passed buffer opMem. @return Number of bytes really read. */ - virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes ); + virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Seeks forward inside the current record. */ - virtual void skip( sal_Int32 nBytes ); + virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Stream operator for integral and floating-point types. */ template< typename Type > @@ -352,9 +352,6 @@ public: // ------------------------------------------------------------------------ private: - /** Forwards calls of readValue() template functions to the record buffer. */ - virtual void readAtom( void* opMem, sal_uInt8 nSize ); - /** Initializes all members after base stream has been seeked to new record. */ void setupRecord(); /** Restarts the current record from the beginning. */ @@ -383,16 +380,9 @@ private: records, stores the length in mnComplRecSize. */ void calcRecordLength(); - /** Ensures that reading nBytes bytes is possible with next stream access. - @descr Stream must be located at the end of a raw record, and handling - of CONTINUE records must be enabled. - @return True if nBytes can be read from stream. */ - bool ensureRawReadSize( sal_uInt16 nBytes ); /** Returns the maximum size of raw data possible to read in one block. */ - sal_uInt16 getMaxRawReadSize( sal_Int32 nBytes ) const; + sal_uInt16 getMaxRawReadSize( sal_Int32 nBytes, size_t nAtomSize ) const; - /** Reads an array of Unicode characters and appends them to the passed buffer. */ - void appendUnicodeArray( ::rtl::OUStringBuffer& orBuffer, sal_uInt16 nChars, bool b16BitChars, bool bAllowNulChars ); /** Reads the BIFF8 Unicode string header fields. */ void readUniStringHeader( bool& orb16BitChars, sal_Int32& ornAddSize ); diff --git a/oox/inc/oox/xls/biffoutputstream.hxx b/oox/inc/oox/xls/biffoutputstream.hxx index 256bd8f90..b2e96ce1d 100644 --- a/oox/inc/oox/xls/biffoutputstream.hxx +++ b/oox/inc/oox/xls/biffoutputstream.hxx @@ -94,9 +94,6 @@ private: CONTINUE record, use setPortionSize(). Example: To write a sequence of 16-bit values where 4 values form a unit and cannot be split, call setPortionSize(8) first (4*2 bytes == 8). - - To write unicode character arrays, call writeUnicodeBuffer(). It creates - CONTINUE records and repeats the unicode string flag byte automatically. */ class BiffOutputStream : public BinaryOutputStream { @@ -113,47 +110,44 @@ public: /** Finishes the current record. Must be called for every started record. */ void endRecord(); - /** Sets size of data portion in bytes. 0 means no portions are used. */ - void setPortionSize( sal_uInt16 nSize ); + /** Sets size of data portion in bytes. 0 or 1 means no portions are used. */ + void setPortionSize( sal_uInt8 nSize ); // BinaryStreamBase interface (seeking) ----------------------------------- /** Returns the absolute position in the wrapped binary stream. */ sal_Int64 tellBase() const; /** Returns the total size of the wrapped binary stream. */ - sal_Int64 getBaseLength() const; + sal_Int64 sizeBase() const; // BinaryOutputStream interface (stream write access) --------------------- /** Writes the passed data sequence. */ - virtual void writeData( const StreamDataSequence& rData ); + virtual void writeData( const StreamDataSequence& rData, size_t nAtomSize = 1 ); /** Writes nBytes bytes from the passed buffer pMem. */ - virtual void writeMemory( const void* pMem, sal_Int32 nBytes ); + virtual void writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize = 1 ); /** Writes a sequence of nBytes bytes with the passed value. */ - void fill( sal_uInt8 nValue, sal_Int32 nBytes ); - /** Writes a block of memory, ensures that it is not split to a CONTINUE record. */ - void writeBlock( const void* pMem, sal_uInt16 nBytes ); + void fill( sal_uInt8 nValue, sal_Int32 nBytes, size_t nAtomSize = 1 ); - /** Stream operator for integral and floating-point types. */ + /** Stream operator for all data types supported by the writeValue() function. */ template< typename Type > inline BiffOutputStream& operator<<( Type nValue ) { writeValue( nValue ); return *this; } // ------------------------------------------------------------------------ private: - /** Forwards calls of writeValue() template functions to the record buffer. */ - virtual void writeAtom( const void* pMem, sal_uInt8 nSize ); - /** Checks the remaining size in the current record, creates CONTINUE record if needed. */ void ensureRawBlock( sal_uInt16 nSize ); - /** Checks the remaining size in the current record and creates CONTINUE record if needed. + + /** Checks the remaining size in the current record and creates a CONTINUE + record if needed. @return Maximum size left for writing to current record. */ - sal_uInt16 prepareRawBlock( sal_Int32 nTotalSize ); + sal_uInt16 prepareWriteBlock( sal_Int32 nTotalSize, size_t nAtomSize ); private: prv::BiffOutputRecordBuffer maRecBuffer; /// Raw record data buffer. - sal_uInt16 mnPortionSize; /// Size of data portions. - sal_uInt16 mnPortionPos; /// Position in current portion. + sal_uInt8 mnPortionSize; /// Size of data portions. + sal_uInt8 mnPortionPos; /// Position in current portion. }; // ============================================================================ diff --git a/oox/inc/oox/xls/chartsheetfragment.hxx b/oox/inc/oox/xls/chartsheetfragment.hxx index fc61fb705..3d89aced6 100644 --- a/oox/inc/oox/xls/chartsheetfragment.hxx +++ b/oox/inc/oox/xls/chartsheetfragment.hxx @@ -39,10 +39,8 @@ class ChartsheetFragment : public WorksheetFragmentBase { public: explicit ChartsheetFragment( - const WorkbookHelper& rHelper, - const ::rtl::OUString& rFragmentPath, - const ISegmentProgressBarRef& rxProgressBar, - sal_Int16 nSheet ); + const WorksheetHelper& rHelper, + const ::rtl::OUString& rFragmentPath ); protected: virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ); @@ -67,9 +65,8 @@ class BiffChartsheetFragment : public BiffWorksheetFragmentBase { public: explicit BiffChartsheetFragment( - const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, - sal_Int16 nSheet ); + const WorksheetHelper& rHelper, + const BiffWorkbookFragmentBase& rParent ); /** Imports the entire sheet fragment, returns true, if EOF record has been reached. */ virtual bool importFragment(); diff --git a/oox/inc/oox/xls/commentsbuffer.hxx b/oox/inc/oox/xls/commentsbuffer.hxx index 36d473348..f558c407a 100644 --- a/oox/inc/oox/xls/commentsbuffer.hxx +++ b/oox/inc/oox/xls/commentsbuffer.hxx @@ -40,8 +40,11 @@ struct CommentModel { ::com::sun::star::table::CellRangeAddress maRange; /// Position of the comment in the worksheet. - RichStringRef mxText; /// Formatted text of the comment. - sal_Int32 mnAuthorId; /// Identifier of the comment's author. + RichStringRef mxText; /// Formatted text of the comment (not used in BIFF8). + ::rtl::OUString maAuthor; /// Comment author (BIFF8 only). + sal_Int32 mnAuthorId; /// Identifier of the comment's author (OOXML and BIFF12 only). + sal_uInt16 mnObjId; /// Drawing object identifier (BIFF8 only). + bool mbVisible; /// True = comment is always shown (BIFF2-BIFF8 only). explicit CommentModel(); }; @@ -57,6 +60,8 @@ public: void importComment( const AttributeList& rAttribs ); /** Imports a cell comment from the passed stream of a COMMENT record. */ void importComment( SequenceInputStream& rStrm ); + /** Imports a cell comment from the passed stream of a NOTE record. */ + void importNote( BiffInputStream& rStrm ); /** Creates and returns a new rich-string object for the comment text. */ RichStringRef createText(); @@ -65,6 +70,14 @@ public: void finalizeImport(); private: + /** Reads a BIFF2-BIFF5 NOTE record. */ + void importNoteBiff2( BiffInputStream& rStrm ); + /** Reads a BIFF8 NOTE record. */ + void importNoteBiff8( BiffInputStream& rStrm ); + /** Reads a NOTESOUND record. */ + void importNoteSound( BiffInputStream& rStrm ); + +private: CommentModel maModel; }; diff --git a/oox/inc/oox/xls/condformatbuffer.hxx b/oox/inc/oox/xls/condformatbuffer.hxx index b8d3e0b17..54231e20e 100644 --- a/oox/inc/oox/xls/condformatbuffer.hxx +++ b/oox/inc/oox/xls/condformatbuffer.hxx @@ -44,9 +44,9 @@ namespace xls { /** Model for a single rule in a conditional formatting. */ struct CondFormatRuleModel { - typedef ::std::vector< TokensFormulaContext > ContextVector; + typedef ::std::vector< ApiTokenSequence > ApiTokenSequenceVector; - ContextVector maFormulas; /// Formulas for rule conditions. + ApiTokenSequenceVector maFormulas; /// Formulas for rule conditions. ::rtl::OUString maText; /// Text for 'contains' rules. sal_Int32 mnPriority; /// Priority of this rule. sal_Int32 mnType; /// Type of the rule. diff --git a/oox/inc/oox/xls/defnamesbuffer.hxx b/oox/inc/oox/xls/defnamesbuffer.hxx index aa4367efb..53a593481 100644 --- a/oox/inc/oox/xls/defnamesbuffer.hxx +++ b/oox/inc/oox/xls/defnamesbuffer.hxx @@ -37,7 +37,6 @@ namespace com { namespace sun { namespace star { namespace oox { namespace xls { -class FormulaContext; class BiffInputStreamPos; // ============================================================================ @@ -91,15 +90,15 @@ public: /** Returns the original name as imported from or exported to the file. */ const ::rtl::OUString& getUpcaseModelName() const; /** Returns an Any with a SingleReference or ComplexReference, or an empty Any. */ - ::com::sun::star::uno::Any getReference( const ::com::sun::star::table::CellAddress& rBaseAddress ) const; + ::com::sun::star::uno::Any getReference( const ::com::sun::star::table::CellAddress& rBaseAddr ) const; protected: - /** Imports the OOXML formula string, using the passed formula context. */ - void importOoxFormula( FormulaContext& rContext, sal_Int16 nBaseSheet ); - /** Imports the BIFF12 formula, using the passed formula context. */ - void importBiff12Formula( FormulaContext& rContext, sal_Int16 nBaseSheet, SequenceInputStream& rStrm ); - /** Imports the BIFF formula, using the passed formula context. */ - void importBiffFormula( FormulaContext& rContext, sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize = 0 ); + /** Converts the OOXML formula string stored in the own model. */ + ApiTokenSequence importOoxFormula( sal_Int16 nBaseSheet ); + /** Imports the BIFF12 formula from the passed stream. */ + ApiTokenSequence importBiff12Formula( sal_Int16 nBaseSheet, SequenceInputStream& rStrm ); + /** Imports the BIFF formula from the passed stream. */ + ApiTokenSequence importBiffFormula( sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize = 0 ); /** Tries to convert the passed token sequence to a SingleReference or ComplexReference. */ void extractReference( const ApiTokenSequence& rTokens ); @@ -151,10 +150,10 @@ public: bool getAbsoluteRange( ::com::sun::star::table::CellRangeAddress& orRange ) const; private: - /** Imports the OOXML or BIFF12 formula, using the passed formula context. */ - void implImportOoxFormula( FormulaContext& rContext ); - /** Imports the BIFF formula, using the passed formula context. */ - void implImportBiffFormula( FormulaContext& rContext ); + /** Imports the OOXML or BIFF12 definition of the name. */ + void implImportOoxFormula(); + /** Imports the BIFF definition of the name. */ + void implImportBiffFormula(); private: typedef ::std::auto_ptr< StreamDataSequence > StreamDataSeqPtr; diff --git a/oox/inc/oox/xls/drawingbase.hxx b/oox/inc/oox/xls/drawingbase.hxx new file mode 100755 index 000000000..148d3f12d --- /dev/null +++ b/oox/inc/oox/xls/drawingbase.hxx @@ -0,0 +1,147 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef OOX_XLS_DRAWINGBASE_HXX +#define OOX_XLS_DRAWINGBASE_HXX + +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/xls/worksheethelper.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +/** Absolute position in a spreadsheet (in EMUs) independent from cells. */ +struct AnchorPointModel : public ::oox::drawingml::EmuPoint +{ + inline explicit AnchorPointModel() : ::oox::drawingml::EmuPoint( -1, -1 ) {} + inline bool isValid() const { return (X >= 0) && (Y >= 0); } +}; + +// ---------------------------------------------------------------------------- + +/** Absolute size in a spreadsheet (in EMUs). */ +struct AnchorSizeModel : public ::oox::drawingml::EmuSize +{ + inline explicit AnchorSizeModel() : ::oox::drawingml::EmuSize( -1, -1 ) {} + inline bool isValid() const { return (Width >= 0) && (Height >= 0); } +}; + +// ---------------------------------------------------------------------------- + +/** Position in spreadsheet (cell position and offset inside cell). */ +struct CellAnchorModel +{ + sal_Int32 mnCol; /// Column index. + sal_Int32 mnRow; /// Row index. + sal_Int64 mnColOffset; /// X offset inside the column. + sal_Int64 mnRowOffset; /// Y offset inside the row. + + explicit CellAnchorModel(); + inline bool isValid() const { return (mnCol >= 0) && (mnRow >= 0); } +}; + +// ---------------------------------------------------------------------------- + +/** Application-specific client data of a shape. */ +struct AnchorClientDataModel +{ + bool mbLocksWithSheet; + bool mbPrintsWithSheet; + + explicit AnchorClientDataModel(); +}; + +// ============================================================================ + +/** Contains the position of a shape in the spreadsheet. Supports different + shape anchor modes (absolute, one-cell, two-cell). */ +class ShapeAnchor : public WorksheetHelper +{ +public: + explicit ShapeAnchor( const WorksheetHelper& rHelper ); + + /** Imports the shape anchor (one of the elements xdr:absoluteAnchor, xdr:oneCellAnchor, xdr:twoCellAnchor). */ + void importAnchor( sal_Int32 nElement, const AttributeList& rAttribs ); + /** Imports the absolute anchor position from the xdr:pos element. */ + void importPos( const AttributeList& rAttribs ); + /** Imports the absolute anchor size from the xdr:ext element. */ + void importExt( const AttributeList& rAttribs ); + /** Imports the shape client data from the xdr:clientData element. */ + void importClientData( const AttributeList& rAttribs ); + /** Sets an attribute of the cell-dependent anchor position from xdr:from and xdr:to elements. */ + void setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const ::rtl::OUString& rValue ); + /** Imports the client anchor settings from a VML element. */ + void importVmlAnchor( const ::rtl::OUString& rAnchor ); + /** Imports the client anchor settings from a BIFF or DFF stream. */ + void importBiffAnchor( BinaryInputStream& rStrm ); + + /** Calculates the resulting shape anchor in EMUs. */ + ::oox::drawingml::EmuRectangle calcAnchorRectEmu( + const ::com::sun::star::awt::Size& rPageSizeHmm ) const; + /** Calculates the resulting shape anchor in 1/100 mm. */ + ::com::sun::star::awt::Rectangle calcAnchorRectHmm( + const ::com::sun::star::awt::Size& rPageSizeHmm ) const; + +private: + /** Converts the passed anchor to an absolute position in EMUs. */ + ::oox::drawingml::EmuPoint calcCellAnchorEmu( const CellAnchorModel& rModel ) const; + +private: + enum AnchorType + { + ANCHOR_INVALID, /// Anchor type is unknown. + ANCHOR_ABSOLUTE, /// Absolute anchor (top-left corner and size in absolute units). + ANCHOR_ONECELL, /// One-cell anchor (top-left corner at cell, size in absolute units). + ANCHOR_TWOCELL /// Two-cell anchor (top-left and bottom-right corner at cell). + }; + + /** Specifies how cell positions from CellAnchorModel have to be processed. */ + enum CellAnchorType + { + CELLANCHOR_EMU, /// Offsets are given in EMUs. + CELLANCHOR_PIXEL, /// Offsets are given in screen pixels. + CELLANCHOR_COLROW /// Offsets are given in fractions of column width or row height. + }; + + AnchorType meAnchorType; /// Type of this shape anchor. + CellAnchorType meCellAnchorType; /// Type of the cell anchor models. + AnchorPointModel maPos; /// Top-left position, if anchor is of type absolute. + AnchorSizeModel maSize; /// Anchor size, if anchor is not of type two-cell. + CellAnchorModel maFrom; /// Top-left position, if anchor is not of type absolute. + CellAnchorModel maTo; /// Bottom-right position, if anchor is of type two-cell. + AnchorClientDataModel maClientData; /// Shape client data. + sal_Int32 mnEditAs; /// Anchor mode as shown in the UI. +}; + +// ============================================================================ + +} // namespace xls +} // namespace oox + +#endif diff --git a/oox/inc/oox/xls/drawingfragment.hxx b/oox/inc/oox/xls/drawingfragment.hxx index 15d77d0f9..f1ad1feec 100644 --- a/oox/inc/oox/xls/drawingfragment.hxx +++ b/oox/inc/oox/xls/drawingfragment.hxx @@ -37,6 +37,7 @@ #include "oox/vml/vmldrawing.hxx" #include "oox/vml/vmldrawingfragment.hxx" #include "oox/vml/vmltextbox.hxx" +#include "oox/xls/drawingbase.hxx" #include "oox/xls/excelhandlers.hxx" namespace oox { namespace ole { @@ -51,98 +52,6 @@ namespace xls { // DrawingML // ============================================================================ -/** Absolute position in spreadsheet (in EMUs) independent from cells. */ -struct AnchorPosModel : public ::oox::drawingml::EmuPoint -{ - inline explicit AnchorPosModel() : ::oox::drawingml::EmuPoint( -1, -1 ) {} - inline bool isValid() const { return (X >= 0) && (Y >= 0); } -}; - -// ---------------------------------------------------------------------------- - -/** Absolute size in spreadsheet (in EMUs). */ -struct AnchorSizeModel : public ::oox::drawingml::EmuSize -{ - inline explicit AnchorSizeModel() : ::oox::drawingml::EmuSize( -1, -1 ) {} - inline bool isValid() const { return (Width >= 0) && (Height >= 0); } -}; - -// ---------------------------------------------------------------------------- - -/** Position in spreadsheet (cell position and offset inside cell in EMUs). */ -struct AnchorCellModel -{ - sal_Int32 mnCol; /// Column index. - sal_Int32 mnRow; /// Row index. - sal_Int64 mnColOffset; /// X offset in column mnCol (EMUs). - sal_Int64 mnRowOffset; /// Y offset in row mnRow (EMUs). - - explicit AnchorCellModel(); - inline bool isValid() const { return (mnCol >= 0) && (mnRow >= 0); } -}; - -// ---------------------------------------------------------------------------- - -/** Application-specific client data of a shape. */ -struct AnchorClientDataModel -{ - bool mbLocksWithSheet; - bool mbPrintsWithSheet; - - explicit AnchorClientDataModel(); -}; - -// ============================================================================ - -/** Contains the position of a shape in the spreadsheet. Supports different - shape anchor modes (absolute, one-cell, two-cell). */ -class ShapeAnchor : public WorksheetHelper -{ -public: - explicit ShapeAnchor( const WorksheetHelper& rHelper ); - - /** Imports the shape anchor (one of the elements xdr:absoluteAnchor, xdr:oneCellAnchor, xdr:twoCellAnchor). */ - void importAnchor( sal_Int32 nElement, const AttributeList& rAttribs ); - /** Imports the absolute anchor position from the xdr:pos element. */ - void importPos( const AttributeList& rAttribs ); - /** Imports the absolute anchor size from the xdr:ext element. */ - void importExt( const AttributeList& rAttribs ); - /** Imports the shape client data from the xdr:clientData element. */ - void importClientData( const AttributeList& rAttribs ); - /** Sets an attribute of the cell-dependent anchor position from xdr:from and xdr:to elements. */ - void setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const ::rtl::OUString& rValue ); - /** Imports and converts the VML specific client anchor. */ - void importVmlAnchor( const ::rtl::OUString& rAnchor ); - - /** Returns true, if the anchor contains valid position and size settings. */ - bool isValidAnchor() const; - - /** Calculates the resulting shape anchor in 1/100 mm. */ - ::com::sun::star::awt::Rectangle - calcApiLocation( - const ::com::sun::star::awt::Size& rApiSheetSize, - const AnchorSizeModel& rEmuSheetSize ) const; - - /** Calculates the resulting shape anchor in EMUs. */ - ::com::sun::star::awt::Rectangle - calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) const; - -private: - enum AnchorType { ANCHOR_ABSOLUTE, ANCHOR_ONECELL, ANCHOR_TWOCELL, ANCHOR_VML, ANCHOR_INVALID }; - - AnchorType meType; /// Type of this shape anchor. - AnchorPosModel maPos; /// Top-left position, if anchor is of type absolute. - AnchorSizeModel maSize; /// Anchor size, if anchor is not of type two-cell. - AnchorCellModel maFrom; /// Top-left position, if anchor is not of type absolute. - AnchorCellModel maTo; /// Bottom-right position, if anchor is of type two-cell. - AnchorClientDataModel maClientData; /// Shape client data. - sal_Int32 mnEditAs; /// Anchor mode as shown in the UI. -}; - -typedef ::boost::shared_ptr< ShapeAnchor > ShapeAnchorRef; - -// ============================================================================ - class ShapeMacroAttacher : public ::oox::ole::VbaMacroAttacherBase { public: @@ -220,10 +129,10 @@ protected: virtual void onEndElement(); private: + typedef ::std::auto_ptr< ShapeAnchor > ShapeAnchorRef; + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > mxDrawPage; /// Drawing page of this sheet. - ::com::sun::star::awt::Size maApiSheetSize; /// Sheet size in 1/100 mm. - AnchorSizeModel maEmuSheetSize; /// Sheet size in EMU. ::oox::drawingml::ShapePtr mxShape; /// Current top-level shape. ShapeAnchorRef mxAnchor; /// Current anchor of top-level shape. }; diff --git a/oox/inc/oox/xls/drawingmanager.hxx b/oox/inc/oox/xls/drawingmanager.hxx new file mode 100755 index 000000000..38b1bda38 --- /dev/null +++ b/oox/inc/oox/xls/drawingmanager.hxx @@ -0,0 +1,521 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef OOX_XLS_DRAWINGMANAGER_HXX +#define OOX_XLS_DRAWINGMANAGER_HXX + +#include "oox/xls/drawingbase.hxx" + +namespace com { namespace sun { namespace star { + namespace drawing { class XDrawPage; } + namespace drawing { class XShape; } + namespace drawing { class XShapes; } +} } } + +namespace oox { namespace drawingml { class ShapePropertyMap; } } + +namespace oox { +namespace xls { + +// ============================================================================ + +const sal_uInt16 BIFF_OBJ_INVALID_ID = 0; + +// ============================================================================ +// Model structures for BIFF OBJ record data +// ============================================================================ + +/** This structure contains line formatting attributes from an OBJ record. */ +struct BiffObjLineModel +{ + sal_uInt8 mnColorIdx; /// Index into color palette. + sal_uInt8 mnStyle; /// Line dash style. + sal_uInt8 mnWidth; /// Line width. + bool mbAuto; /// True = automatic line format. + + explicit BiffObjLineModel(); + + /** Returns true, if the line formatting is visible (automatic or explicit). */ + bool isVisible() const; +}; + +// ============================================================================ + +/** This structure contains fill formatting attributes from an OBJ record. */ +struct BiffObjFillModel +{ + sal_uInt8 mnBackColorIdx; /// Index to color palette for background color. + sal_uInt8 mnPattColorIdx; /// Index to color palette for pattern foreground color. + sal_uInt8 mnPattern; /// Fill pattern. + bool mbAuto; /// True = automatic fill format. + + explicit BiffObjFillModel(); + + /** Returns true, if the fill formatting is visible (automatic or explicit). */ + bool isFilled() const; +}; + +// ============================================================================ + +/** This structure contains text formatting attributes from an OBJ record. */ +struct BiffObjTextModel +{ + sal_uInt16 mnTextLen; /// Length of the text (characters). + sal_uInt16 mnFormatSize; /// Size of the formatting array (bytes). + sal_uInt16 mnLinkSize; /// Size of the linked text formula (bytes). + sal_uInt16 mnDefFontId; /// Font index for default font formatting. + sal_uInt16 mnFlags; /// Additional flags. + sal_uInt16 mnOrientation; /// Text orientation. + sal_uInt16 mnButtonFlags; /// Additional flags for push buttons. + sal_uInt16 mnShortcut; /// Shortcut character. + sal_uInt16 mnShortcutEA; /// East-asian shortcut character. + + explicit BiffObjTextModel(); + + /** Reads text data from a BIFF3/BIFF4 OBJ record. */ + void readObj3( BiffInputStream& rStrm ); + /** Reads text data from a BIFF5 OBJ record. */ + void readObj5( BiffInputStream& rStrm ); + /** Reads text data from a BIFF8 TXO record. */ + void readTxo8( BiffInputStream& rStrm ); + + /** Returns the horizontal alignment of the text. */ + sal_uInt8 getHorAlign() const; + /** Returns the vertical alignment of the text. */ + sal_uInt8 getVerAlign() const; +}; + +// ============================================================================ +// BIFF drawing objects +// ============================================================================ + +class BiffDrawingBase; +class BiffDrawingObjectBase; +typedef ::boost::shared_ptr< BiffDrawingObjectBase > BiffDrawingObjectRef; + +// ---------------------------------------------------------------------------- + +class BiffDrawingObjectContainer +{ +public: + explicit BiffDrawingObjectContainer(); + + /** Returns true, if the object list is empty. */ + inline bool empty() const { return maObjects.empty(); } + + /** Appends the passed object to the list of objects. */ + void append( const BiffDrawingObjectRef& rxDrawingObj ); + /** Tries to insert the passed object into the last group or appends it. */ + void insertGrouped( const BiffDrawingObjectRef& rxDrawingObj ); + + /** Creates and inserts all UNO shapes into the passed shape container. */ + void convertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle* pParentRect = 0 ) const; + +private: + typedef RefVector< BiffDrawingObjectBase > BiffDrawingObjectVector; + BiffDrawingObjectVector maObjects; +}; + +// ============================================================================ + +/** Base class for all BIFF drawing objects (OBJ records). */ +class BiffDrawingObjectBase : public WorksheetHelper +{ +public: + explicit BiffDrawingObjectBase( const WorksheetHelper& rHelper ); + virtual ~BiffDrawingObjectBase(); + + /** Reads the BIFF3 OBJ record, returns a new drawing object. */ + static BiffDrawingObjectRef importObjBiff3( const WorksheetHelper& rHelper, BiffInputStream& rStrm ); + /** Reads the BIFF4 OBJ record, returns a new drawing object. */ + static BiffDrawingObjectRef importObjBiff4( const WorksheetHelper& rHelper, BiffInputStream& rStrm ); + /** Reads the BIFF5 OBJ record, returns a new drawing object. */ + static BiffDrawingObjectRef importObjBiff5( const WorksheetHelper& rHelper, BiffInputStream& rStrm ); + /** Reads the BIFF8 OBJ record, returns a new drawing object. */ + static BiffDrawingObjectRef importObjBiff8( const WorksheetHelper& rHelper, BiffInputStream& rStrm ); + + /** Sets whether this is an area object (then its width and height must be greater than 0). */ + inline void setAreaObj( bool bAreaObj ) { mbAreaObj = bAreaObj; } + /** If set to true, the object supports a simple on-click macro and/or hyperlink. */ + inline void setSimpleMacro( bool bMacro ) { mbSimpleMacro = bMacro; } + + /** If set to false, the UNO shape will not be created, processed, or inserted into the draw page. */ + inline void setProcessShape( bool bProcess ) { mbProcessShape = bProcess; } + /** If set to false, the UNO shape will be created or processed, but not be inserted into the draw page. */ + inline void setInsertShape( bool bInsert ) { mbInsertShape = bInsert; } + /** If set to true, a new custom UNO shape will be created while in DFF import (BIFF8 only). */ + inline void setCustomDffObj( bool bCustom ) { mbCustomDff = bCustom; } + + /** Returns the object identifier from the OBJ record. */ + inline sal_uInt16 getObjId() const { return mnObjId; } + /** Returns the object type from the OBJ record. */ + inline sal_uInt16 getObjType() const { return mnObjType; } + + /** Returns true, if the object is hidden. */ + inline bool isHidden() const { return mbHidden; } + /** Returns true, if the object is visible. */ + inline bool isVisible() const { return mbVisible; } + /** Returns true, if the object is printable. */ + inline bool isPrintable() const { return mbPrintable; } + + /** Creates the UNO shape and inserts it into the passed shape container. */ + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + convertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle* pParentRect = 0 ) const; + +protected: + /** Reads the object name in a BIFF5 OBJ record. */ + void readNameBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen ); + /** Reads the macro link in a BIFF3 OBJ record. */ + void readMacroBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the macro link in a BIFF4 OBJ record. */ + void readMacroBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the macro link in a BIFF5 OBJ record. */ + void readMacroBiff5( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the ftMacro sub structure in an OBJ record. */ + void readMacroBiff8( BiffInputStream& rStrm ); + + /** Converts the passed line formatting to the passed property map. */ + void convertLineProperties( ::oox::drawingml::ShapePropertyMap& rPropMap, const BiffObjLineModel& rLineModel, sal_uInt16 nArrows = 0 ) const; + /** Converts the passed fill formatting to the passed property map. */ + void convertFillProperties( ::oox::drawingml::ShapePropertyMap& rPropMap, const BiffObjFillModel& rFillModel ) const; + /** Converts the passed frame flags to the passed property map. */ + void convertFrameProperties( ::oox::drawingml::ShapePropertyMap& rPropMap, sal_uInt16 nFrameFlags ) const; + + /** Derived classes read the contents of the a BIFF3 OBJ record from the passed stream. */ + virtual void implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Derived classes read the contents of the a BIFF4 OBJ record from the passed stream. */ + virtual void implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Derived classes read the contents of the a BIFF5 OBJ record from the passed stream. */ + virtual void implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ); + /** Derived classes read the contents of the specified subrecord of a BIFF8 OBJ record from stream. */ + virtual void implReadObjBiff8SubRec( BiffInputStream& rStrm, sal_uInt16 nSubRecId, sal_uInt16 nSubRecSize ); + + /** Derived classes create the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const = 0; + +private: + /** Reads the contents of a BIFF3 OBJ record. */ + void importObjBiff3( BiffInputStream& rStrm ); + /** Reads the contents of a BIFF4 OBJ record. */ + void importObjBiff4( BiffInputStream& rStrm ); + /** Reads the contents of a BIFF5 OBJ record. */ + void importObjBiff5( BiffInputStream& rStrm ); + /** Reads the contents of a BIFF8 OBJ record. */ + void importObjBiff8( BiffInputStream& rStrm ); + +private: + ShapeAnchor maAnchor; /// Position of the drawing object. + ::rtl::OUString maObjName; /// Name of the object. + ::rtl::OUString maMacroName; /// Name of an attached macro. + ::rtl::OUString maHyperlink; /// On-click hyperlink URL. + sal_uInt32 mnDffShapeId; /// Shape identifier from DFF stream (BIFF8 only). + sal_uInt32 mnDffFlags; /// Shape flags from DFF stream. + sal_uInt16 mnObjId; /// The object identifier (unique per drawing). + sal_uInt16 mnObjType; /// The object type from OBJ record. + bool mbHasAnchor; /// True = anchor has been initialized. + bool mbHidden; /// True = object is hidden. + bool mbVisible; /// True = object is visible (form controls). + bool mbPrintable; /// True = object is printable. + bool mbAreaObj; /// True = width and height must be greater than 0. + bool mbAutoMargin; /// True = set automatic text margin. + bool mbSimpleMacro; /// True = create simple macro link and hyperlink. + bool mbProcessShape; /// True = object is valid, do processing and insertion. + bool mbInsertShape; /// True = insert the UNO shape into the draw page. + bool mbCustomDff; /// True = recreate UNO shape in DFF import (BIFF8 only). +}; + +// ============================================================================ + +/** A placeholder object for unknown/unsupported object types. */ +class BiffPlaceholderObject : public BiffDrawingObjectBase +{ +public: + explicit BiffPlaceholderObject( const WorksheetHelper& rHelper ); + +protected: + /** Creates the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; +}; + +// ============================================================================ + +/** A group object that is able to contain other child objects. */ +class BiffGroupObject : public BiffDrawingObjectBase +{ +public: + explicit BiffGroupObject( const WorksheetHelper& rHelper ); + + /** Tries to insert the passed drawing object into this or a nested group. */ + bool tryInsert( const BiffDrawingObjectRef& rxDrawingObj ); + +protected: + /** Reads the contents of the a BIFF3 OBJ record from the passed stream. */ + virtual void implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF4 OBJ record from the passed stream. */ + virtual void implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF5 OBJ record from the passed stream. */ + virtual void implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ); + + /** Creates the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; + +protected: + BiffDrawingObjectContainer maChildren; /// All child objects contained in this group object. + sal_uInt16 mnFirstUngrouped; /// Object identfier of first object not grouped into this group. +}; + +// ============================================================================ + +/** A simple line object. */ +class BiffLineObject : public BiffDrawingObjectBase +{ +public: + explicit BiffLineObject( const WorksheetHelper& rHelper ); + +protected: + /** Reads the contents of the a BIFF3 OBJ record from the passed stream. */ + virtual void implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF4 OBJ record from the passed stream. */ + virtual void implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF5 OBJ record from the passed stream. */ + virtual void implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ); + + /** Creates the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; + +protected: + BiffObjLineModel maLineModel; /// Line formatting. + sal_uInt16 mnArrows; /// Line arrows. + sal_uInt8 mnStartPoint; /// Starting point. +}; + +// ============================================================================ + +/** A simple rectangle object (used as base class for oval objects). */ +class BiffRectObject : public BiffDrawingObjectBase +{ +public: + explicit BiffRectObject( const WorksheetHelper& rHelper ); + +protected: + /** Reads the fill model, the line model, and frame flags. */ + void readFrameData( BiffInputStream& rStrm ); + + /** Converts fill formatting, line formatting, and frame style. */ + void convertRectProperties( ::oox::drawingml::ShapePropertyMap& rPropMap ) const; + + /** Reads the contents of the a BIFF3 OBJ record from the passed stream. */ + virtual void implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF4 OBJ record from the passed stream. */ + virtual void implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF5 OBJ record from the passed stream. */ + virtual void implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ); + + /** Creates the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; + +protected: + BiffObjFillModel maFillModel; /// Fill formatting. + BiffObjLineModel maLineModel; /// Line formatting. + sal_uInt16 mnFrameFlags; /// Additional flags. +}; + +// ============================================================================ + +/** A simple oval object. */ +class BiffOvalObject : public BiffRectObject +{ +public: + explicit BiffOvalObject( const WorksheetHelper& rHelper ); + +protected: + /** Creates the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; +}; + +// ============================================================================ + +/** A simple arc object. */ +class BiffArcObject : public BiffDrawingObjectBase +{ +public: + explicit BiffArcObject( const WorksheetHelper& rHelper ); + +protected: + /** Reads the contents of the a BIFF3 OBJ record from the passed stream. */ + virtual void implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF4 OBJ record from the passed stream. */ + virtual void implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF5 OBJ record from the passed stream. */ + virtual void implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ); + + /** Creates the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; + +protected: + BiffObjFillModel maFillModel; /// Fill formatting. + BiffObjLineModel maLineModel; /// Line formatting. + sal_uInt8 mnQuadrant; /// Visible quadrant of the circle. +}; + +// ============================================================================ + +/** A simple polygon object. */ +class BiffPolygonObject : public BiffRectObject +{ +public: + explicit BiffPolygonObject( const WorksheetHelper& rHelper ); + +protected: + /** Reads the contents of the a BIFF4 OBJ record from the passed stream. */ + virtual void implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ); + /** Reads the contents of the a BIFF5 OBJ record from the passed stream. */ + virtual void implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ); + + /** Creates the corresponding XShape and insert it into the passed container. */ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + implConvertAndInsert( BiffDrawingBase& rDrawing, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; + +private: + /** Reads the COORDLIST record following the OBJ record. */ + void importCoordList( BiffInputStream& rStrm ); + +protected: + typedef ::std::vector< ::com::sun::star::awt::Point > PointVector; + PointVector maCoords; /// Coordinates relative to bounding rectangle. + sal_uInt16 mnPolyFlags; /// Additional flags. + sal_uInt16 mnPointCount; /// Polygon point count. +}; + +// ============================================================================ +// BIFF drawing page +// ============================================================================ + +/** Base class for a container for all objects on a drawing page (in a + spreadsheet or in an embedded chart object). + + For BIFF import, it is needed to load all drawing objects before converting + them to UNO shapes. There might be some dummy drawing objects (e.g. the + dropdown buttons of autofilters) which have to be skipped. The information, + that a drawing object is a dummy object, may be located after the drawing + objects themselves. + + The BIFF8 format stores drawing objects in the DFF stream (stored + fragmented in MSODRAWING records), and in the OBJ records. The DFF stream + fragments are collected in a single stream, and the complete stream will be + processed afterwards. + */ +class BiffDrawingBase : public WorksheetHelper +{ +public: + explicit BiffDrawingBase( const WorksheetHelper& rHelper, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& rxDrawPage ); + + /** Imports a plain OBJ record (without leading DFF data). */ + void importObj( BiffInputStream& rStrm ); + /** Sets the object with the passed identifier to be skipped on import. */ + void setSkipObj( sal_uInt16 nObjId ); + + /** Final processing after import of the all drawing objects. */ + void finalizeImport(); + + /** Creates a new UNO shape object, inserts it into the passed UNO shape + container, and sets the shape position and size. */ + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + createAndInsertXShape( + const ::rtl::OUString& rService, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes, + const ::com::sun::star::awt::Rectangle& rShapeRect ) const; + + /** Derived classes may want to know that a shape has been inserted. Will + be called from the convertAndInsert() implementation. */ + virtual void notifyShapeInserted( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rxShape, + const ::com::sun::star::awt::Rectangle& rShapeRect ) = 0; + +protected: + /** Appends a new drawing object to the list of raw objects (without DFF data). */ + void appendRawObject( const BiffDrawingObjectRef& rxDrawingObj ); + +private: + typedef RefMap< sal_uInt16, BiffDrawingObjectBase > BiffDrawingObjectMapById; + typedef ::std::vector< sal_uInt16 > BiffObjIdVector; + + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > + mxDrawPage; /// UNO draw page used to insert the shapes. + BiffDrawingObjectContainer maRawObjs; /// Drawing objects without DFF data. + BiffDrawingObjectMapById maObjMapId; /// Maps drawing objects by their object identifiers. + BiffObjIdVector maSkipObjs; /// Identifiers of all objects to be skipped. +}; + +// ---------------------------------------------------------------------------- + +/** Drawing manager of a single sheet. */ +class BiffSheetDrawing : public BiffDrawingBase +{ +public: + explicit BiffSheetDrawing( const WorksheetHelper& rHelper ); + + /** Called when a new UNO shape has been inserted into the draw page. */ + virtual void notifyShapeInserted( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rxShape, + const ::com::sun::star::awt::Rectangle& rShapeRect ); +}; + +// ============================================================================ + +} // namespace xls +} // namespace oox + +#endif diff --git a/oox/inc/oox/xls/excelfilter.hxx b/oox/inc/oox/xls/excelfilter.hxx index a5176dd9e..73fe7aa2f 100644 --- a/oox/inc/oox/xls/excelfilter.hxx +++ b/oox/inc/oox/xls/excelfilter.hxx @@ -34,23 +34,23 @@ namespace oox { namespace xls { -class WorkbookData; +class WorkbookGlobals; // ============================================================================ class ExcelFilterBase { public: - void registerWorkbookData( WorkbookData& rData ); - WorkbookData& getWorkbookData() const; - void unregisterWorkbookData(); + void registerWorkbookGlobals( WorkbookGlobals& rBookGlob ); + WorkbookGlobals& getWorkbookGlobals() const; + void unregisterWorkbookGlobals(); protected: explicit ExcelFilterBase(); virtual ~ExcelFilterBase(); private: - WorkbookData* mpData; + WorkbookGlobals* mpBookGlob; }; // ============================================================================ diff --git a/oox/inc/oox/xls/excelhandlers.hxx b/oox/inc/oox/xls/excelhandlers.hxx index 4899b1681..2f9eeec8a 100644 --- a/oox/inc/oox/xls/excelhandlers.hxx +++ b/oox/inc/oox/xls/excelhandlers.hxx @@ -45,55 +45,24 @@ class WorkbookContextBase : public ::oox::core::ContextHandler2, public Workbook { public: template< typename ParentType > - explicit WorkbookContextBase( ParentType& rParent ); + inline explicit WorkbookContextBase( ParentType& rParent ) : + ::oox::core::ContextHandler2( rParent ), WorkbookHelper( rParent ) {} }; -// ---------------------------------------------------------------------------- - -template< typename ParentType > -WorkbookContextBase::WorkbookContextBase( ParentType& rParent ) : - ::oox::core::ContextHandler2( rParent ), - WorkbookHelper( rParent ) -{ -} - // ============================================================================ /** Context handler derived from the WorksheetHelper helper class. Used to import contexts in sheet fragments. */ -class WorksheetContextBase : public ::oox::core::ContextHandler2, public WorksheetHelperRoot +class WorksheetContextBase : public ::oox::core::ContextHandler2, public WorksheetHelper { public: template< typename ParentType > - explicit WorksheetContextBase( - ParentType& rParent, - const ISegmentProgressBarRef& rxProgressBar, - WorksheetType eSheetType, - sal_Int16 nSheet ); - - template< typename ParentType > - explicit WorksheetContextBase( ParentType& rParent ); + inline explicit WorksheetContextBase( ParentType& rParent ) : + ::oox::core::ContextHandler2( rParent ), WorksheetHelper( rParent ) {} }; -// ---------------------------------------------------------------------------- - -template< typename ParentType > -WorksheetContextBase::WorksheetContextBase( ParentType& rParent, - const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : - ::oox::core::ContextHandler2( rParent ), - WorksheetHelperRoot( rParent, rxProgressBar, eSheetType, nSheet ) -{ -} - -template< typename ParentType > -WorksheetContextBase::WorksheetContextBase( ParentType& rParent ) : - ::oox::core::ContextHandler2( rParent ), - WorksheetHelperRoot( rParent ) -{ -} - // ============================================================================ /** Fragment handler derived from the WorkbookHelper helper class. @@ -114,17 +83,10 @@ public: Used to import sheet fragments. */ -class WorksheetFragmentBase : public ::oox::core::FragmentHandler2, public WorksheetHelperRoot +class WorksheetFragmentBase : public ::oox::core::FragmentHandler2, public WorksheetHelper { public: explicit WorksheetFragmentBase( - const WorkbookHelper& rHelper, - const ::rtl::OUString& rFragmentPath, - const ISegmentProgressBarRef& rxProgressBar, - WorksheetType eSheetType, - sal_Int16 nSheet ); - - explicit WorksheetFragmentBase( const WorksheetHelper& rHelper, const ::rtl::OUString& rFragmentPath ); }; @@ -164,15 +126,9 @@ protected: Used to import contexts in sheet fragments. */ -class BiffWorksheetContextBase : public BiffContextHandler, public WorksheetHelperRoot +class BiffWorksheetContextBase : public BiffContextHandler, public WorksheetHelper { protected: - explicit BiffWorksheetContextBase( - const WorkbookHelper& rHelper, - const ISegmentProgressBarRef& rxProgressBar, - WorksheetType eSheetType, - sal_Int16 nSheet ); - explicit BiffWorksheetContextBase( const WorksheetHelper& rHelper ); }; @@ -220,17 +176,6 @@ protected: */ BiffFragmentType startFragment( BiffType eBiff ); - /** Starts a new fragment at a specific position in the workbbok stream and - returns the fragment type. - - The passed record handle must specify the stream position of the BOF - record of the fragment substream. The function will try to start the - next record and read the contents of the BOF record, if extant. - - @return Fragment type according to the imported BOF record. - */ - BiffFragmentType startFragment( BiffType eBiff, sal_Int64 nRecHandle ); - /** Skips the current fragment up to its trailing EOF record. Skips all records until next EOF record. When this function returns, @@ -273,14 +218,12 @@ protected: Used to import sheet fragments. */ -class BiffWorksheetFragmentBase : public BiffFragmentHandler, public WorksheetHelperRoot +class BiffWorksheetFragmentBase : public BiffFragmentHandler, public WorksheetHelper { protected: explicit BiffWorksheetFragmentBase( - const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, - WorksheetType eSheetType, - sal_Int16 nSheet ); + const WorksheetHelper& rHelper, + const BiffWorkbookFragmentBase& rParent ); }; // ---------------------------------------------------------------------------- @@ -291,9 +234,8 @@ class BiffSkipWorksheetFragment : public BiffWorksheetFragmentBase { public: explicit BiffSkipWorksheetFragment( - const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, - sal_Int16 nSheet ); + const WorksheetHelper& rHelper, + const BiffWorkbookFragmentBase& rParent ); virtual bool importFragment(); }; diff --git a/oox/inc/oox/xls/formulabase.hxx b/oox/inc/oox/xls/formulabase.hxx index dbe388d17..f5862999b 100644 --- a/oox/inc/oox/xls/formulabase.hxx +++ b/oox/inc/oox/xls/formulabase.hxx @@ -28,6 +28,7 @@ #ifndef OOX_XLS_FORMULABASE_HXX #define OOX_XLS_FORMULABASE_HXX +#include <com/sun/star/beans/Pair.hpp> #include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp> #include <com/sun/star/sheet/FormulaToken.hpp> #include <com/sun/star/table/CellAddress.hpp> @@ -40,7 +41,6 @@ namespace com { namespace sun { namespace star { namespace sheet { class XFormulaOpCodeMapper; } namespace sheet { class XFormulaParser; } - namespace sheet { class XFormulaTokens; } } } } namespace oox { template< typename Type > class Matrix; } @@ -216,7 +216,20 @@ const sal_uInt16 BIFF_FUNC_CEILING = 288; /// Function identif const sal_uInt16 BIFF_FUNC_HYPERLINK = 359; /// Function identifier of the HYPERLINK function. const sal_uInt16 BIFF_FUNC_WEEKNUM = 465; /// Function identifier of the WEEKNUM function. -// reference helpers ========================================================== +// Formula type =============================================================== + +/** Enumerates all possible types of a formula. */ +enum FormulaType +{ + FORMULATYPE_CELL, /// Simple cell formula, or reference to a shared formula name. + FORMULATYPE_ARRAY, /// Array (matrix) formula. + FORMULATYPE_SHAREDFORMULA, /// Shared formula definition. + FORMULATYPE_CONDFORMAT, /// Condition of a conditional format rule. + FORMULATYPE_VALIDATION, /// Condition of a data validation. + FORMULATYPE_DEFINEDNAME /// Definition of a defined name. +}; + +// Reference helpers ========================================================== /** A 2D formula cell reference struct with relative flags. */ struct BinSingleRef2d @@ -250,11 +263,15 @@ struct BinComplexRef2d void readBiff8Data( BiffInputStream& rStrm, bool bRelativeAsOffset ); }; -// token vector, sequence ===================================================== +// Token vector, token sequence =============================================== typedef ::com::sun::star::sheet::FormulaToken ApiToken; typedef ::com::sun::star::uno::Sequence< ApiToken > ApiTokenSequence; +/** Contains the base address and type of a special token representing an array + formula or a shared formula (sal_False), or a table operation (sal_True). */ +typedef ::com::sun::star::beans::Pair< ::com::sun::star::table::CellAddress, sal_Bool > ApiSpecialTokenInfo; + /** A vector of formula tokens with additional convenience functions. */ class ApiTokenVector : public ::std::vector< ApiToken > { @@ -270,7 +287,7 @@ public: inline void append( sal_Int32 nOpCode, const Type& rData ) { append( nOpCode ) <<= rData; } }; -// token sequence iterator ==================================================== +// Token sequence iterator ==================================================== /** Token sequence iterator that is able to skip space tokens. */ class ApiTokenIterator @@ -297,7 +314,7 @@ private: const bool mbSkipSpaces; /// true = Skip whitespace tokens. }; -// list of API op-codes ======================================================= +// List of API op-codes ======================================================= /** Contains all API op-codes needed to build formulas with tokens. */ struct ApiOpCodes @@ -456,23 +473,23 @@ struct FunctionParamInfo bool mbValType; /// Data type (false = REFTYPE, true = VALTYPE). }; -// function data ============================================================== +// Function data ============================================================== /** This enumeration contains constants for all known external libraries containing supported sheet functions. */ enum FunctionLibraryType { - FUNCLIB_EUROTOOL, /// EuroTool add-in with EUROCONVERT function. - FUNCLIB_UNKNOWN /// Unknown library. + FUNCLIB_UNKNOWN = 0, /// Unknown library (must be zero). + FUNCLIB_EUROTOOL /// EuroTool add-in with EUROCONVERT function. }; // ---------------------------------------------------------------------------- /** Represents information for a spreadsheet function. - The member mpParamInfos points to an array of type information structures + The member mpParamInfos points to a C-array of type information structures for all parameters of the function. The last initialized structure - describing a regular parameter (member meValid == EXC_PARAMVALID_ALWAYS) in + describing a regular parameter (member meValid == FUNC_PARAM_REGULAR) in this array is used repeatedly for all following parameters supported by a function. */ @@ -490,7 +507,7 @@ struct FunctionInfo sal_uInt8 mnMaxParamCount; /// Maximum number of parameters. sal_uInt8 mnRetClass; /// BIFF token class of the return value. const FunctionParamInfo* mpParamInfos; /// Information about all parameters. - bool mbParamPairs; /// true = optional parameters are expected to appear in pairs. + bool mbParamPairs; /// True = optional parameters are expected to appear in pairs. bool mbVolatile; /// True = volatile function. bool mbExternal; /// True = external function in Calc. bool mbMacroFunc; /// True = macro sheet function or command. @@ -499,7 +516,7 @@ struct FunctionInfo typedef RefVector< FunctionInfo > FunctionInfoVector; -// function info parameter class iterator ===================================== +// Function info parameter class iterator ===================================== /** Iterator working on the mpParamInfos member of the FunctionInfo struct. @@ -525,7 +542,7 @@ private: bool mbParamPairs; }; -// base function provider ===================================================== +// Base function provider ===================================================== struct FunctionProviderImpl; @@ -566,7 +583,7 @@ private: FunctionProviderImplRef mxFuncImpl; /// Shared implementation between all copies of the provider. }; -// op-code and function provider ============================================== +// Op-code and function provider ============================================== struct OpCodeProviderImpl; @@ -577,7 +594,7 @@ class OpCodeProvider : public FunctionProvider // not derived from WorkbookHelpe { public: explicit OpCodeProvider( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxModelFactory, FilterType eFilter, BiffType eBiff, bool bImportFilter ); virtual ~OpCodeProvider(); @@ -604,7 +621,7 @@ class ApiParserWrapper : public OpCodeProvider { public: explicit ApiParserWrapper( - const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxFactory, + const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxModelFactory, const OpCodeProvider& rOpCodeProv ); /** Returns read/write access to the formula parser property set. */ @@ -621,74 +638,7 @@ private: PropertySet maParserProps; }; -// formula contexts =========================================================== - -class FormulaContext -{ -public: - inline void setBaseAddress( const ::com::sun::star::table::CellAddress& rBaseAddress ) - { maBaseAddress = rBaseAddress; } - - inline const ::com::sun::star::table::CellAddress& getBaseAddress() const { return maBaseAddress; } - inline bool isRelativeAsOffset() const { return mbRelativeAsOffset; } - inline bool is2dRefsAs3dRefs() const { return mb2dRefsAs3dRefs; } - inline bool isNulCharsAllowed() const { return mbAllowNulChars; } - - virtual void setTokens( const ApiTokenSequence& rTokens ) = 0; - virtual void setSharedFormula( const ::com::sun::star::table::CellAddress& rBaseAddr ); - -protected: - explicit FormulaContext( - bool bRelativeAsOffset, - bool b2dRefsAs3dRefs, - bool bAllowNulChars = false ); - virtual ~FormulaContext(); - -private: - ::com::sun::star::table::CellAddress maBaseAddress; - bool mbRelativeAsOffset; - bool mb2dRefsAs3dRefs; - bool mbAllowNulChars; -}; - -// ---------------------------------------------------------------------------- - -/** Stores the converted formula token sequence in a class member. */ -class TokensFormulaContext : public FormulaContext -{ -public: - explicit TokensFormulaContext( - bool bRelativeAsOffset, - bool b2dRefsAs3dRefs, - bool bAllowNulChars = false ); - - inline const ApiTokenSequence& getTokens() const { return maTokens; } - - virtual void setTokens( const ApiTokenSequence& rTokens ); - -private: - ApiTokenSequence maTokens; -}; - -// ---------------------------------------------------------------------------- - -/** Uses the com.sun.star.sheet.XFormulaTokens interface to set a token sequence. */ -class SimpleFormulaContext : public FormulaContext -{ -public: - explicit SimpleFormulaContext( - const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaTokens >& rxTokens, - bool bRelativeAsOffset, - bool b2dRefsAs3dRefs, - bool bAllowNulChars = false ); - - virtual void setTokens( const ApiTokenSequence& rTokens ); - -private: - ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaTokens > mxTokens; -}; - -// formula parser/printer base class for filters ============================== +// Formula parser/printer base class for filters ============================== /** Base class for import formula parsers and export formula compilers. */ class FormulaProcessorBase : public OpCodeProvider, protected ApiOpCodes, public WorkbookHelper @@ -896,6 +846,24 @@ public: ::rtl::OUString& orString, const ApiTokenSequence& rTokens ) const; + /** Tries to extract information about a special token used for array + formulas, shared formulas, or table operations. + + @param orTokenInfo (output parameter) The extracted information about + the token. Contains the base address and the token type (sal_False + for array or shared formulas, sal_True for table operations). + + @param rTokens The token sequence to be parsed. If it contains exactly + one OPCODE_BAD token with special token information, this + information will be extracted. + + @return True = token sequence is valid, output parameter orTokenInfo + contains the token information extracted from the token sequence. + */ + bool extractSpecialTokenInfo( + ApiSpecialTokenInfo& orTokenInfo, + const ApiTokenSequence& rTokens ) const; + /** Converts a single string with separators in the passed formula token sequence to a list of string tokens. diff --git a/oox/inc/oox/xls/formulaparser.hxx b/oox/inc/oox/xls/formulaparser.hxx index 5ac172634..751aed680 100644 --- a/oox/inc/oox/xls/formulaparser.hxx +++ b/oox/inc/oox/xls/formulaparser.hxx @@ -87,6 +87,7 @@ private: const ApiToken* getSingleToken( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; const ApiToken* skipParentheses( const ApiToken* pToken, const ApiToken* pTokenEnd ) const; const ApiToken* findParameters( ParameterPosVector& rParams, const ApiToken* pToken, const ApiToken* pTokenEnd ) const; + void appendEmptyParameter( const FunctionInfo& rFuncInfo, size_t nParam ); void appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ); void appendRequiredParameters( const FunctionInfo& rFuncInfo, size_t nParamCount ); @@ -113,38 +114,36 @@ public: virtual ~FormulaParser(); /** Converts an OOXML formula string. */ - void importFormula( - FormulaContext& rContext, + ApiTokenSequence importFormula( + const ::com::sun::star::table::CellAddress& rBaseAddr, const ::rtl::OUString& rFormulaString ) const; /** Imports and converts a BIFF12 token array from the passed stream. */ - void importFormula( - FormulaContext& rContext, + ApiTokenSequence importFormula( + const ::com::sun::star::table::CellAddress& rBaseAddr, + FormulaType eType, SequenceInputStream& rStrm ) const; /** Imports and converts a BIFF2-BIFF8 token array from the passed stream. @param pnFmlaSize Size of the token array. If null is passed, reads it from stream (1 byte in BIFF2, 2 bytes otherwise) first. */ - void importFormula( - FormulaContext& rContext, + ApiTokenSequence importFormula( + const ::com::sun::star::table::CellAddress& rBaseAddr, + FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize = 0 ) const; + /** Converts the passed Boolean value to a similar formula. */ + ApiTokenSequence convertBoolToFormula( bool bValue ) const; + /** Converts the passed BIFF error code to a similar formula. */ - void convertErrorToFormula( - FormulaContext& rContext, - sal_uInt8 nErrorCode ) const; + ApiTokenSequence convertErrorToFormula( sal_uInt8 nErrorCode ) const; /** Converts the passed token index of a defined name to a formula calling that name. */ - void convertNameToFormula( - FormulaContext& rContext, - sal_Int32 nTokenIndex ) const; + ApiTokenSequence convertNameToFormula( sal_Int32 nTokenIndex ) const; /** Converts the passed number into a HYPERLINK formula with the passed URL. */ - void convertNumberToHyperlink( - FormulaContext& rContext, - const ::rtl::OUString& rUrl, - double fValue ) const; + ApiTokenSequence convertNumberToHyperlink( const ::rtl::OUString& rUrl, double fValue ) const; /** Converts the passed XML formula to an OLE link target. */ ::rtl::OUString importOleTargetLink( const ::rtl::OUString& rFormulaString ); @@ -153,9 +152,7 @@ public: ::rtl::OUString importOleTargetLink( SequenceInputStream& rStrm ); /** Imports and converts an OLE link target from the passed stream. */ - ::rtl::OUString importOleTargetLink( - BiffInputStream& rStrm, - const sal_uInt16* pnFmlaSize = 0 ) const; + ::rtl::OUString importOleTargetLink( BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize = 0 ) const; /** Converts the passed formula to a macro name for a drawing shape. */ ::rtl::OUString importMacroName( const ::rtl::OUString& rFormulaString ); diff --git a/oox/inc/oox/xls/ooxformulaparser.hxx b/oox/inc/oox/xls/ooxformulaparser.hxx index 90dd072df..2ecd1795f 100644 --- a/oox/inc/oox/xls/ooxformulaparser.hxx +++ b/oox/inc/oox/xls/ooxformulaparser.hxx @@ -46,10 +46,10 @@ class OOXMLFormulaPrinterImpl; typedef ::cppu::WeakImplHelper3< ::com::sun::star::lang::XServiceInfo, ::com::sun::star::lang::XInitialization, - ::com::sun::star::sheet::XFilterFormulaParser > OOXMLFormulaParserBase; + ::com::sun::star::sheet::XFilterFormulaParser > OOXMLFormulaParser_BASE; /** OOXML formula parser/compiler service for usage in ODF filters. */ -class OOXMLFormulaParser : public OOXMLFormulaParserBase +class OOXMLFormulaParser : public OOXMLFormulaParser_BASE { public: explicit OOXMLFormulaParser(); diff --git a/oox/inc/oox/xls/pivotcachebuffer.hxx b/oox/inc/oox/xls/pivotcachebuffer.hxx index 894c851c6..10b582a67 100644 --- a/oox/inc/oox/xls/pivotcachebuffer.hxx +++ b/oox/inc/oox/xls/pivotcachebuffer.hxx @@ -31,6 +31,7 @@ #include <com/sun/star/table/CellAddress.hpp> #include <com/sun/star/table/CellRangeAddress.hpp> #include <com/sun/star/util/DateTime.hpp> +#include "oox/helper/containerhelper.hxx" #include "oox/helper/refvector.hxx" #include "oox/xls/workbookhelper.hxx" @@ -430,15 +431,15 @@ public: void writeSourceHeaderCells( WorksheetHelper& rSheetHelper ) const; /** Writes a source field item value into the passed sheet. */ void writeSourceDataCell( WorksheetHelper& rSheetHelper, - sal_Int32 nCol, sal_Int32 nRow, + sal_Int32 nColIdx, sal_Int32 nRowIdx, const PivotCacheItem& rItem ) const; /** Reads a PCRECORD record and writes all item values to the passed sheet. */ void importPCRecord( SequenceInputStream& rStrm, - WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const; + WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const; /** Reads a PCITEM_INDEXLIST record and writes all item values to the passed sheet. */ void importPCItemIndexList( BiffInputStream& rStrm, - WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const; + WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const; private: /** Reads the worksheet source range from the DCONREF record. */ @@ -456,6 +457,8 @@ private: void finalizeExternalSheetSource(); /** Creates a dummy sheet that will be filled with the pivot cache data. */ void prepareSourceDataSheet(); + /** Checks, if the row index has changed since last call, and initializes the sheet data buffer. */ + void updateSourceDataRow( WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const; private: typedef RefVector< PivotCacheField > PivotCacheFieldVector; @@ -467,7 +470,9 @@ private: PCDefinitionModel maDefModel; /// Global pivot cache settings. PCSourceModel maSourceModel; /// Pivot cache source settings. PCWorksheetSourceModel maSheetSrcModel; /// Sheet source data if cache type is sheet. + ValueRangeSet maColSpans; /// Column spans used by SheetDataBuffer for optimized cell import. ::rtl::OUString maTargetUrl; /// URL of an external source document. + mutable sal_Int32 mnCurrRow; /// Current row index in dummy sheet. bool mbValidSource; /// True = pivot cache is based on supported data source. bool mbDummySheet; /// True = pivot cache is based on a dummy sheet. }; diff --git a/oox/inc/oox/xls/pivotcachefragment.hxx b/oox/inc/oox/xls/pivotcachefragment.hxx index bf00fdecc..659197a7a 100644 --- a/oox/inc/oox/xls/pivotcachefragment.hxx +++ b/oox/inc/oox/xls/pivotcachefragment.hxx @@ -81,7 +81,7 @@ class PivotCacheRecordsFragment : public WorksheetFragmentBase { public: explicit PivotCacheRecordsFragment( - const WorkbookHelper& rHelper, + const WorksheetHelper& rHelper, const ::rtl::OUString& rFragmentPath, const PivotCache& rPivotCache ); @@ -97,8 +97,8 @@ private: private: const PivotCache& mrPivotCache; - sal_Int32 mnCol; - sal_Int32 mnRow; + sal_Int32 mnColIdx; /// Relative column index in source data. + sal_Int32 mnRowIdx; /// Relative row index in source data. bool mbInRecord; }; @@ -126,7 +126,7 @@ class BiffPivotCacheRecordsContext : public BiffWorksheetContextBase { public: explicit BiffPivotCacheRecordsContext( - const WorkbookHelper& rHelper, + const WorksheetHelper& rHelper, const PivotCache& rPivotCache ); /** Reads the current record from stream and tries to insert a cell into @@ -142,7 +142,7 @@ private: const PivotCache& mrPivotCache; ColumnIndexVector maUnsharedCols; /// Column indexes of all unshared cache fields. size_t mnColIdx; /// Current index into maUnsharedCols. - sal_Int32 mnRow; /// Current row in source data (0-based). + sal_Int32 mnRowIdx; /// Current row in source data (0-based). bool mbHasShared; /// True = pivot cache contains fields with shared items. bool mbInRow; /// True = a data row has been started. }; diff --git a/oox/inc/oox/xls/richstring.hxx b/oox/inc/oox/xls/richstring.hxx index 20ae39101..0564bca49 100644 --- a/oox/inc/oox/xls/richstring.hxx +++ b/oox/inc/oox/xls/richstring.hxx @@ -70,11 +70,13 @@ public: /** Returns the text data of this portion. */ inline const ::rtl::OUString& getText() const { return maText; } + /** Returns true, if the portion fontains font formatting. */ + inline bool hasFont() const { return mxFont.get() != 0; } - /** Converts the portion and appends it to the passed XText. */ + /** Converts the portion and replaces or appends to the passed XText. */ void convert( const ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >& rxText, - sal_Int32 nXfId ); + const Font* pFont, bool bReplace ); private: ::rtl::OUString maText; /// Portion text. @@ -246,21 +248,30 @@ public: /** Imports a Unicode rich-string from the passed record stream. */ void importString( SequenceInputStream& rStrm, bool bRich ); - /** Imports a byte string from the passed BIFF stream. */ - void importByteString( BiffInputStream& rStrm, rtl_TextEncoding eDefaultTextEnc, BiffStringFlags nFlags = BIFF_STR_DEFAULT ); - /** Imports a Unicode rich-string from the passed BIFF stream. */ + /** Imports nChars byte characters from the passed BIFF stream and appends a new text portion. */ + void importCharArray( BiffInputStream& rStrm, sal_uInt16 nChars, rtl_TextEncoding eTextEnc ); + /** Imports a byte string from the passed BIFF stream and appends new text portions. */ + void importByteString( BiffInputStream& rStrm, rtl_TextEncoding eTextEnc, BiffStringFlags nFlags = BIFF_STR_DEFAULT ); + /** Imports a Unicode rich-string from the passed BIFF stream and appends new text portions. */ void importUniString( BiffInputStream& rStrm, BiffStringFlags nFlags = BIFF_STR_DEFAULT ); /** Final processing after import of all strings. */ void finalizeImport(); - /** Returns the plain text concatenated from all string portions. */ - ::rtl::OUString getPlainText() const; - - /** Converts the string and writes it into the passed XText. */ + /** Tries to extract a plain string from this object. Returns the string, + if there is only one unformatted portion. */ + bool extractPlainString( + ::rtl::OUString& orString, + const Font* pFirstPortionFont = 0 ) const; + + /** Converts the string and writes it into the passed XText. + @param rxText The XText interface of the target object. + @param bReplaceOld True = replace old contents of the text object. + @param pFirstPortionFont Optional font providing additional rich-text + formatting for the first text portion, e.g. font escapement. */ void convert( const ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >& rxText, - sal_Int32 nXfId ) const; + const Font* pFirstPortionFont = 0 ) const; private: /** Creates, appends, and returns a new empty string portion. */ @@ -269,19 +280,19 @@ private: RichStringPhoneticRef createPhonetic(); /** Create base text portions from the passed string and character formatting. */ - void createFontPortions( const ::rtl::OString& rText, rtl_TextEncoding eDefaultTextEnc, FontPortionModelList& rPortions ); + void createTextPortions( const ::rtl::OString& rText, rtl_TextEncoding eTextEnc, FontPortionModelList& rPortions ); /** Create base text portions from the passed string and character formatting. */ - void createFontPortions( const ::rtl::OUString& rText, FontPortionModelList& rPortions ); + void createTextPortions( const ::rtl::OUString& rText, FontPortionModelList& rPortions ); /** Create phonetic text portions from the passed string and portion data. */ void createPhoneticPortions( const ::rtl::OUString& rText, PhoneticPortionModelList& rPortions, sal_Int32 nBaseLen ); private: - typedef RefVector< RichStringPortion > PortionVec; - typedef RefVector< RichStringPhonetic > PhoneticVec; + typedef RefVector< RichStringPortion > PortionVector; + typedef RefVector< RichStringPhonetic > PhoneticVector; - PortionVec maFontPortions; /// String portions with font data. + PortionVector maTextPortions; /// String portions with font data. PhoneticSettings maPhonSettings; /// Phonetic settings for this string. - PhoneticVec maPhonPortions; /// Phonetic text portions. + PhoneticVector maPhonPortions; /// Phonetic text portions. }; typedef ::boost::shared_ptr< RichString > RichStringRef; diff --git a/oox/inc/oox/xls/sharedformulabuffer.hxx b/oox/inc/oox/xls/sharedformulabuffer.hxx deleted file mode 100644 index 202af6a73..000000000 --- a/oox/inc/oox/xls/sharedformulabuffer.hxx +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#ifndef OOX_XLS_SHAREDFORMULABUFFER_HXX -#define OOX_XLS_SHAREDFORMULABUFFER_HXX - -#include <map> -#include <memory> -#include "oox/xls/worksheethelper.hxx" - -namespace com { namespace sun { namespace star { - namespace sheet { class XFormulaTokens; } - namespace sheet { class XNamedRange; } -} } } - -namespace oox { -namespace xls { - -// ============================================================================ - -/** Formula context that supports shared formulas. */ -class ExtCellFormulaContext : public SimpleFormulaContext, public WorksheetHelper -{ -public: - explicit ExtCellFormulaContext( - const WorksheetHelper& rHelper, - const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaTokens >& rxTokens, - const ::com::sun::star::table::CellAddress& rCellPos ); - - virtual void setSharedFormula( const ::com::sun::star::table::CellAddress& rBaseAddr ); -}; - -// ============================================================================ - -class SharedFormulaBuffer : public WorksheetHelper -{ -public: - explicit SharedFormulaBuffer( const WorksheetHelper& rHelper ); - - /** Imports a shared formula from a OOXML formula string. */ - void importSharedFmla( const ::rtl::OUString& rFormula, - const ::rtl::OUString& rSharedRange, sal_Int32 nId, - const ::com::sun::star::table::CellAddress& rBaseAddr ); - /** Imports a shared formula from a SHAREDFORMULA record in the passed stream */ - void importSharedFmla( SequenceInputStream& rStrm, - const ::com::sun::star::table::CellAddress& rBaseAddr ); - /** Imports a shared formula from a SHAREDFMLA record in the passed stream. */ - void importSharedFmla( BiffInputStream& rStrm, - const ::com::sun::star::table::CellAddress& rBaseAddr ); - - /** Inserts a shared formula with the passed base address into a cell - described by the passed formula context. */ - void setSharedFormulaCell( - ExtCellFormulaContext& rContext, - const ::com::sun::star::table::CellAddress& rBaseAddr ); - /** Inserts a shared formula with the passed base address into a cell - described by the passed formula context. */ - void setSharedFormulaCell( - ExtCellFormulaContext& rContext, - sal_Int32 nSharedId ); - -private: - ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XNamedRange > - createDefinedName( const BinAddress& rMapKey ); - - bool implSetSharedFormulaCell( - ExtCellFormulaContext& rContext, - const BinAddress& rMapKey ); - - void updateCachedCell( - const ::com::sun::star::table::CellAddress& rBaseAddr, - const BinAddress& rMapKey ); - -private: - typedef ::std::map< BinAddress, sal_Int32 > TokenIndexMap; - typedef ::std::auto_ptr< ExtCellFormulaContext > ContextPtr; - - TokenIndexMap maIndexMap; /// Maps shared formula base address to defined name identifier. - ContextPtr mxLastContext; /// Cached formula context for leading formula cell. -}; - -// ============================================================================ - -} // namespace xls -} // namespace oox - -#endif diff --git a/oox/inc/oox/xls/sharedstringsbuffer.hxx b/oox/inc/oox/xls/sharedstringsbuffer.hxx index 81db51d52..ee620593a 100644 --- a/oox/inc/oox/xls/sharedstringsbuffer.hxx +++ b/oox/inc/oox/xls/sharedstringsbuffer.hxx @@ -49,15 +49,12 @@ public: /** Final processing after import of all strings. */ void finalizeImport(); - /** Converts the specified string table entry. */ - void convertString( - const ::com::sun::star::uno::Reference< ::com::sun::star::text::XText >& rxText, - sal_Int32 nStringId, - sal_Int32 nXfId ) const; + /** Returns the specified string. */ + RichStringRef getString( sal_Int32 nStringId ) const; private: - typedef RefVector< RichString > StringVec; - StringVec maStrings; + typedef RefVector< RichString > StringVector; + StringVector maStrings; }; // ============================================================================ diff --git a/oox/inc/oox/xls/sheetdatabuffer.hxx b/oox/inc/oox/xls/sheetdatabuffer.hxx new file mode 100755 index 000000000..82ee27ff7 --- /dev/null +++ b/oox/inc/oox/xls/sheetdatabuffer.hxx @@ -0,0 +1,354 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef OOX_XLS_SHEETDATABUFFER_HXX +#define OOX_XLS_SHEETDATABUFFER_HXX + +#include <list> +#include <map> +#include "oox/xls/richstring.hxx" +#include "oox/xls/worksheethelper.hxx" + +namespace com { namespace sun { namespace star { + namespace sheet { class XNamedRange; } + namespace util { struct DateTime; } +} } } + +namespace oox { +namespace xls { + +// ============================================================================ + +/** Stores basic data about cell values and formatting. */ +struct CellModel +{ + ::com::sun::star::table::CellAddress + maCellAddr; /// The address of the current cell. + sal_Int32 mnCellType; /// Data type of the cell value. + sal_Int32 mnXfId; /// XF (cell formatting) identifier. + bool mbShowPhonetic; /// True = show phonetic text. + + explicit CellModel(); +}; + +// ---------------------------------------------------------------------------- + +/** Stores data about cell formulas. */ +struct CellFormulaModel +{ + ::com::sun::star::table::CellRangeAddress + maFormulaRef; /// Formula range for array/shared formulas and data tables. + sal_Int32 mnFormulaType; /// Type of the formula (regular, array, shared, table). + sal_Int32 mnSharedId; /// Identifier of a shared formula (OOXML only). + + explicit CellFormulaModel(); + + /** Returns true, if the passed cell address is valid for an array formula. */ + bool isValidArrayRef( const ::com::sun::star::table::CellAddress& rCellAddr ); + /** Returns true, if the passed cell address is valid for a shared formula. */ + bool isValidSharedRef( const ::com::sun::star::table::CellAddress& rCellAddr ); +}; + +// ---------------------------------------------------------------------------- + +/** Stores data about table operations. */ +struct DataTableModel +{ + ::rtl::OUString maRef1; /// First reference cell for table operations. + ::rtl::OUString maRef2; /// Second reference cell for table operations. + bool mb2dTable; /// True = 2-dimensional data table. + bool mbRowTable; /// True = row oriented data table. + bool mbRef1Deleted; /// True = first reference cell deleted. + bool mbRef2Deleted; /// True = second reference cell deleted. + + explicit DataTableModel(); +}; + +// ============================================================================ + +/** Stores position and contents of a range of cells for optimized import. */ +class CellBlock : public WorksheetHelper +{ +public: + explicit CellBlock( const WorksheetHelper& rHelper, const ValueRange& rColSpan, sal_Int32 nRow ); + + /** Returns true, if the end index of the passed colspan is greater than + the own column end index, or if the passed range has the same end index + but the start indexes do not match. */ + bool isBefore( const ValueRange& rColSpan ) const; + /** Returns true, if the cell block can be expanded with the passed colspan. */ + bool isExpandable( const ValueRange& rColSpan ) const; + /** Returns true, if the own colspan contains the passed column. */ + bool contains( sal_Int32 nCol ) const; + + /** Returns the specified cell from the last row in the cell buffer array. */ + ::com::sun::star::uno::Any& getCellAny( sal_Int32 nCol ); + /** Inserts a rich-string into the cell block. */ + void insertRichString( + const ::com::sun::star::table::CellAddress& rAddress, + const RichStringRef& rxString, + const Font* pFirstPortionFont ); + + /** Appends a new row to the cell buffer array. */ + void startNextRow(); + /** Writes all buffered cells into the Calc sheet. */ + void finalizeImport(); + +private: + /** Fills unused cells before passed index with empty strings. */ + void fillUnusedCells( sal_Int32 nIndex ); + +private: + /** Stores position and string data of a rich-string cell. */ + struct RichStringCell + { + ::com::sun::star::table::CellAddress + maCellAddr; /// The address of the rich-string cell. + RichStringRef mxString; /// The string with rich formatting. + const Font* mpFirstPortionFont; /// Font information from cell for first text portion. + + explicit RichStringCell( + const ::com::sun::star::table::CellAddress& rCellAddr, + const RichStringRef& rxString, + const Font* pFirstPortionFont ); + }; + typedef ::std::list< RichStringCell > RichStringCellList; + + ::com::sun::star::table::CellRangeAddress + maRange; /// Cell range covered by this cell block. + RichStringCellList maRichStrings; /// Cached rich-string cells. + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > > + maCellArray; /// The array of cells of this cell block. + ::com::sun::star::uno::Any* + mpCurrCellRow; /// Pointer to first cell of current row (last row in maCellArray). + const sal_Int32 mnRowLength; /// Number of cells covered by row of this cell block. + sal_Int32 mnFirstFreeIndex; /// Relative index of first unused cell in current row. +}; + +// ============================================================================ + +/** Manages all cell blocks currently in use. */ +class CellBlockBuffer : public WorksheetHelper +{ +public: + explicit CellBlockBuffer( const WorksheetHelper& rHelper ); + + /** Sets column span information for a row. */ + void setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans ); + + /** Tries to find a cell block. Recalculates the map of cell blocks, if the + passed cell address is located in another row than the last cell. */ + CellBlock* getCellBlock( const ::com::sun::star::table::CellAddress& rCellAddr ); + + /** Inserts all cells of all open cell blocks into the Calc document. */ + void finalizeImport(); + +private: + typedef ::std::map< sal_Int32, ValueRangeVector > ColSpanVectorMap; + typedef RefMap< sal_Int32, CellBlock > CellBlockMap; + + ColSpanVectorMap maColSpans; /// Buffereed column spans, mapped by row index. + CellBlockMap maCellBlocks; /// All open cell blocks, mapped by last (!) column of the block span. + CellBlockMap::iterator maCellBlockIt; /// Pointer to cell block currently in use. + sal_Int32 mnCurrRow; /// Current row index used for buffered cell import. +}; + +// ============================================================================ + +/** Manages the cell contents and cell formatting of a sheet. + */ +class SheetDataBuffer : public WorksheetHelper +{ +public: + explicit SheetDataBuffer( const WorksheetHelper& rHelper ); + + /** Sets column span information for a row. */ + void setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans ); + + /** Inserts a blank cell (with formatting) into the sheet. */ + void setBlankCell( const CellModel& rModel ); + /** Inserts a value cell into the sheet. */ + void setValueCell( const CellModel& rModel, double fValue ); + /** Inserts a simple string cell into the sheet. */ + void setStringCell( const CellModel& rModel, const ::rtl::OUString& rText ); + /** Inserts a rich-string cell into the sheet. */ + void setStringCell( const CellModel& rModel, const RichStringRef& rxString ); + /** Inserts a shared string cell into the sheet. */ + void setStringCell( const CellModel& rModel, sal_Int32 nStringId ); + /** Inserts a date/time cell into the sheet and adjusts number format. */ + void setDateTimeCell( const CellModel& rModel, const ::com::sun::star::util::DateTime& rDateTime ); + /** Inserts a boolean cell into the sheet and adjusts number format. */ + void setBooleanCell( const CellModel& rModel, bool bValue ); + /** Inserts an error cell from the passed error code into the sheet. */ + void setErrorCell( const CellModel& rModel, const ::rtl::OUString& rErrorCode ); + /** Inserts an error cell from the passed BIFF error code into the sheet. */ + void setErrorCell( const CellModel& rModel, sal_uInt8 nErrorCode ); + /** Inserts a formula cell into the sheet. */ + void setFormulaCell( const CellModel& rModel, const ApiTokenSequence& rTokens ); + /** Inserts a shared formula cell into the sheet (OOXML only). */ + void setFormulaCell( const CellModel& rModel, sal_Int32 nSharedId ); + + /** Inserts the passed token array as array formula. */ + void createArrayFormula( + const ::com::sun::star::table::CellRangeAddress& rRange, + const ApiTokenSequence& rTokens ); + /** Sets a multiple table operation to the passed range. */ + void createTableOperation( + const ::com::sun::star::table::CellRangeAddress& rRange, + const DataTableModel& rModel ); + /** Creates a named range with a special name for a shared formula with the + specified identifier and formula definition (OOXML only). */ + void createSharedFormula( + sal_Int32 nSharedId, + const ApiTokenSequence& rTokens ); + /** Creates a named range with a special name for a shared formula with the + specified base address and formula definition (BIFF only). */ + void createSharedFormula( + const ::com::sun::star::table::CellAddress& rCellAddr, + const ApiTokenSequence& rTokens ); + + /** Sets default cell formatting for the specified range of rows. */ + void setRowFormat( sal_Int32 nRow, sal_Int32 nXfId, bool bCustomFormat ); + /** Merges the cells in the passed cell range. */ + void setMergedRange( const ::com::sun::star::table::CellRangeAddress& rRange ); + /** Sets a standard number format (constant from com.sun.star.util.NumberFormat) to the specified cell. */ + void setStandardNumFmt( + const ::com::sun::star::table::CellAddress& rCellAddr, + sal_Int16 nStdNumFmt ); + + /** Final processing after the sheet has been imported. */ + void finalizeImport(); + +private: + struct XfIdRowRange; + struct XfIdRange; + + /** Sets the passed formula token array into a cell. */ + void setCellFormula( + const ::com::sun::star::table::CellAddress& rCellAddr, + const ApiTokenSequence& rTokens ); + + /** Creates a named range with a special name for a shared formula with the + specified base address and formula definition. */ + void createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens ); + /** Creates a formula token array representing the shared formula with the + passed identifier. */ + ApiTokenSequence resolveSharedFormula( const BinAddress& rMapKey ) const; + + /** Inserts the passed array formula into the sheet. */ + void finalizeArrayFormula( + const ::com::sun::star::table::CellRangeAddress& rRange, + const ApiTokenSequence& rTokens ) const; + /** Inserts the passed table operation into the sheet. */ + void finalizeTableOperation( + const ::com::sun::star::table::CellRangeAddress& rRange, + const DataTableModel& rModel ) const; + + /** Processes the cell formatting data of the passed cell. + @param nNumFmtId If set, overrides number format of the cell XF. */ + void setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId = -1 ); + + /** Writes all cell formatting attributes to the passed row range. */ + void writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const; + /** Writes all cell formatting attributes to the passed cell range. */ + void writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const; + /** Tries to merge the ranges last inserted in maXfIdRanges with existing ranges. */ + void mergeXfIdRanges(); + + /** Merges the passed merged range and updates right/bottom cell borders. */ + void finalizeMergedRange( const ::com::sun::star::table::CellRangeAddress& rRange ); + +private: + /** Stores cell range address and formula token array of an array formula. */ + typedef ::std::pair< ::com::sun::star::table::CellRangeAddress, ApiTokenSequence > ArrayFormula; + typedef ::std::list< ArrayFormula > ArrayFormulaList; + + /** Stores cell range address and settings of a table operation. */ + typedef ::std::pair< ::com::sun::star::table::CellRangeAddress, DataTableModel > TableOperation; + typedef ::std::list< TableOperation > TableOperationList; + + typedef ::std::map< BinAddress, sal_Int32 > SharedFormulaMap; + + /** Stores information about a range of rows with equal cell formatting. */ + struct XfIdRowRange + { + ValueRange maRowRange; /// Indexes of first and last row. + sal_Int32 mnXfId; /// XF identifier for the row range. + + explicit XfIdRowRange(); + bool intersects( const ::com::sun::star::table::CellRangeAddress& rRange ) const; + void set( sal_Int32 nRow, sal_Int32 nXfId ); + bool tryExpand( sal_Int32 nRow, sal_Int32 nXfId ); + }; + + /** Stores information about a range of cells with equal formatting. */ + struct XfIdRange + { + ::com::sun::star::table::CellRangeAddress + maRange; /// The formatted cell range. + sal_Int32 mnXfId; /// XF identifier for the range. + sal_Int32 mnNumFmtId; /// Number format overriding the XF. + + void set( const ::com::sun::star::table::CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId ); + bool tryExpand( const ::com::sun::star::table::CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId ); + bool tryMerge( const XfIdRange& rXfIdRange ); + }; + typedef ::std::map< BinAddress, XfIdRange > XfIdRangeMap; + + /** Stores information about a merged cell range. */ + struct MergedRange + { + ::com::sun::star::table::CellRangeAddress + maRange; /// The formatted cell range. + sal_Int32 mnHorAlign; /// Horizontal alignment in the range. + + explicit MergedRange( const ::com::sun::star::table::CellRangeAddress& rRange ); + explicit MergedRange( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nHorAlign ); + bool tryExpand( const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nHorAlign ); + }; + typedef ::std::list< MergedRange > MergedRangeList; + + CellBlockBuffer maCellBlocks; /// Manages all open cell blocks. + ArrayFormulaList maArrayFormulas; /// All array formulas in the sheet. + TableOperationList maTableOperations; /// All table operations in the sheet. + SharedFormulaMap maSharedFormulas; /// Maps shared formula base address to defined name token index. + ::com::sun::star::table::CellAddress + maSharedFmlaAddr; /// Address of a cell containing a pending shared formula. + BinAddress maSharedBaseAddr; /// Base address of the pending shared formula. + XfIdRowRange maXfIdRowRange; /// Cached XF identifier for a range of rows. + XfIdRangeMap maXfIdRanges; /// Collected XF identifiers for cell ranges. + MergedRangeList maMergedRanges; /// Merged cell ranges. + MergedRangeList maCenterFillRanges; /// Merged cell ranges from 'center across' or 'fill' alignment. + bool mbPendingSharedFmla; /// True = maSharedFmlaAddr and maSharedBaseAddr are valid. +}; + +// ============================================================================ + +} // namespace xls +} // namespace oox + +#endif diff --git a/oox/inc/oox/xls/sheetdatacontext.hxx b/oox/inc/oox/xls/sheetdatacontext.hxx index ba8138d40..278aa94d7 100644 --- a/oox/inc/oox/xls/sheetdatacontext.hxx +++ b/oox/inc/oox/xls/sheetdatacontext.hxx @@ -30,22 +30,37 @@ #include "oox/xls/excelhandlers.hxx" #include "oox/xls/richstring.hxx" - -namespace com { namespace sun { namespace star { - namespace table { class XCell; } -} } } +#include "oox/xls/sheetdatabuffer.hxx" namespace oox { namespace xls { // ============================================================================ +/** Used as base for sheet data context classes. Provides fast access to often + used converter objects and sheet index, to improve performance. + */ +struct SheetDataContextBase +{ + AddressConverter& mrAddressConv; /// The address converter. + FormulaParser& mrFormulaParser; /// The formula parser. + SheetDataBuffer& mrSheetData; /// The sheet data buffer for cell content and formatting. + CellModel maCellData; /// Position, contents, formatting of current imported cell. + CellFormulaModel maFmlaData; /// Settings for a cell formula. + sal_Int16 mnSheet; /// Index of the current sheet. + + explicit SheetDataContextBase( const WorksheetHelper& rHelper ); + virtual ~SheetDataContextBase(); +}; + +// ============================================================================ + /** This class implements importing the sheetData element. The sheetData element contains all row settings and all cells in a single sheet of a spreadsheet document. */ -class SheetDataContext : public WorksheetContextBase +class SheetDataContext : public WorksheetContextBase, private SheetDataContextBase { public: explicit SheetDataContext( WorksheetFragmentBase& rFragment ); @@ -64,12 +79,20 @@ private: /** Imports row settings from a row element. */ void importRow( const AttributeList& rAttribs ); /** Imports cell settings from a c element. */ - void importCell( const AttributeList& rAttribs ); + bool importCell( const AttributeList& rAttribs ); /** Imports cell settings from an f element. */ void importFormula( const AttributeList& rAttribs ); - /** Imports a cell address and the following XF identifier. */ - void importCellHeader( SequenceInputStream& rStrm, CellType eCellType ); + /** Imports row settings from a ROW record. */ + void importRow( SequenceInputStream& rStrm ); + + /** Reads a cell address and the following XF identifier. */ + bool readCellHeader( SequenceInputStream& rStrm, CellType eCellType ); + /** Reads a cell formula for the current cell. */ + ApiTokenSequence readCellFormula( SequenceInputStream& rStrm ); + /** Reads the formula range used by shared formulas, arrays, and data tables. */ + bool readFormulaRef( SequenceInputStream& rStrm ); + /** Imports an empty cell from a CELL_BLANK or MULTCELL_BLANK record. */ void importCellBlank( SequenceInputStream& rStrm, CellType eCellType ); /** Imports a boolean cell from a CELL_BOOL, MULTCELL_BOOL, or FORMULA_BOOL record. */ @@ -87,30 +110,28 @@ private: /** Imports a string cell from a CELL_STRING, MULTCELL_STRING, or FORMULA_STRING record. */ void importCellString( SequenceInputStream& rStrm, CellType eCellType ); - /** Imports a cell formula for the current cell. */ - void importCellFormula( SequenceInputStream& rStrm ); - - /** Imports row settings from a ROW record. */ - void importRow( SequenceInputStream& rStrm ); /** Imports an array formula from an ARRAY record. */ void importArray( SequenceInputStream& rStrm ); - /** Imports a shared formula from a SHAREDFORMULA record. */ - void importSharedFmla( SequenceInputStream& rStrm ); /** Imports table operation from a DATATABLE record. */ void importDataTable( SequenceInputStream& rStrm ); + /** Imports a shared formula from a SHAREDFORMULA record. */ + void importSharedFmla( SequenceInputStream& rStrm ); private: - CellModel maCurrCell; /// Position and formatting of current imported cell. - DataTableModel maTableData; /// Additional data for table operation ranges. - BinAddress maCurrPos; /// Current position for binary import. - RichStringRef mxInlineStr; /// Inline rich string from 'is' element. + ::rtl::OUString maCellValue; /// Cell value string (OOXML only). + RichStringRef mxInlineStr; /// Inline rich string (OOXML only). + ApiTokenSequence maTokens; /// Formula token array (OOXML only). + DataTableModel maTableData; /// Settings for table operations. + BinAddress maCurrPos; /// Current cell position (BIFF12 only). + bool mbHasFormula; /// True = current cell has formula data (OOXML only). + bool mbValidRange; /// True = maFmlaData.maFormulaRef is valid (OOXML only). }; // ============================================================================ /** This class implements importing row settings and all cells of a sheet. */ -class BiffSheetDataContext : public BiffWorksheetContextBase +class BiffSheetDataContext : public BiffWorksheetContextBase, private SheetDataContextBase { public: explicit BiffSheetDataContext( const WorksheetHelper& rHelper ); @@ -119,13 +140,15 @@ public: virtual void importRecord( BiffInputStream& rStrm ); private: - /** Sets current cell according to the passed address. */ - void setCurrCell( const BinAddress& rAddr ); + /** Imports row settings from a ROW record. */ + void importRow( BiffInputStream& rStrm ); - /** Imports an XF identifier and sets the mnXfId member. */ - void importXfId( BiffInputStream& rStrm, bool bBiff2 ); - /** Imports a BIFF cell address and the following XF identifier. */ - void importCellHeader( BiffInputStream& rStrm, bool bBiff2 ); + /** Reads an XF identifier and initializes a new cell. */ + bool readCellXfId( BiffInputStream& rStrm, const BinAddress& rAddr, bool bBiff2 ); + /** Reads a BIFF cell address and the following XF identifier. */ + bool readCellHeader( BiffInputStream& rStrm, bool bBiff2 ); + /** Reads the formula range used by shared formulas, arrays, and data tables. */ + bool readFormulaRef( BiffInputStream& rStrm ); /** Imports a BLANK record describing a blank but formatted cell. */ void importBlank( BiffInputStream& rStrm ); @@ -148,20 +171,18 @@ private: /** Imports an RK record describing a numeric cell. */ void importRk( BiffInputStream& rStrm ); - /** Imports row settings from a ROW record. */ - void importRow( BiffInputStream& rStrm ); /** Imports an ARRAY record describing an array formula of a cell range. */ void importArray( BiffInputStream& rStrm ); - /** Imports a SHAREDFMLA record describing a shared formula in a cell range. */ - void importSharedFmla( BiffInputStream& rStrm ); /** Imports table operation from a DATATABLE or DATATABLE2 record. */ void importDataTable( BiffInputStream& rStrm ); + /** Imports a SHAREDFMLA record describing a shared formula in a cell range. */ + void importSharedFmla( BiffInputStream& rStrm ); private: - CellModel maCurrCell; /// Position and formatting of current imported cell. - sal_uInt32 mnFormulaIgnoreSize; /// Number of bytes to be ignored in FORMULA record. - sal_uInt32 mnArrayIgnoreSize; /// Number of bytes to be ignored in ARRAY record. - sal_uInt16 mnBiff2XfId; /// Current XF identifier from IXFE record. + sal_uInt32 mnFormulaSkipSize; /// Number of bytes to be ignored in FORMULA record. + sal_uInt32 mnArraySkipSize; /// Number of bytes to be ignored in ARRAY record. + sal_uInt16 mnBiff2XfId; /// Current XF identifier from IXFE record. + OptValue< bool > mobBiff2HasXfs; /// Select XF formatting or direct formatting in BIFF2. }; // ============================================================================ diff --git a/oox/inc/oox/xls/stylesbuffer.hxx b/oox/inc/oox/xls/stylesbuffer.hxx index d895b0ba0..f714674e8 100644 --- a/oox/inc/oox/xls/stylesbuffer.hxx +++ b/oox/inc/oox/xls/stylesbuffer.hxx @@ -790,6 +790,11 @@ public: /** Writes all formatting attributes to the passed property set. */ void writeToPropertySet( PropertySet& rPropSet ) const; + /** Converts formatting information from BIFF2 cell record data directly. */ + static void writeBiff2CellFormatToPropertySet( + const WorkbookHelper& rHelper, PropertySet& rPropSet, + sal_uInt8 nFlags1, sal_uInt8 nFlags2, sal_uInt8 nFlags3 ); + private: /** Sets 'attribute used' flags from the passed BIFF bit field. */ void setBiffUsedFlags( sal_uInt8 nUsedFlags ); diff --git a/oox/inc/oox/xls/workbookhelper.hxx b/oox/inc/oox/xls/workbookhelper.hxx index c312ddb46..7f3bd4d91 100644 --- a/oox/inc/oox/xls/workbookhelper.hxx +++ b/oox/inc/oox/xls/workbookhelper.hxx @@ -108,47 +108,49 @@ class TableBuffer; class ThemeBuffer; class UnitConverter; class ViewSettings; -class WorkbookData; class WorkbookSettings; class WorksheetBuffer; +class WorkbookGlobals; +typedef ::boost::shared_ptr< WorkbookGlobals > WorkbookGlobalsRef; + /** Helper class to provice access to global workbook data. All classes derived from this helper class will have access to a singleton - object of type WorkbookData containing global workbook settings, buffers, - converters, etc. Nearly all classes in this filter implementation are - derived directly or indirectly from this class. + object of type WorkbookGlobals containing global workbook settings, + buffers, converters, etc. Nearly all classes in this filter implementation + are derived directly or indirectly from this class. - This class contains just a simple reference to the WorkbookData object to - prevent circular references, as the WorkbookData object contains a lot of - objects derived from this class. + This class contains just a simple reference to the WorkbookGlobals object + to prevent circular references, as the WorkbookGlobals object contains a + lot of objects derived from this class. */ class WorkbookHelper { public: - inline /*implicit*/ WorkbookHelper( WorkbookData& rBookData ) : mrBookData( rBookData ) {} + inline /*implicit*/ WorkbookHelper( WorkbookGlobals& rBookGlob ) : mrBookGlob( rBookGlob ) {} virtual ~WorkbookHelper(); + + static WorkbookGlobalsRef constructGlobals( ExcelFilter& rFilter ); + static WorkbookGlobalsRef constructGlobals( ExcelBiffFilter& rFilter, BiffType eBiff ); // filter ----------------------------------------------------------------- /** Returns the base filter object (base class of all filters). */ ::oox::core::FilterBase& getBaseFilter() const; - /** Returns a reference to the global service factory. */ - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > - getGlobalFactory() const; /** Returns the file type of the current filter. */ FilterType getFilterType() const; /** Returns the filter progress bar. */ SegmentProgressBar& getProgressBar() const; /** Returns true, if the file is a multi-sheet document, or false if single-sheet. */ bool isWorkbookFile() const; - /** Returns the index of the current sheet in the Calc document. */ + /** Returns the index of the current Calc sheet, if filter currently processes a sheet. */ sal_Int16 getCurrentSheetIndex() const; - - /** Sets the index of the current sheet in the Calc document. */ - void setCurrentSheetIndex( sal_Int16 nSheet ); - /** Sets the VBA project storage. */ + + /** Sets the VBA project storage used to import VBA source code and forms. */ void setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ); + /** Sets the index of the current Calc sheet, if filter currently processes a sheet. */ + void setCurrentSheetIndex( sal_Int16 nSheet ); /** Final conversion after importing the workbook. */ void finalizeWorkbookImport(); @@ -157,9 +159,6 @@ public: /** Returns a reference to the source/target spreadsheet document model. */ ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument > getDocument() const; - /** Returns a reference to the service factory of the spreadsheet document model. */ - ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > - getDocumentFactory() const; /** Returns a reference to the specified spreadsheet in the document model. */ ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet > @@ -283,38 +282,7 @@ public: BiffCodecHelper& getCodecHelper() const; private: - WorkbookData& mrBookData; -}; - -// ============================================================================ - -namespace prv { - -typedef ::boost::shared_ptr< WorkbookData > WorkbookDataRef; - -struct WorkbookDataOwner -{ - explicit WorkbookDataOwner( WorkbookDataRef xBookData ); - virtual ~WorkbookDataOwner(); - WorkbookDataRef mxBookData; -}; - -} // namespace prv - -// ---------------------------------------------------------------------------- - -class WorkbookHelperRoot : private prv::WorkbookDataOwner, public WorkbookHelper -{ -public: - explicit WorkbookHelperRoot( ExcelFilter& rFilter ); - explicit WorkbookHelperRoot( ExcelBiffFilter& rFilter, BiffType eBiff ); - - /** Returns true, if this helper refers to a valid document. */ - bool isValid() const; - -private: - WorkbookHelperRoot( const WorkbookHelperRoot& ); - WorkbookHelperRoot& operator=( const WorkbookHelperRoot& ); + WorkbookGlobals& mrBookGlob; }; // ============================================================================ diff --git a/oox/inc/oox/xls/worksheetfragment.hxx b/oox/inc/oox/xls/worksheetfragment.hxx index a0501175b..34b392412 100644 --- a/oox/inc/oox/xls/worksheetfragment.hxx +++ b/oox/inc/oox/xls/worksheetfragment.hxx @@ -63,11 +63,8 @@ class WorksheetFragment : public WorksheetFragmentBase { public: explicit WorksheetFragment( - const WorkbookHelper& rHelper, - const ::rtl::OUString& rFragmentPath, - const ISegmentProgressBarRef& rxProgressBar, - WorksheetType eSheetType, - sal_Int16 nSheet ); + const WorksheetHelper& rHelper, + const ::rtl::OUString& rFragmentPath ); protected: virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ); @@ -134,10 +131,8 @@ class BiffWorksheetFragment : public BiffWorksheetFragmentBase { public: explicit BiffWorksheetFragment( - const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, - WorksheetType eSheetType, - sal_Int16 nSheet ); + const WorksheetHelper& rHelper, + const BiffWorkbookFragmentBase& rParent ); virtual ~BiffWorksheetFragment(); /** Imports the entire worksheet fragment, returns true, if EOF record has been reached. */ @@ -168,6 +163,8 @@ private: void importLabelRanges( BiffInputStream& rStrm ); /** Imports the MEREDCELLS record and merges all cells in the document. */ void importMergedCells( BiffInputStream& rStrm ); + /** Imports the NOTE record containing a cell note. */ + void importNote( BiffInputStream& rStrm ); /** Imports the HORPAGEBREAKS or VERPAGEBREAKS record and inserts page breaks. */ void importPageBreaks( BiffInputStream& rStrm, bool bRowBreak ); /** Imports a pivot table. */ diff --git a/oox/inc/oox/xls/worksheethelper.hxx b/oox/inc/oox/xls/worksheethelper.hxx index 2118f738f..deced1ec0 100644 --- a/oox/inc/oox/xls/worksheethelper.hxx +++ b/oox/inc/oox/xls/worksheethelper.hxx @@ -28,6 +28,7 @@ #ifndef OOX_XLS_WORKSHEETHELPER_HXX #define OOX_XLS_WORKSHEETHELPER_HXX +#include "oox/helper/containerhelper.hxx" #include "oox/helper/progressbar.hxx" #include "oox/ole/olehelper.hxx" #include "oox/xls/addressconverter.hxx" @@ -44,7 +45,6 @@ namespace com { namespace sun { namespace star { namespace table { class XCellRange; } namespace table { class XTableColumns; } namespace table { class XTableRows; } - namespace util { struct DateTime; } } } } namespace oox { @@ -53,12 +53,15 @@ namespace xls { class AutoFilterBuffer; struct BinAddress; struct BinRange; +class BiffSheetDrawing; class BinRangeList; class CommentsBuffer; class CondFormatBuffer; +class Font; class PageSettings; class QueryTableBuffer; -class SharedFormulaBuffer; +class RichString; +class SheetDataBuffer; class SheetViewSettings; class VmlDrawing; class WorksheetSettings; @@ -79,47 +82,10 @@ enum WorksheetType // ============================================================================ -/** Stores some data about a cell. */ -struct CellModel -{ - ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell > mxCell; - ::com::sun::star::table::CellAddress maAddress; - ::rtl::OUString maValueStr; /// String containing cell value data. - ::rtl::OUString maFormulaRef; /// String containing formula range for array/shared formulas. - sal_Int32 mnCellType; /// Data type of the cell. - sal_Int32 mnFormulaType; /// Type of the imported formula. - sal_Int32 mnSharedId; /// Shared formula identifier for current cell. - sal_Int32 mnXfId; /// XF identifier for the cell. - sal_Int32 mnNumFmtId; /// Forced number format for the cell. - bool mbHasValueStr; /// True = contents of maValueStr are valid. - bool mbShowPhonetic; /// True = show phonetic text. - - inline explicit CellModel() { reset(); } - void reset(); -}; - -// ---------------------------------------------------------------------------- - -/** Stores data about a data table a.k.a. multiple operation range. */ -struct DataTableModel -{ - ::rtl::OUString maRef1; /// String containing first reference cell for data table formulas. - ::rtl::OUString maRef2; /// String containing second reference cell for data table formulas. - bool mb2dTable; /// True = 2-dimensional data table. - bool mbRowTable; /// True = row oriented data table. - bool mbRef1Deleted; /// True = first reference cell deleted. - bool mbRef2Deleted; /// True = second reference cell deleted. - - explicit DataTableModel(); -}; - -// ---------------------------------------------------------------------------- - -/** Stores formatting data about a range of columns. */ +/** Stores settings and formatting data about a range of sheet columns. */ struct ColumnModel { - sal_Int32 mnFirstCol; /// 1-based (!) index of first column. - sal_Int32 mnLastCol; /// 1-based (!) index of last column. + ValueRange maRange; /// 1-based (!) range of the described columns. double mfWidth; /// Column width in number of characters. sal_Int32 mnXfId; /// Column default formatting. sal_Int32 mnLevel; /// Column outline level. @@ -129,17 +95,17 @@ struct ColumnModel explicit ColumnModel(); - /** Expands this entry with the passed column range, if column settings are equal. */ - bool tryExpand( const ColumnModel& rModel ); + /** Returns true, if this entry can be merged with the passed column range (column settings are equal). */ + bool isMergeable( const ColumnModel& rModel ) const; }; // ---------------------------------------------------------------------------- -/** Stores formatting data about a range of rows. */ +/** Stores settings and formatting data about a sheet row. */ struct RowModel { - sal_Int32 mnFirstRow; /// 1-based (!) index of first row. - sal_Int32 mnLastRow; /// 1-based (!) index of last row. + sal_Int32 mnRow; /// 1-based (!) index of the described row. + ValueRangeSet maColSpans; /// 0-based (!) column ranges of used cells. double mfHeight; /// Row height in points. sal_Int32 mnXfId; /// Row default formatting (see mbIsFormatted). sal_Int32 mnLevel; /// Row outline level. @@ -153,8 +119,10 @@ struct RowModel explicit RowModel(); - /** Expands this entry with the passed row range, if row settings are equal. */ - bool tryExpand( const RowModel& rModel ); + /** Inserts the passed column span into the row model. */ + void insertColSpan( const ValueRange& rColSpan ); + /** Returns true, if this entry can be merged with the passed row range (row settings are equal). */ + bool isMergeable( const RowModel& rModel ) const; }; // ---------------------------------------------------------------------------- @@ -215,13 +183,22 @@ struct ValidationModel // ============================================================================ // ============================================================================ -class WorksheetData; +class WorksheetGlobals; +typedef ::boost::shared_ptr< WorksheetGlobals > WorksheetGlobalsRef; class WorksheetHelper : public WorkbookHelper { public: - /*implicit*/ WorksheetHelper( WorksheetData& rSheetData ); + /*implicit*/ WorksheetHelper( WorksheetGlobals& rSheetGlob ); + static WorksheetGlobalsRef constructGlobals( + const WorkbookHelper& rHelper, + const ISegmentProgressBarRef& rxProgressBar, + WorksheetType eSheetType, + sal_Int16 nSheet ); + + // ------------------------------------------------------------------------ + /** Returns the type of this sheet. */ WorksheetType getSheetType() const; /** Returns the index of the current sheet. */ @@ -232,47 +209,13 @@ public: /** Returns the XCell interface for the passed cell address. */ ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell > - getCell( - const ::com::sun::star::table::CellAddress& rAddress ) const; - /** Returns the XCell interface for the passed cell address string. */ - ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell > - getCell( - const ::rtl::OUString& rAddressStr, - ::com::sun::star::table::CellAddress* opAddress = 0 ) const; - /** Returns the XCell interface for the passed cell address. */ - ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell > - getCell( - const BinAddress& rBinAddress, - ::com::sun::star::table::CellAddress* opAddress = 0 ) const; - + getCell( const ::com::sun::star::table::CellAddress& rAddress ) const; /** Returns the XCellRange interface for the passed cell range address. */ ::com::sun::star::uno::Reference< ::com::sun::star::table::XCellRange > - getCellRange( - const ::com::sun::star::table::CellRangeAddress& rRange ) const; - /** Returns the XCellRange interface for the passed range address string. */ - ::com::sun::star::uno::Reference< ::com::sun::star::table::XCellRange > - getCellRange( - const ::rtl::OUString& rRangeStr, - ::com::sun::star::table::CellRangeAddress* opRange = 0 ) const; - /** Returns the XCellRange interface for the passed range address. */ - ::com::sun::star::uno::Reference< ::com::sun::star::table::XCellRange > - getCellRange( - const BinRange& rBinRange, - ::com::sun::star::table::CellRangeAddress* opRange = 0 ) const; - + getCellRange( const ::com::sun::star::table::CellRangeAddress& rRange ) const; /** Returns the XSheetCellRanges interface for the passed cell range addresses. */ ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSheetCellRanges > getCellRangeList( const ApiCellRangeList& rRanges ) const; - /** Returns the XSheetCellRanges interface for the passed space-separated range list. */ - ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSheetCellRanges > - getCellRangeList( - const ::rtl::OUString& rRangesStr, - ApiCellRangeList* opRanges = 0 ) const; - /** Returns the XSheetCellRanges interface for the passed range list. */ - ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSheetCellRanges > - getCellRangeList( - const BinRangeList& rBinRanges, - ApiCellRangeList* opRanges = 0 ) const; /** Returns the address of the passed cell. The cell reference must be valid. */ static ::com::sun::star::table::CellAddress @@ -292,10 +235,10 @@ public: /** Returns the XTableColumns interface for a range of columns. */ ::com::sun::star::uno::Reference< ::com::sun::star::table::XTableColumns > - getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const; + getColumns( const ValueRange& rColRange ) const; /** Returns the XTableRows interface for a range of rows. */ ::com::sun::star::uno::Reference< ::com::sun::star::table::XTableRows > - getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const; + getRows( const ValueRange& rRowRange ) const; /** Returns the XDrawPage interface of the draw page of the current sheet. */ ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage > @@ -308,10 +251,8 @@ public: /** Returns the size of the entire drawing page in 1/100 mm. */ ::com::sun::star::awt::Size getDrawPageSize() const; - /** Returns the worksheet settings object. */ - WorksheetSettings& getWorksheetSettings() const; - /** Returns the buffer containing all shared formulas in this sheet. */ - SharedFormulaBuffer& getSharedFormulas() const; + /** Returns the buffer for cell contents and cell formatting. */ + SheetDataBuffer& getSheetData() const; /** Returns the conditional formattings in this sheet. */ CondFormatBuffer& getCondFormats() const; /** Returns the buffer for all cell comments in this sheet. */ @@ -320,66 +261,27 @@ public: AutoFilterBuffer& getAutoFilters() const; /** Returns the buffer for all web query tables in this sheet. */ QueryTableBuffer& getQueryTables() const; + /** Returns the worksheet settings object. */ + WorksheetSettings& getWorksheetSettings() const; /** Returns the page/print settings for this sheet. */ PageSettings& getPageSettings() const; /** Returns the view settings for this sheet. */ SheetViewSettings& getSheetViewSettings() const; - /** Returns the VML drawing page for this sheet. */ + /** Returns the VML drawing page for this sheet (OOXML/BIFF12 only). */ VmlDrawing& getVmlDrawing() const; - - /** Sets the passed string to the cell. */ - void setStringCell( - const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell, - const ::rtl::OUString& rText ) const; - /** Sets the shared string with the passed identifier to the cell. */ - void setSharedStringCell( - const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell, - sal_Int32 nStringId, - sal_Int32 nXfId ) const; - /** Sets the passed date/time value to the cell and adjusts number format. */ - void setDateTimeCell( - const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell, - const ::com::sun::star::util::DateTime& rDateTime ) const; - /** Sets the passed boolean value to the cell and adjusts number format. */ - void setBooleanCell( - const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell, - bool bValue ) const; - /** Sets the passed BIFF error code to the cell (by converting it to a formula). */ - void setErrorCell( - const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell, - const ::rtl::OUString& rErrorCode ) const; - /** Sets the passed BIFF error code to the cell (by converting it to a formula). */ - void setErrorCell( - const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell, - sal_uInt8 nErrorCode ) const; - /** Sets cell contents to the cell specified in the passed cell model. */ - void setCell( CellModel& orModel ) const; - - /** Sets a standard number format (constant from com.sun.star.util.NumberFormat) to the passed cell. */ - void setStandardNumFmt( - const ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell >& rxCell, - sal_Int16 nStdNumFmt ) const; + /** Returns the BIFF drawing page for this sheet (BIFF2-BIFF8 only). */ + BiffSheetDrawing& getBiffDrawing() const; /** Changes the current sheet type. */ void setSheetType( WorksheetType eSheetType ); - /** Stores the cell formatting data of the current cell. */ - void setCellFormat( const CellModel& rModel ); - /** Merges the cells in the passed cell range. */ - void setMergedRange( const ::com::sun::star::table::CellRangeAddress& rRange ); /** Sets a column or row page break described in the passed struct. */ void setPageBreak( const PageBreakModel& rModel, bool bRowBreak ); /** Inserts the hyperlink URL into the spreadsheet. */ void setHyperlink( const HyperlinkModel& rModel ); /** Inserts the data validation settings into the spreadsheet. */ void setValidation( const ValidationModel& rModel ); - /** Sets a multiple table operation to the passed range. */ - void setTableOperation( - const ::com::sun::star::table::CellRangeAddress& rRange, - const DataTableModel& rModel ) const; /** Sets the passed label ranges to the current sheet. */ - void setLabelRanges( - const ApiCellRangeList& rColRanges, - const ApiCellRangeList& rRowRanges ); + void setLabelRanges( const ApiCellRangeList& rColRanges, const ApiCellRangeList& rRowRanges ); /** Sets the path to the DrawingML fragment of this sheet. */ void setDrawingPath( const ::rtl::OUString& rDrawingPath ); /** Sets the path to the legacy VML drawing fragment of this sheet. */ @@ -413,6 +315,26 @@ public: @descr Row default formatting is converted directly, other settings are cached and converted in the finalizeWorksheetImport() call. */ void setRowModel( const RowModel& rModel ); + /** Specifies that the passed row needs to set its height manually. */ + void setManualRowHeight( sal_Int32 nRow ); + + /** Inserts a value cell directly into the Calc sheet. */ + void putValue( + const ::com::sun::star::table::CellAddress& rAddress, + double fValue ) const; + /** Inserts a string cell directly into the Calc sheet. */ + void putString( + const ::com::sun::star::table::CellAddress& rAddress, + const ::rtl::OUString& rText ) const; + /** Inserts a rich-string cell directly into the Calc sheet. */ + void putRichString( + const ::com::sun::star::table::CellAddress& rAddress, + const RichString& rString, + const Font* pFirstPortionFont ) const; + /** Inserts a formula cell directly into the Calc sheet. */ + void putFormulaTokens( + const ::com::sun::star::table::CellAddress& rAddress, + const ApiTokenSequence& rTokens ) const; /** Initial conversion before importing the worksheet. */ void initializeWorksheetImport(); @@ -420,50 +342,7 @@ public: void finalizeWorksheetImport(); private: - WorksheetData& mrSheetData; -}; - -// ============================================================================ - -namespace prv { - -typedef ::boost::shared_ptr< WorksheetData > WorksheetDataRef; - -struct WorksheetDataOwner -{ - explicit WorksheetDataOwner( WorksheetDataRef xSheetData ); - virtual ~WorksheetDataOwner(); - WorksheetDataRef mxSheetData; -}; - -} // namespace prv - -// ---------------------------------------------------------------------------- - -class WorksheetHelperRoot : private prv::WorksheetDataOwner, public WorksheetHelper -{ -public: - /** Returns true, if this helper refers to an existing Calc sheet. */ - bool isValidSheet() const; - -protected: - /** Constructs from the passed data, creates and owns a new data object. */ - explicit WorksheetHelperRoot( - const WorkbookHelper& rHelper, - const ISegmentProgressBarRef& rxProgressBar, - WorksheetType eSheetType, - sal_Int16 nSheet ); - - /** Constructs from another sheet helper, does not create a data object. */ - explicit WorksheetHelperRoot( - const WorksheetHelper& rHelper ); - - /** Constructs from another sheet helper, shares ownership of the passed helper. */ - explicit WorksheetHelperRoot( - const WorksheetHelperRoot& rHelper ); - -private: - WorksheetHelperRoot& operator=( const WorksheetHelperRoot& ); + WorksheetGlobals& mrSheetGlob; }; // ============================================================================ diff --git a/oox/prj/d.lst b/oox/prj/d.lst index 69ff66b95..8b27a1963 100644 --- a/oox/prj/d.lst +++ b/oox/prj/d.lst @@ -19,9 +19,10 @@ mkdir: %_DEST%\inc%_EXT%\oox\xls ..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib ..\%__SRC%\inc\oox\token\tokens.hxx %_DEST%\inc%_EXT%\oox\token\tokens.hxx -..\%__SRC%\misc\namespaces.txt %_DEST%\inc%_EXT%\oox\namespaces.txt +..\%__SRC%\misc\namespaces.txt %_DEST%\inc%_EXT%\oox\token\namespaces.txt + +..\source\token\tokens.txt %_DEST%\inc%_EXT%\oox\token\tokens.txt -..\source\token\tokens.txt %_DEST%\inc%_EXT%\oox\token.txt ..\inc\oox\dllapi.h %_DEST%\inc%_EXT%\oox\dllapi.h ..\inc\oox\helper\binarystreambase.hxx %_DEST%\inc%_EXT%\oox\helper\binarystreambase.hxx ..\inc\oox\helper\helper.hxx %_DEST%\inc%_EXT%\oox\helper\helper.hxx diff --git a/oox/source/core/binaryfilterbase.cxx b/oox/source/core/binaryfilterbase.cxx index 135aba6a8..90f97a8d6 100644 --- a/oox/source/core/binaryfilterbase.cxx +++ b/oox/source/core/binaryfilterbase.cxx @@ -55,12 +55,12 @@ BinaryFilterBase::~BinaryFilterBase() StorageRef BinaryFilterBase::implCreateStorage( const Reference< XInputStream >& rxInStream ) const { - return StorageRef( new ::oox::ole::OleStorage( getServiceFactory(), rxInStream, true ) ); + return StorageRef( new ::oox::ole::OleStorage( getComponentContext(), rxInStream, true ) ); } StorageRef BinaryFilterBase::implCreateStorage( const Reference< XStream >& rxOutStream ) const { - return StorageRef( new ::oox::ole::OleStorage( getServiceFactory(), rxOutStream, true ) ); + return StorageRef( new ::oox::ole::OleStorage( getComponentContext(), rxOutStream, true ) ); } // ============================================================================ diff --git a/oox/source/core/contexthandler.cxx b/oox/source/core/contexthandler.cxx index 53db8484b..29bf96d74 100644 --- a/oox/source/core/contexthandler.cxx +++ b/oox/source/core/contexthandler.cxx @@ -42,7 +42,7 @@ using ::rtl::OUString; // ============================================================================ ContextHandler::ContextHandler( ContextHandler& rParent ) : - ContextHandlerImplBase(), + ContextHandler_BASE(), mxBaseData( rParent.mxBaseData ) { } diff --git a/oox/source/core/filterdetect.cxx b/oox/source/core/filterdetect.cxx index d75e0492b..af729be54 100644 --- a/oox/source/core/filterdetect.cxx +++ b/oox/source/core/filterdetect.cxx @@ -269,9 +269,9 @@ const sal_uInt32 ENCRYPT_HASH_SHA1 = 0x00008004; // ---------------------------------------------------------------------------- -bool lclIsZipPackage( const Reference< XMultiServiceFactory >& rxFactory, const Reference< XInputStream >& rxInStrm ) +bool lclIsZipPackage( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm ) { - ZipStorage aZipStorage( rxFactory, rxInStrm ); + ZipStorage aZipStorage( rxContext, rxInStrm ); return aZipStorage.isStorage(); } @@ -499,109 +499,106 @@ PasswordVerifier::PasswordVerifier( const PackageEncryptionInfo& rEncryptInfo ) Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescriptor& rMediaDesc ) const { - Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY ); - if( xFactory.is() ) + // try the plain input stream + Reference< XInputStream > xInStrm( rMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY ); + if( !xInStrm.is() || lclIsZipPackage( mxContext, xInStrm ) ) + return xInStrm; + + // check if a temporary file is passed in the 'ComponentData' property + Reference< XStream > xDecrypted( rMediaDesc.getComponentDataEntry( CREATE_OUSTRING( "DecryptedPackage" ) ), UNO_QUERY ); + if( xDecrypted.is() ) { - // try the plain input stream - Reference< XInputStream > xInStrm( rMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY ); - if( !xInStrm.is() || lclIsZipPackage( xFactory, xInStrm ) ) - return xInStrm; - - // check if a temporary file is passed in the 'ComponentData' property - Reference< XStream > xDecrypted( rMediaDesc.getComponentDataEntry( CREATE_OUSTRING( "DecryptedPackage" ) ), UNO_QUERY ); - if( xDecrypted.is() ) - { - Reference< XInputStream > xDecrInStrm = xDecrypted->getInputStream(); - if( lclIsZipPackage( xFactory, xDecrInStrm ) ) - return xDecrInStrm; - } + Reference< XInputStream > xDecrInStrm = xDecrypted->getInputStream(); + if( lclIsZipPackage( mxContext, xDecrInStrm ) ) + return xDecrInStrm; + } - // try to decrypt an encrypted OLE package - ::oox::ole::OleStorage aOleStorage( xFactory, xInStrm, false ); - if( aOleStorage.isStorage() ) try + // try to decrypt an encrypted OLE package + ::oox::ole::OleStorage aOleStorage( mxContext, xInStrm, false ); + if( aOleStorage.isStorage() ) try + { + // open the required input streams in the encrypted package + Reference< XInputStream > xEncryptionInfo( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptionInfo" ) ), UNO_SET_THROW ); + Reference< XInputStream > xEncryptedPackage( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptedPackage" ) ), UNO_SET_THROW ); + + // read the encryption info stream + PackageEncryptionInfo aEncryptInfo; + BinaryXInputStream aInfoStrm( xEncryptionInfo, true ); + bool bValidInfo = lclReadEncryptionInfo( aEncryptInfo, aInfoStrm ); + + // check flags and agorithm IDs, requiered are AES128 and SHA-1 + bool bImplemented = bValidInfo && + getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_CRYPTOAPI ) && + getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_AES ) && + // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set + ((aEncryptInfo.mnAlgorithmId == 0) || (aEncryptInfo.mnAlgorithmId == ENCRYPT_ALGO_AES128)) && + // hash algorithm ID 0 defaults to SHA-1 too + ((aEncryptInfo.mnAlgorithmIdHash == 0) || (aEncryptInfo.mnAlgorithmIdHash == ENCRYPT_HASH_SHA1)) && + (aEncryptInfo.mnVerifierHashSize == 20); + + if( bImplemented ) { - // open the required input streams in the encrypted package - Reference< XInputStream > xEncryptionInfo( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptionInfo" ) ), UNO_SET_THROW ); - Reference< XInputStream > xEncryptedPackage( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptedPackage" ) ), UNO_SET_THROW ); - - // read the encryption info stream - PackageEncryptionInfo aEncryptInfo; - BinaryXInputStream aInfoStrm( xEncryptionInfo, true ); - bool bValidInfo = lclReadEncryptionInfo( aEncryptInfo, aInfoStrm ); - - // check flags and agorithm IDs, requiered are AES128 and SHA-1 - bool bImplemented = bValidInfo && - getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_CRYPTOAPI ) && - getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_AES ) && - // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set - ((aEncryptInfo.mnAlgorithmId == 0) || (aEncryptInfo.mnAlgorithmId == ENCRYPT_ALGO_AES128)) && - // hash algorithm ID 0 defaults to SHA-1 too - ((aEncryptInfo.mnAlgorithmIdHash == 0) || (aEncryptInfo.mnAlgorithmIdHash == ENCRYPT_HASH_SHA1)) && - (aEncryptInfo.mnVerifierHashSize == 20); - - if( bImplemented ) + /* "VelvetSweatshop" is the built-in default encryption + password used by MS Excel for the "workbook protection" + feature with password. Try this first before prompting the + user for a password. */ + ::std::vector< OUString > aDefaultPasswords; + aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) ); + + /* Use the comphelper password helper to request a password. + This helper returns either with the correct password + (according to the verifier), or with an empty string if + user has cancelled the password input dialog. */ + PasswordVerifier aVerifier( aEncryptInfo ); + Sequence< NamedValue > aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword( + aVerifier, rMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords ); + + if( aEncryptionData.getLength() == 0 ) { - /* "VelvetSweatshop" is the built-in default encryption - password used by MS Excel for the "workbook protection" - feature with password. Try this first before prompting the - user for a password. */ - ::std::vector< OUString > aDefaultPasswords; - aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) ); - - /* Use the comphelper password helper to request a password. - This helper returns either with the correct password - (according to the verifier), or with an empty string if - user has cancelled the password input dialog. */ - PasswordVerifier aVerifier( aEncryptInfo ); - Sequence< NamedValue > aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword( - aVerifier, rMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords ); - - if( aEncryptionData.getLength() == 0 ) - { - rMediaDesc[ MediaDescriptor::PROP_ABORTED() ] <<= true; - } - else + rMediaDesc[ MediaDescriptor::PROP_ABORTED() ] <<= true; + } + else + { + // create temporary file for unencrypted package + Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XStream > xTempFile( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); + Reference< XOutputStream > xDecryptedPackage( xTempFile->getOutputStream(), UNO_SET_THROW ); + BinaryXOutputStream aDecryptedPackage( xDecryptedPackage, true ); + BinaryXInputStream aEncryptedPackage( xEncryptedPackage, true ); + + EVP_CIPHER_CTX aes_ctx; + EVP_CIPHER_CTX_init( &aes_ctx ); + EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, aVerifier.getKey(), 0 ); + EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 ); + + sal_uInt8 pnInBuffer[ 1024 ]; + sal_uInt8 pnOutBuffer[ 1024 ]; + sal_Int32 nInLen; + int nOutLen; + aEncryptedPackage.skip( 8 ); // decrypted size + while( (nInLen = aEncryptedPackage.readMemory( pnInBuffer, sizeof( pnInBuffer ) )) > 0 ) { - // create temporary file for unencrypted package - Reference< XStream > xTempFile( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); - Reference< XOutputStream > xDecryptedPackage( xTempFile->getOutputStream(), UNO_SET_THROW ); - BinaryXOutputStream aDecryptedPackage( xDecryptedPackage, true ); - BinaryXInputStream aEncryptedPackage( xEncryptedPackage, true ); - - EVP_CIPHER_CTX aes_ctx; - EVP_CIPHER_CTX_init( &aes_ctx ); - EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, aVerifier.getKey(), 0 ); - EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 ); - - sal_uInt8 pnInBuffer[ 1024 ]; - sal_uInt8 pnOutBuffer[ 1024 ]; - sal_Int32 nInLen; - int nOutLen; - aEncryptedPackage.skip( 8 ); // decrypted size - while( (nInLen = aEncryptedPackage.readMemory( pnInBuffer, sizeof( pnInBuffer ) )) > 0 ) - { - EVP_DecryptUpdate( &aes_ctx, pnOutBuffer, &nOutLen, pnInBuffer, nInLen ); - aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen ); - } - EVP_DecryptFinal_ex( &aes_ctx, pnOutBuffer, &nOutLen ); + EVP_DecryptUpdate( &aes_ctx, pnOutBuffer, &nOutLen, pnInBuffer, nInLen ); aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen ); + } + EVP_DecryptFinal_ex( &aes_ctx, pnOutBuffer, &nOutLen ); + aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen ); - EVP_CIPHER_CTX_cleanup( &aes_ctx ); - xDecryptedPackage->flush(); - aDecryptedPackage.seekToStart(); + EVP_CIPHER_CTX_cleanup( &aes_ctx ); + xDecryptedPackage->flush(); + aDecryptedPackage.seekToStart(); - // store temp file in media descriptor to keep it alive - rMediaDesc.setComponentDataEntry( CREATE_OUSTRING( "DecryptedPackage" ), Any( xTempFile ) ); + // store temp file in media descriptor to keep it alive + rMediaDesc.setComponentDataEntry( CREATE_OUSTRING( "DecryptedPackage" ), Any( xTempFile ) ); - Reference< XInputStream > xDecrInStrm = xTempFile->getInputStream(); - if( lclIsZipPackage( xFactory, xDecrInStrm ) ) - return xDecrInStrm; - } + Reference< XInputStream > xDecrInStrm = xTempFile->getInputStream(); + if( lclIsZipPackage( mxContext, xDecrInStrm ) ) + return xDecrInStrm; } } - catch( Exception& ) - { - } + } + catch( Exception& ) + { } return Reference< XInputStream >(); @@ -633,7 +630,6 @@ OUString SAL_CALL FilterDetect::detect( Sequence< PropertyValue >& rMediaDescSeq { OUString aFilterName; MediaDescriptor aMediaDesc( rMediaDescSeq ); - Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); /* Check that the user has not choosen to abort detection, e.g. by hitting 'Cancel' in the password input dialog. This may happen because this @@ -650,7 +646,7 @@ OUString SAL_CALL FilterDetect::detect( Sequence< PropertyValue >& rMediaDescSeq Reference< XInputStream > xInStrm( extractUnencryptedPackage( aMediaDesc ), UNO_SET_THROW ); // stream must be a ZIP package - ZipStorage aZipStorage( xFactory, xInStrm ); + ZipStorage aZipStorage( mxContext, xInStrm ); if( aZipStorage.isStorage() ) { // create the fast parser, register the XML namespaces, set document handler diff --git a/oox/source/core/fragmenthandler.cxx b/oox/source/core/fragmenthandler.cxx index 4e986991f..7c91c1605 100644 --- a/oox/source/core/fragmenthandler.cxx +++ b/oox/source/core/fragmenthandler.cxx @@ -52,12 +52,12 @@ FragmentBaseData::FragmentBaseData( XmlFilterBase& rFilter, const OUString& rFra // ============================================================================ FragmentHandler::FragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath ) : - FragmentHandlerImplBase( FragmentBaseDataRef( new FragmentBaseData( rFilter, rFragmentPath, rFilter.importRelations( rFragmentPath ) ) ) ) + FragmentHandler_BASE( FragmentBaseDataRef( new FragmentBaseData( rFilter, rFragmentPath, rFilter.importRelations( rFragmentPath ) ) ) ) { } FragmentHandler::FragmentHandler( XmlFilterBase& rFilter, const OUString& rFragmentPath, RelationsRef xRelations ) : - FragmentHandlerImplBase( FragmentBaseDataRef( new FragmentBaseData( rFilter, rFragmentPath, xRelations ) ) ) + FragmentHandler_BASE( FragmentBaseDataRef( new FragmentBaseData( rFilter, rFragmentPath, xRelations ) ) ) { } diff --git a/oox/source/core/makefile.mk b/oox/source/core/makefile.mk index 2b58b9577..2b58b9577 100644..100755 --- a/oox/source/core/makefile.mk +++ b/oox/source/core/makefile.mk diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx index 06c64c48b..3d3296819 100644 --- a/oox/source/core/xmlfilterbase.cxx +++ b/oox/source/core/xmlfilterbase.cxx @@ -496,12 +496,12 @@ Reference< XInputStream > XmlFilterBase::implGetInputStream( MediaDescriptor& rM StorageRef XmlFilterBase::implCreateStorage( const Reference< XInputStream >& rxInStream ) const { - return StorageRef( new ZipStorage( getServiceFactory(), rxInStream ) ); + return StorageRef( new ZipStorage( getComponentContext(), rxInStream ) ); } StorageRef XmlFilterBase::implCreateStorage( const Reference< XStream >& rxOutStream ) const { - return StorageRef( new ZipStorage( getServiceFactory(), rxOutStream ) ); + return StorageRef( new ZipStorage( getComponentContext(), rxOutStream ) ); } // ============================================================================ diff --git a/oox/source/docprop/makefile.mk b/oox/source/docprop/makefile.mk index 5687178da..5687178da 100644..100755 --- a/oox/source/docprop/makefile.mk +++ b/oox/source/docprop/makefile.mk diff --git a/oox/source/drawingml/chart/chartdrawingfragment.cxx b/oox/source/drawingml/chart/chartdrawingfragment.cxx index 03c634453..deac5ee3f 100644 --- a/oox/source/drawingml/chart/chartdrawingfragment.cxx +++ b/oox/source/drawingml/chart/chartdrawingfragment.cxx @@ -83,42 +83,41 @@ void ShapeAnchor::setPos( sal_Int32 nElement, sal_Int32 nParentContext, const OU } } -Rectangle ShapeAnchor::calcEmuLocation( const EmuRectangle& rEmuChartRect ) const +EmuRectangle ShapeAnchor::calcAnchorRectEmu( const EmuRectangle& rChartRect ) const { - Rectangle aLoc( -1, -1, -1, -1 ); + EmuRectangle aAnchorRect( -1, -1, -1, -1 ); - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcEmuLocation - invalid from position" ); - OSL_ENSURE( mbRelSize ? maTo.isValid() : maSize.isValid(), "ShapeAnchor::calcEmuLocation - invalid to/size" ); + OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid from position" ); + OSL_ENSURE( mbRelSize ? maTo.isValid() : maSize.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid to/size" ); if( maFrom.isValid() && (mbRelSize ? maTo.isValid() : maSize.isValid()) ) { // calculate shape position - aLoc.X = getLimitedValue< sal_Int32, double >( maFrom.mfX * rEmuChartRect.Width, 0, SAL_MAX_INT32 ); - aLoc.Y = getLimitedValue< sal_Int32, double >( maFrom.mfY * rEmuChartRect.Height, 0, SAL_MAX_INT32 ); + aAnchorRect.X = static_cast< sal_Int64 >( maFrom.mfX * rChartRect.Width + 0.5 ); + aAnchorRect.Y = static_cast< sal_Int64 >( maFrom.mfY * rChartRect.Height + 0.5 ); // calculate shape size if( mbRelSize ) { - aLoc.Width = getLimitedValue< sal_Int32, double >( maTo.mfX * rEmuChartRect.Width, 0, SAL_MAX_INT32 ) - aLoc.X; - if( aLoc.Width < 0 ) + aAnchorRect.Width = static_cast< sal_Int64 >( maTo.mfX * rChartRect.Width + 0.5 ) - aAnchorRect.X; + if( aAnchorRect.Width < 0 ) { - aLoc.X += aLoc.Width; - aLoc.Width *= -1; + aAnchorRect.X += aAnchorRect.Width; + aAnchorRect.Width *= -1; } - aLoc.Height = getLimitedValue< sal_Int32, double >( maTo.mfY * rEmuChartRect.Height, 0, SAL_MAX_INT32 ) - aLoc.Y; - if( aLoc.Height < 0 ) + aAnchorRect.Height = static_cast< sal_Int64 >( maTo.mfY * rChartRect.Height + 0.5 ) - aAnchorRect.Y; + if( aAnchorRect.Height < 0 ) { - aLoc.Y += aLoc.Height; - aLoc.Height *= -1; + aAnchorRect.Y += aAnchorRect.Height; + aAnchorRect.Height *= -1; } } else { - aLoc.Width = getLimitedValue< sal_Int32, sal_Int64 >( maSize.Width, 0, SAL_MAX_INT32 ); - aLoc.Height = getLimitedValue< sal_Int32, sal_Int64 >( maSize.Height, 0, SAL_MAX_INT32 ); + aAnchorRect.setSize( maSize ); } } - return aLoc; + return aAnchorRect; } // ============================================================================ @@ -129,10 +128,10 @@ ChartDrawingFragment::ChartDrawingFragment( XmlFilterBase& rFilter, mxDrawPage( rxDrawPage ), mbOleSupport( bOleSupport ) { - maEmuChartRect.X = static_cast< sal_Int64 >( rShapesOffset.X ) * 360; - maEmuChartRect.Y = static_cast< sal_Int64 >( rShapesOffset.Y ) * 360; - maEmuChartRect.Width = static_cast< sal_Int64 >( rChartSize.Width ) * 360; - maEmuChartRect.Height = static_cast< sal_Int64 >( rChartSize.Height ) * 360; + maChartRectEmu.X = convertHmmToEmu( rShapesOffset.X ); + maChartRectEmu.Y = convertHmmToEmu( rShapesOffset.Y ); + maChartRectEmu.Width = convertHmmToEmu( rChartSize.Width ); + maChartRectEmu.Height = convertHmmToEmu( rChartSize.Height ); } ChartDrawingFragment::~ChartDrawingFragment() @@ -216,9 +215,17 @@ void ChartDrawingFragment::onEndElement() { if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() ) { - Rectangle aLoc = mxAnchor->calcEmuLocation( maEmuChartRect ); - if( (aLoc.X >= 0) && (aLoc.Y >= 0) && (aLoc.Width >= 0) && (aLoc.Height >= 0) ) - mxShape->addShape( getFilter(), getFilter().getCurrentTheme(), mxDrawPage, &aLoc ); + EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( maChartRectEmu ); + if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) ) + { + // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle) + Rectangle aShapeRectEmu32( + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.X, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Y, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Width, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Height, 0, SAL_MAX_INT32 ) ); + mxShape->addShape( getFilter(), getFilter().getCurrentTheme(), mxDrawPage, &aShapeRectEmu32 ); + } } mxShape.reset(); mxAnchor.reset(); diff --git a/oox/source/drawingml/chart/converterbase.cxx b/oox/source/drawingml/chart/converterbase.cxx index bc9849b45..a8b3a73be 100644 --- a/oox/source/drawingml/chart/converterbase.cxx +++ b/oox/source/drawingml/chart/converterbase.cxx @@ -33,6 +33,7 @@ #include <com/sun/star/chart/XChartDocument.hpp> #include <com/sun/star/chart/XSecondAxisTitleSupplier.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> +#include <com/sun/star/chart2/RelativeSize.hpp> #include <com/sun/star/drawing/FillStyle.hpp> #include <com/sun/star/drawing/LineStyle.hpp> #include <com/sun/star/frame/XModel.hpp> @@ -78,8 +79,7 @@ struct TitleLayoutInfo { typedef Reference< XShape > (*GetShapeFunc)( const Reference< cssc::XChartDocument >& ); - ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XTitle > - mxTitle; /// The API title object. + Reference< XTitle > mxTitle; /// The API title object. ModelRef< LayoutModel > mxLayout; /// The layout model, if existing. GetShapeFunc mpGetShape; /// Helper function to receive the title shape. @@ -323,9 +323,9 @@ sal_Int32 lclCalcSize( sal_Int32 nPos, sal_Int32 nChartSize, double fSize, sal_I sal_Int32 nValue = getLimitedValue< sal_Int32, double >( nChartSize * fSize + 0.5, 0, nChartSize ); switch( nSizeMode ) { - case XML_factor: // size as factor of chart size + case XML_factor: // passed value is width/height return nValue; - case XML_edge: // absolute end position as factor of chart size + case XML_edge: // passed value is right/bottom position return nValue - nPos + 1; }; @@ -333,6 +333,23 @@ sal_Int32 lclCalcSize( sal_Int32 nPos, sal_Int32 nChartSize, double fSize, sal_I return -1; } +/** Returns a relative size value in the chart area. */ +double lclCalcRelSize( double fPos, double fSize, sal_Int32 nSizeMode ) +{ + switch( nSizeMode ) + { + case XML_factor: // passed value is width/height + break; + case XML_edge: // passed value is right/bottom position + fSize -= fPos; + break; + default: + OSL_ENSURE( false, "lclCalcRelSize - unknown size mode" ); + fSize = 0.0; + }; + return getLimitedValue< double, double >( fSize, 0.0, 1.0 - fPos ); +} + } // namespace // ---------------------------------------------------------------------------- @@ -369,12 +386,20 @@ bool LayoutConverter::convertFromModel( PropertySet& rPropSet ) (mrModel.mnXMode == XML_edge) && (mrModel.mfX >= 0.0) && (mrModel.mnYMode == XML_edge) && (mrModel.mfY >= 0.0) ) { - RelativePosition aPos; - aPos.Primary = getLimitedValue< double, double >( mrModel.mfX, 0.0, 1.0 ); - aPos.Secondary = getLimitedValue< double, double >( mrModel.mfY, 0.0, 1.0 ); - aPos.Anchor = ::com::sun::star::drawing::Alignment_TOP_LEFT; + RelativePosition aPos( + getLimitedValue< double, double >( mrModel.mfX, 0.0, 1.0 ), + getLimitedValue< double, double >( mrModel.mfY, 0.0, 1.0 ), + Alignment_TOP_LEFT ); rPropSet.setProperty( PROP_RelativePosition, aPos ); - return true; + + RelativeSize aSize( + lclCalcRelSize( aPos.Primary, mrModel.mfW, mrModel.mnWMode ), + lclCalcRelSize( aPos.Secondary, mrModel.mfH, mrModel.mnHMode ) ); + if( (aSize.Primary > 0.0) && (aSize.Secondary > 0.0) ) + { + rPropSet.setProperty( PROP_RelativeSize, aSize ); + return true; + } } return false; } diff --git a/oox/source/drawingml/chart/makefile.mk b/oox/source/drawingml/chart/makefile.mk index 84762e6a2..84762e6a2 100644..100755 --- a/oox/source/drawingml/chart/makefile.mk +++ b/oox/source/drawingml/chart/makefile.mk diff --git a/oox/source/drawingml/chart/objectformatter.cxx b/oox/source/drawingml/chart/objectformatter.cxx index 76c369600..a656dad4c 100644 --- a/oox/source/drawingml/chart/objectformatter.cxx +++ b/oox/source/drawingml/chart/objectformatter.cxx @@ -34,6 +34,7 @@ #include "oox/core/xmlfilterbase.hxx" #include "oox/drawingml/fillproperties.hxx" #include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/shapepropertymap.hxx" #include "oox/drawingml/textbody.hxx" #include "oox/drawingml/textparagraph.hxx" #include "oox/drawingml/theme.hxx" @@ -489,19 +490,50 @@ const AutoTextEntry* lclGetAutoTextEntry( const AutoTextEntry* pEntries, sal_Int // ---------------------------------------------------------------------------- -/** Enumerates different sets of property names for chart object formatting. */ -enum PropertyType +/** Property identifiers for common chart objects, to be used in ShapePropertyInfo. */ +static const sal_Int32 spnCommonPropIds[] = { - PROPERTYTYPE_COMMON, /// Common objects, no special handling. - PROPERTYTYPE_LINEARSERIES, /// Specific to linear data series. - PROPERTYTYPE_FILLEDSERIES /// Specific to filled data series. + PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDashName, + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillGradientName, + PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, + PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; +/** Property identifiers for linear data series, to be used in ShapePropertyInfo. */ +static const sal_Int32 spnLinearPropIds[] = +{ + PROP_LineStyle, PROP_LineWidth, PROP_Color, PROP_Transparency, PROP_LineDashName, + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_INVALID, PROP_INVALID, PROP_INVALID +}; + +/** Property identifiers for filled data series, to be used in ShapePropertyInfo. */ +static const sal_Int32 spnFilledPropIds[] = +{ + PROP_BorderStyle, PROP_BorderWidth, PROP_BorderColor, PROP_BorderTransparency, PROP_BorderDashName, + PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, + PROP_FillStyle, PROP_Color, PROP_Transparency, PROP_GradientName, + PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, + PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint +}; + +/** Property info for common chart objects, to be used in ShapePropertyMap. */ +static const ShapePropertyInfo saCommonPropInfo( spnCommonPropIds, false, true, true, true ); +/** Property info for linear data series, to be used in ShapePropertyMap. */ +static const ShapePropertyInfo saLinearPropInfo( spnLinearPropIds, false, true, true, true ); +/** Property info for filled data series, to be used in ShapePropertyMap. */ +static const ShapePropertyInfo saFilledPropInfo( spnFilledPropIds, false, true, true, true ); + +// ---------------------------------------------------------------------------- + /** Contains information about formatting of a specific chart object type. */ struct ObjectTypeFormatEntry { ObjectType meObjType; /// Object type for automatic format. - PropertyType mePropType; /// Property type for property names. + const ShapePropertyInfo* mpPropInfo; /// Property info for the ShapePropertyMap class. const AutoFormatEntry* mpAutoLines; /// Automatic line formatting for all chart styles. const AutoFormatEntry* mpAutoFills; /// Automatic fill formatting for all chart styles. const AutoFormatEntry* mpAutoEffects; /// Automatic effect formatting for all chart styles. @@ -517,37 +549,38 @@ struct ObjectTypeFormatEntry static const ObjectTypeFormatEntry spObjTypeFormatEntries[] = { - // object type property type auto text auto line auto fill auto effect - TYPEFORMAT_FRAME( OBJECTTYPE_CHARTSPACE, PROPERTYTYPE_COMMON, 0, spChartSpaceLines, spChartSpaceFills, 0 /* eq to Ch2 */ ), - TYPEFORMAT_FRAME( OBJECTTYPE_CHARTTITLE, PROPERTYTYPE_COMMON, spChartTitleTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), - TYPEFORMAT_FRAME( OBJECTTYPE_LEGEND, PROPERTYTYPE_COMMON, spOtherTexts, spNoFormats, spNoFormats, 0 /* eq to Ch2 */ ), - TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA2D, PROPERTYTYPE_COMMON, 0, 0 /* eq to Ch2 */, spPlotArea2dFills, 0 /* eq to Ch2 */ ), - TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA3D, PROPERTYTYPE_COMMON, 0, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), - TYPEFORMAT_FRAME( OBJECTTYPE_WALL, PROPERTYTYPE_COMMON, 0, 0 /* eq to Ch2 */, spWallFloorFills, 0 /* eq to Ch2 */ ), - TYPEFORMAT_FRAME( OBJECTTYPE_FLOOR, PROPERTYTYPE_COMMON, 0, spFloorLines, spWallFloorFills, 0 /* eq to Ch2 */ ), - TYPEFORMAT_LINE( OBJECTTYPE_AXIS, PROPERTYTYPE_COMMON, spOtherTexts, spAxisLines ), - TYPEFORMAT_FRAME( OBJECTTYPE_AXISTITLE, PROPERTYTYPE_COMMON, spAxisTitleTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), - TYPEFORMAT_FRAME( OBJECTTYPE_AXISUNIT, PROPERTYTYPE_COMMON, spAxisTitleTexts, 0 /* eq in Ch2 */, 0 /* eq in Ch2 */, 0 /* eq in Ch2 */ ), - TYPEFORMAT_LINE( OBJECTTYPE_MAJORGRIDLINE, PROPERTYTYPE_COMMON, 0, spMajorGridLines ), - TYPEFORMAT_LINE( OBJECTTYPE_MINORGRIDLINE, PROPERTYTYPE_COMMON, 0, spMinorGridLines ), - TYPEFORMAT_LINE( OBJECTTYPE_LINEARSERIES2D, PROPERTYTYPE_LINEARSERIES, 0, spLinearSeriesLines ), - TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES2D, PROPERTYTYPE_FILLEDSERIES, 0, spFilledSeriesLines, spFilledSeries2dFills, spFilledSeriesEffects ), - TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES3D, PROPERTYTYPE_FILLEDSERIES, 0, spFilledSeriesLines, spFilledSeries3dFills, spFilledSeriesEffects ), - TYPEFORMAT_FRAME( OBJECTTYPE_DATALABEL, PROPERTYTYPE_COMMON, spOtherTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), - TYPEFORMAT_LINE( OBJECTTYPE_TRENDLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), - TYPEFORMAT_FRAME( OBJECTTYPE_TRENDLINELABEL, PROPERTYTYPE_COMMON, spOtherTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), - TYPEFORMAT_LINE( OBJECTTYPE_ERRORBAR, PROPERTYTYPE_COMMON, 0, spOtherLines ), - TYPEFORMAT_LINE( OBJECTTYPE_SERLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), - TYPEFORMAT_LINE( OBJECTTYPE_LEADERLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), - TYPEFORMAT_LINE( OBJECTTYPE_DROPLINE, PROPERTYTYPE_COMMON, 0, spOtherLines ), - TYPEFORMAT_LINE( OBJECTTYPE_HILOLINE, PROPERTYTYPE_LINEARSERIES, 0, spOtherLines ), - TYPEFORMAT_FRAME( OBJECTTYPE_UPBAR, PROPERTYTYPE_COMMON, 0, spUpDownBarLines, spUpBarFills, spUpDownBarEffects ), - TYPEFORMAT_FRAME( OBJECTTYPE_DOWNBAR, PROPERTYTYPE_COMMON, 0, spUpDownBarLines, spDownBarFills, spUpDownBarEffects ), - TYPEFORMAT_LINE( OBJECTTYPE_DATATABLE, PROPERTYTYPE_COMMON, spOtherTexts, spChartSpaceLines ) + // object type property info auto text auto line auto fill auto effect + TYPEFORMAT_FRAME( OBJECTTYPE_CHARTSPACE, &saCommonPropInfo, 0, spChartSpaceLines, spChartSpaceFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_CHARTTITLE, &saCommonPropInfo, spChartTitleTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_LEGEND, &saCommonPropInfo, spOtherTexts, spNoFormats, spNoFormats, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA2D, &saCommonPropInfo, 0, 0 /* eq to Ch2 */, spPlotArea2dFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_PLOTAREA3D, &saCommonPropInfo, 0, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_WALL, &saCommonPropInfo, 0, 0 /* eq to Ch2 */, spWallFloorFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_FLOOR, &saCommonPropInfo, 0, spFloorLines, spWallFloorFills, 0 /* eq to Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_AXIS, &saCommonPropInfo, spOtherTexts, spAxisLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_AXISTITLE, &saCommonPropInfo, spAxisTitleTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_FRAME( OBJECTTYPE_AXISUNIT, &saCommonPropInfo, spAxisTitleTexts, 0 /* eq in Ch2 */, 0 /* eq in Ch2 */, 0 /* eq in Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_MAJORGRIDLINE, &saCommonPropInfo, 0, spMajorGridLines ), + TYPEFORMAT_LINE( OBJECTTYPE_MINORGRIDLINE, &saCommonPropInfo, 0, spMinorGridLines ), + TYPEFORMAT_LINE( OBJECTTYPE_LINEARSERIES2D, &saLinearPropInfo, 0, spLinearSeriesLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES2D, &saFilledPropInfo, 0, spFilledSeriesLines, spFilledSeries2dFills, spFilledSeriesEffects ), + TYPEFORMAT_FRAME( OBJECTTYPE_FILLEDSERIES3D, &saFilledPropInfo, 0, spFilledSeriesLines, spFilledSeries3dFills, spFilledSeriesEffects ), + TYPEFORMAT_FRAME( OBJECTTYPE_DATALABEL, &saCommonPropInfo, spOtherTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_TRENDLINE, &saCommonPropInfo, 0, spOtherLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_TRENDLINELABEL, &saCommonPropInfo, spOtherTexts, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */, 0 /* eq to Ch2 */ ), + TYPEFORMAT_LINE( OBJECTTYPE_ERRORBAR, &saCommonPropInfo, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_SERLINE, &saCommonPropInfo, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_LEADERLINE, &saCommonPropInfo, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_DROPLINE, &saCommonPropInfo, 0, spOtherLines ), + TYPEFORMAT_LINE( OBJECTTYPE_HILOLINE, &saLinearPropInfo, 0, spOtherLines ), + TYPEFORMAT_FRAME( OBJECTTYPE_UPBAR, &saCommonPropInfo, 0, spUpDownBarLines, spUpBarFills, spUpDownBarEffects ), + TYPEFORMAT_FRAME( OBJECTTYPE_DOWNBAR, &saCommonPropInfo, 0, spUpDownBarLines, spDownBarFills, spUpDownBarEffects ), + TYPEFORMAT_LINE( OBJECTTYPE_DATATABLE, &saCommonPropInfo, spOtherTexts, spChartSpaceLines ) }; #undef TYPEFORMAT_FRAME #undef TYPEFORMAT_LINE + // ---------------------------------------------------------------------------- void lclConvertPictureOptions( FillProperties& orFillProps, const PictureOptionsModel& rPicOptions ) @@ -556,15 +589,6 @@ void lclConvertPictureOptions( FillProperties& orFillProps, const PictureOptions orFillProps.maBlipProps.moBitmapMode = bStacked ? XML_tile : XML_stretch; } -// ---------------------------------------------------------------------------- - -const sal_Int32 spnCommonLineIds[ LineId_END ] = { PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; -const sal_Int32 spnLinearLineIds[ LineId_END ] = { PROP_LineStyle, PROP_LineWidth, PROP_Color, PROP_Transparency, PROP_LineDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; -const sal_Int32 spnFilledLineIds[ LineId_END ] = { PROP_BorderStyle, PROP_BorderWidth, PROP_BorderColor, PROP_BorderTransparency, PROP_BorderDashName, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID, PROP_INVALID }; - -const sal_Int32 spnCommonFillIds[ FillId_END ] = { PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillGradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; -const sal_Int32 spnFilledFillIds[ FillId_END ] = { PROP_FillStyle, PROP_Color, PROP_Transparency, PROP_GradientName, PROP_FillBitmapName, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint }; - } // namespace // ============================================================================ @@ -606,18 +630,16 @@ class LineFormatter : public DetailFormatterBase public: explicit LineFormatter( ObjectFormatterData& rData, - const AutoFormatEntry* pAutoFormatEntry, - PropertyType ePropType ); + const AutoFormatEntry* pAutoFormatEntry ); /** Converts line formatting to the passed property set. */ void convertFormatting( - PropertySet& rPropSet, + ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx ); private: LinePropertiesPtr mxAutoLine; /// Automatic line properties. - LinePropertyIds& mrLinePropIds; /// Property identifiers for border/line formatting. }; // ---------------------------------------------------------------------------- @@ -627,19 +649,17 @@ class FillFormatter : public DetailFormatterBase public: explicit FillFormatter( ObjectFormatterData& rData, - const AutoFormatEntry* pAutoFormatEntry, - PropertyType ePropType ); + const AutoFormatEntry* pAutoFormatEntry ); /** Converts area formatting to the passed property set. */ void convertFormatting( - PropertySet& rPropSet, + ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ); private: FillPropertiesPtr mxAutoFill; /// Automatic fill properties. - FillPropertyIds& mrFillPropIds; /// Property identifiers for fill formatting. }; // ---------------------------------------------------------------------------- @@ -649,12 +669,11 @@ class EffectFormatter : public DetailFormatterBase public: explicit EffectFormatter( ObjectFormatterData& rData, - const AutoFormatEntry* pAutoFormatEntry, - PropertyType ePropType ); + const AutoFormatEntry* pAutoFormatEntry ); /** Converts effect formatting to the passed property set. */ void convertFormatting( - PropertySet& rPropSet, + ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx ); }; @@ -731,6 +750,7 @@ private: FillFormatter maFillFormatter; /// Converter for fill formatting. EffectFormatter maEffectFormatter; /// Converter for effect formatting. TextFormatter maTextFormatter; /// Converter for text formatting. + ModelObjectHelper& mrModelObjHelper; /// Helper for named drawing formatting. const ObjectTypeFormatEntry& mrEntry; /// Additional settings. }; @@ -743,11 +763,6 @@ struct ObjectFormatterData const XmlFilterBase& mrFilter; /// Base filter object. ObjectTypeFormatterMap maTypeFormatters; /// Formatters for all types of objects in a chart. ModelObjectHelper maModelObjHelper; /// Helper for named drawing formatting (dashes, gradients, bitmaps). - LinePropertyIds maCommonLineIds; /// Property identifiers for common border formatting. - LinePropertyIds maLinearLineIds; /// Property identifiers for line formatting of linear series. - LinePropertyIds maFilledLineIds; /// Property identifiers for line formatting of filled series. - FillPropertyIds maCommonFillIds; /// Property identifiers for common area fill. - FillPropertyIds maFilledFillIds; /// Property identifiers for area fill of filled series. Reference< XNumberFormats > mxNumFmts; /// Number formats collection of container document. Reference< XNumberFormatTypes > mxNumTypes; /// Number format types collection of container document. Locale maEnUsLocale; /// Locale struct containing en-US. @@ -760,9 +775,6 @@ struct ObjectFormatterData const ChartSpaceModel& rChartSpace ); ObjectTypeFormatter* getTypeFormatter( ObjectType eObjType ); - - LinePropertyIds& getLinePropertyIds( PropertyType ePropType ); - FillPropertyIds& getFillPropertyIds( PropertyType ePropType ); }; // ============================================================================ @@ -859,9 +871,8 @@ sal_Int32 DetailFormatterBase::getSchemeColor( sal_Int32 nColorToken, sal_Int32 // ============================================================================ -LineFormatter::LineFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, PropertyType ePropType ) : - DetailFormatterBase( rData, pAutoFormatEntry ), - mrLinePropIds( rData.getLinePropertyIds( ePropType ) ) +LineFormatter::LineFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry ) : + DetailFormatterBase( rData, pAutoFormatEntry ) { if( pAutoFormatEntry ) { @@ -876,21 +887,20 @@ LineFormatter::LineFormatter( ObjectFormatterData& rData, const AutoFormatEntry* } } -void LineFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx ) +void LineFormatter::convertFormatting( ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, sal_Int32 nSeriesIdx ) { LineProperties aLineProps; if( mxAutoLine.get() ) aLineProps.assignUsed( *mxAutoLine ); if( rxShapeProp.is() ) aLineProps.assignUsed( rxShapeProp->getLineProperties() ); - aLineProps.pushToPropSet( rPropSet, mrData.maModelObjHelper, mrData.mrFilter.getGraphicHelper(), mrLinePropIds, getPhColor( nSeriesIdx ) ); + aLineProps.pushToPropMap( rPropMap, mrData.mrFilter.getGraphicHelper(), getPhColor( nSeriesIdx ) ); } // ============================================================================ -FillFormatter::FillFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, PropertyType ePropType ) : - DetailFormatterBase( rData, pAutoFormatEntry ), - mrFillPropIds( rData.getFillPropertyIds( ePropType ) ) +FillFormatter::FillFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry ) : + DetailFormatterBase( rData, pAutoFormatEntry ) { if( pAutoFormatEntry ) { @@ -902,7 +912,7 @@ FillFormatter::FillFormatter( ObjectFormatterData& rData, const AutoFormatEntry* } } -void FillFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) +void FillFormatter::convertFormatting( ShapePropertyMap& rPropMap, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) { FillProperties aFillProps; if( mxAutoFill.get() ) @@ -911,17 +921,17 @@ void FillFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Sh aFillProps.assignUsed( rxShapeProp->getFillProperties() ); if( pPicOptions ) lclConvertPictureOptions( aFillProps, *pPicOptions ); - aFillProps.pushToPropSet( rPropSet, mrData.maModelObjHelper, mrData.mrFilter.getGraphicHelper(), mrFillPropIds, 0, getPhColor( nSeriesIdx ) ); + aFillProps.pushToPropMap( rPropMap, mrData.mrFilter.getGraphicHelper(), 0, getPhColor( nSeriesIdx ) ); } // ============================================================================ -EffectFormatter::EffectFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry, PropertyType /*ePropType*/ ) : +EffectFormatter::EffectFormatter( ObjectFormatterData& rData, const AutoFormatEntry* pAutoFormatEntry ) : DetailFormatterBase( rData, pAutoFormatEntry ) { } -void EffectFormatter::convertFormatting( PropertySet& /*rPropSet*/, const ModelRef< Shape >& /*rxShapeProp*/, sal_Int32 /*nSeriesIdx*/ ) +void EffectFormatter::convertFormatting( ShapePropertyMap& /*rPropMap*/, const ModelRef< Shape >& /*rxShapeProp*/, sal_Int32 /*nSeriesIdx*/ ) { } @@ -979,20 +989,23 @@ void TextFormatter::convertFormatting( PropertySet& rPropSet, const ModelRef< Te // ============================================================================ ObjectTypeFormatter::ObjectTypeFormatter( ObjectFormatterData& rData, const ObjectTypeFormatEntry& rEntry, const ChartSpaceModel& rChartSpace ) : - maLineFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoLines, rChartSpace.mnStyle ), rEntry.mePropType ), - maFillFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoFills, rChartSpace.mnStyle ), rEntry.mePropType ), - maEffectFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoEffects, rChartSpace.mnStyle ), rEntry.mePropType ), + maLineFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoLines, rChartSpace.mnStyle ) ), + maFillFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoFills, rChartSpace.mnStyle ) ), + maEffectFormatter( rData, lclGetAutoFormatEntry( rEntry.mpAutoEffects, rChartSpace.mnStyle ) ), maTextFormatter( rData, lclGetAutoTextEntry( rEntry.mpAutoTexts, rChartSpace.mnStyle ), rChartSpace.mxTextProp ), + mrModelObjHelper( rData.maModelObjHelper ), mrEntry( rEntry ) { } void ObjectTypeFormatter::convertFrameFormatting( PropertySet& rPropSet, const ModelRef< Shape >& rxShapeProp, const PictureOptionsModel* pPicOptions, sal_Int32 nSeriesIdx ) { - maLineFormatter.convertFormatting( rPropSet, rxShapeProp, nSeriesIdx ); + ShapePropertyMap aPropMap( mrModelObjHelper, *mrEntry.mpPropInfo ); + maLineFormatter.convertFormatting( aPropMap, rxShapeProp, nSeriesIdx ); if( mrEntry.mbIsFrame ) - maFillFormatter.convertFormatting( rPropSet, rxShapeProp, pPicOptions, nSeriesIdx ); - maEffectFormatter.convertFormatting( rPropSet, rxShapeProp, nSeriesIdx ); + maFillFormatter.convertFormatting( aPropMap, rxShapeProp, pPicOptions, nSeriesIdx ); + maEffectFormatter.convertFormatting( aPropMap, rxShapeProp, nSeriesIdx ); + rPropSet.setProperties( aPropMap ); } void ObjectTypeFormatter::convertTextFormatting( PropertySet& rPropSet, const ModelRef< TextBody >& rxTextProp ) @@ -1013,16 +1026,20 @@ void ObjectTypeFormatter::convertTextFormatting( PropertySet& rPropSet, const Te void ObjectTypeFormatter::convertAutomaticLine( PropertySet& rPropSet, sal_Int32 nSeriesIdx ) { + ShapePropertyMap aPropMap( mrModelObjHelper, *mrEntry.mpPropInfo ); ModelRef< Shape > xShapeProp; - maLineFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); - maEffectFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); + maLineFormatter.convertFormatting( aPropMap, xShapeProp, nSeriesIdx ); + maEffectFormatter.convertFormatting( aPropMap, xShapeProp, nSeriesIdx ); + rPropSet.setProperties( aPropMap ); } void ObjectTypeFormatter::convertAutomaticFill( PropertySet& rPropSet, sal_Int32 nSeriesIdx ) { + ShapePropertyMap aPropMap( mrModelObjHelper, *mrEntry.mpPropInfo ); ModelRef< Shape > xShapeProp; - maFillFormatter.convertFormatting( rPropSet, xShapeProp, 0, nSeriesIdx ); - maEffectFormatter.convertFormatting( rPropSet, xShapeProp, nSeriesIdx ); + maFillFormatter.convertFormatting( aPropMap, xShapeProp, 0, nSeriesIdx ); + maEffectFormatter.convertFormatting( aPropMap, xShapeProp, nSeriesIdx ); + rPropSet.setProperties( aPropMap ); } // ============================================================================ @@ -1030,11 +1047,6 @@ void ObjectTypeFormatter::convertAutomaticFill( PropertySet& rPropSet, sal_Int32 ObjectFormatterData::ObjectFormatterData( const XmlFilterBase& rFilter, const Reference< XChartDocument >& rxChartDoc, const ChartSpaceModel& rChartSpace ) : mrFilter( rFilter ), maModelObjHelper( Reference< XMultiServiceFactory >( rxChartDoc, UNO_QUERY ) ), - maCommonLineIds( spnCommonLineIds, true, false ), - maLinearLineIds( spnLinearLineIds, true, false ), - maFilledLineIds( spnFilledLineIds, true, false ), - maCommonFillIds( spnCommonFillIds, true, true ), - maFilledFillIds( spnFilledFillIds, true, true ), maEnUsLocale( CREATE_OUSTRING( "en" ), CREATE_OUSTRING( "US" ), OUString() ), mnMaxSeriesIdx( -1 ) { @@ -1060,28 +1072,6 @@ ObjectTypeFormatter* ObjectFormatterData::getTypeFormatter( ObjectType eObjType return maTypeFormatters.get( eObjType ).get(); } -LinePropertyIds& ObjectFormatterData::getLinePropertyIds( PropertyType ePropType ) -{ - switch( ePropType ) - { - case PROPERTYTYPE_COMMON: return maCommonLineIds; - case PROPERTYTYPE_LINEARSERIES: return maLinearLineIds; - case PROPERTYTYPE_FILLEDSERIES: return maFilledLineIds; - } - return maCommonLineIds; -} - -FillPropertyIds& ObjectFormatterData::getFillPropertyIds( PropertyType ePropType ) -{ - switch( ePropType ) - { - case PROPERTYTYPE_COMMON: return maCommonFillIds; - case PROPERTYTYPE_LINEARSERIES: return maCommonFillIds; - case PROPERTYTYPE_FILLEDSERIES: return maFilledFillIds; - } - return maCommonFillIds; -} - // ============================================================================ ObjectFormatter::ObjectFormatter( const XmlFilterBase& rFilter, const Reference< XChartDocument >& rxChartDoc, const ChartSpaceModel& rChartSpace ) : @@ -1160,7 +1150,7 @@ void ObjectFormatter::convertNumberFormat( PropertySet& rPropSet, const NumberFo sal_Int32 nPropId = bPercentFormat ? PROP_PercentageNumberFormat : PROP_NumberFormat; if( rNumberFormat.mbSourceLinked || (rNumberFormat.maFormatCode.getLength() == 0) ) { - rPropSet.setProperty( nPropId, Any() ); + rPropSet.setAnyProperty( nPropId, Any() ); } else try { diff --git a/oox/source/drawingml/chart/titleconverter.cxx b/oox/source/drawingml/chart/titleconverter.cxx index 7144845e6..7b917d314 100644 --- a/oox/source/drawingml/chart/titleconverter.cxx +++ b/oox/source/drawingml/chart/titleconverter.cxx @@ -27,7 +27,7 @@ #include "oox/drawingml/chart/titleconverter.hxx" -#include <com/sun/star/chart2/LegendExpansion.hpp> +#include <com/sun/star/chart/ChartLegendExpansion.hpp> #include <com/sun/star/chart2/LegendPosition.hpp> #include <com/sun/star/chart2/XDiagram.hpp> #include <com/sun/star/chart2/XFormattedString.hpp> @@ -198,6 +198,7 @@ void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) { if( rxDiagram.is() ) try { + namespace cssc = ::com::sun::star::chart; namespace cssc2 = ::com::sun::star::chart2; // create the legend @@ -211,46 +212,35 @@ void LegendConverter::convertFromModel( const Reference< XDiagram >& rxDiagram ) // predefined legend position and expansion cssc2::LegendPosition eLegendPos = cssc2::LegendPosition_CUSTOM; - cssc2::LegendExpansion eLegendExpand = cssc2::LegendExpansion_HIGH; + cssc::ChartLegendExpansion eLegendExpand = cssc::ChartLegendExpansion_CUSTOM; switch( mrModel.mnPosition ) { case XML_l: eLegendPos = cssc2::LegendPosition_LINE_START; - eLegendExpand = cssc2::LegendExpansion_HIGH; + eLegendExpand = cssc::ChartLegendExpansion_HIGH; break; case XML_r: + case XML_tr: // top-right not supported eLegendPos = cssc2::LegendPosition_LINE_END; - eLegendExpand = cssc2::LegendExpansion_HIGH; + eLegendExpand = cssc::ChartLegendExpansion_HIGH; break; case XML_t: eLegendPos = cssc2::LegendPosition_PAGE_START; - eLegendExpand = cssc2::LegendExpansion_WIDE; + eLegendExpand = cssc::ChartLegendExpansion_WIDE; break; case XML_b: eLegendPos = cssc2::LegendPosition_PAGE_END; - eLegendExpand = cssc2::LegendExpansion_WIDE; - break; - case XML_tr: - eLegendPos = cssc2::LegendPosition_LINE_END; // top-right not supported - eLegendExpand = cssc2::LegendExpansion_HIGH; + eLegendExpand = cssc::ChartLegendExpansion_WIDE; break; } - // manual positioning - LayoutModel& rLayout = mrModel.mxLayout.getOrCreate(); - LayoutConverter aLayoutConv( *this, rLayout ); - aLayoutConv.convertFromModel( aPropSet ); - Rectangle aLegendRect; - if( aLayoutConv.calcAbsRectangle( aLegendRect ) ) + // manual positioning and size + if( mrModel.mxLayout.get() ) { - // #i71697# it is not possible to set the size directly, do some magic here - double fRatio = static_cast< double >( aLegendRect.Width ) / aLegendRect.Height; - if( fRatio > 1.5 ) - eLegendExpand = cssc2::LegendExpansion_WIDE; - else if( fRatio < 0.75 ) - eLegendExpand = cssc2::LegendExpansion_HIGH; - else - eLegendExpand = cssc2::LegendExpansion_BALANCED; + LayoutConverter aLayoutConv( *this, *mrModel.mxLayout ); + // manual size needs ChartLegendExpansion_CUSTOM + if( aLayoutConv.convertFromModel( aPropSet ) ) + eLegendExpand = cssc::ChartLegendExpansion_CUSTOM; } // set position and expansion properties diff --git a/oox/source/drawingml/color.cxx b/oox/source/drawingml/color.cxx index f2dc99772..72d70c01d 100644 --- a/oox/source/drawingml/color.cxx +++ b/oox/source/drawingml/color.cxx @@ -512,12 +512,12 @@ sal_Int32 Color::getColor( const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr return mnC1; } -bool Color::hasTransparence() const +bool Color::hasTransparency() const { return mnAlpha < MAX_PERCENT; } -sal_Int16 Color::getTransparence() const +sal_Int16 Color::getTransparency() const { return static_cast< sal_Int16 >( (MAX_PERCENT - mnAlpha) / PER_PERCENT ); } diff --git a/oox/source/drawingml/diagram/makefile.mk b/oox/source/drawingml/diagram/makefile.mk index 9d526ed3d..9d526ed3d 100644..100755 --- a/oox/source/drawingml/diagram/makefile.mk +++ b/oox/source/drawingml/diagram/makefile.mk diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx index 267ab456a..9ce69fc35 100644 --- a/oox/source/drawingml/fillproperties.cxx +++ b/oox/source/drawingml/fillproperties.cxx @@ -26,6 +26,7 @@ ************************************************************************/ #include "oox/drawingml/fillproperties.hxx" + #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/awt/Gradient.hpp> @@ -37,10 +38,8 @@ #include <com/sun/star/drawing/RectanglePoint.hpp> #include <com/sun/star/graphic/XGraphicTransformer.hpp> #include "oox/helper/graphichelper.hxx" -#include "oox/helper/modelobjecthelper.hxx" -#include "oox/helper/propertymap.hxx" -#include "oox/helper/propertyset.hxx" #include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/shapepropertymap.hxx" #include "oox/token/tokens.hxx" using namespace ::com::sun::star; @@ -61,21 +60,6 @@ namespace drawingml { namespace { -static const sal_Int32 spnDefaultFillIds[ FillId_END ] = -{ - PROP_FillStyle, - PROP_FillColor, - PROP_FillTransparence, - PROP_FillGradient, - PROP_FillBitmapURL, - PROP_FillBitmapMode, - PROP_FillBitmapSizeX, - PROP_FillBitmapSizeY, - PROP_FillBitmapPositionOffsetX, - PROP_FillBitmapPositionOffsetY, - PROP_FillBitmapRectanglePoint -}; - BitmapMode lclGetBitmapMode( sal_Int32 nToken ) { switch( nToken ) @@ -129,16 +113,6 @@ const awt::Size lclGetOriginalSize( const GraphicHelper& rGraphicHelper, const R // ============================================================================ -FillPropertyIds::FillPropertyIds( const sal_Int32* pnPropertyIds, bool bNamedFillGradient, bool bNamedFillBitmap ) : - mpnPropertyIds( pnPropertyIds ), - mbNamedFillGradient( bNamedFillGradient ), - mbNamedFillBitmap( bNamedFillBitmap ) -{ - OSL_ENSURE( mpnPropertyIds != 0, "FillPropertyIds::FillPropertyIds - missing property identifiers" ); -} - -// ============================================================================ - void GradientFillProperties::assignUsed( const GradientFillProperties& rSourceProps ) { if( !rSourceProps.maGradientStops.empty() ) @@ -185,8 +159,6 @@ void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps ) // ============================================================================ -FillPropertyIds FillProperties::DEFAULT_IDS( spnDefaultFillIds, false, false ); - void FillProperties::assignUsed( const FillProperties& rSourceProps ) { moFillType.assignIfUsed( rSourceProps.moFillType ); @@ -215,9 +187,8 @@ Color FillProperties::getBestSolidColor() const return aSolidColor; } -void FillProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rModelObjHelper, - const GraphicHelper& rGraphicHelper, const FillPropertyIds& rPropIds, - sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const +void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap, + const GraphicHelper& rGraphicHelper, sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const { if( moFillType.has() ) { @@ -231,16 +202,16 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rM case XML_solidFill: if( maFillColor.isUsed() ) { - rPropMap.setProperty( rPropIds[ FillColorId ], maFillColor.getColor( rGraphicHelper, nPhClr ) ); - if( maFillColor.hasTransparence() ) - rPropMap.setProperty( rPropIds[ FillTransparenceId ], maFillColor.getTransparence() ); + rPropMap.setProperty( SHAPEPROP_FillColor, maFillColor.getColor( rGraphicHelper, nPhClr ) ); + if( maFillColor.hasTransparency() ) + rPropMap.setProperty( SHAPEPROP_FillTransparency, maFillColor.getTransparency() ); eFillStyle = FillStyle_SOLID; } break; case XML_gradFill: // do not create gradient struct if property is not supported... - if( rPropIds.has( FillGradientId ) ) + if( rPropMap.supportsProperty( SHAPEPROP_FillGradient ) ) { awt::Gradient aGradient; aGradient.Angle = 900; @@ -290,62 +261,35 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rM aGradient.Angle = static_cast< sal_Int16 >( (4500 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 ); // push gradient or named gradient to property map - if( rPropIds.mbNamedFillGradient ) - { - OUString aGradientName = rModelObjHelper.insertFillGradient( aGradient ); - if( aGradientName.getLength() > 0 ) - { - rPropMap.setProperty( rPropIds[ FillGradientId ], aGradientName ); - eFillStyle = FillStyle_GRADIENT; - } - } - else - { - rPropMap.setProperty( rPropIds[ FillGradientId ], aGradient ); + if( rPropMap.setProperty( SHAPEPROP_FillGradient, aGradient ) ) eFillStyle = FillStyle_GRADIENT; - } } break; case XML_blipFill: // do not start complex graphic transformation if property is not supported... - if( maBlipProps.mxGraphic.is() && rPropIds.has( FillBitmapUrlId ) ) + if( maBlipProps.mxGraphic.is() && rPropMap.supportsProperty( SHAPEPROP_FillBitmapUrl ) ) { // TODO: "rotate with shape" is not possible with our current core OUString aGraphicUrl = rGraphicHelper.createGraphicObject( maBlipProps.mxGraphic ); - if( aGraphicUrl.getLength() > 0 ) - { - // push bitmap or named bitmap to property map - if( rPropIds.mbNamedFillBitmap ) - { - OUString aBitmapName = rModelObjHelper.insertFillBitmap( aGraphicUrl ); - if( aBitmapName.getLength() > 0 ) - { - rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aBitmapName ); - eFillStyle = FillStyle_BITMAP; - } - } - else - { - rPropMap.setProperty( rPropIds[ FillBitmapUrlId ], aGraphicUrl ); - eFillStyle = FillStyle_BITMAP; - } - } + // push bitmap or named bitmap to property map + if( (aGraphicUrl.getLength() > 0) && rPropMap.setProperty( SHAPEPROP_FillBitmapUrl, aGraphicUrl ) ) + eFillStyle = FillStyle_BITMAP; // set other bitmap properties, if bitmap has been inserted into the map if( eFillStyle == FillStyle_BITMAP ) { // bitmap mode (single, repeat, stretch) BitmapMode eBitmapMode = lclGetBitmapMode( maBlipProps.moBitmapMode.get( XML_TOKEN_INVALID ) ); - rPropMap.setProperty( rPropIds[ FillBitmapModeId ], eBitmapMode ); + rPropMap.setProperty( SHAPEPROP_FillBitmapMode, eBitmapMode ); // additional settings for repeated bitmap if( eBitmapMode == BitmapMode_REPEAT ) { // anchor position inside bitmap RectanglePoint eRectPoint = lclGetRectanglePoint( maBlipProps.moTileAlign.get( XML_tl ) ); - rPropMap.setProperty( rPropIds[ FillBitmapRectanglePointId ], eRectPoint ); + rPropMap.setProperty( SHAPEPROP_FillBitmapRectanglePoint, eRectPoint ); awt::Size aOriginalSize = lclGetOriginalSize( rGraphicHelper, maBlipProps.mxGraphic ); if( (aOriginalSize.Width > 0) && (aOriginalSize.Height > 0) ) @@ -353,16 +297,16 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rM // size of one bitmap tile (given as 1/1000 percent of bitmap size), convert to 1/100 mm double fScaleX = maBlipProps.moTileScaleX.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT ); sal_Int32 nFillBmpSizeX = getLimitedValue< sal_Int32, double >( aOriginalSize.Width * fScaleX, 1, SAL_MAX_INT32 ); - rPropMap.setProperty( rPropIds[ FillBitmapSizeXId ], nFillBmpSizeX ); + rPropMap.setProperty( SHAPEPROP_FillBitmapSizeX, nFillBmpSizeX ); double fScaleY = maBlipProps.moTileScaleY.get( MAX_PERCENT ) / static_cast< double >( MAX_PERCENT ); sal_Int32 nFillBmpSizeY = getLimitedValue< sal_Int32, double >( aOriginalSize.Height * fScaleY, 1, SAL_MAX_INT32 ); - rPropMap.setProperty( rPropIds[ FillBitmapSizeYId ], nFillBmpSizeY ); + rPropMap.setProperty( SHAPEPROP_FillBitmapSizeY, nFillBmpSizeY ); // offset of the first bitmap tile (given as EMUs), convert to percent sal_Int16 nTileOffsetX = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetX.get( 0 ) / 3.6 / aOriginalSize.Width, 0, 100 ); - rPropMap.setProperty( rPropIds[ FillBitmapOffsetXId ], nTileOffsetX ); + rPropMap.setProperty( SHAPEPROP_FillBitmapOffsetX, nTileOffsetX ); sal_Int16 nTileOffsetY = getDoubleIntervalValue< sal_Int16 >( maBlipProps.moTileOffsetY.get( 0 ) / 3.6 / aOriginalSize.Height, 0, 100 ); - rPropMap.setProperty( rPropIds[ FillBitmapOffsetYId ], nTileOffsetY ); + rPropMap.setProperty( SHAPEPROP_FillBitmapOffsetY, nTileOffsetY ); } } } @@ -375,9 +319,9 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rM Color aColor = getBestSolidColor(); if( aColor.isUsed() ) { - rPropMap.setProperty( rPropIds[ FillColorId ], aColor.getColor( rGraphicHelper, nPhClr ) ); - if( aColor.hasTransparence() ) - rPropMap.setProperty( rPropIds[ FillTransparenceId ], aColor.getTransparence() ); + rPropMap.setProperty( SHAPEPROP_FillColor, aColor.getColor( rGraphicHelper, nPhClr ) ); + if( aColor.hasTransparency() ) + rPropMap.setProperty( SHAPEPROP_FillTransparency, aColor.getTransparency() ); eFillStyle = FillStyle_SOLID; } } @@ -390,19 +334,10 @@ void FillProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rM } // set final fill style property - rPropMap.setProperty( rPropIds[ FillStyleId ], eFillStyle ); + rPropMap.setProperty( SHAPEPROP_FillStyle, eFillStyle ); } } -void FillProperties::pushToPropSet( PropertySet& rPropSet, ModelObjectHelper& rModelObjHelper, - const GraphicHelper& rGraphicHelper, const FillPropertyIds& rPropIds, - sal_Int32 nShapeRotation, sal_Int32 nPhClr ) const -{ - PropertyMap aPropMap; - pushToPropMap( aPropMap, rModelObjHelper, rGraphicHelper, rPropIds, nShapeRotation, nPhClr ); - rPropSet.setProperties( aPropMap ); -} - // ============================================================================ void GraphicProperties::assignUsed( const GraphicProperties& rSourceProps ) @@ -420,9 +355,9 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe { sal_Int32 nFromColor = maBlipProps.maColorChangeFrom.getColor( rGraphicHelper, nPhClr ); sal_Int32 nToColor = maBlipProps.maColorChangeTo.getColor( rGraphicHelper, nPhClr ); - if ( (nFromColor != nToColor) || maBlipProps.maColorChangeTo.hasTransparence() ) try + if ( (nFromColor != nToColor) || maBlipProps.maColorChangeTo.hasTransparency() ) try { - sal_Int16 nToTransparence = maBlipProps.maColorChangeTo.getTransparence(); + sal_Int16 nToTransparence = maBlipProps.maColorChangeTo.getTransparency(); sal_Int8 nToAlpha = static_cast< sal_Int8 >( (100 - nToTransparence) / 39.062 ); // ?!? correct ?!? Reference< XGraphicTransformer > xTransformer( maBlipProps.mxGraphic, UNO_QUERY_THROW ); xGraphic = xTransformer->colorChange( maBlipProps.mxGraphic, nFromColor, 9, nToColor, nToAlpha ); @@ -475,13 +410,6 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe rPropMap[ PROP_AdjustContrast ] <<= nContrast; } -void GraphicProperties::pushToPropSet( PropertySet& rPropSet, const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const -{ - PropertyMap aPropMap; - pushToPropMap( aPropMap, rGraphicHelper, nPhClr ); - rPropSet.setProperties( aPropMap ); -} - // ============================================================================ } // namespace drawingml diff --git a/oox/source/drawingml/lineproperties.cxx b/oox/source/drawingml/lineproperties.cxx index c31544cd9..e2a86bf77 100644 --- a/oox/source/drawingml/lineproperties.cxx +++ b/oox/source/drawingml/lineproperties.cxx @@ -28,6 +28,7 @@ #include "oox/drawingml/lineproperties.hxx" #include <vector> #include <rtl/ustrbuf.hxx> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/container/XNameContainer.hpp> #include <com/sun/star/drawing/FlagSequence.hpp> #include <com/sun/star/drawing/LineDash.hpp> @@ -35,14 +36,13 @@ #include <com/sun/star/drawing/LineStyle.hpp> #include <com/sun/star/drawing/PointSequence.hpp> #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include "oox/drawingml/drawingmltypes.hxx" +#include "oox/drawingml/shapepropertymap.hxx" #include "oox/helper/containerhelper.hxx" #include "oox/helper/graphichelper.hxx" -#include "oox/helper/modelobjecthelper.hxx" -#include "oox/helper/propertymap.hxx" -#include "oox/helper/propertyset.hxx" -#include "oox/drawingml/drawingmltypes.hxx" #include "oox/token/tokens.hxx" +using namespace ::com::sun::star::beans; using namespace ::com::sun::star::drawing; using ::rtl::OUString; @@ -59,24 +59,6 @@ namespace drawingml { namespace { -static const sal_Int32 spnDefaultLineIds[ LineId_END ] = -{ - PROP_LineStyle, - PROP_LineWidth, - PROP_LineColor, - PROP_LineTransparence, - PROP_LineDash, - PROP_LineJoint, - PROP_LineStartName, - PROP_LineStartWidth, - PROP_LineStartCenter, - PROP_LineEndName, - PROP_LineEndWidth, - PROP_LineEndCenter -}; - -// ---------------------------------------------------------------------------- - void lclSetDashData( LineDash& orLineDash, sal_Int16 nDots, sal_Int32 nDotLen, sal_Int16 nDashes, sal_Int32 nDashLen, sal_Int32 nDistance ) { @@ -195,15 +177,16 @@ sal_Int32 lclGetArrowSize( sal_Int32 nToken ) // ---------------------------------------------------------------------------- -void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& rArrowProps, - ModelObjectHelper& rModelObjHelper, const LinePropertyIds& rPropIds, sal_Int32 nLineWidth, bool bLineEnd ) +void lclPushMarkerProperties( ShapePropertyMap& rPropMap, + const LineArrowProperties& rArrowProps, sal_Int32 nLineWidth, bool bLineEnd ) { - PolyPolygonBezierCoords aMarker; - OUString aMarkerName; - sal_Int32 nMarkerWidth = 0; - bool bMarkerCenter = false; + /* Store the marker polygon and the marker name in a single value, to be + able to pass both to the ShapePropertyMap::setProperty() function. */ + NamedValue aNamedMarker; OUStringBuffer aBuffer; + sal_Int32 nMarkerWidth = 0; + bool bMarkerCenter = false; sal_Int32 nArrowType = rArrowProps.moArrowType.get( XML_none ); switch( nArrowType ) { @@ -233,7 +216,7 @@ void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& sal_Int32 nNameIndex = nWidth * 3 + nLength + 1; aBuffer.append( sal_Unicode( ' ' ) ).append( nNameIndex ); - aMarkerName = aBuffer.makeStringAndClear(); + OUString aMarkerName = aBuffer.makeStringAndClear(); bool bIsArrow = nArrowType == XML_arrow; double fArrowLength = 1.0; @@ -250,12 +233,15 @@ void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& case OOX_ARROWSIZE_MEDIUM: fArrowWidth = (bIsArrow ? 4.5 : 3.0); break; case OOX_ARROWSIZE_LARGE: fArrowWidth = (bIsArrow ? 6.0 : 5.0); break; } - // set arrow width relative to line width (convert line width from EMUs to 1/100 mm) - sal_Int32 nApiLineWidth = ::std::max< sal_Int32 >( GetCoordinate( nLineWidth ), 70 ); - nMarkerWidth = static_cast< sal_Int32 >( fArrowWidth * nApiLineWidth ); - - // test if the arrow already exists, do not create it again in this case - if( !rPropIds.mbNamedLineMarker || !rModelObjHelper.hasLineMarker( aMarkerName ) ) + // set arrow width relative to line width + sal_Int32 nBaseLineWidth = ::std::max< sal_Int32 >( nLineWidth, 70 ); + nMarkerWidth = static_cast< sal_Int32 >( fArrowWidth * nBaseLineWidth ); + + /* Test if the marker already exists in the marker table, do not + create it again in this case. If markers are inserted explicitly + instead by their name, the polygon will be created always. + TODO: this can be optimized by using a map. */ + if( !rPropMap.hasNamedLineMarkerInTable( aMarkerName ) ) { // pass X and Y as percentage to OOX_ARROW_POINT #define OOX_ARROW_POINT( x, y ) Point( static_cast< sal_Int32 >( fArrowWidth * x ), static_cast< sal_Int32 >( fArrowLength * y ) ) @@ -310,46 +296,44 @@ void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& } #undef OOX_ARROW_POINT - OSL_ENSURE( !aPoints.empty(), "ApiLineMarkerProperties::ApiLineMarkerProperties - missing arrow coordinates" ); + OSL_ENSURE( !aPoints.empty(), "lclPushMarkerProperties - missing arrow coordinates" ); if( !aPoints.empty() ) { - aMarker.Coordinates.realloc( 1 ); - aMarker.Coordinates[ 0 ] = ContainerHelper::vectorToSequence( aPoints ); + PolyPolygonBezierCoords aMarkerCoords; + aMarkerCoords.Coordinates.realloc( 1 ); + aMarkerCoords.Coordinates[ 0 ] = ContainerHelper::vectorToSequence( aPoints ); ::std::vector< PolygonFlags > aFlags( aPoints.size(), PolygonFlags_NORMAL ); - aMarker.Flags.realloc( 1 ); - aMarker.Flags[ 0 ] = ContainerHelper::vectorToSequence( aFlags ); + aMarkerCoords.Flags.realloc( 1 ); + aMarkerCoords.Flags[ 0 ] = ContainerHelper::vectorToSequence( aFlags ); - if( rPropIds.mbNamedLineMarker && !rModelObjHelper.insertLineMarker( aMarkerName, aMarker ) ) - aMarkerName = OUString(); - } - else - { - aMarkerName = OUString(); + aNamedMarker.Name = aMarkerName; + aNamedMarker.Value <<= aMarkerCoords; } } + else + { + /* Named marker object exists already in the marker table, pass + its name only. This will set the name as property value, but + does not create a new object in the marker table. */ + aNamedMarker.Name = aMarkerName; + } } - // push the properties (filled aMarkerName indicates valid marker) - if( aMarkerName.getLength() > 0 ) + // push the properties (filled aNamedMarker.Name indicates valid marker) + if( aNamedMarker.Name.getLength() > 0 ) { if( bLineEnd ) { - if( rPropIds.mbNamedLineMarker ) - rPropMap.setProperty( rPropIds[ LineEndId ], aMarkerName ); - else - rPropMap.setProperty( rPropIds[ LineEndId ], aMarker ); - rPropMap.setProperty( rPropIds[ LineEndWidthId ], nMarkerWidth ); - rPropMap.setProperty( rPropIds[ LineEndCenterId ], bMarkerCenter ); + rPropMap.setProperty( SHAPEPROP_LineEnd, aNamedMarker ); + rPropMap.setProperty( SHAPEPROP_LineEndWidth, nMarkerWidth ); + rPropMap.setProperty( SHAPEPROP_LineEndCenter, bMarkerCenter ); } else { - if( rPropIds.mbNamedLineMarker ) - rPropMap.setProperty( rPropIds[ LineStartId ], aMarkerName ); - else - rPropMap.setProperty( rPropIds[ LineStartId ], aMarker ); - rPropMap.setProperty( rPropIds[ LineStartWidthId ], nMarkerWidth ); - rPropMap.setProperty( rPropIds[ LineStartCenterId ], bMarkerCenter ); + rPropMap.setProperty( SHAPEPROP_LineStart, aNamedMarker ); + rPropMap.setProperty( SHAPEPROP_LineStartWidth, nMarkerWidth ); + rPropMap.setProperty( SHAPEPROP_LineStartCenter, bMarkerCenter ); } } } @@ -358,16 +342,6 @@ void lclPushMarkerProperties( PropertyMap& rPropMap, const LineArrowProperties& // ============================================================================ -LinePropertyIds::LinePropertyIds( const sal_Int32* pnPropertyIds, bool bNamedLineDash, bool bNamedLineMarker ) : - mpnPropertyIds( pnPropertyIds ), - mbNamedLineDash( bNamedLineDash ), - mbNamedLineMarker( bNamedLineMarker ) -{ - OSL_ENSURE( mpnPropertyIds != 0, "LinePropertyIds::LinePropertyIds - missing property identifiers" ); -} - -// ============================================================================ - void LineArrowProperties::assignUsed( const LineArrowProperties& rSourceProps ) { moArrowType.assignIfUsed( rSourceProps.moArrowType ); @@ -377,8 +351,6 @@ void LineArrowProperties::assignUsed( const LineArrowProperties& rSourceProps ) // ============================================================================ -LinePropertyIds LineProperties::DEFAULT_IDS( spnDefaultLineIds, false, true ); - void LineProperties::assignUsed( const LineProperties& rSourceProps ) { maStartArrow.assignUsed( rSourceProps.maStartArrow ); @@ -393,14 +365,17 @@ void LineProperties::assignUsed( const LineProperties& rSourceProps ) moLineJoint.assignIfUsed( rSourceProps.moLineJoint ); } -void LineProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rModelObjHelper, - const GraphicHelper& rGraphicHelper, const LinePropertyIds& rPropIds, sal_Int32 nPhClr ) const +void LineProperties::pushToPropMap( ShapePropertyMap& rPropMap, + const GraphicHelper& rGraphicHelper, sal_Int32 nPhClr ) const { // line fill type must exist, otherwise ignore other properties if( maLineFill.moFillType.has() ) { // line style (our core only supports none and solid) LineStyle eLineStyle = (maLineFill.moFillType.get() == XML_noFill) ? LineStyle_NONE : LineStyle_SOLID; + + // convert line width from EMUs to 1/100mm + sal_Int32 nLineWidth = convertEmuToHmm( moLineWidth.get( 0 ) ); // create line dash from preset dash token (not for invisible line) if( (eLineStyle != LineStyle_NONE) && (moPresetDash.differsFrom( XML_solid ) || (!moPresetDash && !maCustomDash.empty())) ) @@ -415,61 +390,40 @@ void LineProperties::pushToPropMap( PropertyMap& rPropMap, ModelObjectHelper& rM lclConvertCustomDash( aLineDash, maCustomDash ); // convert relative dash/dot length to absolute length - sal_Int32 nLineWidth = GetCoordinate( moLineWidth.get( 103500 ) ); - aLineDash.DotLen *= nLineWidth; - aLineDash.DashLen *= nLineWidth; - aLineDash.Distance *= nLineWidth; + sal_Int32 nBaseLineWidth = ::std::max< sal_Int32 >( nLineWidth, 35 ); + aLineDash.DotLen *= nBaseLineWidth; + aLineDash.DashLen *= nBaseLineWidth; + aLineDash.Distance *= nBaseLineWidth; - if( rPropIds.mbNamedLineDash ) - { - OUString aDashName = rModelObjHelper.insertLineDash( aLineDash ); - if( aDashName.getLength() > 0 ) - { - rPropMap.setProperty( rPropIds[ LineDashId ], aDashName ); - eLineStyle = LineStyle_DASH; - } - } - else - { - rPropMap.setProperty( rPropIds[ LineDashId ], aLineDash ); + if( rPropMap.setProperty( SHAPEPROP_LineDash, aLineDash ) ) eLineStyle = LineStyle_DASH; - } } // set final line style property - rPropMap.setProperty( rPropIds[ LineStyleId ], eLineStyle ); + rPropMap.setProperty( SHAPEPROP_LineStyle, eLineStyle ); // line joint type if( moLineJoint.has() ) - rPropMap.setProperty( rPropIds[ LineJointId ], lclGetLineJoint( moLineJoint.get() ) ); + rPropMap.setProperty( SHAPEPROP_LineJoint, lclGetLineJoint( moLineJoint.get() ) ); - // convert line width from EMUs to 1/100 mm - if( moLineWidth.has() ) - rPropMap.setProperty( rPropIds[ LineWidthId ], GetCoordinate( moLineWidth.get() ) ); + // line width in 1/100mm + rPropMap.setProperty( SHAPEPROP_LineWidth, nLineWidth ); // line color and transparence Color aLineColor = maLineFill.getBestSolidColor(); if( aLineColor.isUsed() ) { - rPropMap.setProperty( rPropIds[ LineColorId ], aLineColor.getColor( rGraphicHelper, nPhClr ) ); - if( aLineColor.hasTransparence() ) - rPropMap.setProperty( rPropIds[ LineTransparenceId ], aLineColor.getTransparence() ); + rPropMap.setProperty( SHAPEPROP_LineColor, aLineColor.getColor( rGraphicHelper, nPhClr ) ); + if( aLineColor.hasTransparency() ) + rPropMap.setProperty( SHAPEPROP_LineTransparency, aLineColor.getTransparency() ); } // line markers - lclPushMarkerProperties( rPropMap, maStartArrow, rModelObjHelper, rPropIds, moLineWidth.get( 0 ), false ); - lclPushMarkerProperties( rPropMap, maEndArrow, rModelObjHelper, rPropIds, moLineWidth.get( 0 ), true ); + lclPushMarkerProperties( rPropMap, maStartArrow, nLineWidth, false ); + lclPushMarkerProperties( rPropMap, maEndArrow, nLineWidth, true ); } } -void LineProperties::pushToPropSet( PropertySet& rPropSet, ModelObjectHelper& rModelObjHelper, - const GraphicHelper& rGraphicHelper, const LinePropertyIds& rPropIds, sal_Int32 nPhClr ) const -{ - PropertyMap aPropMap; - pushToPropMap( aPropMap, rModelObjHelper, rGraphicHelper, rPropIds, nPhClr ); - rPropSet.setProperties( aPropMap ); -} - // ============================================================================ } // namespace drawingml diff --git a/oox/source/drawingml/makefile.mk b/oox/source/drawingml/makefile.mk index e2d4ea6b8..0546fb4c2 100644..100755 --- a/oox/source/drawingml/makefile.mk +++ b/oox/source/drawingml/makefile.mk @@ -62,6 +62,7 @@ SLOFILES = \ $(SLO)$/shapecontext.obj\ $(SLO)$/shapegroupcontext.obj\ $(SLO)$/shapepropertiescontext.obj\ + $(SLO)$/shapepropertymap.obj\ $(SLO)$/shapestylecontext.obj\ $(SLO)$/spdefcontext.obj\ $(SLO)$/textbody.obj\ diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index d41cefc39..77a49cf9f 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -30,6 +30,7 @@ #include "oox/drawingml/theme.hxx" #include "oox/drawingml/fillproperties.hxx" #include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/shapepropertymap.hxx" #include "oox/drawingml/textbody.hxx" #include "oox/drawingml/table/tableproperties.hxx" #include "oox/drawingml/chart/chartconverter.hxx" @@ -413,7 +414,6 @@ Reference< XShape > Shape::createAndInsert( } } - ModelObjectHelper& rModelObjectHelper = rFilterBase.getModelObjectHelper(); const GraphicHelper& rGraphicHelper = rFilterBase.getGraphicHelper(); LineProperties aLineProperties; @@ -448,26 +448,20 @@ Reference< XShape > Shape::createAndInsert( aLineProperties.assignUsed( getLineProperties() ); aFillProperties.assignUsed( getFillProperties() ); - PropertyMap aShapeProperties; - PropertyMap::const_iterator aShapePropIter; + ShapePropertyMap aShapeProps( rFilterBase.getModelObjectHelper() ); // add properties from textbody to shape properties if( mpTextBody.get() ) - { - for ( aShapePropIter = mpTextBody->getTextProperties().maPropertyMap.begin(); - aShapePropIter != mpTextBody->getTextProperties().maPropertyMap.end(); aShapePropIter++ ) - aShapeProperties[ (*aShapePropIter).first ] = (*aShapePropIter).second; - } + aShapeProps.assignUsed( mpTextBody->getTextProperties().maPropertyMap ); - aShapeProperties.insert( getShapeProperties().begin(), getShapeProperties().end() ); // applying properties - PropertySet aPropSet( xSet ); + aShapeProps.assignUsed( getShapeProperties() ); if ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.GraphicObjectShape" ) ) - mpGraphicPropertiesPtr->pushToPropSet( aPropSet, rGraphicHelper ); + mpGraphicPropertiesPtr->pushToPropMap( aShapeProps, rGraphicHelper ); if ( mpTablePropertiesPtr.get() && ( aServiceName == OUString::createFromAscii( "com.sun.star.drawing.TableShape" ) ) ) mpTablePropertiesPtr->pushToPropSet( rFilterBase, xSet, mpMasterTextListStyle ); - aFillProperties.pushToPropSet( aPropSet, rModelObjectHelper, rGraphicHelper, FillProperties::DEFAULT_IDS, mnRotation, nFillPhClr ); - aLineProperties.pushToPropSet( aPropSet, rModelObjectHelper, rGraphicHelper, LineProperties::DEFAULT_IDS, nLinePhClr ); + aFillProperties.pushToPropMap( aShapeProps, rGraphicHelper, mnRotation, nFillPhClr ); + aLineProperties.pushToPropMap( aShapeProps, rGraphicHelper, nLinePhClr ); // applying autogrowheight property before setting shape size, because // the shape size might be changed if currently autogrowheight is true @@ -475,12 +469,12 @@ Reference< XShape > Shape::createAndInsert( Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); const OUString& rPropName = PropertyMap::getPropertyName( PROP_TextAutoGrowHeight ); if( xSetInfo.is() && xSetInfo->hasPropertyByName( rPropName ) ) - if( /*const Any* pAutoGrowHeight =*/ aShapeProperties.getProperty( PROP_TextAutoGrowHeight ) ) + if( aShapeProps.hasProperty( PROP_TextAutoGrowHeight ) ) xSet->setPropertyValue( rPropName, Any( false ) ); // do not set properties at a group shape (this causes assertions from svx) if( aServiceName != OUString::createFromAscii( "com.sun.star.drawing.GroupShape" ) ) - aPropSet.setProperties( aShapeProperties ); + PropertySet( xSet ).setProperties( aShapeProps ); if( bIsCustomShape ) { diff --git a/oox/source/drawingml/shapepropertymap.cxx b/oox/source/drawingml/shapepropertymap.cxx new file mode 100755 index 000000000..e19578fd0 --- /dev/null +++ b/oox/source/drawingml/shapepropertymap.cxx @@ -0,0 +1,194 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "oox/drawingml/shapepropertymap.hxx" + +#include <com/sun/star/awt/Gradient.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/drawing/LineDash.hpp> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> +#include "oox/helper/modelobjecthelper.hxx" + +namespace oox { +namespace drawingml { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::uno; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +static const sal_Int32 spnDefaultShapeIds[ SHAPEPROP_END ] = +{ + PROP_LineStyle, PROP_LineWidth, PROP_LineColor, PROP_LineTransparence, PROP_LineDash, PROP_LineJoint, + PROP_LineStartName, PROP_LineStartWidth, PROP_LineStartCenter, PROP_LineEndName, PROP_LineEndWidth, PROP_LineEndCenter, + PROP_FillStyle, PROP_FillColor, PROP_FillTransparence, PROP_FillGradient, + PROP_FillBitmapURL, PROP_FillBitmapMode, PROP_FillBitmapSizeX, PROP_FillBitmapSizeY, + PROP_FillBitmapPositionOffsetX, PROP_FillBitmapPositionOffsetY, PROP_FillBitmapRectanglePoint +}; + +} // namespace + +ShapePropertyInfo ShapePropertyInfo::DEFAULT( spnDefaultShapeIds, true, false, false, false ); + +ShapePropertyInfo::ShapePropertyInfo( const sal_Int32* pnPropertyIds, + bool bNamedLineMarker, bool bNamedLineDash, bool bNamedFillGradient, bool bNamedFillBitmapUrl ) : + mpnPropertyIds( pnPropertyIds ), + mbNamedLineMarker( bNamedLineMarker ), + mbNamedLineDash( bNamedLineDash ), + mbNamedFillGradient( bNamedFillGradient ), + mbNamedFillBitmapUrl( bNamedFillBitmapUrl ) +{ + OSL_ENSURE( mpnPropertyIds != 0, "ShapePropertyInfo::ShapePropertyInfo - missing property identifiers" ); +} + +// ============================================================================ + +ShapePropertyMap::ShapePropertyMap( ModelObjectHelper& rModelObjHelper, const ShapePropertyInfo& rShapePropInfo ) : + mrModelObjHelper( rModelObjHelper ), + maShapePropInfo( rShapePropInfo ) +{ +} + +bool ShapePropertyMap::supportsProperty( ShapePropertyId ePropId ) const +{ + return maShapePropInfo.has( ePropId ); +} + +bool ShapePropertyMap::hasNamedLineMarkerInTable( const OUString& rMarkerName ) const +{ + return maShapePropInfo.mbNamedLineMarker && mrModelObjHelper.hasLineMarker( rMarkerName ); +} + +bool ShapePropertyMap::setAnyProperty( ShapePropertyId ePropId, const Any& rValue ) +{ + // get current property identifier for the specified property + sal_Int32 nPropId = maShapePropInfo[ ePropId ]; + if( nPropId < 0 ) return false; + + // special handling for properties supporting named objects in tables + switch( ePropId ) + { + case SHAPEPROP_LineStart: + case SHAPEPROP_LineEnd: + return setLineMarker( nPropId, rValue ); + + case SHAPEPROP_LineDash: + return setLineDash( nPropId, rValue ); + + case SHAPEPROP_FillGradient: + return setFillGradient( nPropId, rValue ); + + case SHAPEPROP_FillBitmapUrl: + return setFillBitmapUrl( nPropId, rValue ); + + default:; // suppress compiler warnings + } + + // set plain property value + operator[]( nPropId ) = rValue; + return true; +} + +// private -------------------------------------------------------------------- + +bool ShapePropertyMap::setLineMarker( sal_Int32 nPropId, const Any& rValue ) +{ + NamedValue aNamedMarker; + if( (rValue >>= aNamedMarker) && (aNamedMarker.Name.getLength() > 0) ) + { + // push line marker explicitly + if( !maShapePropInfo.mbNamedLineMarker ) + return setAnyProperty( nPropId, aNamedMarker.Value ); + + // create named line marker (if coordinates have been passed) and push its name + bool bInserted = !aNamedMarker.Value.has< PolyPolygonBezierCoords >() || + mrModelObjHelper.insertLineMarker( aNamedMarker.Name, aNamedMarker.Value.get< PolyPolygonBezierCoords >() ); + return bInserted && setProperty( nPropId, aNamedMarker.Name ); + } + return false; +} + +bool ShapePropertyMap::setLineDash( sal_Int32 nPropId, const Any& rValue ) +{ + // push line dash explicitly + if( !maShapePropInfo.mbNamedLineDash ) + return setAnyProperty( nPropId, rValue ); + + // create named line dash and push its name + if( rValue.has< LineDash >() ) + { + OUString aDashName = mrModelObjHelper.insertLineDash( rValue.get< LineDash >() ); + return (aDashName.getLength() > 0) && setProperty( nPropId, aDashName ); + } + + return false; +} + +bool ShapePropertyMap::setFillGradient( sal_Int32 nPropId, const Any& rValue ) +{ + // push gradient explicitly + if( !maShapePropInfo.mbNamedFillGradient ) + return setAnyProperty( nPropId, rValue ); + + // create named gradient and push its name + if( rValue.has< Gradient >() ) + { + OUString aGradientName = mrModelObjHelper.insertFillGradient( rValue.get< Gradient >() ); + return (aGradientName.getLength() > 0) && setProperty( nPropId, aGradientName ); + } + + return false; +} + +bool ShapePropertyMap::setFillBitmapUrl( sal_Int32 nPropId, const Any& rValue ) +{ + // push bitmap URL explicitly + if( !maShapePropInfo.mbNamedFillBitmapUrl ) + return setAnyProperty( nPropId, rValue ); + + // create named bitmap URL and push its name + if( rValue.has< OUString >() ) + { + OUString aBitmapUrlName = mrModelObjHelper.insertFillBitmapUrl( rValue.get< OUString >() ); + return (aBitmapUrlName.getLength() > 0) && setProperty( nPropId, aBitmapUrlName ); + } + + return false; +} + +// ============================================================================ + +} // namespace drawingml +} // namespace oox diff --git a/oox/source/drawingml/table/makefile.mk b/oox/source/drawingml/table/makefile.mk index fa71971fc..fa71971fc 100644..100755 --- a/oox/source/drawingml/table/makefile.mk +++ b/oox/source/drawingml/table/makefile.mk diff --git a/oox/source/drawingml/table/tablecell.cxx b/oox/source/drawingml/table/tablecell.cxx index ad7a623ba..18fe6f8b5 100644 --- a/oox/source/drawingml/table/tablecell.cxx +++ b/oox/source/drawingml/table/tablecell.cxx @@ -27,6 +27,7 @@ #include "oox/drawingml/table/tablecell.hxx" #include "oox/drawingml/table/tableproperties.hxx" +#include "oox/drawingml/shapepropertymap.hxx" #include "oox/drawingml/textbody.hxx" #include "oox/core/xmlfilterbase.hxx" #include "oox/helper/propertyset.hxx" @@ -355,9 +356,10 @@ void TableCell::pushToXCell( const ::oox::core::XmlFilterBase& rFilterBase, ::oo applyLineAttributes( rFilterBase, xPropSet, aLinePropertiesBottomLeftToTopRight, PROP_DiagonalBLTR ); aFillProperties.assignUsed( maFillProperties ); - PropertySet aPropSet( xPropSet ); + ShapePropertyMap aPropMap( rFilterBase.getModelObjectHelper() ); // TODO: phClr? - aFillProperties.pushToPropSet( aPropSet, rFilterBase.getModelObjectHelper(), rFilterBase.getGraphicHelper() ); + aFillProperties.pushToPropMap( aPropMap, rFilterBase.getGraphicHelper() ); + PropertySet( xPropSet ).setProperties( aPropMap ); } } } } diff --git a/oox/source/dump/biffdumper.cxx b/oox/source/dump/biffdumper.cxx index d7d85a714..00d2811b1 100644 --- a/oox/source/dump/biffdumper.cxx +++ b/oox/source/dump/biffdumper.cxx @@ -166,7 +166,7 @@ void BiffCtlsStreamObject::implDump() { IndentGuard aIndGuard( mxOut ); mxStrm->seek( mnStartPos ); - RelativeInputStreamRef xRelStrm( new RelativeInputStream( *mxStrm, mnLength ) ); + BinaryInputStreamRef xRelStrm( new RelativeInputStream( *mxStrm, mnLength ) ); FormControlStreamObject( *this, xRelStrm ).dump(); } writeEmptyItem( "CTLS-END" ); @@ -356,7 +356,7 @@ bool BiffObjectBase::implStartRecord( BinaryInputStream&, sal_Int64& ornRecPos, break; } - ornRecSize = mxBiffStrm->getLength(); + ornRecSize = mxBiffStrm->size(); return bValid; } @@ -810,7 +810,7 @@ void FormulaObject::implDump() if( mnSize == 0 ) return; sal_Int64 nStartPos = mxStrm->tell(); - sal_Int64 nEndPos = ::std::min< sal_Int64 >( nStartPos + mnSize, mxStrm->getLength() ); + sal_Int64 nEndPos = ::std::min< sal_Int64 >( nStartPos + mnSize, mxStrm->size() ); bool bValid = mxTokens.get(); mxStack.reset( new FormulaStack ); @@ -1603,7 +1603,7 @@ void WorkbookStreamObject::implDumpRecordBody() { BiffInputStream& rStrm = getBiffStream(); sal_uInt16 nRecId = rStrm.getRecId(); - sal_Int64 nRecSize = rStrm.getLength(); + sal_Int64 nRecSize = rStrm.size(); BiffType eBiff = getBiff(); switch( nRecId ) @@ -1929,7 +1929,7 @@ void WorkbookStreamObject::implDumpRecordBody() case BIFF_ID_CHPICFORMAT: dumpDec< sal_uInt16 >( "bitmap-mode", "CHPICFORMAT-BITMAP-MODE" ); - dumpDec< sal_uInt16 >( "image-format", "CHPICFORMAT-IMAGE-FORMAT" ); + dumpUnused( 2 ); dumpHex< sal_uInt16 >( "flags", "CHPICFORMAT-FLAGS" ); dumpDec< double >( "scaling-factor" ); break; @@ -2572,6 +2572,12 @@ void WorkbookStreamObject::implDumpRecordBody() dumpDec< sal_Int32 >( "sst-idx" ); break; + case BIFF_ID_MERGEDCELLS: + mxOut->resetItemIndex(); + for( sal_uInt16 nIdx = 0, nCount = dumpDec< sal_uInt16 >( "count" ); !rStrm.isEof() && (nIdx < nCount); ++nIdx ) + dumpRange( "#range" ); + break; + case BIFF_ID_MSODRAWING: case BIFF_ID_MSODRAWINGGROUP: case BIFF_ID_MSODRAWINGSEL: @@ -2625,14 +2631,32 @@ void WorkbookStreamObject::implDumpRecordBody() { dumpHex< sal_uInt16 >( "flags", "NOTE-FLAGS" ); dumpDec< sal_uInt16 >( "obj-id" ); + dumpUniString( "author" ); + dumpUnused( 1 ); } else { - sal_uInt16 nTextLen = ::std::min( dumpDec< sal_uInt16 >( "text-len" ), static_cast< sal_uInt16 >( rStrm.getRemaining() ) ); + sal_uInt16 nTextLen = dumpDec< sal_uInt16 >( "text-len" ); + nTextLen = ::std::min( nTextLen, static_cast< sal_uInt16 >( rStrm.getRemaining() ) ); writeStringItem( "note-text", rStrm.readCharArrayUC( nTextLen, getBiffData().getTextEncoding(), true ) ); } break; + case BIFF_ID_NOTESOUND: + dumpHex< sal_uInt32 >( "identifier" ); + dumpDec< sal_uInt32 >( "total-data-size" ); + dumpDec< sal_uInt32 >( "wave-data-size" ); + if( dumpDec< sal_uInt32 >( "fmt-size" ) >= 16 ) + { + dumpDec< sal_uInt16 >( "format", "NOTESOUND-FORMAT" ); + dumpDec< sal_uInt16 >( "channels" ); + dumpDec< sal_uInt32 >( "sampling-rate" ); + dumpDec< sal_uInt32 >( "data-rate" ); + dumpDec< sal_uInt16 >( "data-block-size" ); + dumpDec< sal_uInt16 >( "bits-per-sample" ); + } + break; + case BIFF2_ID_NUMBER: case BIFF3_ID_NUMBER: dumpCellHeader( nRecId == BIFF2_ID_NUMBER ); @@ -2671,6 +2695,16 @@ void WorkbookStreamObject::implDumpRecordBody() } break; + case BIFF_ID_PALETTE: + mxOut->resetItemIndex( 8 ); + for( sal_uInt16 nIdx = 0, nCount = dumpDec< sal_uInt16 >( "count" ); !rStrm.isEof() && (nIdx < nCount); ++nIdx ) + { + OUStringBuffer aColorName; + StringHelper::appendHex( aColorName, dumpColorABGR( "#color" ) ); + mxColors->setName( nIdx + 8, aColorName.makeStringAndClear() ); + } + break; + case BIFF_ID_PANE: dumpDec< sal_uInt16 >( "x-pos", "CONV-TWIP-TO-CM" ); dumpDec< sal_uInt16 >( "y-pos", "CONV-TWIP-TO-CM" ); @@ -4490,7 +4524,7 @@ RootStorageObject::RootStorageObject( const DumperBase& rParent ) addPreferredStream( "Workbook" ); } -void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) +void RootStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { if( (rStrgPath.getLength() == 0) && (rStrmName.equalsAscii( "Book" ) || rStrmName.equalsAscii( "Workbook" )) ) WorkbookStreamObject( *this, rxStrm, rSysFileName ).dump(); @@ -4528,13 +4562,13 @@ Dumper::Dumper( const FilterBase& rFilter ) DumperBase::construct( xCfg ); } -Dumper::Dumper( const Reference< XMultiServiceFactory >& rxFactory, const Reference< XInputStream >& rxInStrm, const OUString& rSysFileName ) +Dumper::Dumper( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, const OUString& rSysFileName ) { - if( rxFactory.is() && rxInStrm.is() ) + if( rxContext.is() && rxInStrm.is() ) { - StorageRef xStrg( new ::oox::ole::OleStorage( rxFactory, rxInStrm, true ) ); + StorageRef xStrg( new ::oox::ole::OleStorage( rxContext, rxInStrm, true ) ); MediaDescriptor aMediaDesc; - ConfigRef xCfg( new Config( DUMP_BIFF_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName, aMediaDesc ) ); + ConfigRef xCfg( new Config( DUMP_BIFF_CONFIG_ENVVAR, rxContext, xStrg, rSysFileName, aMediaDesc ) ); DumperBase::construct( xCfg ); } } diff --git a/oox/source/dump/biffdumper.ini b/oox/source/dump/biffdumper.ini index 2e25ff81c..02f70261e 100644 --- a/oox/source/dump/biffdumper.ini +++ b/oox/source/dump/biffdumper.ini @@ -324,7 +324,7 @@ multilist=RECORD-NAMES-BIFF4 exclude=0x0206,0x0209,0x001E,0x0243 0x0085=SHEET 0x0088=,,,,,,SHEETSOFFSET,SHEETHEADER - 0x0090=,,,,,SOUND,SYNC + 0x0090=,,,,,,NOTESOUND,SYNC 0x0098=LPR,STANDARDWIDTH,FNGROUPNAME,,FNGROUPCOUNT,,, 0x00A0=SCL,PAGESETUP,FNPROTO,PROJEXTSHEET,,,, 0x00A8=DRAGDROP,COORDLIST,,GCW,,,, @@ -358,7 +358,7 @@ multilist=RECORD-NAMES-BIFF5 # chart records exclude=0x1004,0x102D,0x102F,0x1036,0x1037,0x1038,0x103B 0x1040=CHRADARAREA,CHAXESSET,,CHLEGENDENTRY,CHPROPERTIES,CHSERGROUP,CHUSEDAXESSETS, - 0x1048=CHPIVOTREF,,CHSERPARENT,CHSERTRENDLINE,,,CHFORMAT,CHFRAMEPOS + 0x1048=CHPIVOTRANGE,,CHSERPARENT,CHSERTRENDLINE,,,CHFORMAT,CHFRAMEPOS 0x1050=CHFORMATRUNS,CHSOURCELINK,,,,,, 0x1058=,,,CHSERERRORBAR,,CHSERIESFORMAT,, end @@ -1049,17 +1049,7 @@ end shortlist=CHPICFORMAT-BITMAP-MODE,1,stretched,stacked,stacked-scaled -constlist=CHPICFORMAT-IMAGE-FORMAT - 2=wmf - 9=bmp - 19=?emf -end - -shortlist=CHPICFORMAT-ENV,1,windows,apple - combilist=CHPICFORMAT-FLAGS - 0x00FF=uint16,dec,environment,CHPICFORMAT-ENV - 0x0100=format-only 0x0200=top-bottom 0x0400=front-back 0x0800=left-right @@ -1511,6 +1501,18 @@ shortlist=IMGDATA-ENV,1,windows,apple flagslist=NOTE-FLAGS-BIFF8 0x0002=visible + 0x0080=row-hidden + 0x0100=col-hidden +end + +# NOTESOUND ------------------------------------------------------------------ + +constlist=NOTESOUND-FORMAT + 1=pcm + 3=ieee-float + 6=a-law + 7=mu-law + 0xFFFE=extensible end # OBJ ------------------------------------------------------------------------ @@ -2344,7 +2346,7 @@ combilist=XF-FILLCOLOR-BIFF8 0x3F80=uint8,dec,bg-color-idx,COLORS end -# BIFF2 XF index field ------------------------------------------------------- +# BIFF2 cell records ---------------------------------------------------------- constlist=XFINDEX-BIFF2 default= diff --git a/oox/source/dump/dffdumper.ini b/oox/source/dump/dffdumper.ini index 5526663e0..02bce03b6 100644 --- a/oox/source/dump/dffdumper.ini +++ b/oox/source/dump/dffdumper.ini @@ -79,6 +79,9 @@ end shortlist=DFF-COLORMOD-TYPE,0,none,shade,tint +unitconverter=DFF-OPACITY,/655.36,% +unitconverter=DFF-DEGREES,/65536,° + # DFFBSE --------------------------------------------------------------------- combilist=DFFBSE-RECORD-INST @@ -136,8 +139,8 @@ multilist=DFFOPT-PROPERTY-NAMES # 0x0100-0x013F: picture (BLIP) 0x0100=blip-crop-top,blip-crop-bottom,blip-crop-left,blip-crop-right,blip-id,blip-name,blip-opt,blip-transparency-color 0x0108=blip-contrast,blip-brightness,blip-gamma,blip-ole-id,blip-double-cr-mod,blip-fill-cr-mod,blip-line-cr-mod,blip-print-id - 0x0110=blip-print-name,blip-print-opt,blip-movie,,,blip-transparency-color-ext,,blip-transparency-color-ext-mod - 0x0118,,blip-recolor,blip-recolor,blip-recolor-ext,,blip-recolor-ext-mod + 0x0110=blip-print-name,blip-print-opt,blip-movie,,,blip-transparency-color-ext,reserved,blip-transparency-color-ext-mod + 0x0118=reserved,reserved,blip-recolor,blip-recolor-ext,reserved,blip-recolor-ext-mod,reserved,reserved 0x013F=blip-flags # 0x0140-0x017F: shape geometry 0x0140=geo-left,geo-top,geo-right,geo-bottom,geo-shape-path,geo-vertices,geo-segment-info,geo-adjust-1 @@ -149,20 +152,21 @@ multilist=DFFOPT-PROPERTY-NAMES 0x0180=fill-type,fill-color,fill-opacity,fill-back-color,fill-back-opacity,fill-cr-mod,fill-blip,fill-blip-name 0x0188=fill-blip-opt,fill-width,fill-height,fill-angle,fill-focus,fill-to-left,fill-to-top,fill-to-right 0x0190=fill-to-bottom,fill-rect-left,fill-rect-top,fill-rect-right,fill-rect-bottom,fill-dz-type,fill-shade-preset,fill-shade-colors - 0x0198=fill-origin-x,fill-origin-y,fill-shape-origin-x,fill-shape-origin-y,fill-shade-type,,fill-color-ext, - 0x01A0=fill-color-ext-mod,,fill-back-color-ext,,fill-back-color-ext-mod + 0x0198=fill-origin-x,fill-origin-y,fill-shape-origin-x,fill-shape-origin-y,fill-shade-type,,fill-color-ext,reserved + 0x01A0=fill-color-ext-mod,reserved,fill-back-color-ext,reserved,fill-back-color-ext-mod,reserved,reserved,reserved 0x01BF=fill-flags # 0x01C0-0x01FF: line style 0x01C0=line-color,line-opacity,line-back-color,line-cr-mod,line-type,line-fill-blip,line-fill-blip-name,line-fill-blip-opt 0x01C8=line-fill-width,line-fill-height,line-fill-dz-type,line-width,line-miter-limit,line-style,line-dash,line-dash-style 0x01D0=line-start-arrow-head,line-end-arrow-head,line-start-arrow-width,line-start-arrow-length,line-end-arrow-width,line-end-arrow-length,line-join-style,line-end-cap-style - 0x01D8=,line-color-ext,,line-color-ext-mod,,line-back-color-ext,,line-back-color-ext-mod + 0x01D8=,line-color-ext,reserved,line-color-ext-mod,reserved,line-back-color-ext,reserved,line-back-color-ext-mod + 0x01E0=reserved,reserved,reserved 0x01FF=line-flags # 0x0200-0x023F: shadow style 0x0200=shadow-type,shadow-color,shadow-highlight,shadow-cr-mod,shadow-opacity,shadow-offset-x,shadow-offset-y,shadow-2nd-offset-x 0x0208=shadow-2nd-offset-y,,,,,,, - 0x0210=shadow-origin-x,shadow-origin-y,shadow-color-ext,,shadow-color-ext-mod,,shadow-highlight-ext, - 0x0218=shadow-highlight-ext-mod + 0x0210=shadow-origin-x,shadow-origin-y,shadow-color-ext,reserved,shadow-color-ext-mod,reserved,shadow-highlight-ext,reserved + 0x0218=shadow-highlight-ext-mod,reserved,reserved,reserved 0x023F=shadow-flags # 0x0240-0x027F: perspective 0x0240=persp-type,persp-offset-x,persp-offsety,persp-scale-x-to-x,persp-scale-y-to-x,persp-scale-x-to-y,persp-scale-y-to-y,persp-persp-x @@ -170,7 +174,7 @@ multilist=DFFOPT-PROPERTY-NAMES 0x027F=persp-flags # 0x0280-0x02BF: 3d object 0x0280=3dobj-specular-amt,3dobj-diffuse-amt,3dobj-shininess,3dobj-edge-thickness,3dobj-extrude-forward,3dobj-extrude-backward,3dobj-extrude-plane,3dobj-extrusion-color - 0x0288=3dobj-cr-mod,3dobj-extrusion-color-ext,,3dobj-extrusion-color-ext-mod + 0x0288=3dobj-cr-mod,3dobj-extrusion-color-ext,reserved,3dobj-extrusion-color-ext-mod,reserved,reserved 0x02BF=3dobj-flags # 0x02C0-0x02FF: 3d style 0x02C0=3dstyle-y-rotation,3dstyle-x-rotation,3dstyle-rotation-axis-x,3dstyle-rotation-axis-y,3dstyle-rotation-axis-z,3dstyle-rotation,3dstyle-rotation-center-x,3dstyle-rotation-center-y @@ -208,25 +212,29 @@ multilist=DFFOPT-PROPERTY-NAMES 0x0540=lline-color,lline-opacity,lline-back-color,lline-cr-mod,lline-type,lline-fill-blip,lline-fill-blip-name,lline-fill-blip-opt 0x0548=lline-fill-width,lline-fill-height,lline-fill-dz-type,lline-width,lline-miter-limit,lline-style,lline-dash,lline-dash-style 0x0550=lline-start-arrow-head,lline-end-arrow-head,lline-start-arrow-width,lline-start-arrow-length,lline-end-arrow-width,lline-end-arrow-length,lline-join-style,lline-end-cap-style - 0x0558=,lline-color-ext,,lline-color-ext-mod,,lline-back-color-ext,,lline-back-color-ext-mod + 0x0558=,lline-color-ext,reserved,lline-color-ext-mod,reserved,lline-back-color-ext,reserved,lline-back-color-ext-mod + 0x0560=reserved,reserved,reserved 0x057F=lline-flags # 0x0580-0x05BF: top line style 0x0580=tline-color,tline-opacity,tline-back-color,tline-cr-mod,tline-type,tline-fill-blip,tline-fill-blip-name,tline-fill-blip-opt 0x0588=tline-fill-width,tline-fill-height,tline-fill-dz-type,tline-width,tline-miter-limit,tline-style,tline-dash,tline-dash-style 0x0590=tline-start-arrow-head,tline-end-arrow-head,tline-start-arrow-width,tline-start-arrow-length,tline-end-arrow-width,tline-end-arrow-length,tline-join-style,tline-end-cap-style - 0x0598=,tline-color-ext,,tline-color-ext-mod,,tline-back-color-ext,,tline-back-color-ext-mod + 0x0598=,tline-color-ext,reserved,tline-color-ext-mod,reserved,tline-back-color-ext,reserved,tline-back-color-ext-mod + 0x05A0=reserved,reserved,reserved 0x05BF=tline-flags # 0x05C0-0x05FF: right line style 0x05C0=rline-color,rline-opacity,rline-back-color,rline-cr-mod,rline-type,rline-fill-blip,rline-fill-blip-name,rline-fill-blip-opt 0x05C8=rline-fill-width,rline-fill-height,rline-fill-dz-type,rline-width,rline-miter-limit,rline-style,rline-dash,rline-dash-style 0x05D0=rline-start-arrow-head,rline-end-arrow-head,rline-start-arrow-width,rline-start-arrow-length,rline-end-arrow-width,rline-end-arrow-length,rline-join-style,rline-end-cap-style - 0x05D8=,rline-color-ext,,rline-color-ext-mod,,rline-back-color-ext,,rline-back-color-ext-mod + 0x05D8=,rline-color-ext,reserved,rline-color-ext-mod,reserved,rline-back-color-ext,reserved,rline-back-color-ext-mod + 0x05E0=reserved,reserved,reserved 0x05FF=rline-flags # 0x0600-0x063F: bottom line style 0x0600=bline-color,bline-opacity,bline-back-color,bline-cr-mod,bline-type,bline-fill-blip,bline-fill-blip-name,bline-fill-blip-opt 0x0608=bline-fill-width,bline-fill-height,bline-fill-dz-type,bline-width,bline-miter-limit,bline-style,bline-dash,bline-dash-style 0x0610=bline-start-arrow-head,bline-end-arrow-head,bline-start-arrow-width,bline-start-arrow-length,bline-end-arrow-width,bline-end-arrow-length,bline-join-style,bline-end-cap-style - 0x0618=,bline-color-ext,,bline-color-ext-mod,,bline-back-color-ext,,bline-back-color-ext-mod + 0x0618=,bline-color-ext,reserved,bline-color-ext-mod,reserved,bline-back-color-ext,reserved,bline-back-color-ext-mod + 0x0620=reserved,reserved,reserved 0x063F=bline-flags # 0x0680-0x06BF: web component 0x0680=webcomp-html,webcomp-name,webcomp-url @@ -258,7 +266,7 @@ constlist=DFFOPT-SIMPLE-PROPERTIES # fill style 0x0180=uint32,dec,type,DFFOPT-FILL-TYPE 0x0181=uint32,hex,color,DFF-COLOR - 0x0182=int32,fix,opacity,CONV-FLOAT-TO-PERC + 0x0182=int32,fix,opacity,DFF-OPACITY 0x0183=uint32,hex,color,DFF-COLOR 0x0184=int32,fix,opacity,DFF-OPACITY 0x0185=uint32,hex,color,DFF-COLOR @@ -266,22 +274,22 @@ constlist=DFFOPT-SIMPLE-PROPERTIES 0x0188=uint32,dec,blip-opt,DFFOPT-BLIPOPT 0x0189=int32,dec,width 0x018A=int32,dec,height - 0x018B=int32,fix,angle,CONV-DEG + 0x018B=int32,fix,angle,DFF-DEGREES 0x018C=int32,dec,focus,CONV-PERCENT - 0x018D=int32,fix,size,CONV-FLOAT-TO-PERC - 0x018E=int32,fix,size,CONV-FLOAT-TO-PERC - 0x018F=int32,fix,size,CONV-FLOAT-TO-PERC - 0x0190=int32,fix,size,CONV-FLOAT-TO-PERC + 0x018D=int32,fix,size,DFF-OPACITY + 0x018E=int32,fix,size,DFF-OPACITY + 0x018F=int32,fix,size,DFF-OPACITY + 0x0190=int32,fix,size,DFF-OPACITY 0x0191=int32,fix,size,CONV-EMU-TO-CM 0x0192=int32,fix,size,CONV-EMU-TO-CM 0x0193=int32,fix,size,CONV-EMU-TO-CM 0x0194=int32,fix,size,CONV-EMU-TO-CM 0x0195=uint32,dec,type,DFFOPT-FILL-DZTYPE 0x0196=int32,dec,preset - 0x0198=int32,fix,pos,CONV-FLOAT-TO-PERC - 0x0199=int32,fix,pos,CONV-FLOAT-TO-PERC - 0x019A=int32,fix,pos,CONV-FLOAT-TO-PERC - 0x019B=int32,fix,pos,CONV-FLOAT-TO-PERC + 0x0198=int32,fix,pos,DFF-OPACITY + 0x0199=int32,fix,pos,DFF-OPACITY + 0x019A=int32,fix,pos,DFF-OPACITY + 0x019B=int32,fix,pos,DFF-OPACITY 0x019C=uint32,hex,type,DFFOPT-FILL-SHADETYPE 0x019E=uint32,hex,color,DFF-COLOR 0x01A0=uint32,hex,color-mod,DFF-COLORMOD @@ -443,6 +451,7 @@ shortlist=DFFOPT-FILL-DZTYPE-UNIT,0,unused,emu,pixel,shape-size-rel shortlist=DFFOPT-FILL-DZTYPE-ASPECT,0,none,fixed,prefer-largest flagslist=DFFOPT-FILL-SHADETYPE + ignore=0x40000000 0x00000001=none 0x00000002=gamma 0x00000004=sigma-transfer diff --git a/oox/source/dump/dumperbase.cxx b/oox/source/dump/dumperbase.cxx index 8689f1ae3..83a2edecc 100644 --- a/oox/source/dump/dumperbase.cxx +++ b/oox/source/dump/dumperbase.cxx @@ -29,14 +29,13 @@ #include <algorithm> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/io/XActiveDataSink.hpp> #include <com/sun/star/io/XActiveDataSource.hpp> -#include <com/sun/star/io/XTextInputStream.hpp> #include <com/sun/star/io/XTextOutputStream.hpp> #include <com/sun/star/ucb/XSimpleFileAccess.hpp> #include <comphelper/docpasswordhelper.hxx> #include <osl/file.hxx> #include <rtl/math.hxx> +#include <rtl/tencinfo.h> #include "oox/core/filterbase.hxx" #include "oox/helper/binaryoutputstream.hxx" #include "oox/helper/textinputstream.hxx" @@ -112,20 +111,14 @@ OUString InputOutputHelper::getFileNameExtension( const OUString& rFileUrl ) // input streams -------------------------------------------------------------- -Reference< XInputStream > InputOutputHelper::getXInputStream( BinaryInputStream& rStrm ) -{ - if( BinaryXInputStream* pXStrm = dynamic_cast< BinaryXInputStream* >( &rStrm ) ) - return pXStrm->getXInputStream(); - return 0; -} - Reference< XInputStream > InputOutputHelper::openInputStream( - const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName ) + const Reference< XComponentContext >& rxContext, const OUString& rFileName ) { Reference< XInputStream > xInStrm; - if( rxFactory.is() ) try + if( rxContext.is() ) try { - Reference< XSimpleFileAccess > xFileAccess( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); xInStrm = xFileAccess->openFileRead( rFileName ); } catch( Exception& ) @@ -134,38 +127,16 @@ Reference< XInputStream > InputOutputHelper::openInputStream( return xInStrm; } -Reference< XTextInputStream > InputOutputHelper::openTextInputStream( - const Reference< XMultiServiceFactory >& rxFactory, const Reference< XInputStream >& rxInStrm, const OUString& rEncoding ) -{ - Reference< XTextInputStream > xTextInStrm; - if( rxFactory.is() && rxInStrm.is() ) try - { - Reference< XActiveDataSink > xDataSink( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextInputStream" ) ), UNO_QUERY_THROW ); - xDataSink->setInputStream( rxInStrm ); - xTextInStrm.set( xDataSink, UNO_QUERY_THROW ); - xTextInStrm->setEncoding( rEncoding ); - } - catch( Exception& ) - { - } - return xTextInStrm; -} - -Reference< XTextInputStream > InputOutputHelper::openTextInputStream( - const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName, const OUString& rEncoding ) -{ - return openTextInputStream( rxFactory, openInputStream( rxFactory, rFileName ), rEncoding ); -} - // output streams ------------------------------------------------------------- Reference< XOutputStream > InputOutputHelper::openOutputStream( - const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName ) + const Reference< XComponentContext >& rxContext, const OUString& rFileName ) { Reference< XOutputStream > xOutStrm; - if( rxFactory.is() ) try + if( rxContext.is() ) try { - Reference< XSimpleFileAccess > xFileAccess( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); xOutStrm = xFileAccess->openFileWrite( rFileName ); } catch( Exception& ) @@ -175,15 +146,17 @@ Reference< XOutputStream > InputOutputHelper::openOutputStream( } Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream( - const Reference< XMultiServiceFactory >& rxFactory, const Reference< XOutputStream >& rxOutStrm, const OUString& rEncoding ) + const Reference< XComponentContext >& rxContext, const Reference< XOutputStream >& rxOutStrm, rtl_TextEncoding eTextEnc ) { Reference< XTextOutputStream > xTextOutStrm; - if( rxFactory.is() && rxOutStrm.is() ) try + const char* pcCharset = rtl_getMimeCharsetFromTextEncoding( eTextEnc ); + if( rxContext.is() && rxOutStrm.is() && pcCharset ) try { - Reference< XActiveDataSource > xDataSource( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextOutputStream" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XActiveDataSource > xDataSource( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextOutputStream" ) ), UNO_QUERY_THROW ); xDataSource->setOutputStream( rxOutStrm ); xTextOutStrm.set( xDataSource, UNO_QUERY_THROW ); - xTextOutStrm->setEncoding( rEncoding ); + xTextOutStrm->setEncoding( OUString::createFromAscii( pcCharset ) ); } catch( Exception& ) { @@ -192,9 +165,9 @@ Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream( } Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream( - const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName, const OUString& rEncoding ) + const Reference< XComponentContext >& rxContext, const OUString& rFileName, rtl_TextEncoding eTextEnc ) { - return openTextOutputStream( rxFactory, openOutputStream( rxFactory, rFileName ), rEncoding ); + return openTextOutputStream( rxContext, openOutputStream( rxContext, rFileName ), eTextEnc ); } // ============================================================================ @@ -1531,9 +1504,9 @@ NameListRef NameListWrapper::getNameList( const Config& rCfg ) const // ============================================================================ SharedConfigData::SharedConfigData( const OUString& rFileName, - const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, + const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) : - mxFactory( rxFactory ), + mxContext( rxContext ), mxRootStrg( rxRootStrg ), maSysFileName( rSysFileName ), mrMediaDesc( rMediaDesc ), @@ -1600,7 +1573,7 @@ Sequence< NamedValue > SharedConfigData::requestEncryptionData( ::comphelper::ID bool SharedConfigData::implIsValid() const { - return mbLoaded && mxFactory.is() && mxRootStrg.get() && (maSysFileName.getLength() > 0); + return mbLoaded && mxContext.is() && mxRootStrg.get() && (maSysFileName.getLength() > 0); } void SharedConfigData::implProcessConfigItemStr( @@ -1629,9 +1602,8 @@ bool SharedConfigData::readConfigFile( const OUString& rFileUrl ) bool bLoaded = maConfigFiles.count( rFileUrl ) > 0; if( !bLoaded ) { - Reference< XInputStream > xInStrm = InputOutputHelper::openInputStream( mxFactory, rFileUrl ); - BinaryXInputStream aInStrm( xInStrm, true ); - TextInputStream aTxtStrm( aInStrm, RTL_TEXTENCODING_UTF8 ); + Reference< XInputStream > xInStrm = InputOutputHelper::openInputStream( mxContext, rFileUrl ); + TextInputStream aTxtStrm( mxContext, xInStrm, RTL_TEXTENCODING_UTF8 ); if( !aTxtStrm.isEof() ) { maConfigFiles.insert( rFileUrl ); @@ -1698,9 +1670,9 @@ Config::Config( const sal_Char* pcEnvVar, const FilterBase& rFilter ) construct( pcEnvVar, rFilter ); } -Config::Config( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) +Config::Config( const sal_Char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) { - construct( pcEnvVar, rxFactory, rxRootStrg, rSysFileName, rMediaDesc ); + construct( pcEnvVar, rxContext, rxRootStrg, rSysFileName, rMediaDesc ); } Config::~Config() @@ -1715,14 +1687,14 @@ void Config::construct( const Config& rParent ) void Config::construct( const sal_Char* pcEnvVar, const FilterBase& rFilter ) { if( rFilter.getFileUrl().getLength() > 0 ) - construct( pcEnvVar, rFilter.getServiceFactory(), rFilter.getStorage(), rFilter.getFileUrl(), rFilter.getMediaDescriptor() ); + construct( pcEnvVar, rFilter.getComponentContext(), rFilter.getStorage(), rFilter.getFileUrl(), rFilter.getMediaDescriptor() ); } -void Config::construct( const sal_Char* pcEnvVar, const Reference< XMultiServiceFactory >& rxFactory, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) +void Config::construct( const sal_Char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) { if( pcEnvVar && rxRootStrg.get() && (rSysFileName.getLength() > 0) ) if( const sal_Char* pcFileName = ::getenv( pcEnvVar ) ) - mxCfgData.reset( new SharedConfigData( OUString::createFromAscii( pcFileName ), rxFactory, rxRootStrg, rSysFileName, rMediaDesc ) ); + mxCfgData.reset( new SharedConfigData( OUString::createFromAscii( pcFileName ), rxContext, rxRootStrg, rSysFileName, rMediaDesc ) ); } void Config::setStringOption( const String& rKey, const String& rData ) @@ -1795,14 +1767,16 @@ NameListRef Config::implGetNameList( const OUString& rListName ) const // ============================================================================ // ============================================================================ -Output::Output( const Reference< XTextOutputStream >& rxStrm ) -{ - construct( rxStrm ); -} - -Output::Output( const Reference< XMultiServiceFactory >& rxFactory, const OUString& rFileName ) +Output::Output( const Reference< XComponentContext >& rxContext, const OUString& rFileName ) : + mxStrm( InputOutputHelper::openTextOutputStream( rxContext, rFileName, RTL_TEXTENCODING_UTF8 ) ), + mnCol( 0 ), + mnItemLevel( 0 ), + mnMultiLevel( 0 ), + mnItemIdx( 0 ), + mnLastItem( 0 ) { - construct( InputOutputHelper::openTextOutputStream( rxFactory, rFileName, CREATE_OUSTRING( "UTF-8" ) ) ); + if( mxStrm.is() ) + mxStrm->writeString( OUString( OOX_DUMP_BOM ) ); } // ---------------------------------------------------------------------------- @@ -2084,19 +2058,6 @@ void Output::writeRangeList( const RangeList& rRanges ) // ---------------------------------------------------------------------------- -void Output::construct( const Reference< XTextOutputStream >& rxStrm ) -{ - mxStrm = rxStrm; - mnCol = mnItemLevel = mnMultiLevel = 0; - mnItemIdx = 0; - mnLastItem = 0; - if( mxStrm.is() ) - { - writeChar( OOX_DUMP_BOM ); - newLine(); - } -} - bool Output::implIsValid() const { return mxStrm.is(); @@ -2240,7 +2201,8 @@ void StorageObjectBase::implDump() if( bIsRoot ) try { aSysOutPath += OOX_DUMP_DUMPEXT; - Reference< XSimpleFileAccess > xFileAccess( getFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( getContext()->getServiceManager(), UNO_QUERY_THROW ); + Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); xFileAccess->kill( aSysOutPath ); } catch( Exception& ) @@ -2259,7 +2221,7 @@ void StorageObjectBase::implDump() } } -void StorageObjectBase::implDumpStream( const BinaryInputStreamRef&, const OUString&, const OUString&, const OUString& ) +void StorageObjectBase::implDumpStream( const Reference< XInputStream >&, const OUString&, const OUString&, const OUString& ) { } @@ -2305,12 +2267,12 @@ void StorageObjectBase::extractStream( StorageBase& rStrg, const OUString& rStrg BinaryXInputStream aInStrm( rStrg.openInputStream( rStrmName ), true ); if( !aInStrm.isEof() ) { - BinaryXOutputStream aOutStrm( InputOutputHelper::openOutputStream( getFactory(), rSysFileName ), true ); + BinaryXOutputStream aOutStrm( InputOutputHelper::openOutputStream( getContext(), rSysFileName ), true ); if( !aOutStrm.isEof() ) aInStrm.copyToStream( aOutStrm ); } - BinaryXInputStreamRef xDumpStrm( new BinaryXInputStream( InputOutputHelper::openInputStream( getFactory(), rSysFileName ), true ) ); - if( !xDumpStrm->isEof() ) + Reference< XInputStream > xDumpStrm = InputOutputHelper::openInputStream( getContext(), rSysFileName ); + if( xDumpStrm.is() ) implDumpStream( xDumpStrm, rStrgPath, rStrmName, rSysFileName ); } @@ -2366,13 +2328,10 @@ void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rSy { ObjectBase::construct( rParent ); if( ObjectBase::implIsValid() ) - mxOut.reset( new Output( getFactory(), rSysFileName + OOX_DUMP_DUMPEXT ) ); -} - -void OutputObjectBase::construct( const ObjectBase& rParent, const OutputRef& rxOut ) -{ - ObjectBase::construct( rParent ); - mxOut = rxOut; + { + maSysFileName = rSysFileName; + mxOut.reset( new Output( getContext(), rSysFileName + OOX_DUMP_DUMPEXT ) ); + } } void OutputObjectBase::construct( const OutputObjectBase& rParent ) @@ -2551,12 +2510,6 @@ void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStr mxStrm = rxStrm; } -void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OutputRef& rxOut ) -{ - OutputObjectBase::construct( rParent, rxOut ); - mxStrm = rxStrm; -} - void InputObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm ) { OutputObjectBase::construct( rParent ); @@ -2575,7 +2528,7 @@ bool InputObjectBase::implIsValid() const void InputObjectBase::skipBlock( sal_Int64 nBytes, bool bShowSize ) { - sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->getLength() ); + sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() ); if( mxStrm->tell() < nEndPos ) { if( bShowSize ) @@ -2595,8 +2548,8 @@ void InputObjectBase::dumpRawBinary( sal_Int64 nBytes, bool bShowOffset, bool bS sal_Int64 nMaxShowSize = cfg().getIntOption< sal_Int64 >( bStream ? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64 ); - bool bSeekable = mxStrm->getLength() >= 0; - sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->getLength() ) : 0; + bool bSeekable = mxStrm->size() >= 0; + sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() ) : 0; sal_Int64 nDumpEnd = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nMaxShowSize, nEndPos ) : nMaxShowSize; sal_Int64 nPos = bSeekable ? mxStrm->tell() : 0; bool bLoop = true; @@ -2671,12 +2624,12 @@ void InputObjectBase::dumpRemainingTo( sal_Int64 nPos ) void InputObjectBase::dumpRemainingStream() { - dumpRemainingTo( mxStrm->getLength() ); + dumpRemainingTo( mxStrm->size() ); } void InputObjectBase::dumpArray( const String& rName, sal_Int32 nBytes, sal_Unicode cSep ) { - sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->getLength() - mxStrm->tell(), 0, nBytes ); + sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nBytes ); if( nDumpSize > OOX_DUMP_MAXARRAY ) { dumpBinary( rName, nBytes, false ); @@ -2712,7 +2665,7 @@ sal_Unicode InputObjectBase::dumpUnicode( const String& rName ) OUString InputObjectBase::dumpCharArray( const String& rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc, bool bHideTrailingNul ) { - sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->getLength() - mxStrm->tell(), 0, nLen ); + sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nLen ); OUString aString; if( nDumpSize > 0 ) { @@ -2892,7 +2845,7 @@ BinaryStreamObject::BinaryStreamObject( const OutputObjectBase& rParent, const B void BinaryStreamObject::dumpBinaryStream( bool bShowOffset ) { mxStrm->seekToStart(); - dumpRawBinary( mxStrm->getLength(), bShowOffset, true ); + dumpRawBinary( mxStrm->size(), bShowOffset, true ); mxOut->emptyLine(); } @@ -2902,42 +2855,70 @@ void BinaryStreamObject::implDump() } // ============================================================================ +// ============================================================================ -TextStreamObject::TextStreamObject( const ObjectBase& rParent, +void TextStreamObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName ) { InputObjectBase::construct( rParent, rxStrm, rSysFileName ); - if( rxStrm.get() ) - mxTextStrm.reset( new TextInputStream( *rxStrm, eTextEnc ) ); + constructTextStrmObj( eTextEnc ); } -TextStreamObject::TextStreamObject( const OutputObjectBase& rParent, +void TextStreamObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc ) { InputObjectBase::construct( rParent, rxStrm ); - if( rxStrm.get() ) - mxTextStrm.reset( new TextInputStream( *rxStrm, eTextEnc ) ); + constructTextStrmObj( eTextEnc ); +} + +void TextStreamObjectBase::construct( const InputObjectBase& rParent, rtl_TextEncoding eTextEnc ) +{ + InputObjectBase::construct( rParent ); + constructTextStrmObj( eTextEnc ); } -bool TextStreamObject::implIsValid() const +bool TextStreamObjectBase::implIsValid() const { return InputObjectBase::implIsValid() && mxTextStrm.get(); } -void TextStreamObject::implDump() +void TextStreamObjectBase::implDump() +{ + implDumpText( *mxTextStrm ); +} + +void TextStreamObjectBase::constructTextStrmObj( rtl_TextEncoding eTextEnc ) +{ + if( mxStrm.get() ) + mxTextStrm.reset( new TextInputStream( getContext(), *mxStrm, eTextEnc ) ); +} + +// ============================================================================ + +TextLineStreamObject::TextLineStreamObject( const ObjectBase& rParent, + const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName ) +{ + TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc, rSysFileName ); +} + +TextLineStreamObject::TextLineStreamObject( const OutputObjectBase& rParent, + const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc ) +{ + TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc ); +} + +void TextLineStreamObject::implDumpText( TextInputStream& rTextStrm ) { - OUString aLine; sal_uInt32 nLine = 0; - while( !mxTextStrm->isEof() ) + while( !rTextStrm.isEof() ) { - aLine = mxTextStrm->readLine(); - if( !mxTextStrm->isEof() ) + OUString aLine = rTextStrm.readLine(); + if( !rTextStrm.isEof() || (aLine.getLength() > 0) ) implDumpLine( aLine, ++nLine ); } - mxOut->emptyLine(); } -void TextStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 nLine ) +void TextLineStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 nLine ) { TableGuard aTabGuard( mxOut, 8 ); mxOut->writeDec( nLine, 6 ); @@ -2948,110 +2929,93 @@ void TextStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 nLine ) // ============================================================================ -XmlStreamObject::XmlStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName ) : - TextStreamObject( rParent, rxStrm, RTL_TEXTENCODING_UTF8, rSysFileName ) +XmlStreamObject::XmlStreamObject( const ObjectBase& rParent, + const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName ) { + TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8, rSysFileName ); } -void XmlStreamObject::implDump() +XmlStreamObject::XmlStreamObject( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm ) { - maIncompleteLine = OUString(); - TextStreamObject::implDump(); - if( maIncompleteLine.getLength() > 0 ) - { - mxOut->resetIndent(); - mxOut->writeString( maIncompleteLine ); - mxOut->emptyLine(); - writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM ); - } + TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8 ); } -void XmlStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 ) +void XmlStreamObject::implDumpText( TextInputStream& rTextStrm ) { - // build input line from cached incomplete element and new text data - OUStringBuffer aLine; - if( maIncompleteLine.getLength() > 0 ) - aLine.append( maIncompleteLine ).append( sal_Unicode( ' ' ) ); - aLine.append( rLine ); - maIncompleteLine = OUString(); + /* Buffers a start element and the following element text. Needed to dump + matching start/end elements and the element text on the same line. */ + OUStringBuffer aOldStartElem; + // special handling for VML + bool bIsVml = InputOutputHelper::getFileNameExtension( maSysFileName ).equalsIgnoreAsciiCaseAscii( "vml" ); - if( aLine.getLength() == 0 ) + while( !rTextStrm.isEof() ) { - mxOut->newLine(); - return; - } + // get the next element and the following element text from text stream + OUString aElem = rTextStrm.readToChar( '>', true ).trim(); + OUString aText = rTextStrm.readToChar( '<', false ); - const sal_Unicode* pcPos = aLine.getStr(); - const sal_Unicode* pcEnd = pcPos + aLine.getLength(); - while( pcPos < pcEnd ) - { - OUStringBuffer aOutLine; - bool bIsStartElement = false; - bool bIsComplElement = false; - bool bIsEndElement = false; - - /* check for start element at beginning of the line - pcEnd and thus (pcPos+1) - are dereferenceable, because OUStringBuffer::getStr is null-terminated. */ - if( (*pcPos == '<') && (pcPos[ 1 ] != '/') ) + // remove multiple whitespace from element + sal_Int32 nPos = 0; + while( nPos < aElem.getLength() ) { - const sal_Unicode* pcElementEnd = ::std::find( pcPos, pcEnd, '>' ); - if( pcElementEnd == pcEnd ) - { - // incomplete start element - maIncompleteLine = OUString( pcPos, static_cast< sal_Int32 >( pcEnd - pcPos ) ); - pcPos = pcEnd; - } - else - { - bIsComplElement = (pcPos[ 1 ] == '?') || (pcPos[ 1 ] == '!') || (pcElementEnd[ -1 ] == '/'); - bIsStartElement = !bIsComplElement; - ++pcElementEnd; - aOutLine.append( pcPos, static_cast< sal_Int32 >( pcElementEnd - pcPos ) ); - pcPos = pcElementEnd; - } + while( (nPos < aElem.getLength()) && (aElem[ nPos ] >= 32) ) ++nPos; + if( nPos < aElem.getLength() ) + aElem = OUStringBuffer( aElem.copy( 0, nPos ) ).append( sal_Unicode( ' ' ) ).append( aElem.copy( nPos ).trim() ).makeStringAndClear(); + ++nPos; } - // check for following element text - if( !bIsComplElement && (pcPos < pcEnd) ) + sal_Int32 nElemLen = aElem.getLength(); + if( (nElemLen >= 2) && (aElem[ 0 ] == '<') && (aElem[ nElemLen - 1 ] == '>') ) { - const sal_Unicode* pcElementStart = ::std::find( pcPos, pcEnd, '<' ); - // append text between elements - if( pcPos < pcElementStart ) + // determine type of the element + bool bSimpleElem = (aElem[ 1 ] == '!') || (aElem[ 1 ] == '?') || (aElem[ nElemLen - 2 ] == '/') || + (bIsVml && (nElemLen == 4) && (aElem[ 1 ] == 'b') && (aElem[ 2 ] == 'r')); + bool bStartElem = !bSimpleElem && (aElem[ 1 ] != '/'); + bool bEndElem = !bSimpleElem && !bStartElem; + + /* Start element or simple element: flush old start element and + its text from previous iteration, and start a new indentation + level for the new element. Trim whitespace and line breaks from + the text of the old start element. */ + if( (bSimpleElem || bStartElem) && (aOldStartElem.getLength() > 0) ) { - OUString aText( pcPos, static_cast< sal_Int32 >( pcElementStart - pcPos ) ); - if( aText.trim().getLength() > 0 ) - aOutLine.append( aText ); - pcPos = pcElementStart; + mxOut->writeString( aOldStartElem.makeStringAndClear().trim() ); + mxOut->newLine(); + mxOut->incIndent(); } - } - // check for stand-alone or following end element - if( !bIsComplElement && (pcPos < pcEnd) && (pcPos[ 1 ] == '/') ) - { - const sal_Unicode* pcElementEnd = ::std::find( pcPos, pcEnd, '>' ); - if( pcElementEnd == pcEnd ) + /* Start element: remember it and its text, to be able to print the + matching end element on the same line in the next iteration. */ + if( bStartElem ) { - // incomplete end element - aOutLine.append( pcPos, static_cast< sal_Int32 >( pcEnd - pcPos ) ); - maIncompleteLine = aOutLine.makeStringAndClear(); - pcPos = pcEnd; + aOldStartElem.append( aElem ).append( aText ); } else { - bIsEndElement = true; - ++pcElementEnd; - aOutLine.append( pcPos, static_cast< sal_Int32 >( pcElementEnd - pcPos ) ); - pcPos = pcElementEnd; - } - } + /* End element: if a start element has been remembered in the + previous iteration, write it out here untrimmed, to show + all whitespace in the element text, and without trailing + line break. Code below will add the end element right after + it. Otherwise, return to previous indentation level. */ + if( bEndElem ) + { + if( aOldStartElem.getLength() == 0 ) + mxOut->decIndent(); + else + mxOut->writeString( aOldStartElem.makeStringAndClear() ); + } - // flush output line - if( maIncompleteLine.getLength() == 0 ) - { - if( !bIsStartElement && bIsEndElement ) mxOut->decIndent(); - mxOut->writeString( aOutLine.makeStringAndClear() ); - mxOut->newLine(); - if( bIsStartElement && !bIsEndElement ) mxOut->incIndent(); + /* Write the element. Write following element text in a new + line, but only, if it does not contain of white space + entirely. */ + mxOut->writeString( aElem ); + mxOut->newLine(); + if( aText.trim().getLength() > 0 ) + { + mxOut->writeString( aText ); + mxOut->newLine(); + } + } } } } @@ -3167,7 +3131,7 @@ bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream& rBaseStrm, sa { ornRecPos = rBaseStrm.tell(); // do not try to overread seekable streams, may cause assertions - bValid = ornRecPos < rBaseStrm.getLength(); + bValid = ornRecPos < rBaseStrm.size(); } // read the record header diff --git a/oox/source/dump/makefile.mk b/oox/source/dump/makefile.mk index 1e5f61567..1e5f61567 100644..100755 --- a/oox/source/dump/makefile.mk +++ b/oox/source/dump/makefile.mk diff --git a/oox/source/dump/oledumper.cxx b/oox/source/dump/oledumper.cxx index 664165c3b..f2b123536 100644 --- a/oox/source/dump/oledumper.cxx +++ b/oox/source/dump/oledumper.cxx @@ -469,9 +469,9 @@ void OlePropertyStreamObject::dumpCodePageProperty( sal_uInt32 nStartPos ) if( nType == OLEPROP_TYPE_INT16 ) { sal_uInt16 nCodePage = dumpDec< sal_uInt16 >( "codepage", "CODEPAGES" ); - rtl_TextEncoding nNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage ); - if( nNewTextEnc != RTL_TEXTENCODING_DONTKNOW ) - meTextEnc = nNewTextEnc; + rtl_TextEncoding eNewTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage ); + if( eNewTextEnc != RTL_TEXTENCODING_DONTKNOW ) + meTextEnc = eNewTextEnc; mbIsUnicode = nCodePage == CODEPAGE_UNICODE; } else @@ -586,15 +586,8 @@ OUString OlePropertyStreamObject::dumpString8( const String& rName ) OUString OlePropertyStreamObject::dumpCharArray8( const String& rName, sal_Int32 nLen ) { - OUString aData; - size_t nNewLen = getLimitedValue< size_t, sal_Int32 >( nLen, 0, 1024 ); - if( nNewLen > 0 ) - { - ::std::vector< sal_Char > aBuffer( nNewLen + 1 ); - mxStrm->readMemory( &aBuffer.front(), nNewLen ); - aBuffer[ nNewLen ] = 0; - aData = OStringToOUString( OString( &aBuffer.front() ), meTextEnc ); - } + sal_Int32 nNewLen = getLimitedValue< sal_Int32, sal_Int32 >( nLen, 0, 1024 ); + OUString aData = mxStrm->readCharArrayUC( nNewLen, meTextEnc ); writeStringItem( rName, aData ); return aData; } @@ -607,13 +600,8 @@ OUString OlePropertyStreamObject::dumpString16( const String& rName ) OUString OlePropertyStreamObject::dumpCharArray16( const String& rName, sal_Int32 nLen ) { - size_t nNewLen = getLimitedValue< size_t, sal_Int32 >( nLen, 0, 1024 ); - ::std::vector< sal_Unicode > aBuffer; - aBuffer.reserve( nNewLen + 1 ); - for( size_t nIdx = 0; nIdx < nNewLen; ++nIdx ) - aBuffer.push_back( static_cast< sal_Unicode >( mxStrm->readuInt16() ) ); - aBuffer.push_back( 0 ); - OUString aData( &aBuffer.front() ); + sal_Int32 nNewLen = getLimitedValue< sal_Int32, sal_Int32 >( nLen, 0, 1024 ); + OUString aData = mxStrm->readUnicodeArray( nNewLen ); writeStringItem( rName, aData ); if( nNewLen & 1 ) dumpUnused( 2 ); // always padding to 32bit return aData; @@ -687,7 +675,7 @@ void OleStorageObject::construct( const ObjectBase& rParent ) StorageObjectBase::construct( rParent ); } -void OleStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& /*rStrgPath*/, const OUString& rStrmName, const OUString& rSysFileName ) +void OleStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& /*rStrgPath*/, const OUString& rStrmName, const OUString& rSysFileName ) { if( rStrmName.equalsAscii( "\001CompObj" ) ) OleCompObjObject( *this, rxStrm, rSysFileName ).dump(); @@ -1926,7 +1914,7 @@ void VbaFStreamObject::dumpSiteData() sal_uInt32 nSiteCount = dumpDec< sal_uInt32 >( "site-count" ); sal_uInt32 nSiteLength = dumpDec< sal_uInt32 >( "site-data-size" ); sal_Int64 nEndPos = mxStrm->tell() + nSiteLength; - if( ensureValid( nEndPos <= mxStrm->getLength() ) ) + if( ensureValid( nEndPos <= mxStrm->size() ) ) { mxOut->resetItemIndex(); sal_uInt32 nSiteIdx = 0; @@ -1984,7 +1972,7 @@ void VbaOStreamObject::implDump() writeDecItem( "control-id", aIt->mnId ); writeInfoItem( "prog-id", aIt->maProgId ); IndentGuard aIndGuard( mxOut ); - RelativeInputStreamRef xRelStrm( new RelativeInputStream( *mxStrm, aIt->mnLength ) ); + BinaryInputStreamRef xRelStrm( new RelativeInputStream( *mxStrm, aIt->mnLength ) ); FormControlStreamObject( *this, xRelStrm, &aIt->maProgId ).dump(); } } @@ -2068,7 +2056,7 @@ VbaContainerStorageObject::VbaContainerStorageObject( const ObjectBase& rParent, addPreferredStream( "f" ); } -void VbaContainerStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) +void VbaContainerStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { if( rStrmName.equalsAscii( "f" ) ) VbaFStreamObject( *this, rxStrm, rSysFileName, maFormData ).dump(); @@ -2280,7 +2268,7 @@ void VbaModuleStreamObject::implDump() writeEmptyItem( "source-code" ); IndentGuard aIndGuard( mxOut ); BinaryInputStreamRef xVbaStrm( new ::oox::ole::VbaInputStream( *mxStrm ) ); - TextStreamObject( *this, xVbaStrm, mrVbaData.meTextEnc ).dump(); + TextLineStreamObject( *this, xVbaStrm, mrVbaData.meTextEnc ).dump(); } // ============================================================================ @@ -2292,7 +2280,7 @@ VbaStorageObject::VbaStorageObject( const ObjectBase& rParent, const StorageRef& addPreferredStream( "dir" ); } -void VbaStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) +void VbaStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { if( (rStrgPath.getLength() == 0) && rStrmName.equalsAscii( "dir" ) ) VbaDirStreamObject( *this, rxStrm, rSysFileName, mrVbaData ).dump(); @@ -2310,10 +2298,10 @@ VbaFormStorageObject::VbaFormStorageObject( const ObjectBase& rParent, const Sto { } -void VbaFormStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) +void VbaFormStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { if( rStrmName.equalsAscii( "\003VBFrame" ) ) - TextStreamObject( *this, rxStrm, mrVbaData.meTextEnc, rSysFileName ).dump(); + TextLineStreamObject( *this, rxStrm, mrVbaData.meTextEnc, rSysFileName ).dump(); else VbaContainerStorageObject::implDumpStream( rxStrm, rStrgPath, rStrmName, rSysFileName ); } @@ -2326,10 +2314,10 @@ VbaProjectStorageObject::VbaProjectStorageObject( const ObjectBase& rParent, con addPreferredStorage( "VBA" ); } -void VbaProjectStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) +void VbaProjectStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { if( (rStrgPath.getLength() == 0) && rStrmName.equalsAscii( "PROJECT" ) ) - TextStreamObject( *this, rxStrm, maVbaData.meTextEnc, rSysFileName ).dump(); + TextLineStreamObject( *this, rxStrm, maVbaData.meTextEnc, rSysFileName ).dump(); else OleStorageObject::implDumpStream( rxStrm, rStrgPath, rStrmName, rSysFileName ); } diff --git a/oox/source/dump/pptxdumper.cxx b/oox/source/dump/pptxdumper.cxx index bf596d2df..b032f6480 100644 --- a/oox/source/dump/pptxdumper.cxx +++ b/oox/source/dump/pptxdumper.cxx @@ -56,14 +56,13 @@ RootStorageObject::RootStorageObject( const DumperBase& rParent ) StorageObjectBase::construct( rParent ); } -void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) +void RootStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { OUString aExt = InputOutputHelper::getFileNameExtension( rStrmName ); - Reference< XInputStream > xInStrm = InputOutputHelper::getXInputStream( *rxStrm ); if( aExt.equalsIgnoreAsciiCaseAscii( "pptx" ) || aExt.equalsIgnoreAsciiCaseAscii( "potx" ) ) { - Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + Dumper( getContext(), rxStrm, rSysFileName ).dump(); } else if( aExt.equalsIgnoreAsciiCaseAscii( "xlsb" ) || @@ -72,7 +71,7 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons aExt.equalsIgnoreAsciiCaseAscii( "xltm" ) || aExt.equalsIgnoreAsciiCaseAscii( "xltx" ) ) { - ::oox::dump::xlsb::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + ::oox::dump::xlsb::Dumper( getContext(), rxStrm, rSysFileName ).dump(); } else if( aExt.equalsIgnoreAsciiCaseAscii( "xla" ) || @@ -82,7 +81,7 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons aExt.equalsIgnoreAsciiCaseAscii( "xlt" ) || aExt.equalsIgnoreAsciiCaseAscii( "xlw" ) ) { - ::oox::dump::biff::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + ::oox::dump::biff::Dumper( getContext(), rxStrm, rSysFileName ).dump(); } else if( aExt.equalsIgnoreAsciiCaseAscii( "xml" ) || @@ -95,17 +94,17 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons { if( rStrgPath.equalsAscii( "ppt" ) && rStrmName.equalsAscii( "vbaProject.bin" ) ) { - StorageRef xStrg( new ::oox::ole::OleStorage( getFactory(), xInStrm, false ) ); + StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, false ) ); VbaProjectStorageObject( *this, xStrg, rSysFileName ).dump(); } else if( rStrgPath.equalsAscii( "ppt/embeddings" ) ) { - StorageRef xStrg( new ::oox::ole::OleStorage( getFactory(), xInStrm, false ) ); + StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, false ) ); OleStorageObject( *this, xStrg, rSysFileName ).dump(); } else if( rStrgPath.equalsAscii( "ppt/activeX" ) ) { - StorageRef xStrg( new ::oox::ole::OleStorage( getFactory(), xInStrm, true ) ); + StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, true ) ); ActiveXStorageObject( *this, xStrg, rSysFileName ).dump(); } else @@ -125,13 +124,13 @@ Dumper::Dumper( const FilterBase& rFilter ) DumperBase::construct( xCfg ); } -Dumper::Dumper( const Reference< XMultiServiceFactory >& rxFactory, const Reference< XInputStream >& rxInStrm, const OUString& rSysFileName ) +Dumper::Dumper( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, const OUString& rSysFileName ) { - if( rxFactory.is() && rxInStrm.is() ) + if( rxContext.is() && rxInStrm.is() ) { - StorageRef xStrg( new ZipStorage( rxFactory, rxInStrm ) ); + StorageRef xStrg( new ZipStorage( rxContext, rxInStrm ) ); MediaDescriptor aMediaDesc; - ConfigRef xCfg( new Config( DUMP_PPTX_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName, aMediaDesc ) ); + ConfigRef xCfg( new Config( DUMP_PPTX_CONFIG_ENVVAR, rxContext, xStrg, rSysFileName, aMediaDesc ) ); DumperBase::construct( xCfg ); } } diff --git a/oox/source/dump/xlsbdumper.cxx b/oox/source/dump/xlsbdumper.cxx index bd00e6a52..447d381d7 100644 --- a/oox/source/dump/xlsbdumper.cxx +++ b/oox/source/dump/xlsbdumper.cxx @@ -368,7 +368,7 @@ void FormulaObject::implDump() if( mnSize < 0 ) return; sal_Int64 nStartPos = mxStrm->tell(); - sal_Int64 nEndPos = ::std::min< sal_Int64 >( nStartPos + mnSize, mxStrm->getLength() ); + sal_Int64 nEndPos = ::std::min< sal_Int64 >( nStartPos + mnSize, mxStrm->size() ); bool bValid = mxTokens.get(); mxStack.reset( new FormulaStack ); @@ -889,8 +889,8 @@ bool FormulaObject::dumpAttrToken() void FormulaObject::dumpAddTokenData() { mxOut->resetItemIndex(); - sal_Int32 nAddDataSize = (mxStrm->getLength() - mxStrm->tell() >= 4) ? dumpDec< sal_Int32 >( "add-data-size" ) : 0; - sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nAddDataSize, mxStrm->getLength() ); + sal_Int32 nAddDataSize = (mxStrm->size() - mxStrm->tell() >= 4) ? dumpDec< sal_Int32 >( "add-data-size" ) : 0; + sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nAddDataSize, mxStrm->size() ); for( AddDataTypeVec::const_iterator aIt = maAddData.begin(), aEnd = maAddData.end(); (aIt != aEnd) && !mxStrm->isEof() && (mxStrm->tell() < nEndPos); ++aIt ) { AddDataType eType = *aIt; @@ -2231,10 +2231,9 @@ RootStorageObject::RootStorageObject( const DumperBase& rParent ) StorageObjectBase::construct( rParent ); } -void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) +void RootStorageObject::implDumpStream( const Reference< XInputStream >& rxStrm, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) { OUString aExt = InputOutputHelper::getFileNameExtension( rStrmName ); - Reference< XInputStream > xInStrm = InputOutputHelper::getXInputStream( *rxStrm ); if( aExt.equalsIgnoreAsciiCaseAscii( "xlsb" ) || aExt.equalsIgnoreAsciiCaseAscii( "xlsm" ) || @@ -2242,7 +2241,7 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons aExt.equalsIgnoreAsciiCaseAscii( "xltm" ) || aExt.equalsIgnoreAsciiCaseAscii( "xltx" ) ) { - Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + Dumper( getContext(), rxStrm, rSysFileName ).dump(); } else if( aExt.equalsIgnoreAsciiCaseAscii( "xla" ) || @@ -2252,13 +2251,13 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons aExt.equalsIgnoreAsciiCaseAscii( "xlt" ) || aExt.equalsIgnoreAsciiCaseAscii( "xlw" ) ) { - ::oox::dump::biff::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + ::oox::dump::biff::Dumper( getContext(), rxStrm, rSysFileName ).dump(); } else if( aExt.equalsIgnoreAsciiCaseAscii( "pptx" ) || aExt.equalsIgnoreAsciiCaseAscii( "potx" ) ) { - ::oox::dump::pptx::Dumper( getFactory(), xInStrm, rSysFileName ).dump(); + ::oox::dump::pptx::Dumper( getContext(), rxStrm, rSysFileName ).dump(); } else if( aExt.equalsIgnoreAsciiCaseAscii( "xml" ) || @@ -2271,12 +2270,12 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons { if( rStrgPath.equalsAscii( "xl" ) && rStrmName.equalsAscii( "vbaProject.bin" ) ) { - StorageRef xStrg( new ::oox::ole::OleStorage( getFactory(), xInStrm, false ) ); + StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, false ) ); VbaProjectStorageObject( *this, xStrg, rSysFileName ).dump(); } else if( rStrgPath.equalsAscii( "xl/embeddings" ) ) { - StorageRef xStrg( new ::oox::ole::OleStorage( getFactory(), xInStrm, false ) ); + StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, false ) ); OleStorageObject( *this, xStrg, rSysFileName ).dump(); } else if( @@ -2295,7 +2294,7 @@ void RootStorageObject::implDumpStream( const BinaryInputStreamRef& rxStrm, cons } else if( rStrgPath.equalsAscii( "xl/activeX" ) ) { - StorageRef xStrg( new ::oox::ole::OleStorage( getFactory(), xInStrm, true ) ); + StorageRef xStrg( new ::oox::ole::OleStorage( getContext(), rxStrm, true ) ); ActiveXStorageObject( *this, xStrg, rSysFileName ).dump(); } else @@ -2315,13 +2314,13 @@ Dumper::Dumper( const FilterBase& rFilter ) DumperBase::construct( xCfg ); } -Dumper::Dumper( const Reference< XMultiServiceFactory >& rxFactory, const Reference< XInputStream >& rxInStrm, const OUString& rSysFileName ) +Dumper::Dumper( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, const OUString& rSysFileName ) { - if( rxFactory.is() && rxInStrm.is() ) + if( rxContext.is() && rxInStrm.is() ) { - StorageRef xStrg( new ZipStorage( rxFactory, rxInStrm ) ); + StorageRef xStrg( new ZipStorage( getContext(), rxInStrm ) ); MediaDescriptor aMediaDesc; - ConfigRef xCfg( new Config( DUMP_XLSB_CONFIG_ENVVAR, rxFactory, xStrg, rSysFileName, aMediaDesc ) ); + ConfigRef xCfg( new Config( DUMP_XLSB_CONFIG_ENVVAR, rxContext, xStrg, rSysFileName, aMediaDesc ) ); DumperBase::construct( xCfg ); } } diff --git a/oox/source/dump/xlsbdumper.ini b/oox/source/dump/xlsbdumper.ini index 3490111c4..16b97172d 100644 --- a/oox/source/dump/xlsbdumper.ini +++ b/oox/source/dump/xlsbdumper.ini @@ -278,6 +278,7 @@ end # ARRAY ---------------------------------------------------------------------- flagslist=ARRAY-FLAGS + ignore=0xFE 0x01=recalc-always end diff --git a/oox/workben/ooxml-export-notes.txt b/oox/source/export/ooxml-export-notes.txt index 8da4582b7..8da4582b7 100644 --- a/oox/workben/ooxml-export-notes.txt +++ b/oox/source/export/ooxml-export-notes.txt diff --git a/oox/source/helper/binaryinputstream.cxx b/oox/source/helper/binaryinputstream.cxx index 640f9f3d0..1582b17e1 100644 --- a/oox/source/helper/binaryinputstream.cxx +++ b/oox/source/helper/binaryinputstream.cxx @@ -27,6 +27,8 @@ #include "oox/helper/binaryinputstream.hxx" +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> #include <string.h> #include <vector> #include <rtl/strbuf.hxx> @@ -80,11 +82,16 @@ OString BinaryInputStream::readCharArray( sal_Int32 nChars, bool bAllowNulChars if( nChars <= 0 ) return OString(); - ::std::vector< sal_Char > aBuffer( static_cast< size_t >( nChars ) ); - size_t nCharsRead = static_cast< size_t >( readMemory( &aBuffer.front(), nChars ) ); + ::std::vector< sal_uInt8 > aBuffer; + sal_Int32 nCharsRead = readArray( aBuffer, nChars ); + if( nCharsRead <= 0 ) + return OString(); + + aBuffer.resize( static_cast< size_t >( nCharsRead ) ); if( !bAllowNulChars ) - ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' ); - return OString( &aBuffer.front(), nCharsRead ); + ::std::replace( aBuffer.begin(), aBuffer.end(), '\0', '?' ); + + return OString( reinterpret_cast< sal_Char* >( &aBuffer.front() ), nCharsRead ); } OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars ) @@ -94,30 +101,44 @@ OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding OUString BinaryInputStream::readUnicodeArray( sal_Int32 nChars, bool bAllowNulChars ) { - OUStringBuffer aBuffer; - if( nChars > 0 ) - { - aBuffer.ensureCapacity( nChars ); - sal_uInt16 nChar; - for( sal_uInt16 nCharIdx = 0; !mbEof && (nCharIdx < nChars); ++nCharIdx ) - { - readValue( nChar ); - aBuffer.append( static_cast< sal_Unicode >( (!bAllowNulChars && (nChar == 0)) ? '?' : nChar ) ); - } - } - return aBuffer.makeStringAndClear(); + if( nChars <= 0 ) + return OUString(); + + ::std::vector< sal_uInt16 > aBuffer; + sal_Int32 nCharsRead = readArray( aBuffer, nChars ); + if( nCharsRead <= 0 ) + return OUString(); + + aBuffer.resize( static_cast< size_t >( nCharsRead ) ); + if( !bAllowNulChars ) + ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' ); + + OUStringBuffer aStringBuffer; + aStringBuffer.ensureCapacity( nCharsRead ); + for( ::std::vector< sal_uInt16 >::iterator aIt = aBuffer.begin(), aEnd = aBuffer.end(); aIt != aEnd; ++aIt ) + aStringBuffer.append( static_cast< sal_Unicode >( *aIt ) ); + return aStringBuffer.makeStringAndClear(); +} + +OUString BinaryInputStream::readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed, bool bAllowNulChars ) +{ + return bCompressed ? + // ISO-8859-1 maps all byte values 0xHH to the same Unicode code point U+00HH + readCharArrayUC( nChars, RTL_TEXTENCODING_ISO_8859_1, bAllowNulChars ) : + readUnicodeArray( nChars, bAllowNulChars ); } -void BinaryInputStream::copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes ) +void BinaryInputStream::copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes, sal_Int32 nAtomSize ) { if( nBytes > 0 ) { - sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, INPUTSTREAM_BUFFERSIZE ); + // make buffer size a multiple of the passed atom size + sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, (INPUTSTREAM_BUFFERSIZE / nAtomSize) * nAtomSize ); StreamDataSequence aBuffer( nBufferSize ); while( nBytes > 0 ) { sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, nBufferSize ); - sal_Int32 nBytesRead = readData( aBuffer, nReadSize ); + sal_Int32 nBytesRead = readData( aBuffer, nReadSize, nAtomSize ); rOutStrm.writeData( aBuffer ); if( nReadSize == nBytesRead ) nBytes -= nReadSize; @@ -127,34 +148,44 @@ void BinaryInputStream::copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nB } } -void BinaryInputStream::readAtom( void* opMem, sal_uInt8 nSize ) -{ - readMemory( opMem, nSize ); -} - // ============================================================================ BinaryXInputStream::BinaryXInputStream( const Reference< XInputStream >& rxInStrm, bool bAutoClose ) : + BinaryStreamBase( Reference< XSeekable >( rxInStrm, UNO_QUERY ).is() ), BinaryXSeekableStream( Reference< XSeekable >( rxInStrm, UNO_QUERY ) ), maBuffer( INPUTSTREAM_BUFFERSIZE ), mxInStrm( rxInStrm ), - mbAutoClose( bAutoClose ) + mbAutoClose( bAutoClose && rxInStrm.is() ) { mbEof = !mxInStrm.is(); } BinaryXInputStream::~BinaryXInputStream() { - if( mbAutoClose ) - close(); + close(); +} + +void BinaryXInputStream::close() +{ + OSL_ENSURE( !mbAutoClose || mxInStrm.is(), "BinaryXInputStream::close - invalid call" ); + if( mbAutoClose && mxInStrm.is() ) try + { + mxInStrm->closeInput(); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryXInputStream::close - closing input stream failed" ); + } + mxInStrm.clear(); + mbAutoClose = false; + BinaryXSeekableStream::close(); } -sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes ) +sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ ) { sal_Int32 nRet = 0; if( !mbEof && (nBytes > 0) ) try { - OSL_ENSURE( mxInStrm.is(), "BinaryXInputStream::readData - invalid call" ); nRet = mxInStrm->readBytes( orData, nBytes ); mbEof = nRet != nBytes; } @@ -165,7 +196,7 @@ sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nB return nRet; } -sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes ) +sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nRet = 0; if( !mbEof && (nBytes > 0) ) @@ -175,7 +206,7 @@ sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes ) while( !mbEof && (nBytes > 0) ) { sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, nBufferSize ); - sal_Int32 nBytesRead = readData( maBuffer, nReadSize ); + sal_Int32 nBytesRead = readData( maBuffer, nReadSize, nAtomSize ); if( nBytesRead > 0 ) memcpy( opnMem, maBuffer.getConstArray(), static_cast< size_t >( nBytesRead ) ); opnMem += nBytesRead; @@ -186,11 +217,10 @@ sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes ) return nRet; } -void BinaryXInputStream::skip( sal_Int32 nBytes ) +void BinaryXInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ ) { if( !mbEof ) try { - OSL_ENSURE( mxInStrm.is(), "BinaryXInputStream::skip - invalid call" ); mxInStrm->skipBytes( nBytes ); } catch( Exception& ) @@ -199,60 +229,48 @@ void BinaryXInputStream::skip( sal_Int32 nBytes ) } } -void BinaryXInputStream::close() -{ - if( mxInStrm.is() ) try - { - mxInStrm->closeInput(); - mxInStrm.clear(); - } - catch( Exception& ) - { - OSL_ENSURE( false, "BinaryXInputStream::close - closing input stream failed" ); - } -} - // ============================================================================ SequenceInputStream::SequenceInputStream( const StreamDataSequence& rData ) : + BinaryStreamBase( true ), SequenceSeekableStream( rData ) { } -sal_Int32 SequenceInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes ) +sal_Int32 SequenceInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ ) { sal_Int32 nReadBytes = 0; if( !mbEof ) { - nReadBytes = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, mrData.getLength() - mnPos ); + nReadBytes = getMaxBytes( nBytes ); orData.realloc( nReadBytes ); if( nReadBytes > 0 ) - memcpy( orData.getArray(), mrData.getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) ); + memcpy( orData.getArray(), mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) ); mnPos += nReadBytes; mbEof = nReadBytes < nBytes; } return nReadBytes; } -sal_Int32 SequenceInputStream::readMemory( void* opMem, sal_Int32 nBytes ) +sal_Int32 SequenceInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ ) { sal_Int32 nReadBytes = 0; if( !mbEof ) { - nReadBytes = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, mrData.getLength() - mnPos ); + nReadBytes = getMaxBytes( nBytes ); if( nReadBytes > 0 ) - memcpy( opMem, mrData.getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) ); + memcpy( opMem, mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) ); mnPos += nReadBytes; mbEof = nReadBytes < nBytes; } return nReadBytes; } -void SequenceInputStream::skip( sal_Int32 nBytes ) +void SequenceInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ ) { if( !mbEof ) { - sal_Int32 nSkipBytes = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, mrData.getLength() - mnPos ); + sal_Int32 nSkipBytes = getMaxBytes( nBytes ); mnPos += nSkipBytes; mbEof = nSkipBytes < nBytes; } @@ -260,73 +278,75 @@ void SequenceInputStream::skip( sal_Int32 nBytes ) // ============================================================================ -RelativeInputStream::RelativeInputStream( BinaryInputStream& rInStrm, sal_Int64 nLength ) : - mrInStrm( rInStrm ), +RelativeInputStream::RelativeInputStream( BinaryInputStream& rInStrm, sal_Int64 nSize ) : + BinaryStreamBase( rInStrm.isSeekable() ), + mpInStrm( &rInStrm ), mnStartPos( rInStrm.tell() ), mnRelPos( 0 ) { sal_Int64 nRemaining = rInStrm.getRemaining(); - mnLength = (nRemaining >= 0) ? ::std::min( nLength, nRemaining ) : nLength; - mbEof = mnLength < 0; + mnSize = (nRemaining >= 0) ? ::std::min( nSize, nRemaining ) : nSize; + mbEof = mbEof || rInStrm.isEof() || (mnSize < 0); } -bool RelativeInputStream::isSeekable() const +sal_Int64 RelativeInputStream::size() const { - return mrInStrm.isSeekable(); -} - -sal_Int64 RelativeInputStream::getLength() const -{ - return mnLength; + return mpInStrm ? mnSize : -1; } sal_Int64 RelativeInputStream::tell() const { - return mnRelPos; + return mpInStrm ? mnRelPos : -1; } void RelativeInputStream::seek( sal_Int64 nPos ) { - if( mrInStrm.isSeekable() && (mnStartPos >= 0) ) + if( mpInStrm && isSeekable() && (mnStartPos >= 0) ) { - mnRelPos = getLimitedValue< sal_Int64, sal_Int64 >( nPos, 0, mnLength ); - mrInStrm.seek( mnStartPos + mnRelPos ); - mbEof = (mnRelPos != nPos) || mrInStrm.isEof(); + mnRelPos = getLimitedValue< sal_Int64, sal_Int64 >( nPos, 0, mnSize ); + mpInStrm->seek( mnStartPos + mnRelPos ); + mbEof = (mnRelPos != nPos) || mpInStrm->isEof(); } } -sal_Int32 RelativeInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes ) +void RelativeInputStream::close() +{ + mpInStrm = 0; + mbEof = true; +} + +sal_Int32 RelativeInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nReadBytes = 0; if( !mbEof ) { - sal_Int32 nRealBytes = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, mnLength - mnRelPos ); - nReadBytes = mrInStrm.readData( orData, nRealBytes ); + sal_Int32 nMaxBytes = getMaxBytes( nBytes ); + nReadBytes = mpInStrm->readData( orData, nMaxBytes, nAtomSize ); mnRelPos += nReadBytes; - mbEof = (nRealBytes < nBytes) || mrInStrm.isEof(); + mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof(); } return nReadBytes; } -sal_Int32 RelativeInputStream::readMemory( void* opMem, sal_Int32 nBytes ) +sal_Int32 RelativeInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nReadBytes = 0; if( !mbEof ) { - sal_Int32 nRealBytes = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, mnLength - mnRelPos ); - nReadBytes = mrInStrm.readMemory( opMem, nRealBytes ); + sal_Int32 nMaxBytes = getMaxBytes( nBytes ); + nReadBytes = mpInStrm->readMemory( opMem, nMaxBytes, nAtomSize ); mnRelPos += nReadBytes; - mbEof = (nRealBytes < nBytes) || mrInStrm.isEof(); + mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof(); } return nReadBytes; } -void RelativeInputStream::skip( sal_Int32 nBytes ) +void RelativeInputStream::skip( sal_Int32 nBytes, size_t nAtomSize ) { if( !mbEof ) { - sal_Int32 nSkipBytes = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, mnLength - mnRelPos ); - mrInStrm.skip( nSkipBytes ); + sal_Int32 nSkipBytes = getMaxBytes( nBytes ); + mpInStrm->skip( nSkipBytes, nAtomSize ); mnRelPos += nSkipBytes; mbEof = nSkipBytes < nBytes; } diff --git a/oox/source/helper/binaryoutputstream.cxx b/oox/source/helper/binaryoutputstream.cxx index 45fa4e67d..3dbae0882 100644 --- a/oox/source/helper/binaryoutputstream.cxx +++ b/oox/source/helper/binaryoutputstream.cxx @@ -27,6 +27,8 @@ #include "oox/helper/binaryoutputstream.hxx" +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> #include <osl/diagnose.h> #include <string.h> @@ -45,33 +47,43 @@ const sal_Int32 OUTPUTSTREAM_BUFFERSIZE = 0x8000; // ============================================================================ -void BinaryOutputStream::writeAtom( const void* pMem, sal_uInt8 nSize ) -{ - writeMemory( pMem, nSize ); -} - -// ============================================================================ - BinaryXOutputStream::BinaryXOutputStream( const Reference< XOutputStream >& rxOutStrm, bool bAutoClose ) : + BinaryStreamBase( Reference< XSeekable >( rxOutStrm, UNO_QUERY ).is() ), BinaryXSeekableStream( Reference< XSeekable >( rxOutStrm, UNO_QUERY ) ), maBuffer( OUTPUTSTREAM_BUFFERSIZE ), mxOutStrm( rxOutStrm ), - mbAutoClose( bAutoClose ) + mbAutoClose( bAutoClose && rxOutStrm.is() ) { mbEof = !mxOutStrm.is(); } BinaryXOutputStream::~BinaryXOutputStream() { - if( mbAutoClose ) - close(); + close(); +} + +void BinaryXOutputStream::close() +{ + OSL_ENSURE( !mbAutoClose || mxOutStrm.is(), "BinaryXOutputStream::close - invalid call" ); + if( mxOutStrm.is() ) try + { + mxOutStrm->flush(); + if( mbAutoClose ) + mxOutStrm->closeOutput(); + } + catch( Exception& ) + { + OSL_ENSURE( false, "BinaryXOutputStream::close - closing output stream failed" ); + } + mxOutStrm.clear(); + mbAutoClose = false; + BinaryXSeekableStream::close(); } -void BinaryXOutputStream::writeData( const StreamDataSequence& rData ) +void BinaryXOutputStream::writeData( const StreamDataSequence& rData, size_t /*nAtomSize*/ ) { - try + if( mxOutStrm.is() ) try { - OSL_ENSURE( mxOutStrm.is(), "BinaryXOutputStream::writeData - invalid call" ); mxOutStrm->writeBytes( rData ); } catch( Exception& ) @@ -80,57 +92,45 @@ void BinaryXOutputStream::writeData( const StreamDataSequence& rData ) } } -void BinaryXOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes ) +void BinaryXOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize ) { - if( nBytes > 0 ) + if( mxOutStrm.is() && (nBytes > 0) ) { - sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, OUTPUTSTREAM_BUFFERSIZE ); + sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, (OUTPUTSTREAM_BUFFERSIZE / nAtomSize) * nAtomSize ); const sal_uInt8* pnMem = reinterpret_cast< const sal_uInt8* >( pMem ); while( nBytes > 0 ) { sal_Int32 nWriteSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, nBufferSize ); maBuffer.realloc( nWriteSize ); memcpy( maBuffer.getArray(), pnMem, static_cast< size_t >( nWriteSize ) ); - writeData( maBuffer ); + writeData( maBuffer, nAtomSize ); pnMem += nWriteSize; nBytes -= nWriteSize; } } } -void BinaryXOutputStream::close() -{ - if( mxOutStrm.is() ) try - { - mxOutStrm->flush(); - mxOutStrm->closeOutput(); - } - catch( Exception& ) - { - OSL_ENSURE( false, "BinaryXOutputStream::close - closing output stream failed" ); - } -} - // ============================================================================ SequenceOutputStream::SequenceOutputStream( StreamDataSequence& rData ) : + BinaryStreamBase( true ), SequenceSeekableStream( rData ) { } -void SequenceOutputStream::writeData( const StreamDataSequence& rData ) +void SequenceOutputStream::writeData( const StreamDataSequence& rData, size_t nAtomSize ) { - if( rData.hasElements() ) - writeMemory( rData.getConstArray(), rData.getLength() ); + if( mpData && rData.hasElements() ) + writeMemory( rData.getConstArray(), rData.getLength(), nAtomSize ); } -void SequenceOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes ) +void SequenceOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes, size_t /*nAtomSize*/ ) { - if( nBytes > 0 ) + if( mpData && (nBytes > 0) ) { - if( mrData.getLength() - mnPos < nBytes ) - const_cast< StreamDataSequence& >( mrData ).realloc( mnPos + nBytes ); - memcpy( const_cast< StreamDataSequence& >( mrData ).getArray() + mnPos, pMem, static_cast< size_t >( nBytes ) ); + if( mpData->getLength() - mnPos < nBytes ) + const_cast< StreamDataSequence* >( mpData )->realloc( mnPos + nBytes ); + memcpy( const_cast< StreamDataSequence* >( mpData )->getArray() + mnPos, pMem, static_cast< size_t >( nBytes ) ); mnPos += nBytes; } } diff --git a/oox/source/helper/binarystreambase.cxx b/oox/source/helper/binarystreambase.cxx index a825a6042..b9104182e 100644 --- a/oox/source/helper/binarystreambase.cxx +++ b/oox/source/helper/binarystreambase.cxx @@ -27,6 +27,7 @@ #include "oox/helper/binarystreambase.hxx" +#include <com/sun/star/io/XSeekable.hpp> #include <osl/diagnose.h> namespace oox { @@ -42,30 +43,11 @@ BinaryStreamBase::~BinaryStreamBase() { } -bool BinaryStreamBase::isSeekable() const -{ - return false; -} - -sal_Int64 BinaryStreamBase::getLength() const -{ - return -1; -} - -sal_Int64 BinaryStreamBase::tell() const -{ - return -1; -} - -void BinaryStreamBase::seek( sal_Int64 ) -{ -} - sal_Int64 BinaryStreamBase::getRemaining() const { // do not use isSeekable(), implementations may provide stream position and size even if not seekable sal_Int64 nPos = tell(); - sal_Int64 nLen = getLength(); + sal_Int64 nLen = size(); return ((nPos >= 0) && (nLen >= 0)) ? ::std::max< sal_Int64 >( nLen - nPos, 0 ) : -1; } @@ -73,7 +55,7 @@ void BinaryStreamBase::alignToBlock( sal_Int32 nBlockSize, sal_Int64 nAnchorPos { sal_Int64 nStrmPos = tell(); // nothing to do, if stream is at anchor position - if( isSeekable() && (0 <= nAnchorPos) && (nAnchorPos != nStrmPos) && (nBlockSize > 1) ) + if( mbSeekable && (0 <= nAnchorPos) && (nAnchorPos != nStrmPos) && (nBlockSize > 1) ) { // prevent modulo with negative arguments... sal_Int64 nSkipSize = (nAnchorPos < nStrmPos) ? @@ -86,16 +68,16 @@ void BinaryStreamBase::alignToBlock( sal_Int32 nBlockSize, sal_Int64 nAnchorPos // ============================================================================ BinaryXSeekableStream::BinaryXSeekableStream( const Reference< XSeekable >& rxSeekable ) : + BinaryStreamBase( mxSeekable.is() ), mxSeekable( rxSeekable ) { } -bool BinaryXSeekableStream::isSeekable() const +BinaryXSeekableStream::~BinaryXSeekableStream() { - return mxSeekable.is(); } -sal_Int64 BinaryXSeekableStream::getLength() const +sal_Int64 BinaryXSeekableStream::size() const { if( mxSeekable.is() ) try { @@ -103,7 +85,7 @@ sal_Int64 BinaryXSeekableStream::getLength() const } catch( Exception& ) { - OSL_ENSURE( false, "BinaryXSeekableStream::getLength - exception caught" ); + OSL_ENSURE( false, "BinaryXSeekableStream::size - exception caught" ); } return -1; } @@ -134,27 +116,44 @@ void BinaryXSeekableStream::seek( sal_Int64 nPos ) } } +void BinaryXSeekableStream::close() +{ + mxSeekable.clear(); + mbEof = true; +} + // ============================================================================ -bool SequenceSeekableStream::isSeekable() const +SequenceSeekableStream::SequenceSeekableStream( const StreamDataSequence& rData ) : + BinaryStreamBase( true ), + mpData( &rData ), + mnPos( 0 ) { - return true; } -sal_Int64 SequenceSeekableStream::getLength() const +sal_Int64 SequenceSeekableStream::size() const { - return mrData.getLength(); + return mpData ? mpData->getLength() : -1; } sal_Int64 SequenceSeekableStream::tell() const { - return mnPos; + return mpData ? mnPos : -1; } void SequenceSeekableStream::seek( sal_Int64 nPos ) { - mnPos = getLimitedValue< sal_Int32, sal_Int64 >( nPos, 0, mrData.getLength() ); - mbEof = mnPos != nPos; + if( mpData ) + { + mnPos = getLimitedValue< sal_Int32, sal_Int64 >( nPos, 0, mpData->getLength() ); + mbEof = mnPos != nPos; + } +} + +void SequenceSeekableStream::close() +{ + mpData = 0; + mbEof = true; } // ============================================================================ diff --git a/oox/source/helper/containerhelper.cxx b/oox/source/helper/containerhelper.cxx index 513e0d8c6..d3fa0215f 100644 --- a/oox/source/helper/containerhelper.cxx +++ b/oox/source/helper/containerhelper.cxx @@ -30,6 +30,7 @@ #include <com/sun/star/container/XIndexContainer.hpp> #include <com/sun/star/container/XNameContainer.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <rtl/ustrbuf.hxx> #include "oox/helper/helper.hxx" @@ -46,12 +47,66 @@ using ::rtl::OUStringBuffer; // ============================================================================ -Reference< XIndexContainer > ContainerHelper::createIndexContainer( const Reference< XMultiServiceFactory >& rxFactory ) +namespace { + +struct ValueRangeComp +{ + inline bool operator()( const ValueRange& rRange, sal_Int32 nValue ) const { return rRange.mnLast < nValue; } +}; + +} // namespace + +// ---------------------------------------------------------------------------- + +void ValueRangeSet::insert( const ValueRange& rRange ) +{ + // find the first range that contains or follows the starting point of the passed range + ValueRangeVector::iterator aBeg = maRanges.begin(); + ValueRangeVector::iterator aEnd = maRanges.end(); + ValueRangeVector::iterator aIt = ::std::lower_bound( aBeg, aEnd, rRange.mnFirst, ValueRangeComp() ); + // nothing to do if found range contains passed range + if( (aIt != aEnd) && aIt->contains( rRange ) ) return; + // check if previous range can be used to merge with the passed range + if( (aIt != aBeg) && ((aIt - 1)->mnLast + 1 == rRange.mnFirst) ) --aIt; + // check if current range (aIt) can be used to merge with passed range + if( (aIt != aEnd) && aIt->intersects( rRange ) ) + { + // set new start value to existing range + aIt->mnFirst = ::std::min( aIt->mnFirst, rRange.mnFirst ); + // search first range that cannot be merged anymore (aNext) + ValueRangeVector::iterator aNext = aIt + 1; + while( (aNext != aEnd) && aNext->intersects( rRange ) ) ++aNext; + // set new end value to existing range + aIt->mnLast = ::std::max( (aNext - 1)->mnLast, rRange.mnLast ); + // remove ranges covered by new existing range (aIt) + maRanges.erase( aIt + 1, aNext ); + } + else + { + // merging not possible: insert new range + maRanges.insert( aIt, rRange ); + } +} + +ValueRangeVector ValueRangeSet::getIntersection( const ValueRange& rRange ) const +{ + ValueRangeVector aRanges; + // find the range that contains nFirst or the first range that follows nFirst + ValueRangeVector::const_iterator aIt = ::std::lower_bound( maRanges.begin(), maRanges.end(), rRange.mnFirst, ValueRangeComp() ); + for( ValueRangeVector::const_iterator aEnd = maRanges.end(); (aIt != aEnd) && (aIt->mnFirst <= rRange.mnLast); ++aIt ) + aRanges.push_back( ValueRange( ::std::max( aIt->mnFirst, rRange.mnFirst ), ::std::min( aIt->mnLast, rRange.mnLast ) ) ); + return aRanges; +} + +// ============================================================================ + +Reference< XIndexContainer > ContainerHelper::createIndexContainer( const Reference< XComponentContext >& rxContext ) { Reference< XIndexContainer > xContainer; - if( rxFactory.is() ) try + if( rxContext.is() ) try { - xContainer.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.IndexedPropertyValues" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + xContainer.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.IndexedPropertyValues" ) ), UNO_QUERY_THROW ); } catch( Exception& ) { @@ -78,12 +133,13 @@ bool ContainerHelper::insertByIndex( return bRet; } -Reference< XNameContainer > ContainerHelper::createNameContainer( const Reference< XMultiServiceFactory >& rxFactory ) +Reference< XNameContainer > ContainerHelper::createNameContainer( const Reference< XComponentContext >& rxContext ) { Reference< XNameContainer > xContainer; - if( rxFactory.is() ) try + if( rxContext.is() ) try { - xContainer.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.NamedPropertyValues" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + xContainer.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.NamedPropertyValues" ) ), UNO_QUERY_THROW ); } catch( Exception& ) { diff --git a/oox/source/helper/graphichelper.cxx b/oox/source/helper/graphichelper.cxx index 616a80e3c..d7f05cf79 100755 --- a/oox/source/helper/graphichelper.cxx +++ b/oox/source/helper/graphichelper.cxx @@ -69,14 +69,13 @@ inline sal_Int32 lclConvertScreenPixelToHmm( double fPixel, double fPixelPerHmm // ============================================================================ GraphicHelper::GraphicHelper( const Reference< XComponentContext >& rxContext, const Reference< XFrame >& rxTargetFrame, const StorageRef& rxStorage ) : - mxCompContext( rxContext ), + mxContext( rxContext ), mxStorage( rxStorage ), maGraphicObjScheme( CREATE_OUSTRING( "vnd.sun.star.GraphicObject:" ) ) { - OSL_ENSURE( mxCompContext.is(), "GraphicHelper::GraphicHelper - missing component context" ); - Reference< XMultiServiceFactory > xFactory( mxCompContext->getServiceManager(), UNO_QUERY_THROW ); + OSL_ENSURE( mxContext.is(), "GraphicHelper::GraphicHelper - missing component context" ); + Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY ); OSL_ENSURE( xFactory.is(), "GraphicHelper::GraphicHelper - missing service factory" ); - if( xFactory.is() ) mxGraphicProvider.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.graphic.GraphicProvider" ) ), UNO_QUERY ); @@ -319,9 +318,9 @@ Reference< XGraphic > GraphicHelper::importEmbeddedGraphic( const OUString& rStr OUString GraphicHelper::createGraphicObject( const Reference< XGraphic >& rxGraphic ) const { OUString aGraphicObjUrl; - if( mxCompContext.is() && rxGraphic.is() ) try + if( mxContext.is() && rxGraphic.is() ) try { - Reference< XGraphicObject > xGraphicObj( GraphicObject::create( mxCompContext ), UNO_SET_THROW ); + Reference< XGraphicObject > xGraphicObj( GraphicObject::create( mxContext ), UNO_SET_THROW ); xGraphicObj->setGraphic( rxGraphic ); maGraphicObjects.push_back( xGraphicObj ); aGraphicObjUrl = maGraphicObjScheme + xGraphicObj->getUniqueID(); diff --git a/oox/source/helper/makefile.mk b/oox/source/helper/makefile.mk index f31736faa..f31736faa 100644..100755 --- a/oox/source/helper/makefile.mk +++ b/oox/source/helper/makefile.mk diff --git a/oox/source/helper/modelobjecthelper.cxx b/oox/source/helper/modelobjecthelper.cxx index b28f8b71d..66e7e8507 100644 --- a/oox/source/helper/modelobjecthelper.cxx +++ b/oox/source/helper/modelobjecthelper.cxx @@ -48,12 +48,12 @@ using ::rtl::OUString; // ============================================================================ -ObjectContainer::ObjectContainer( const Reference< XMultiServiceFactory >& rxFactory, const OUString& rServiceName ) : - mxFactory( rxFactory ), +ObjectContainer::ObjectContainer( const Reference< XMultiServiceFactory >& rxModelFactory, const OUString& rServiceName ) : + mxModelFactory( rxModelFactory ), maServiceName( rServiceName ), mnIndex( 0 ) { - OSL_ENSURE( mxFactory.is(), "ObjectContainer::ObjectContainer - missing service factory" ); + OSL_ENSURE( mxModelFactory.is(), "ObjectContainer::ObjectContainer - missing service factory" ); } ObjectContainer::~ObjectContainer() @@ -94,9 +94,10 @@ OUString ObjectContainer::insertObject( const OUString& rObjName, const Any& rOb void ObjectContainer::createContainer() const { - if( !mxContainer.is() && mxFactory.is() ) try + if( !mxContainer.is() && mxModelFactory.is() ) try { - mxContainer.set( mxFactory->createInstance( maServiceName ), UNO_QUERY_THROW ); + mxContainer.set( mxModelFactory->createInstance( maServiceName ), UNO_QUERY_THROW ); + mxModelFactory.clear(); } catch( Exception& ) { @@ -107,13 +108,13 @@ void ObjectContainer::createContainer() const // ============================================================================ ModelObjectHelper::ModelObjectHelper( const Reference< XMultiServiceFactory >& rxModelFactory ) : - maMarkerContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.MarkerTable" ) ), - maDashContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.DashTable" ) ), - maGradientContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.GradientTable" ) ), - maBitmapContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.BitmapTable" ) ), - maDashNameBase( CREATE_OUSTRING( "msLineDash " ) ), - maGradientNameBase( CREATE_OUSTRING( "msFillGradient " ) ), - maBitmapNameBase( CREATE_OUSTRING( "msFillBitmap " ) ) + maMarkerContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.MarkerTable" ) ), + maDashContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.DashTable" ) ), + maGradientContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.GradientTable" ) ), + maBitmapUrlContainer( rxModelFactory, CREATE_OUSTRING( "com.sun.star.drawing.BitmapTable" ) ), + maDashNameBase( CREATE_OUSTRING( "msLineDash " ) ), + maGradientNameBase( CREATE_OUSTRING( "msFillGradient " ) ), + maBitmapUrlNameBase( CREATE_OUSTRING( "msFillBitmap " ) ) { } @@ -140,10 +141,10 @@ OUString ModelObjectHelper::insertFillGradient( const Gradient& rGradient ) return maGradientContainer.insertObject( maGradientNameBase, Any( rGradient ), true ); } -OUString ModelObjectHelper::insertFillBitmap( const OUString& rGraphicUrl ) +OUString ModelObjectHelper::insertFillBitmapUrl( const OUString& rGraphicUrl ) { if( rGraphicUrl.getLength() > 0 ) - return maBitmapContainer.insertObject( maBitmapNameBase, Any( rGraphicUrl ), true ); + return maBitmapUrlContainer.insertObject( maBitmapUrlNameBase, Any( rGraphicUrl ), true ); return OUString(); } diff --git a/oox/source/helper/propertymap.cxx b/oox/source/helper/propertymap.cxx index 312f414e9..014240a82 100644 --- a/oox/source/helper/propertymap.cxx +++ b/oox/source/helper/propertymap.cxx @@ -161,10 +161,6 @@ PropertyMap::PropertyMap() : { } -PropertyMap::~PropertyMap() -{ -} - /*static*/ const OUString& PropertyMap::getPropertyName( sal_Int32 nPropId ) { OSL_ENSURE( (0 <= nPropId) && (nPropId < PROP_COUNT), "PropertyMap::getPropertyName - invalid property identifier" ); diff --git a/oox/source/helper/propertyset.cxx b/oox/source/helper/propertyset.cxx index 8351db40f..1313fa8d0 100644 --- a/oox/source/helper/propertyset.cxx +++ b/oox/source/helper/propertyset.cxx @@ -48,26 +48,34 @@ void PropertySet::set( const Reference< XPropertySet >& rxPropSet ) { mxPropSet = rxPropSet; mxMultiPropSet.set( mxPropSet, UNO_QUERY ); + if( mxPropSet.is() ) try + { + mxPropSetInfo = mxPropSet->getPropertySetInfo(); + } + catch( Exception& ) + { + } } -// Get properties ------------------------------------------------------------- - -bool PropertySet::getAnyProperty( Any& orValue, sal_Int32 nPropId ) const +bool PropertySet::hasProperty( sal_Int32 nPropId ) const { - return getAnyProperty( orValue, PropertyMap::getPropertyName( nPropId ) ); + if( mxPropSetInfo.is() ) try + { + const OUString& rPropName = PropertyMap::getPropertyName( nPropId ); + return mxPropSetInfo->hasPropertyByName( rPropName ); + } + catch( Exception& ) + { + } + return false; } +// Get properties ------------------------------------------------------------- + Any PropertySet::getAnyProperty( sal_Int32 nPropId ) const { Any aValue; - return getAnyProperty( aValue, nPropId ) ? aValue : Any(); -} - -bool PropertySet::getBoolProperty( sal_Int32 nPropId ) const -{ - Any aAny; - bool bValue = false; - return getAnyProperty( aAny, nPropId ) && (aAny >>= bValue) && bValue; + return implGetPropertyValue( aValue, PropertyMap::getPropertyName( nPropId ) ) ? aValue : Any(); } void PropertySet::getProperties( Sequence< Any >& orValues, const Sequence< OUString >& rPropNames ) const @@ -90,15 +98,15 @@ void PropertySet::getProperties( Sequence< Any >& orValues, const Sequence< OUSt orValues.realloc( nLen ); Any* pValue = orValues.getArray(); for( ; pPropName != pPropNameEnd; ++pPropName, ++pValue ) - getAnyProperty( *pValue, *pPropName ); + implGetPropertyValue( *pValue, *pPropName ); } } // Set properties ------------------------------------------------------------- -void PropertySet::setAnyProperty( sal_Int32 nPropId, const Any& rValue ) +bool PropertySet::setAnyProperty( sal_Int32 nPropId, const Any& rValue ) { - setAnyProperty( PropertyMap::getPropertyName( nPropId ), rValue ); + return implSetPropertyValue( PropertyMap::getPropertyName( nPropId ), rValue ); } void PropertySet::setProperties( const Sequence< OUString >& rPropNames, const Sequence< Any >& rValues ) @@ -122,7 +130,7 @@ void PropertySet::setProperties( const Sequence< OUString >& rPropNames, const S const OUString* pPropNameEnd = pPropName + rPropNames.getLength(); const Any* pValue = rValues.getConstArray(); for( ; pPropName != pPropNameEnd; ++pPropName, ++pValue ) - setAnyProperty( *pPropName, *pValue ); + implSetPropertyValue( *pPropName, *pValue ); } } @@ -139,37 +147,34 @@ void PropertySet::setProperties( const PropertyMap& rPropertyMap ) // private -------------------------------------------------------------------- -bool PropertySet::getAnyProperty( Any& orValue, const OUString& rPropName ) const +bool PropertySet::implGetPropertyValue( Any& orValue, const OUString& rPropName ) const { - bool bHasValue = false; - try + if( mxPropSet.is() ) try { - if( mxPropSet.is() ) - { - orValue = mxPropSet->getPropertyValue( rPropName ); - bHasValue = true; - } + orValue = mxPropSet->getPropertyValue( rPropName ); + return true; } catch( Exception& ) { - OSL_ENSURE( false, OStringBuffer( "PropertySet::getAnyProperty - cannot get property \"" ). + OSL_ENSURE( false, OStringBuffer( "PropertySet::implGetPropertyValue - cannot get property \"" ). append( OUStringToOString( rPropName, RTL_TEXTENCODING_ASCII_US ) ).append( '"' ).getStr() ); } - return bHasValue; + return false; } -void PropertySet::setAnyProperty( const OUString& rPropName, const Any& rValue ) +bool PropertySet::implSetPropertyValue( const OUString& rPropName, const Any& rValue ) { - try + if( mxPropSet.is() ) try { - if( mxPropSet.is() ) - mxPropSet->setPropertyValue( rPropName, rValue ); + mxPropSet->setPropertyValue( rPropName, rValue ); + return true; } catch( Exception& ) { - OSL_ENSURE( false, OStringBuffer( "PropertySet::setAnyProperty - cannot set property \"" ). + OSL_ENSURE( false, OStringBuffer( "PropertySet::implSetPropertyValue - cannot set property \"" ). append( OUStringToOString( rPropName, RTL_TEXTENCODING_ASCII_US ) ).append( '"' ).getStr() ); } + return false; } // ============================================================================ diff --git a/oox/source/helper/textinputstream.cxx b/oox/source/helper/textinputstream.cxx index ae8999491..c6c0848c6 100755 --- a/oox/source/helper/textinputstream.cxx +++ b/oox/source/helper/textinputstream.cxx @@ -27,102 +27,209 @@ #include "oox/helper/textinputstream.hxx" -#include <rtl/strbuf.hxx> -#include <rtl/ustrbuf.hxx> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XTextInputStream.hpp> +#include <cppuhelper/implbase1.hxx> +#include <rtl/tencinfo.h> #include "oox/helper/binaryinputstream.hxx" namespace oox { // ============================================================================ -using ::rtl::OStringBuffer; -using ::rtl::OStringToOUString; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; + using ::rtl::OUString; -using ::rtl::OUStringBuffer; // ============================================================================ namespace { -/** Reads a text line from stream. First, tries to skip the second character of - a two-character line end sequence. Returns the new line-end character. */ -template< typename BufferType, typename CharType, typename StreamDataType > -sal_Unicode lclReadLine( BufferType& orBuffer, BinaryInputStream& rInStrm, sal_Unicode cLastEolChar ) +typedef ::cppu::WeakImplHelper1< XInputStream > UnoBinaryInputStream_BASE; + +/** Implementation of a UNO input stream wrapping a binary input stream. + */ +class UnoBinaryInputStream : public UnoBinaryInputStream_BASE { - // try to skip LF following CR, or CR following LF - if( !rInStrm.isEof() && (cLastEolChar != 0) ) - { - CharType cChar = static_cast< CharType >( rInStrm.readValue< StreamDataType >() ); - // return on EOF after line-end - if( rInStrm.isEof() ) - return 0; - // return on sequence of equal line-end characters - bool bIsEolChar = (cChar == 10) || (cChar == 13); - if( bIsEolChar && (cChar == cLastEolChar) ) - return cChar; - // append the character, if it is not the other line-end charcter - if( !bIsEolChar ) - orBuffer.append( cChar ); - } +public: + explicit UnoBinaryInputStream( BinaryInputStream& rInStrm ); + + virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); + virtual sal_Int32 SAL_CALL available() + throw (NotConnectedException, IOException, RuntimeException); + virtual void SAL_CALL closeInput() + throw (NotConnectedException, IOException, RuntimeException); + +private: + void ensureConnected() const throw (NotConnectedException); + +private: + BinaryInputStream* mpInStrm; +}; + +// ---------------------------------------------------------------------------- + +UnoBinaryInputStream::UnoBinaryInputStream( BinaryInputStream& rInStrm ) : + mpInStrm( &rInStrm ) +{ +} - // read chars until EOF or line end character (LF or CR) - while( true ) - { - CharType cChar = static_cast< CharType >( rInStrm.readValue< StreamDataType >() ); - if( rInStrm.isEof() ) - return 0; - if( (cChar == 10) || (cChar == 13) ) - return cChar; - orBuffer.append( cChar ); - } +sal_Int32 SAL_CALL UnoBinaryInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + ensureConnected(); + return mpInStrm->readData( rData, nBytesToRead, 1 ); +} + +sal_Int32 SAL_CALL UnoBinaryInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + ensureConnected(); + return mpInStrm->readData( rData, nMaxBytesToRead, 1 ); +} + +void SAL_CALL UnoBinaryInputStream::skipBytes( sal_Int32 nBytesToSkip ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + ensureConnected(); + mpInStrm->skip( nBytesToSkip, 1 ); +} + +sal_Int32 SAL_CALL UnoBinaryInputStream::available() throw (NotConnectedException, IOException, RuntimeException) +{ + ensureConnected(); + throw RuntimeException( CREATE_OUSTRING( "Functionality not supported" ), Reference< XInputStream >() ); +} + +void SAL_CALL UnoBinaryInputStream::closeInput() throw (NotConnectedException, IOException, RuntimeException) +{ + ensureConnected(); + mpInStrm->close(); + mpInStrm = 0; +} + +void UnoBinaryInputStream::ensureConnected() const throw (NotConnectedException) +{ + if( !mpInStrm ) + throw NotConnectedException( CREATE_OUSTRING( "Stream closed" ), Reference< XInterface >() ); } } // namespace // ============================================================================ -TextInputStream::TextInputStream( BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc ) : - mrInStrm( rInStrm ), - meTextEnc( eTextEnc ), - mcLastEolChar( 0 ) +TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc ) +{ + init( rxContext, rxInStrm, eTextEnc ); +} + +TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc ) +{ + init( rxContext, new UnoBinaryInputStream( rInStrm ), eTextEnc ); +} + +TextInputStream::~TextInputStream() { } bool TextInputStream::isEof() const { - // do not return EOF, if last text line missed line-end character (see below) - return mrInStrm.isEof() && (mcLastEolChar == 0); + if( mxTextStrm.is() ) try + { + return mxTextStrm->isEOF(); + } + catch( Exception& ) + { + } + return true; } OUString TextInputStream::readLine() { - if( mrInStrm.isEof() ) + if( mxTextStrm.is() ) try { - mcLastEolChar = 0; - return OUString(); + /* The function createFinalString() adds a character that may have + been buffered in the previous call of readToChar() (see below). */ + return createFinalString( mxTextStrm->readLine() ); } - - OUString aLine; - if( meTextEnc == RTL_TEXTENCODING_UCS2 ) + catch( Exception& ) + { + mxTextStrm.clear(); + } + return OUString(); +} + +OUString TextInputStream::readToChar( sal_Unicode cChar, bool bIncludeChar ) +{ + if( mxTextStrm.is() ) try { - // read 16-bit characters for UCS2 encoding - OUStringBuffer aBuffer; - mcLastEolChar = lclReadLine< OUStringBuffer, sal_Unicode, sal_uInt16 >( aBuffer, mrInStrm, mcLastEolChar ); - aLine = aBuffer.makeStringAndClear(); + Sequence< sal_Unicode > aDelimiters( 1 ); + aDelimiters[ 0 ] = cChar; + /* Always get the delimiter character from the UNO text input stream. + In difference to this implementation, it will not return it in the + next call but silently skip it. If caller specifies to exclude the + character in this call, it will be returned in the next call of one + of the own member functions. The function createFinalString() adds + a character that has been buffered in the previous call. */ + OUString aString = createFinalString( mxTextStrm->readString( aDelimiters, sal_False ) ); + // remove last character from string and remember it for next call + if( !bIncludeChar && (aString.getLength() > 0) && (aString[ aString.getLength() - 1 ] == cChar) ) + { + mcPendingChar = cChar; + aString = aString.copy( 0, aString.getLength() - 1 ); + } + return aString; } - else + catch( Exception& ) { - // otherwise, read 8-bit characters and convert according to text encoding - OStringBuffer aBuffer; - mcLastEolChar = lclReadLine< OStringBuffer, sal_Char, sal_uInt8 >( aBuffer, mrInStrm, mcLastEolChar ); - aLine = OStringToOUString( aBuffer.makeStringAndClear(), meTextEnc ); + mxTextStrm.clear(); } + return OUString(); +} - // if last line is not empty but line-end character is missing, do not return EOF - if( mrInStrm.isEof() && (aLine.getLength() > 0) ) - mcLastEolChar = 10; +/*static*/ Reference< XTextInputStream > TextInputStream::createXTextInputStream( + const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc ) +{ + Reference< XTextInputStream > xTextStrm; + const char* pcCharset = rtl_getMimeCharsetFromTextEncoding( eTextEnc ); + OSL_ENSURE( pcCharset, "TextInputStream::createXTextInputStream - unsupported text encoding" ); + if( rxContext.is() && rxInStrm.is() && pcCharset ) try + { + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XActiveDataSink > xDataSink( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextInputStream" ) ), UNO_QUERY_THROW ); + xDataSink->setInputStream( rxInStrm ); + xTextStrm.set( xDataSink, UNO_QUERY_THROW ); + xTextStrm->setEncoding( OUString::createFromAscii( pcCharset ) ); + } + catch( Exception& ) + { + } + return xTextStrm; +} + +// private -------------------------------------------------------------------- + +OUString TextInputStream::createFinalString( const OUString& rString ) +{ + if( mcPendingChar == 0 ) + return rString; - return aLine; + OUString aString = OUString( mcPendingChar ) + rString; + mcPendingChar = 0; + return aString; +} + +void TextInputStream::init( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc ) +{ + mcPendingChar = 0; + mxTextStrm = createXTextInputStream( rxContext, rxInStrm, eTextEnc ); } // ============================================================================ diff --git a/oox/source/helper/zipstorage.cxx b/oox/source/helper/zipstorage.cxx index 98f5ccbf2..b6a296fbe 100644 --- a/oox/source/helper/zipstorage.cxx +++ b/oox/source/helper/zipstorage.cxx @@ -33,6 +33,7 @@ #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/XOutputStream.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <comphelper/storagehelper.hxx> #include "oox/helper/helper.hxx" @@ -50,47 +51,46 @@ using ::rtl::OUString; // ============================================================================ -ZipStorage::ZipStorage( - const Reference< XMultiServiceFactory >& rxFactory, - const Reference< XInputStream >& rxInStream ) : +ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStream ) : StorageBase( rxInStream, false ) { - OSL_ENSURE( rxFactory.is(), "ZipStorage::ZipStorage - missing service factory" ); + OSL_ENSURE( rxContext.is(), "ZipStorage::ZipStorage - missing component context" ); // create base storage object - try + if( rxContext.is() ) try { /* #i105325# ::comphelper::OStorageHelper::GetStorageFromInputStream() cannot be used here as it will open a storage with format type 'PackageFormat' that will not work with OOXML packages. - #161971# The MS-document storages should always be opened in Repair-Mode to - ignore the format errors and get so much info as possible. I hate this - solution, but it seems to be the only consistent way to handle the MS-documents. + #161971# The MS-document storages should always be opened in repair + mode to ignore the format errors and get so much info as possible. + I hate this solution, but it seems to be the only consistent way to + handle the MS documents. TODO: #i105410# switch to 'OFOPXMLFormat' and use its - implementation of relations handling. */ - + implementation of relations handling. + */ + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( - ZIP_STORAGE_FORMAT_STRING, rxInStream, rxFactory, - sal_False /* DEV300_m80: Was sal_True, but DOCX and others did not load */ ); + ZIP_STORAGE_FORMAT_STRING, rxInStream, xFactory, + sal_False ); // DEV300_m80: Was sal_True, but DOCX and others did not load } catch( Exception& ) { } } -ZipStorage::ZipStorage( - const Reference< XMultiServiceFactory >& rxFactory, - const Reference< XStream >& rxStream ) : +ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const Reference< XStream >& rxStream ) : StorageBase( rxStream, false ) { - OSL_ENSURE( rxFactory.is(), "ZipStorage::ZipStorage - missing service factory" ); + OSL_ENSURE( rxContext.is(), "ZipStorage::ZipStorage - missing component context" ); // create base storage object - try + if( rxContext.is() ) try { - using namespace ::com::sun::star::embed::ElementModes; + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + const sal_Int32 nOpenMode = ElementModes::READWRITE | ElementModes::TRUNCATE; mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( - OFOPXML_STORAGE_FORMAT_STRING, rxStream, READWRITE | TRUNCATE, rxFactory, sal_True ); + OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, xFactory, sal_True ); } catch( Exception& ) { diff --git a/oox/source/ole/axbinaryreader.cxx b/oox/source/ole/axbinaryreader.cxx index d7cf8e5b6..669ca2e47 100644 --- a/oox/source/ole/axbinaryreader.cxx +++ b/oox/source/ole/axbinaryreader.cxx @@ -48,14 +48,22 @@ const sal_uInt32 AX_STRING_COMPRESSED = 0x80000000; // ============================================================================ AxAlignedInputStream::AxAlignedInputStream( BinaryInputStream& rInStrm ) : - mrInStrm( rInStrm ), - mnStrmPos( 0 ) + BinaryStreamBase( false ), + mpInStrm( &rInStrm ), + mnStrmPos( 0 ), + mnStrmSize( rInStrm.getRemaining() ) { + mbEof = mbEof || rInStrm.isEof(); +} + +sal_Int64 AxAlignedInputStream::size() const +{ + return mpInStrm ? mnStrmSize : -1; } sal_Int64 AxAlignedInputStream::tell() const { - return mnStrmPos; + return mpInStrm ? mnStrmPos : -1; } void AxAlignedInputStream::seek( sal_Int64 nPos ) @@ -65,24 +73,44 @@ void AxAlignedInputStream::seek( sal_Int64 nPos ) skip( static_cast< sal_Int32 >( nPos - mnStrmPos ) ); } -sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes ) +void AxAlignedInputStream::close() +{ + mpInStrm = 0; + mbEof = true; +} + +sal_Int32 AxAlignedInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) { - sal_Int32 nReadSize = mrInStrm.readData( orData, nBytes ); - mnStrmPos += nReadSize; + sal_Int32 nReadSize = 0; + if( !mbEof ) + { + nReadSize = mpInStrm->readData( orData, nBytes, nAtomSize ); + mnStrmPos += nReadSize; + mbEof = mpInStrm->isEof(); + } return nReadSize; } -sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes ) +sal_Int32 AxAlignedInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) { - sal_Int32 nReadSize = mrInStrm.readMemory( opMem, nBytes ); - mnStrmPos += nReadSize; + sal_Int32 nReadSize = 0; + if( !mbEof ) + { + nReadSize = mpInStrm->readMemory( opMem, nBytes, nAtomSize ); + mnStrmPos += nReadSize; + mbEof = mpInStrm->isEof(); + } return nReadSize; } -void AxAlignedInputStream::skip( sal_Int32 nBytes ) +void AxAlignedInputStream::skip( sal_Int32 nBytes, size_t nAtomSize ) { - mrInStrm.skip( nBytes ); - mnStrmPos += nBytes; + if( !mbEof ) + { + mpInStrm->skip( nBytes, nAtomSize ); + mnStrmPos += nBytes; + mbEof = mpInStrm->isEof(); + } } void AxAlignedInputStream::align( size_t nSize ) @@ -174,10 +202,7 @@ bool lclReadString( AxAlignedInputStream& rInStrm, OUString& rValue, sal_uInt32 OSL_ENSURE( bValidChars, "lclReadString - string too long" ); sal_Int64 nEndPos = rInStrm.tell() + nChars * (bCompressed ? 1 : 2); nChars = ::std::min< sal_Int32 >( nChars, 65536 ); - rValue = bCompressed ? - // ISO-8859-1 maps all byte values xx to the same Unicode code point U+00xx - rInStrm.readCharArrayUC( nChars, RTL_TEXTENCODING_ISO_8859_1 ) : - rInStrm.readUnicodeArray( nChars ); + rValue = rInStrm.readCompressedUnicodeArray( nChars, bCompressed ); rInStrm.seek( nEndPos ); return bValidChars; } diff --git a/oox/source/ole/axcontrol.cxx b/oox/source/ole/axcontrol.cxx index 9f121a737..de304542a 100644 --- a/oox/source/ole/axcontrol.cxx +++ b/oox/source/ole/axcontrol.cxx @@ -226,11 +226,11 @@ void lclPrepareConverter( PropertySet& rConverter, const Reference< XModel >& rx { if( !rConverter.is() ) try { - Reference< XMultiServiceFactory > xFactory( rxDocModel, UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xModelFactory( rxDocModel, UNO_QUERY_THROW ); OUString aServiceName = bRange ? CREATE_OUSTRING( "com.sun.star.table.CellRangeAddressConversion" ) : CREATE_OUSTRING( "com.sun.star.table.CellAddressConversion" ); - rConverter.set( xFactory->createInstance( aServiceName ) ); + rConverter.set( xModelFactory->createInstance( aServiceName ) ); } catch( Exception& ) { @@ -344,8 +344,8 @@ void ControlConverter::bindToSources( const Reference< XControlModel >& rxCtrlMo aArgs[ 0 ] <<= aValue; // create the CellValueBinding instance and set at the control model - Reference< XMultiServiceFactory > xFactory( mxDocModel, UNO_QUERY_THROW ); - Reference< XValueBinding > xBinding( xFactory->createInstanceWithArguments( + Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW ); + Reference< XValueBinding > xBinding( xModelFactory->createInstanceWithArguments( CREATE_OUSTRING( "com.sun.star.table.CellValueBinding" ), aArgs ), UNO_QUERY_THROW ); xBindable->setValueBinding( xBinding ); } @@ -376,8 +376,8 @@ void ControlConverter::bindToSources( const Reference< XControlModel >& rxCtrlMo aArgs[ 0 ] <<= aValue; // create the EntrySource instance and set at the control model - Reference< XMultiServiceFactory > xFactory( mxDocModel, UNO_QUERY_THROW ); - Reference< XListEntrySource > xEntrySource( xFactory->createInstanceWithArguments( + Reference< XMultiServiceFactory > xModelFactory( mxDocModel, UNO_QUERY_THROW ); + Reference< XListEntrySource > xEntrySource( xModelFactory->createInstanceWithArguments( CREATE_OUSTRING( "com.sun.star.table.CellRangeListSource" ), aArgs ), UNO_QUERY_THROW ); xEntrySink->setListEntrySource( xEntrySource ); } diff --git a/oox/source/ole/axcontrolfragment.cxx b/oox/source/ole/axcontrolfragment.cxx index 64d15bc4e..972387266 100644 --- a/oox/source/ole/axcontrolfragment.cxx +++ b/oox/source/ole/axcontrolfragment.cxx @@ -140,7 +140,7 @@ ContextHandlerRef AxControlFragment::onCreateContext( sal_Int32 nElement, const Reference< XInputStream > xStrgStrm = getFilter().openInputStream( aFragmentPath ); if( xStrgStrm.is() ) { - OleStorage aStorage( getFilter().getServiceFactory(), xStrgStrm, false ); + OleStorage aStorage( getFilter().getComponentContext(), xStrgStrm, false ); BinaryXInputStream aInStrm( aStorage.openInputStream( CREATE_OUSTRING( "f" ) ), true ); if( !aInStrm.isEof() ) if( AxContainerModelBase* pModel = dynamic_cast< AxContainerModelBase* >( mrControl.createModelFromGuid( aClassId ) ) ) diff --git a/oox/source/ole/makefile.mk b/oox/source/ole/makefile.mk index a5232247c..a5232247c 100644..100755 --- a/oox/source/ole/makefile.mk +++ b/oox/source/ole/makefile.mk diff --git a/oox/source/ole/oleobjecthelper.cxx b/oox/source/ole/oleobjecthelper.cxx index 34d3e0da0..520127be1 100644 --- a/oox/source/ole/oleobjecthelper.cxx +++ b/oox/source/ole/oleobjecthelper.cxx @@ -44,6 +44,7 @@ namespace ole { using namespace ::com::sun::star::awt; using namespace ::com::sun::star::container; +using namespace ::com::sun::star::embed; using namespace ::com::sun::star::io; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::uno; @@ -61,12 +62,17 @@ OleObjectInfo::OleObjectInfo() : // ============================================================================ -OleObjectHelper::OleObjectHelper( const Reference< XMultiServiceFactory >& rxFactory ) : +OleObjectHelper::OleObjectHelper( const Reference< XMultiServiceFactory >& rxModelFactory ) : maEmbeddedObjScheme( CREATE_OUSTRING( "vnd.sun.star.EmbeddedObject:" ) ), mnObjectId( 100 ) { - if( rxFactory.is() ) - mxResolver.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.ImportEmbeddedObjectResolver" ) ), UNO_QUERY ); + if( rxModelFactory.is() ) try + { + mxResolver.set( rxModelFactory->createInstance( CREATE_OUSTRING( "com.sun.star.document.ImportEmbeddedObjectResolver" ) ), UNO_QUERY ); + } + catch( Exception& ) + { + } } OleObjectHelper::~OleObjectHelper() @@ -122,11 +128,7 @@ bool OleObjectHelper::importOleObject( PropertyMap& rPropMap, const OleObjectInf if( bRet ) { - // aspect mode - using namespace ::com::sun::star::embed::Aspects; - sal_Int64 nAspect = rOleObject.mbShowAsIcon ? MSOLE_ICON : MSOLE_CONTENT; - rPropMap[ PROP_Aspect ] <<= nAspect; - // visual area + rPropMap[ PROP_Aspect ] <<= (rOleObject.mbShowAsIcon ? Aspects::MSOLE_ICON : Aspects::MSOLE_CONTENT); rPropMap[ PROP_VisualArea ] <<= Rectangle( 0, 0, rObjSize.Width, rObjSize.Height ); } return bRet; diff --git a/oox/source/ole/olestorage.cxx b/oox/source/ole/olestorage.cxx index 1acb82298..ceb02b355 100644..100755 --- a/oox/source/ole/olestorage.cxx +++ b/oox/source/ole/olestorage.cxx @@ -35,6 +35,7 @@ #include <com/sun/star/io/XSeekable.hpp> #include <com/sun/star/io/XStream.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <cppuhelper/implbase2.hxx> #include "oox/helper/binaryinputstream.hxx" #include "oox/helper/binaryoutputstream.hxx" @@ -68,7 +69,7 @@ class OleOutputStream : public OleOutputStreamBase { public: explicit OleOutputStream( - const Reference< XMultiServiceFactory >& rxFactory, + const Reference< XComponentContext >& rxContext, const Reference< XNameContainer >& rxStorage, const OUString& rElementName ); virtual ~OleOutputStream(); @@ -95,14 +96,15 @@ private: // ---------------------------------------------------------------------------- -OleOutputStream::OleOutputStream( const Reference< XMultiServiceFactory >& rxFactory, +OleOutputStream::OleOutputStream( const Reference< XComponentContext >& rxContext, const Reference< XNameContainer >& rxStorage, const OUString& rElementName ) : mxStorage( rxStorage ), maElementName( rElementName ) { try { - mxTempFile.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); + mxTempFile.set( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); mxOutStrm = mxTempFile->getOutputStream(); mxSeekable.set( mxOutStrm, UNO_QUERY ); } @@ -179,49 +181,40 @@ void OleOutputStream::ensureConnected() const throw( NotConnectedException ) // ============================================================================ -OleStorage::OleStorage( - const Reference< XMultiServiceFactory >& rxFactory, - const Reference< XInputStream >& rxInStream, - bool bBaseStreamAccess ) : +OleStorage::OleStorage( const Reference< XComponentContext >& rxContext, + const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) : StorageBase( rxInStream, bBaseStreamAccess ), - mxFactory( rxFactory ), + mxContext( rxContext ), mpParentStorage( 0 ) { - OSL_ENSURE( mxFactory.is(), "OleStorage::OleStorage - missing service factory" ); + OSL_ENSURE( mxContext.is(), "OleStorage::OleStorage - missing component context" ); initStorage( rxInStream ); } -OleStorage::OleStorage( - const Reference< XMultiServiceFactory >& rxFactory, - const Reference< XStream >& rxOutStream, - bool bBaseStreamAccess ) : +OleStorage::OleStorage( const Reference< XComponentContext >& rxContext, + const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) : StorageBase( rxOutStream, bBaseStreamAccess ), - mxFactory( rxFactory ), + mxContext( rxContext ), mpParentStorage( 0 ) { - OSL_ENSURE( mxFactory.is(), "OleStorage::OleStorage - missing service factory" ); + OSL_ENSURE( mxContext.is(), "OleStorage::OleStorage - missing component context" ); initStorage( rxOutStream ); } -OleStorage::OleStorage( - const OleStorage& rParentStorage, - const Reference< XNameContainer >& rxStorage, - const OUString& rElementName, - bool bReadOnly ) : +OleStorage::OleStorage( const OleStorage& rParentStorage, + const Reference< XNameContainer >& rxStorage, const OUString& rElementName, bool bReadOnly ) : StorageBase( rParentStorage, rElementName, bReadOnly ), - mxFactory( rParentStorage.mxFactory ), + mxContext( rParentStorage.mxContext ), mxStorage( rxStorage ), mpParentStorage( &rParentStorage ) { OSL_ENSURE( mxStorage.is(), "OleStorage::OleStorage - missing substorage elements" ); } -OleStorage::OleStorage( - const OleStorage& rParentStorage, - const Reference< XStream >& rxOutStream, - const OUString& rElementName ) : +OleStorage::OleStorage( const OleStorage& rParentStorage, + const Reference< XStream >& rxOutStream, const OUString& rElementName ) : StorageBase( rParentStorage, rElementName, false ), - mxFactory( rParentStorage.mxFactory ), + mxContext( rParentStorage.mxContext ), mpParentStorage( &rParentStorage ) { initStorage( rxOutStream ); @@ -239,7 +232,8 @@ void OleStorage::initStorage( const Reference< XInputStream >& rxInStream ) Reference< XInputStream > xInStrm = rxInStream; if( !Reference< XSeekable >( xInStrm, UNO_QUERY ).is() ) try { - Reference< XStream > xTempFile( mxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XStream > xTempFile( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); { Reference< XOutputStream > xOutStrm( xTempFile->getOutputStream(), UNO_SET_THROW ); /* Pass false to both binary stream objects to keep the UNO @@ -259,10 +253,11 @@ void OleStorage::initStorage( const Reference< XInputStream >& rxInStream ) // create base storage object if( xInStrm.is() ) try { + Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); Sequence< Any > aArgs( 2 ); aArgs[ 0 ] <<= xInStrm; aArgs[ 1 ] <<= true; // true = do not create a copy of the input stream - mxStorage.set( mxFactory->createInstanceWithArguments( + mxStorage.set( xFactory->createInstanceWithArguments( CREATE_OUSTRING( "com.sun.star.embed.OLESimpleStorage" ), aArgs ), UNO_QUERY_THROW ); } catch( Exception& ) @@ -275,10 +270,11 @@ void OleStorage::initStorage( const Reference< XStream >& rxOutStream ) // create base storage object if( rxOutStream.is() ) try { + Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); Sequence< Any > aArgs( 2 ); aArgs[ 0 ] <<= rxOutStream; aArgs[ 1 ] <<= true; // true = do not create a copy of the stream - mxStorage.set( mxFactory->createInstanceWithArguments( + mxStorage.set( xFactory->createInstanceWithArguments( CREATE_OUSTRING( "com.sun.star.embed.OLESimpleStorage" ), aArgs ), UNO_QUERY_THROW ); } catch( Exception& ) @@ -347,7 +343,8 @@ StorageRef OleStorage::implOpenSubStorage( const OUString& rElementName, bool bC if( !isReadOnly() && (bCreateMissing || xSubStorage.get()) ) try { // create new storage based on a temp file - Reference< XStream > xTempFile( mxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XStream > xTempFile( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW ); StorageRef xTempStorage( new OleStorage( *this, xTempFile, rElementName ) ); // copy existing substorage into temp storage if( xSubStorage.get() ) @@ -379,7 +376,7 @@ Reference< XOutputStream > OleStorage::implOpenOutputStream( const OUString& rEl { Reference< XOutputStream > xOutStream; if( mxStorage.is() && (rElementName.getLength() > 0) ) - xOutStream.set( new OleOutputStream( mxFactory, mxStorage, rElementName ) ); + xOutStream.set( new OleOutputStream( mxContext, mxStorage, rElementName ) ); return xOutStream; } diff --git a/oox/source/ole/vbacontrol.cxx b/oox/source/ole/vbacontrol.cxx index 27cb88cb8..617bbf9e8 100644 --- a/oox/source/ole/vbacontrol.cxx +++ b/oox/source/ole/vbacontrol.cxx @@ -756,11 +756,11 @@ bool lclEatKeyword( OUString& rCodeLine, const OUString& rKeyword ) VbaUserForm::VbaUserForm( const Reference< XComponentContext >& rxContext, const Reference< XModel >& rxDocModel, const GraphicHelper& rGraphicHelper, bool bDefaultColorBgr ) : - mxCompContext( rxContext ), + mxContext( rxContext ), mxDocModel( rxDocModel ), maConverter( rxDocModel, rGraphicHelper, bDefaultColorBgr ) { - OSL_ENSURE( mxCompContext.is(), "VbaUserForm::VbaUserForm - missing component context" ); + OSL_ENSURE( mxContext.is(), "VbaUserForm::VbaUserForm - missing component context" ); OSL_ENSURE( mxDocModel.is(), "VbaUserForm::VbaUserForm - missing document model" ); } @@ -768,7 +768,7 @@ void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib, StorageBase& rVbaFormStrg, const OUString& rModuleName, rtl_TextEncoding eTextEnc ) { OSL_ENSURE( rxDialogLib.is(), "VbaUserForm::importForm - missing dialog library" ); - if( !mxCompContext.is() || !mxDocModel.is() || !rxDialogLib.is() ) + if( !mxContext.is() || !mxDocModel.is() || !rxDialogLib.is() ) return; // check that the '03VBFrame' stream exists, this is required for forms @@ -778,7 +778,7 @@ void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib, return; // scan for the line 'Begin {GUID} <FormName>' - TextInputStream aFrameTextStrm( aInStrm, eTextEnc ); + TextInputStream aFrameTextStrm( mxContext, aInStrm, eTextEnc ); const OUString aBegin = CREATE_OUSTRING( "Begin" ); OUString aLine; bool bBeginFound = false; @@ -826,7 +826,7 @@ void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib, { // create the dialog model OUString aServiceName = mxCtrlModel->getServiceName(); - Reference< XMultiServiceFactory > xFactory( mxCompContext->getServiceManager(), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); Reference< XControlModel > xDialogModel( xFactory->createInstance( aServiceName ), UNO_QUERY_THROW ); Reference< XNameContainer > xDialogNC( xDialogModel, UNO_QUERY_THROW ); @@ -834,7 +834,7 @@ void VbaUserForm::importForm( const Reference< XNameContainer >& rxDialogLib, if( convertProperties( xDialogModel, maConverter, 0 ) ) { // export the dialog to XML and insert it into the dialog library - Reference< XInputStreamProvider > xDialogSource( ::xmlscript::exportDialogModel( xDialogNC, mxCompContext ), UNO_SET_THROW ); + Reference< XInputStreamProvider > xDialogSource( ::xmlscript::exportDialogModel( xDialogNC, mxContext ), UNO_SET_THROW ); OSL_ENSURE( !rxDialogLib->hasByName( aFormName ), "VbaUserForm::importForm - multiple dialogs with equal name" ); ContainerHelper::insertByName( rxDialogLib, aFormName, Any( xDialogSource ) ); } diff --git a/oox/source/ole/vbainputstream.cxx b/oox/source/ole/vbainputstream.cxx index 15b2aab98..bff01a5ac 100644 --- a/oox/source/ole/vbainputstream.cxx +++ b/oox/source/ole/vbainputstream.cxx @@ -47,17 +47,38 @@ const sal_uInt16 VBACHUNK_LENMASK = 0x0FFF; // ============================================================================ VbaInputStream::VbaInputStream( BinaryInputStream& rInStrm ) : - mrInStrm( rInStrm ), + BinaryStreamBase( false ), + mpInStrm( &rInStrm ), mnChunkPos( 0 ) { maChunk.reserve( 4096 ); - sal_uInt8 nSig = mrInStrm.readuInt8(); + sal_uInt8 nSig = rInStrm.readuInt8(); OSL_ENSURE( nSig == VBASTREAM_SIGNATURE, "VbaInputStream::VbaInputStream - wrong signature" ); - mbEof = nSig != VBASTREAM_SIGNATURE; + mbEof = mbEof || rInStrm.isEof() || (nSig != VBASTREAM_SIGNATURE); } -sal_Int32 VbaInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes ) +sal_Int64 VbaInputStream::size() const +{ + return -1; +} + +sal_Int64 VbaInputStream::tell() const +{ + return -1; +} + +void VbaInputStream::seek( sal_Int64 ) +{ +} + +void VbaInputStream::close() +{ + mpInStrm = 0; + mbEof = true; +} + +sal_Int32 VbaInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nRet = 0; if( !mbEof ) @@ -65,7 +86,7 @@ sal_Int32 VbaInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes orData.realloc( ::std::max< sal_Int32 >( nBytes, 0 ) ); if( nBytes > 0 ) { - nRet = readMemory( orData.getArray(), nBytes ); + nRet = readMemory( orData.getArray(), nBytes, nAtomSize ); if( nRet < nBytes ) orData.realloc( nRet ); } @@ -73,7 +94,7 @@ sal_Int32 VbaInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes return nRet; } -sal_Int32 VbaInputStream::readMemory( void* opMem, sal_Int32 nBytes ) +sal_Int32 VbaInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ ) { sal_Int32 nRet = 0; sal_uInt8* opnMem = reinterpret_cast< sal_uInt8* >( opMem ); @@ -90,7 +111,7 @@ sal_Int32 VbaInputStream::readMemory( void* opMem, sal_Int32 nBytes ) return nRet; } -void VbaInputStream::skip( sal_Int32 nBytes ) +void VbaInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ ) { while( (nBytes > 0) && updateChunk() ) { @@ -108,8 +129,8 @@ bool VbaInputStream::updateChunk() if( mbEof || (mnChunkPos < maChunk.size()) ) return !mbEof; // try to read next chunk header, this may trigger EOF - sal_uInt16 nHeader = mrInStrm.readuInt16(); - mbEof = mrInStrm.isEof(); + sal_uInt16 nHeader = mpInStrm->readuInt16(); + mbEof = mpInStrm->isEof(); if( mbEof ) return false; // check header signature @@ -126,15 +147,15 @@ bool VbaInputStream::updateChunk() maChunk.clear(); sal_uInt8 nBitCount = 4; sal_uInt16 nChunkPos = 0; - while( !mbEof && !mrInStrm.isEof() && (nChunkPos < nChunkLen) ) + while( !mbEof && !mpInStrm->isEof() && (nChunkPos < nChunkLen) ) { - sal_uInt8 nTokenFlags = mrInStrm.readuInt8(); + sal_uInt8 nTokenFlags = mpInStrm->readuInt8(); ++nChunkPos; - for( int nBit = 0; !mbEof && !mrInStrm.isEof() && (nBit < 8) && (nChunkPos < nChunkLen); ++nBit, nTokenFlags >>= 1 ) + for( int nBit = 0; !mbEof && !mpInStrm->isEof() && (nBit < 8) && (nChunkPos < nChunkLen); ++nBit, nTokenFlags >>= 1 ) { if( nTokenFlags & 1 ) { - sal_uInt16 nCopyToken = mrInStrm.readuInt16(); + sal_uInt16 nCopyToken = mpInStrm->readuInt16(); nChunkPos = nChunkPos + 2; // update bit count used for offset/length in the token while( static_cast< size_t >( 1 << nBitCount ) < maChunk.size() ) ++nBitCount; @@ -164,7 +185,7 @@ bool VbaInputStream::updateChunk() else { maChunk.resize( maChunk.size() + 1 ); - mrInStrm >> maChunk.back(); + *mpInStrm >> maChunk.back(); ++nChunkPos; } } @@ -173,7 +194,7 @@ bool VbaInputStream::updateChunk() else { maChunk.resize( nChunkLen ); - mrInStrm.readMemory( &maChunk.front(), nChunkLen ); + mpInStrm->readMemory( &maChunk.front(), nChunkLen ); } mnChunkPos = 0; diff --git a/oox/source/ole/vbamodule.cxx b/oox/source/ole/vbamodule.cxx index 2da92b935..628c2abb8 100644 --- a/oox/source/ole/vbamodule.cxx +++ b/oox/source/ole/vbamodule.cxx @@ -54,7 +54,9 @@ using ::rtl::OUStringBuffer; // ============================================================================ -VbaModule::VbaModule( const Reference< XModel >& rxDocModel, const OUString& rName, rtl_TextEncoding eTextEnc, bool bExecutable ) : +VbaModule::VbaModule( const Reference< XComponentContext >& rxContext, const Reference< XModel >& rxDocModel, + const OUString& rName, rtl_TextEncoding eTextEnc, bool bExecutable ) : + mxContext( rxContext ), mxDocModel( rxDocModel ), maName( rName ), meTextEnc( eTextEnc ), @@ -161,7 +163,7 @@ OUString VbaModule::readSourceCode( StorageBase& rVbaStrg ) const // decompression starts at current stream position of aInStrm VbaInputStream aVbaStrm( aInStrm ); // load the source code line-by-line, with some more processing - TextInputStream aVbaTextStrm( aVbaStrm, meTextEnc ); + TextInputStream aVbaTextStrm( mxContext, aVbaStrm, meTextEnc ); while( !aVbaTextStrm.isEof() ) { OUString aCodeLine = aVbaTextStrm.readLine(); diff --git a/oox/source/ole/vbaproject.cxx b/oox/source/ole/vbaproject.cxx index 89d83e0e5..249bd94cb 100644 --- a/oox/source/ole/vbaproject.cxx +++ b/oox/source/ole/vbaproject.cxx @@ -155,11 +155,11 @@ void VbaMacroAttacherBase::resolveAndAttachMacro( const Reference< XVBAMacroReso VbaProject::VbaProject( const Reference< XComponentContext >& rxContext, const Reference< XModel >& rxDocModel, const OUString& rConfigCompName ) : VbaFilterConfig( rxContext, rConfigCompName ), - mxCompContext( rxContext ), + mxContext( rxContext ), mxDocModel( rxDocModel ), maPrjName( CREATE_OUSTRING( "Standard" ) ) { - OSL_ENSURE( mxCompContext.is(), "VbaProject::VbaProject - missing component context" ); + OSL_ENSURE( mxContext.is(), "VbaProject::VbaProject - missing component context" ); OSL_ENSURE( mxDocModel.is(), "VbaProject::VbaProject - missing document model" ); mxBasicLib = openLibrary( PROP_BasicLibraries, false ); mxDialogLib = openLibrary( PROP_DialogLibraries, false ); @@ -332,7 +332,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap OSL_ENSURE( aName.getLength() > 0, "VbaProject::importVba - invalid module name" ); OSL_ENSURE( !aModules.has( aName ), "VbaProject::importVba - multiple modules with the same name" ); VbaModuleMap::mapped_type& rxModule = aModules[ aName ]; - rxModule.reset( new VbaModule( mxDocModel, aName, eTextEnc, bExecutable ) ); + rxModule.reset( new VbaModule( mxContext, mxDocModel, aName, eTextEnc, bExecutable ) ); // read all remaining records until the MODULEEND record rxModule->importDirRecords( aDirStrm ); OSL_ENSURE( !aModulesByStrm.has( rxModule->getStreamName() ), "VbaProject::importVba - multiple modules with the same stream name" ); @@ -369,7 +369,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap // do not exit if this stream does not exist, but proceed to load the modules below if( !aPrjStrm.isEof() ) { - TextInputStream aPrjTextStrm( aPrjStrm, eTextEnc ); + TextInputStream aPrjTextStrm( mxContext, aPrjStrm, eTextEnc ); OUString aKey, aValue; bool bExitLoop = false; while( !bExitLoop && !aPrjTextStrm.isEof() ) @@ -413,7 +413,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap { OSL_ENSURE( !aModules.has( aIt->first ) && !aDummyModules.has( aIt->first ), "VbaProject::importVba - multiple modules with the same name" ); VbaModuleMap::mapped_type& rxModule = aDummyModules[ aIt->first ]; - rxModule.reset( new VbaModule( mxDocModel, aIt->first, eTextEnc, bExecutable ) ); + rxModule.reset( new VbaModule( mxContext, mxDocModel, aIt->first, eTextEnc, bExecutable ) ); rxModule->setType( aIt->second ); } @@ -489,7 +489,7 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap // create and import the form Reference< XNameContainer > xDialogLib( createDialogLibrary(), UNO_SET_THROW ); - VbaUserForm aForm( mxCompContext, mxDocModel, rGraphicHelper, bDefaultColorBgr ); + VbaUserForm aForm( mxContext, mxDocModel, rGraphicHelper, bDefaultColorBgr ); aForm.importForm( xDialogLib, *xSubStrg, aModuleName, eTextEnc ); } catch( Exception& ) @@ -506,14 +506,14 @@ void VbaProject::importVba( StorageBase& rVbaPrjStrg, const GraphicHelper& rGrap void VbaProject::attachMacros() { - if( !maMacroAttachers.empty() && mxCompContext.is() ) try + if( !maMacroAttachers.empty() && mxContext.is() ) try { - Reference< XMultiComponentFactory > xFactory( mxCompContext->getServiceManager(), UNO_SET_THROW ); + Reference< XMultiComponentFactory > xFactory( mxContext->getServiceManager(), UNO_SET_THROW ); Sequence< Any > aArgs( 2 ); aArgs[ 0 ] <<= mxDocModel; aArgs[ 1 ] <<= maPrjName; Reference< XVBAMacroResolver > xResolver( xFactory->createInstanceWithArgumentsAndContext( - CREATE_OUSTRING( "com.sun.star.script.vba.VBAMacroResolver" ), aArgs, mxCompContext ), UNO_QUERY_THROW ); + CREATE_OUSTRING( "com.sun.star.script.vba.VBAMacroResolver" ), aArgs, mxContext ), UNO_QUERY_THROW ); maMacroAttachers.forEachMem( &VbaMacroAttacherBase::resolveAndAttachMacro, ::boost::cref( xResolver ) ); } catch( Exception& ) @@ -523,15 +523,14 @@ void VbaProject::attachMacros() void VbaProject::copyStorage( StorageBase& rVbaPrjStrg ) { - if( mxCompContext.is() ) try + if( mxContext.is() ) try { - Reference< XMultiServiceFactory > xFactory( mxCompContext->getServiceManager(), UNO_QUERY_THROW ); Reference< XStorageBasedDocument > xStorageBasedDoc( mxDocModel, UNO_QUERY_THROW ); Reference< XStorage > xDocStorage( xStorageBasedDoc->getDocumentStorage(), UNO_QUERY_THROW ); { - using namespace ::com::sun::star::embed::ElementModes; - Reference< XStream > xDocStream( xDocStorage->openStreamElement( CREATE_OUSTRING( "_MS_VBA_Macros" ), SEEKABLE | WRITE | TRUNCATE ), UNO_SET_THROW ); - OleStorage aDestStorage( xFactory, xDocStream, false ); + const sal_Int32 nOpenMode = ElementModes::SEEKABLE | ElementModes::WRITE | ElementModes::TRUNCATE; + Reference< XStream > xDocStream( xDocStorage->openStreamElement( CREATE_OUSTRING( "_MS_VBA_Macros" ), nOpenMode ), UNO_SET_THROW ); + OleStorage aDestStorage( mxContext, xDocStream, false ); rVbaPrjStrg.copyStorageToStorage( aDestStorage ); aDestStorage.commit(); } diff --git a/oox/source/ppt/makefile.mk b/oox/source/ppt/makefile.mk index 8d902ed51..8d902ed51 100644..100755 --- a/oox/source/ppt/makefile.mk +++ b/oox/source/ppt/makefile.mk diff --git a/oox/source/ppt/slidefragmenthandler.cxx b/oox/source/ppt/slidefragmenthandler.cxx index c6b1da033..6beb13cfd 100644 --- a/oox/source/ppt/slidefragmenthandler.cxx +++ b/oox/source/ppt/slidefragmenthandler.cxx @@ -147,7 +147,7 @@ Reference< XFastContextHandler > SlideFragmentHandler::createFastChildContext( s { FillPropertiesPtr pFillPropertiesPtr( new FillProperties( *mpSlidePersistPtr->getTheme()->getFillStyle( xAttribs->getOptionalValue( XML_idx ).toInt32() ) ) ); - xRet.set( new ColorContext( *this, mpSlidePersistPtr->getBackgroundColorRef() ) ); + xRet.set( new ColorContext( *this, mpSlidePersistPtr->getBackgroundColor() ) ); mpSlidePersistPtr->setBackgroundProperties( pFillPropertiesPtr ); } break; diff --git a/oox/source/ppt/slidepersist.cxx b/oox/source/ppt/slidepersist.cxx index dc824fd73..cafe16b65 100644 --- a/oox/source/ppt/slidepersist.cxx +++ b/oox/source/ppt/slidepersist.cxx @@ -25,11 +25,12 @@ * ************************************************************************/ -#include "oox/helper/propertyset.hxx" #include "oox/ppt/timenode.hxx" #include "oox/ppt/pptshape.hxx" #include "oox/ppt/slidepersist.hxx" #include "oox/drawingml/fillproperties.hxx" +#include "oox/drawingml/shapepropertymap.hxx" +#include "oox/helper/propertyset.hxx" #include "oox/vml/vmldrawing.hxx" #include "oox/core/xmlfilterbase.hxx" @@ -169,24 +170,12 @@ void SlidePersist::createBackground( const XmlFilterBase& rFilterBase ) { if ( mpBackgroundPropertiesPtr ) { - try - { - sal_Int32 nPhClr = API_RGB_TRANSPARENT; - if ( maBackgroundColorRef.isUsed() ) - nPhClr = maBackgroundColorRef.getColor( rFilterBase.getGraphicHelper() ); + sal_Int32 nPhClr = maBackgroundColor.isUsed() ? + maBackgroundColor.getColor( rFilterBase.getGraphicHelper() ) : API_RGB_TRANSPARENT; - PropertyMap aPropMap; - static const rtl::OUString sBackground( RTL_CONSTASCII_USTRINGPARAM( "Background" ) ); - uno::Reference< beans::XPropertySet > xPagePropSet( mxPage, uno::UNO_QUERY_THROW ); - uno::Reference< beans::XPropertySet > xPropertySet( aPropMap.makePropertySet() ); - PropertySet aPropSet( xPropertySet ); - mpBackgroundPropertiesPtr->pushToPropSet( aPropSet, rFilterBase.getModelObjectHelper(), - rFilterBase.getGraphicHelper(), oox::drawingml::FillProperties::DEFAULT_IDS, 0, nPhClr ); - xPagePropSet->setPropertyValue( sBackground, Any( xPropertySet ) ); - } - catch( Exception ) - { - } + ::oox::drawingml::ShapePropertyMap aPropMap( rFilterBase.getModelObjectHelper() ); + mpBackgroundPropertiesPtr->pushToPropMap( aPropMap, rFilterBase.getGraphicHelper(), 0, nPhClr ); + PropertySet( mxPage ).setProperty( PROP_Background, aPropMap.makePropertySet() ); } } diff --git a/oox/source/shape/makefile.mk b/oox/source/shape/makefile.mk index c6534b3a8..c6534b3a8 100644..100755 --- a/oox/source/shape/makefile.mk +++ b/oox/source/shape/makefile.mk diff --git a/oox/source/token/makefile.mk b/oox/source/token/makefile.mk index ff42967f0..ff42967f0 100644..100755 --- a/oox/source/token/makefile.mk +++ b/oox/source/token/makefile.mk diff --git a/oox/source/token/namespaces.hxx.tail b/oox/source/token/namespaces.hxx.tail index 651fc3851..60ce5b183 100755 --- a/oox/source/token/namespaces.hxx.tail +++ b/oox/source/token/namespaces.hxx.tail @@ -1,8 +1,8 @@ // ============================================================================ -const sal_Int32 TOKEN_MASK = static_cast< sal_Int32 >( (1 << NMSP_SHIFT) - 1 ); -const sal_Int32 NMSP_MASK = static_cast< sal_Int32 >( SAL_MAX_INT16 & ~TOKEN_MASK ); +const sal_Int32 TOKEN_MASK = static_cast< sal_Int32 >( (1 << NMSP_SHIFT) - 1 ); +const sal_Int32 NMSP_MASK = static_cast< sal_Int32 >( SAL_MAX_INT16 & ~TOKEN_MASK ); /** Returns the raw token identifier without namespace of the passed token. */ inline sal_Int32 getBaseToken( sal_Int32 nToken ) { return nToken & TOKEN_MASK; } @@ -10,23 +10,26 @@ inline sal_Int32 getBaseToken( sal_Int32 nToken ) { return nToken & TOKEN_MASK; /** Returns the namespace without token identifier of the passed token. */ inline sal_Int32 getNamespace( sal_Int32 nToken ) { return nToken & NMSP_MASK; } + // defines for tokens with specific namespaces -#define A_TOKEN( token ) (::oox::NMSP_dml | XML_##token) -#define AX_TOKEN( token ) (::oox::NMSP_ax | XML_##token) -#define C_TOKEN( token ) (::oox::NMSP_dmlChart | XML_##token) -#define CDR_TOKEN( token ) (::oox::NMSP_dmlChartDr | XML_##token) -#define DGM_TOKEN( token ) (::oox::NMSP_dmlDiagram | XML_##token) -#define O_TOKEN( token ) (::oox::NMSP_vmlOffice | XML_##token) -#define PC_TOKEN( token ) (::oox::NMSP_packageContentTypes | XML_##token) -#define PPT_TOKEN( token ) (::oox::NMSP_ppt | XML_##token) -#define PR_TOKEN( token ) (::oox::NMSP_packageRel | XML_##token) -#define R_TOKEN( token ) (::oox::NMSP_officeRel | XML_##token) -#define VML_TOKEN( token ) (::oox::NMSP_vml | XML_##token) -#define VMLX_TOKEN( token ) (::oox::NMSP_vmlExcel | XML_##token) -#define XDR_TOKEN( token ) (::oox::NMSP_dmlSpreadDr | XML_##token) -#define XLS_TOKEN( token ) (::oox::NMSP_xls | XML_##token) -#define XM_TOKEN( token ) (::oox::NMSP_xm | XML_##token) -#define XML_TOKEN( token ) (::oox::NMSP_xml | XML_##token) +#define OOX_TOKEN( namespace, token ) (::oox::NMSP_##namespace | ::oox::XML_##token) + +#define A_TOKEN( token ) OOX_TOKEN( dml, token ) +#define AX_TOKEN( token ) OOX_TOKEN( ax, token ) +#define C_TOKEN( token ) OOX_TOKEN( dmlChart, token ) +#define CDR_TOKEN( token ) OOX_TOKEN( dmlChartDr, token ) +#define DGM_TOKEN( token ) OOX_TOKEN( dmlDiagram, token ) +#define O_TOKEN( token ) OOX_TOKEN( vmlOffice, token ) +#define PC_TOKEN( token ) OOX_TOKEN( packageContentTypes, token ) +#define PPT_TOKEN( token ) OOX_TOKEN( ppt, token ) +#define PR_TOKEN( token ) OOX_TOKEN( packageRel, token ) +#define R_TOKEN( token ) OOX_TOKEN( officeRel, token ) +#define VML_TOKEN( token ) OOX_TOKEN( vml, token ) +#define VMLX_TOKEN( token ) OOX_TOKEN( vmlExcel, token ) +#define XDR_TOKEN( token ) OOX_TOKEN( dmlSpreadDr, token ) +#define XLS_TOKEN( token ) OOX_TOKEN( xls, token ) +#define XM_TOKEN( token ) OOX_TOKEN( xm, token ) +#define XML_TOKEN( token ) OOX_TOKEN( xml, token ) // ============================================================================ diff --git a/oox/source/token/properties.txt b/oox/source/token/properties.txt index 016ffc28b..553af0d72 100644 --- a/oox/source/token/properties.txt +++ b/oox/source/token/properties.txt @@ -19,6 +19,7 @@ AutoShowInfo Autocomplete BackGraphicLocation BackGraphicURL +Background BackgroundColor BasicLibraries BlackDay @@ -79,6 +80,9 @@ CharUnderlineHasColor CharWeight CharWeightAsian CharWeightComplex +CircleEndAngle +CircleKind +CircleStartAngle CodeName Color ColumnGrand @@ -312,6 +316,7 @@ PercentageNumberFormat PersistName Perspective PolyPolygon +PolygonKind Position PositionBottom PositionLeft @@ -348,6 +353,7 @@ RegularExpressions RelId RelativeHorizontalTabbarWidth RelativePosition +RelativeSize Repeat RepeatDelay Representation diff --git a/oox/source/vml/makefile.mk b/oox/source/vml/makefile.mk index 094d37cd8..094d37cd8 100644..100755 --- a/oox/source/vml/makefile.mk +++ b/oox/source/vml/makefile.mk diff --git a/oox/source/vml/vmldrawing.cxx b/oox/source/vml/vmldrawing.cxx index 58b727257..b24aca355 100644 --- a/oox/source/vml/vmldrawing.cxx +++ b/oox/source/vml/vmldrawing.cxx @@ -214,8 +214,8 @@ Reference< XShape > Drawing::createAndInsertXShape( const OUString& rService, Reference< XShape > xShape; if( (rService.getLength() > 0) && rxShapes.is() ) try { - Reference< XMultiServiceFactory > xFactory( mrFilter.getModelFactory(), UNO_SET_THROW ); - xShape.set( xFactory->createInstance( rService ), UNO_QUERY_THROW ); + Reference< XMultiServiceFactory > xModelFactory( mrFilter.getModelFactory(), UNO_SET_THROW ); + xShape.set( xModelFactory->createInstance( rService ), UNO_QUERY_THROW ); // insert shape into passed shape collection (maybe drawpage or group shape) rxShapes->add( xShape ); xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) ); diff --git a/oox/source/vml/vmldrawingfragment.cxx b/oox/source/vml/vmldrawingfragment.cxx index bf0647ee4..a5b45a77e 100644 --- a/oox/source/vml/vmldrawingfragment.cxx +++ b/oox/source/vml/vmldrawingfragment.cxx @@ -27,6 +27,7 @@ #include "oox/vml/vmldrawingfragment.hxx" +#include "oox/core/xmlfilterbase.hxx" #include "oox/vml/vmldrawing.hxx" #include "oox/vml/vmlinputstream.hxx" #include "oox/vml/vmlshapecontext.hxx" @@ -53,7 +54,7 @@ DrawingFragment::DrawingFragment( XmlFilterBase& rFilter, const OUString& rFragm Reference< XInputStream > DrawingFragment::openFragmentStream() const { // #i104719# create an input stream that preprocesses the VML data - return new InputStream( FragmentHandler2::openFragmentStream() ); + return new InputStream( getFilter().getComponentContext(), FragmentHandler2::openFragmentStream() ); } ContextHandlerRef DrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) diff --git a/oox/source/vml/vmlformatting.cxx b/oox/source/vml/vmlformatting.cxx index 0f2f899a3..a12215733 100644 --- a/oox/source/vml/vmlformatting.cxx +++ b/oox/source/vml/vmlformatting.cxx @@ -32,9 +32,9 @@ #include "oox/drawingml/drawingmltypes.hxx" #include "oox/drawingml/fillproperties.hxx" #include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/shapepropertymap.hxx" #include "oox/helper/attributelist.hxx" #include "oox/helper/graphichelper.hxx" -#include "oox/helper/propertymap.hxx" namespace oox { namespace vml { @@ -47,6 +47,7 @@ using ::oox::drawingml::Color; using ::oox::drawingml::FillProperties; using ::oox::drawingml::LineArrowProperties; using ::oox::drawingml::LineProperties; +using ::oox::drawingml::ShapePropertyMap; using ::rtl::OStringBuffer; using ::rtl::OUString; @@ -109,7 +110,7 @@ bool lclExtractDouble( double& orfValue, sal_Int32& ornEndPos, const OUString& r return fDefValue; } -/*static*/ sal_Int32 ConversionHelper::decodeMeasureToEmu( const GraphicHelper& rGraphicHelper, +/*static*/ sal_Int64 ConversionHelper::decodeMeasureToEmu( const GraphicHelper& rGraphicHelper, const OUString& rValue, sal_Int32 nRefValue, bool bPixelX, bool bDefaultAsPixel ) { // default for missing values is 0 @@ -152,10 +153,11 @@ bool lclExtractDouble( double& orfValue, sal_Int32& ornEndPos, const OUString& r fValue *= 12700.0; else if( (cChar1 == 'p') && (cChar2 == 'c') ) // 1 pica = 1/6 inch = 152,400 EMU fValue *= 152400.0; - else if( (cChar1 == 'p') && (cChar2 == 'x') ) // 1 pixel, dependent on output device, factor 360 to convert 1/100mm to EMU - fValue = bPixelX ? - rGraphicHelper.convertScreenPixelXToHmm( 360.0 * fValue ) : - rGraphicHelper.convertScreenPixelYToHmm( 360.0 * fValue ); + else if( (cChar1 == 'p') && (cChar2 == 'x') ) // 1 pixel, dependent on output device + fValue = static_cast< double >( ::oox::drawingml::convertHmmToEmu( + bPixelX ? + rGraphicHelper.convertScreenPixelXToHmm( fValue ) : + rGraphicHelper.convertScreenPixelYToHmm( fValue ) ) ); } else if( (aUnit.getLength() == 1) && (aUnit[ 0 ] == '%') ) { @@ -166,13 +168,13 @@ bool lclExtractDouble( double& orfValue, sal_Int32& ornEndPos, const OUString& r OSL_ENSURE( false, "ConversionHelper::decodeMeasureToEmu - unknown measure unit" ); fValue = nRefValue; } - return static_cast< sal_Int32 >( fValue + 0.5 ); + return static_cast< sal_Int64 >( fValue + 0.5 ); } /*static*/ sal_Int32 ConversionHelper::decodeMeasureToHmm( const GraphicHelper& rGraphicHelper, const OUString& rValue, sal_Int32 nRefValue, bool bPixelX, bool bDefaultAsPixel ) { - return (decodeMeasureToEmu( rGraphicHelper, rValue, nRefValue, bPixelX, bDefaultAsPixel ) + 180) / 360; + return ::oox::drawingml::convertEmuToHmm( decodeMeasureToEmu( rGraphicHelper, rValue, nRefValue, bPixelX, bDefaultAsPixel ) ); } /*static*/ Color ConversionHelper::decodeColor( const GraphicHelper& rGraphicHelper, @@ -271,7 +273,7 @@ bool lclExtractDouble( double& orfValue, sal_Int32& ornEndPos, const OUString& r namespace { -sal_Int32 lclGetEmu( const GraphicHelper& rGraphicHelper, const OptValue< OUString >& roValue, sal_Int32 nDefValue ) +sal_Int64 lclGetEmu( const GraphicHelper& rGraphicHelper, const OptValue< OUString >& roValue, sal_Int64 nDefValue ) { return roValue.has() ? ConversionHelper::decodeMeasureToEmu( rGraphicHelper, roValue.get(), 0, false, false ) : nDefValue; } @@ -415,8 +417,7 @@ void StrokeModel::assignUsed( const StrokeModel& rSource ) moJoinStyle.assignIfUsed( rSource.moJoinStyle ); } -void StrokeModel::pushToPropMap( PropertyMap& rPropMap, - ModelObjectHelper& rModelObjectHelper, const GraphicHelper& rGraphicHelper ) const +void StrokeModel::pushToPropMap( ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper ) const { /* Convert VML line formatting to DrawingML line formatting and let the DrawingML code do the hard work. */ @@ -428,7 +429,7 @@ void StrokeModel::pushToPropMap( PropertyMap& rPropMap, lclConvertArrow( aLineProps.maStartArrow, maStartArrow ); lclConvertArrow( aLineProps.maEndArrow, maEndArrow ); aLineProps.maLineFill.maFillColor = ConversionHelper::decodeColor( rGraphicHelper, moColor, moOpacity, API_RGB_BLACK ); - aLineProps.moLineWidth = lclGetEmu( rGraphicHelper, moWeight, 1 ); + aLineProps.moLineWidth = getLimitedValue< sal_Int32, sal_Int64 >( lclGetEmu( rGraphicHelper, moWeight, 1 ), 0, SAL_MAX_INT32 ); lclGetDmlLineDash( aLineProps.moPresetDash, aLineProps.maCustomDash, moDashStyle ); aLineProps.moLineCompound = lclGetDmlLineCompound( moLineStyle ); aLineProps.moLineCap = lclGetDmlLineCap( moEndCap ); @@ -439,7 +440,7 @@ void StrokeModel::pushToPropMap( PropertyMap& rPropMap, aLineProps.maLineFill.moFillType = XML_noFill; } - aLineProps.pushToPropMap( rPropMap, rModelObjectHelper, rGraphicHelper ); + aLineProps.pushToPropMap( rPropMap, rGraphicHelper ); } // ============================================================================ @@ -460,8 +461,7 @@ void FillModel::assignUsed( const FillModel& rSource ) moRotate.assignIfUsed( rSource.moRotate ); } -void FillModel::pushToPropMap( PropertyMap& rPropMap, - ModelObjectHelper& rModelObjectHelper, const GraphicHelper& rGraphicHelper ) const +void FillModel::pushToPropMap( ShapePropertyMap& rPropMap, const GraphicHelper& rGraphicHelper ) const { /* Convert VML fill formatting to DrawingML fill formatting and let the DrawingML code do the hard work. */ @@ -578,7 +578,7 @@ void FillModel::pushToPropMap( PropertyMap& rPropMap, aFillProps.moFillType = XML_noFill; } - aFillProps.pushToPropMap( rPropMap, rModelObjectHelper, rGraphicHelper ); + aFillProps.pushToPropMap( rPropMap, rGraphicHelper ); } // ============================================================================ diff --git a/oox/source/vml/vmlinputstream.cxx b/oox/source/vml/vmlinputstream.cxx index 87a52c30a..cdc9dce91 100644 --- a/oox/source/vml/vmlinputstream.cxx +++ b/oox/source/vml/vmlinputstream.cxx @@ -27,10 +27,12 @@ #include "oox/vml/vmlinputstream.hxx" +#include <com/sun/star/io/XTextInputStream.hpp> #include <map> -#include <rtl/strbuf.hxx> +#include <string.h> #include <rtl/strbuf.hxx> #include "oox/helper/helper.hxx" +#include "oox/helper/textinputstream.hxx" namespace oox { namespace vml { @@ -55,7 +57,7 @@ inline const sal_Char* lclFindCharacter( const sal_Char* pcBeg, const sal_Char* inline bool lclIsWhiteSpace( sal_Char cChar ) { - return (cChar == ' ') || (cChar == '\t') || (cChar == '\n') || (cChar == '\r'); + return cChar < 32; } const sal_Char* lclFindWhiteSpace( const sal_Char* pcBeg, const sal_Char* pcEnd ) @@ -151,14 +153,78 @@ void lclProcessAttribs( OStringBuffer& rBuffer, const sal_Char* pcBeg, const sal lclAppendToBuffer( rBuffer, pcBeg, pcEnd ); } -void lclProcessContents( OStringBuffer& rBuffer, const sal_Char* pcBeg, const sal_Char* pcEnd ) +void lclProcessElement( OStringBuffer& rBuffer, const OString& rElement ) +{ + // check that passed string starts and ends with the brackets of an XML element + sal_Int32 nElementLen = rElement.getLength(); + if( nElementLen == 0 ) + return; + + const sal_Char* pcOpen = rElement.getStr(); + const sal_Char* pcClose = pcOpen + nElementLen - 1; + + // no complete element found + if( (pcOpen >= pcClose) || (*pcOpen != '<') || (*pcClose != '>') ) + { + // just append all passed characters + rBuffer.append( rElement ); + } + + // skip parser instructions: '<![...]>' + else if( (nElementLen >= 5) && (pcOpen[ 1 ] == '!') && (pcOpen[ 2 ] == '[') && (pcClose[ -1 ] == ']') ) + { + // do nothing + } + + // replace '<br>' element with newline + else if( (nElementLen >= 4) && (pcOpen[ 1 ] == 'b') && (pcOpen[ 2 ] == 'r') && (lclFindNonWhiteSpace( pcOpen + 3, pcClose ) == pcClose) ) + { + rBuffer.append( '\n' ); + } + + // check start elements and simple elements for repeated attributes + else if( pcOpen[ 1 ] != '/' ) + { + // find positions of text content inside brackets, exclude '/' in '<simpleelement/>' + const sal_Char* pcContentBeg = pcOpen + 1; + bool bIsEmptyElement = pcClose[ -1 ] == '/'; + const sal_Char* pcContentEnd = bIsEmptyElement ? (pcClose - 1) : pcClose; + // append opening bracket and element name to buffer + const sal_Char* pcWhiteSpace = lclFindWhiteSpace( pcContentBeg, pcContentEnd ); + lclAppendToBuffer( rBuffer, pcOpen, pcWhiteSpace ); + // find begin of attributes, and process all attributes + const sal_Char* pcAttribBeg = lclFindNonWhiteSpace( pcWhiteSpace, pcContentEnd ); + if( pcAttribBeg < pcContentEnd ) + lclProcessAttribs( rBuffer, pcAttribBeg, pcContentEnd ); + // close the element + if( bIsEmptyElement ) + rBuffer.append( '/' ); + rBuffer.append( '>' ); + } + + // append end elements without further processing + else + { + rBuffer.append( rElement ); + } +} + +bool lclProcessCharacters( OStringBuffer& rBuffer, const OString& rChars ) { /* MSO has a very weird way to store and handle whitespaces. The stream may contain lots of spaces, tabs, and newlines which have to be handled as single space character. This will be done in this function. If the element text contains a literal line break, it will be stored as - <br> tag (without matching closing </br> element). + <br> tag (without matching </br> element). This input stream wrapper + will replace this element with a literal LF character (see below). + + A single space character for its own is stored as is. Example: The + element + <font> </font> + represents a single space character. The XML parser will ignore this + space character completely without issuing a 'characters' event. The + VML import filter implementation has to react on this case manually. A single space character following another character is stored literally and must not be stipped away here. Example: The element @@ -167,20 +233,23 @@ void lclProcessContents( OStringBuffer& rBuffer, const sal_Char* pcBeg, const sa Consecutive space characters, or a leading single space character, are stored in a <span> element. If there are N space characters (N > 1), - then the <span> element contains exactly (N-1) NBSP characters - (non-breaking space), followed by a regular space character. Example: + then the <span> element contains exactly (N-1) NBSP (non-breaking + space) characters, followed by a regular space character. Examples: The element <font><span style='mso-spacerun:yes'>\xA0\xA0\xA0 </span></font> represents 4 consecutive space characters. Has to be handled by the - implementation. - - A single space character for its own is stored in an empty element. - Example: The element - <font></font> - represents a single space character. Has to be handled by the - implementation. + implementation. The element + <font><span style='mso-spacerun:yes'> abc</span></font> + represents a space characters followed by the letters a, b, c. These + strings have to be handled by the VML import filter implementation. */ + // passed string ends with the leading opening bracket of an XML element + const sal_Char* pcBeg = rChars.getStr(); + const sal_Char* pcEnd = pcBeg + rChars.getLength(); + bool bHasBracket = (pcBeg < pcEnd) && (pcEnd[ -1 ] == '<'); + if( bHasBracket ) --pcEnd; + // skip leading whitespace const sal_Char* pcContentsBeg = lclFindNonWhiteSpace( pcBeg, pcEnd ); while( pcContentsBeg < pcEnd ) @@ -191,132 +260,139 @@ void lclProcessContents( OStringBuffer& rBuffer, const sal_Char* pcBeg, const sa rBuffer.append( ' ' ); pcContentsBeg = lclFindNonWhiteSpace( pcWhitespaceBeg, pcEnd ); } + + return bHasBracket; } } // namespace // ============================================================================ -StreamDataContainer::StreamDataContainer( const Reference< XInputStream >& rxInStrm ) +InputStream::InputStream( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm ) : + // use single-byte ISO-8859-1 encoding which maps all byte characters to the first 256 Unicode characters + mxTextStrm( TextInputStream::createXTextInputStream( rxContext, rxInStrm, RTL_TEXTENCODING_ISO_8859_1 ) ), + maOpeningBracket( 1 ), + maClosingBracket( 1 ), + maOpeningCData( CREATE_OSTRING( "<![CDATA[" ) ), + maClosingCData( CREATE_OSTRING( "]]>" ) ), + mnBufferPos( 0 ) { - if( rxInStrm.is() ) try + maOpeningBracket[ 0 ] = '<'; + maClosingBracket[ 0 ] = '>'; +} + +InputStream::~InputStream() +{ +} + +sal_Int32 SAL_CALL InputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + if( nBytesToRead < 0 ) + throw IOException(); + + rData.realloc( nBytesToRead ); + sal_Int8* pcDest = rData.getArray(); + sal_Int32 nRet = 0; + while( (nBytesToRead > 0) && !mxTextStrm->isEOF() ) { - // read all bytes we can read - rxInStrm->readBytes( maDataSeq, SAL_MAX_INT32 ); + updateBuffer(); + sal_Int32 nReadSize = ::std::min( nBytesToRead, maBuffer.getLength() - mnBufferPos ); + if( nReadSize > 0 ) + { + memcpy( pcDest + nRet, maBuffer.getStr() + mnBufferPos, static_cast< size_t >( nReadSize ) ); + mnBufferPos += nReadSize; + nBytesToRead -= nReadSize; + nRet += nReadSize; + } } - catch( Exception& ) + if( nRet < rData.getLength() ) + rData.realloc( nRet ); + return nRet; +} + +sal_Int32 SAL_CALL InputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + return readBytes( rData, nMaxBytesToRead ); +} + +void SAL_CALL InputStream::skipBytes( sal_Int32 nBytesToSkip ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) +{ + if( nBytesToSkip < 0 ) + throw IOException(); + + while( (nBytesToSkip > 0) && !mxTextStrm->isEOF() ) { + updateBuffer(); + sal_Int32 nSkipSize = ::std::min( nBytesToSkip, maBuffer.getLength() - mnBufferPos ); + mnBufferPos += nSkipSize; + nBytesToSkip -= nSkipSize; } +} - if( maDataSeq.hasElements() ) +sal_Int32 SAL_CALL InputStream::available() throw (NotConnectedException, IOException, RuntimeException) +{ + updateBuffer(); + return maBuffer.getLength() - mnBufferPos; +} + +void SAL_CALL InputStream::closeInput() throw (NotConnectedException, IOException, RuntimeException) +{ + mxTextStrm->closeInput(); +} + +// private -------------------------------------------------------------------- + +void InputStream::updateBuffer() throw (IOException, RuntimeException) +{ + while( (mnBufferPos >= maBuffer.getLength()) && !mxTextStrm->isEOF() ) { - const OString aCDataOpen = CREATE_OSTRING( "<![CDATA[" ); - const OString aCDataClose = CREATE_OSTRING( "]]>" ); - + // collect new contents in a string buffer OStringBuffer aBuffer; - aBuffer.ensureCapacity( maDataSeq.getLength() + 256 ); - const sal_Char* pcCurr = reinterpret_cast< const sal_Char* >( maDataSeq.getConstArray() ); - const sal_Char* pcEnd = pcCurr + maDataSeq.getLength(); - while( pcCurr < pcEnd ) - { - // look for the next opening angle bracket - const sal_Char* pcOpen = lclFindCharacter( pcCurr, pcEnd, '<' ); - - // copy all characters from current position to opening bracket - lclProcessContents( aBuffer, pcCurr, pcOpen ); - - // nothing to do if no opening bracket has been found - if( pcOpen < pcEnd ) - { - // string length from opening bracket to end - sal_Int32 nLengthToEnd = static_cast< sal_Int32 >( pcEnd - pcOpen ); - // check for CDATA part, starting with '<![CDATA[' - if( rtl_str_compare_WithLength( pcOpen, nLengthToEnd, aCDataOpen.getStr(), aCDataOpen.getLength() ) == 0 ) - { - // search the position after the end tag ']]>' - sal_Int32 nClosePos = rtl_str_indexOfStr_WithLength( pcOpen, nLengthToEnd, aCDataClose.getStr(), aCDataClose.getLength() ); - pcCurr = (nClosePos < 0) ? pcEnd : (pcOpen + nClosePos + aCDataClose.getLength()); - // copy the entire CDATA part - lclAppendToBuffer( aBuffer, pcOpen, pcCurr ); - } + // read and process characters until the opening bracket of the next XML element + OString aChars = readToElementBegin(); + bool bHasOpeningBracket = lclProcessCharacters( aBuffer, aChars ); - // no CDATA part - process the element starting at pcOpen - else - { - // look for the next closing angle bracket - const sal_Char* pcClose = lclFindCharacter( pcOpen + 1, pcEnd, '>' ); - // complete element found? - if( pcClose < pcEnd ) - { - // continue after closing bracket - pcCurr = pcClose + 1; - // length of entire element with angle brackets - sal_Int32 nElementLen = static_cast< sal_Int32 >( pcCurr - pcOpen ); - - // skip parser instructions: '<![...]>' - if( (nElementLen >= 5) && (pcOpen[ 1 ] == '!') && (pcOpen[ 2 ] == '[') && (pcClose[ -1 ] == ']') ) - { - // do nothing - } - - // replace '<br>' element with newline - else if( (nElementLen >= 4) && (pcOpen[ 1 ] == 'b') && (pcOpen[ 2 ] == 'r') && (lclFindNonWhiteSpace( pcOpen + 3, pcClose ) == pcClose) ) - { - aBuffer.append( '\n' ); - } - - // check start elements and empty elements for repeated attributes - else if( pcOpen[ 1 ] != '/' ) - { - // find positions of text content inside brackets, exclude '/' in '<emptyelement/>' - const sal_Char* pcContentBeg = pcOpen + 1; - bool bIsEmptyElement = pcClose[ -1 ] == '/'; - const sal_Char* pcContentEnd = bIsEmptyElement ? (pcClose - 1) : pcClose; - // append element name to buffer - const sal_Char* pcWhiteSpace = lclFindWhiteSpace( pcContentBeg, pcContentEnd ); - lclAppendToBuffer( aBuffer, pcOpen, pcWhiteSpace ); - // find begin of attributes, and process all attributes - const sal_Char* pcAttribBeg = lclFindNonWhiteSpace( pcWhiteSpace, pcContentEnd ); - if( pcAttribBeg < pcContentEnd ) - lclProcessAttribs( aBuffer, pcAttribBeg, pcContentEnd ); - // close the element - if( bIsEmptyElement ) - aBuffer.append( '/' ); - aBuffer.append( '>' ); - } - - // append end elements without further processing - else - { - lclAppendToBuffer( aBuffer, pcOpen, pcCurr ); - } - } - else - { - // no complete element found, copy all from opening bracket to end - lclAppendToBuffer( aBuffer, pcOpen, pcEnd ); - pcCurr = pcEnd; - } - } + // read and process characters until (and including) closing bracket (an XML element) + OSL_ENSURE( bHasOpeningBracket || mxTextStrm->isEOF(), "InputStream::updateBuffer - missing opening bracket of XML element" ); + if( bHasOpeningBracket && !mxTextStrm->isEOF() ) + { + // read the element text (add the leading opening bracket manually) + OString aElement = OString( '<' ) + readToElementEnd(); + // check for CDATA part, starting with '<![CDATA[' + if( aElement.match( maOpeningCData ) ) + { + // search the end tag ']]>' + while( ((aElement.getLength() < maClosingCData.getLength()) || !aElement.match( maClosingCData, aElement.getLength() - maClosingCData.getLength() )) && !mxTextStrm->isEOF() ) + aElement += readToElementEnd(); + // copy the entire CDATA part + aBuffer.append( aElement ); + } + else + { + // no CDATA part - process the contents of the element + lclProcessElement( aBuffer, aElement ); } } - // set the final data sequence - maDataSeq = ::comphelper::ByteSequence( reinterpret_cast< const sal_Int8* >( aBuffer.getStr() ), aBuffer.getLength() ); + maBuffer = aBuffer.makeStringAndClear(); + mnBufferPos = 0; } } -// ============================================================================ - -InputStream::InputStream( const Reference< XInputStream >& rxInStrm ) : - StreamDataContainer( rxInStrm ), - ::comphelper::SequenceInputStream( maDataSeq ) +OString InputStream::readToElementBegin() throw (IOException, RuntimeException) { + return OUStringToOString( mxTextStrm->readString( maOpeningBracket, sal_False ), RTL_TEXTENCODING_ISO_8859_1 ); } -InputStream::~InputStream() +OString InputStream::readToElementEnd() throw (IOException, RuntimeException) { + OString aText = OUStringToOString( mxTextStrm->readString( maClosingBracket, sal_False ), RTL_TEXTENCODING_ISO_8859_1 ); + OSL_ENSURE( (aText.getLength() > 0) && (aText[ aText.getLength() - 1 ] == '>'), "InputStream::readToElementEnd - missing closing bracket of XML element" ); + return aText; } // ============================================================================ diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx index 47975d6bf..3b8c491cf 100644 --- a/oox/source/vml/vmlshape.cxx +++ b/oox/source/vml/vmlshape.cxx @@ -36,9 +36,9 @@ #include <rtl/math.hxx> #include <rtl/ustrbuf.hxx> #include "oox/core/xmlfilterbase.hxx" +#include "oox/drawingml/shapepropertymap.hxx" #include "oox/helper/containerhelper.hxx" #include "oox/helper/graphichelper.hxx" -#include "oox/helper/propertymap.hxx" #include "oox/helper/propertyset.hxx" #include "oox/ole/axcontrol.hxx" #include "oox/ole/axcontrolfragment.hxx" @@ -274,9 +274,10 @@ Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxS xShape = implConvertAndInsert( rxShapes, aShapeRect ); if( xShape.is() ) { - // set shape name (imported or generated) + // set imported or generated shape name (not supported by form controls) PropertySet aShapeProp( xShape ); - aShapeProp.setProperty( PROP_Name, getShapeName() ); + if( aShapeProp.hasProperty( PROP_Name ) ) + aShapeProp.setProperty( PROP_Name, getShapeName() ); /* Notify the drawing that a new shape has been inserted. For convenience, pass the rectangle that contains position and @@ -322,15 +323,11 @@ Rectangle ShapeBase::calcShapeRectangle( const ShapeParentAnchor* pParentAnchor void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const { - ModelObjectHelper& rModelObjectHelper = mrDrawing.getFilter().getModelObjectHelper(); + ::oox::drawingml::ShapePropertyMap aPropMap( mrDrawing.getFilter().getModelObjectHelper() ); const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper(); - - PropertyMap aPropMap; - maTypeModel.maStrokeModel.pushToPropMap( aPropMap, rModelObjectHelper, rGraphicHelper ); - maTypeModel.maFillModel.pushToPropMap( aPropMap, rModelObjectHelper, rGraphicHelper ); - - PropertySet aPropSet( rxShape ); - aPropSet.setProperties( aPropMap ); + maTypeModel.maStrokeModel.pushToPropMap( aPropMap, rGraphicHelper ); + maTypeModel.maFillModel.pushToPropMap( aPropMap, rGraphicHelper ); + PropertySet( rxShape ).setProperties( aPropMap ); } // ============================================================================ diff --git a/oox/source/vml/vmltextboxcontext.cxx b/oox/source/vml/vmltextboxcontext.cxx index 3d08e085e..4a4149286 100755 --- a/oox/source/vml/vmltextboxcontext.cxx +++ b/oox/source/vml/vmltextboxcontext.cxx @@ -75,6 +75,8 @@ TextPortionContext::TextPortionContext( ContextHandler2Helper& rParent, OSL_ENSURE( !maFont.mobStrikeout, "TextPortionContext::TextPortionContext - nested <s> elements" ); maFont.mobStrikeout = true; break; + case XML_span: + break; default: OSL_ENSURE( false, "TextPortionContext::TextPortionContext - unknown element" ); } @@ -92,7 +94,7 @@ void TextPortionContext::onCharacters( const OUString& rChars ) { case XML_span: // replace all NBSP characters with SP - mrTextBox.appendPortion( maFont, rChars.replace( 160, ' ' ) ); + mrTextBox.appendPortion( maFont, rChars.replace( 0xA0, ' ' ) ); break; default: mrTextBox.appendPortion( maFont, rChars ); @@ -101,19 +103,23 @@ void TextPortionContext::onCharacters( const OUString& rChars ) void TextPortionContext::onEndElement() { - /* An empty child element without own child elements represents a single - space character, for example: - - <font> - <i>abc</i> - <font></font> - <b>def</b> - </font> - + /* A child element without own child elements may contain a single space + character, for example: + + <div> + <font><i>abc</i></font> + <font> </font> + <font><b>def</b></font> + </div> + represents the italic text 'abc', an unformatted space character, and - the bold text 'def'. + the bold text 'def'. Unfortunately, the XML parser skips the space + character without issuing a 'characters' event. The class member + 'mnInitialPortions' contains the number of text portions existing when + this context has been constructed. If no text has been added in the + meantime, the space character has to be added manually. */ - if( (mnInitialPortions > 0) && (mrTextBox.getPortionCount() == mnInitialPortions) ) + if( mrTextBox.getPortionCount() == mnInitialPortions ) mrTextBox.appendPortion( maFont, OUString( sal_Unicode( ' ' ) ) ); } @@ -143,4 +149,3 @@ ContextHandlerRef TextBoxContext::onCreateContext( sal_Int32 nElement, const Att } // namespace vml } // namespace oox - diff --git a/oox/source/xls/addressconverter.cxx b/oox/source/xls/addressconverter.cxx index da29767ea..062daa117 100644 --- a/oox/source/xls/addressconverter.cxx +++ b/oox/source/xls/addressconverter.cxx @@ -98,12 +98,12 @@ const sal_Unicode BIFF_DCON_ENCODED = '\x01'; /// First character of an en const sal_Unicode BIFF_DCON_INTERN = '\x02'; /// First character of an encoded sheet name from DCON* records. -inline sal_uInt16 lclGetBiffAddressSize( bool bCol16Bit, bool bRow32Bit ) +inline sal_uInt8 lclGetBiffAddressSize( bool bCol16Bit, bool bRow32Bit ) { return (bCol16Bit ? 2 : 1) + (bRow32Bit ? 4 : 2); } -inline sal_uInt16 lclGetBiffRangeSize( bool bCol16Bit, bool bRow32Bit ) +inline sal_uInt8 lclGetBiffRangeSize( bool bCol16Bit, bool bRow32Bit ) { return 2 * lclGetBiffAddressSize( bCol16Bit, bRow32Bit ); } diff --git a/oox/source/xls/autofilterbuffer.cxx b/oox/source/xls/autofilterbuffer.cxx index 9f5ea11cd..fc1d6eb5b 100755 --- a/oox/source/xls/autofilterbuffer.cxx +++ b/oox/source/xls/autofilterbuffer.cxx @@ -842,7 +842,7 @@ bool AutoFilterBuffer::finalizeImport( const Reference< XDatabaseRange >& rxData AutoFilter* AutoFilterBuffer::getActiveAutoFilter() { // Excel expects not more than one auto filter per sheet or table - OSL_ENSURE( maAutoFilters.size() == 1, "AutoFilterBuffer::getActiveAutoFilter - too many auto filters" ); + OSL_ENSURE( maAutoFilters.size() <= 1, "AutoFilterBuffer::getActiveAutoFilter - too many auto filters" ); // stick to the last imported auto filter return maAutoFilters.empty() ? 0 : maAutoFilters.back().get(); } diff --git a/oox/source/xls/biffdetector.cxx b/oox/source/xls/biffdetector.cxx index a9aaaf687..af23af7f0 100644 --- a/oox/source/xls/biffdetector.cxx +++ b/oox/source/xls/biffdetector.cxx @@ -82,14 +82,14 @@ BiffDetector::~BiffDetector() /*static*/ BiffType BiffDetector::detectStreamBiffVersion( BinaryInputStream& rInStream ) { BiffType eBiff = BIFF_UNKNOWN; - if( !rInStream.isEof() && rInStream.isSeekable() && (rInStream.getLength() > 4) ) + if( !rInStream.isEof() && rInStream.isSeekable() && (rInStream.size() > 4) ) { sal_Int64 nOldPos = rInStream.tell(); rInStream.seekToStart(); sal_uInt16 nBofId, nBofSize; rInStream >> nBofId >> nBofSize; - if( (4 <= nBofSize) && (nBofSize <= 16) && (rInStream.tell() + nBofSize <= rInStream.getLength()) ) + if( (4 <= nBofSize) && (nBofSize <= 16) && (rInStream.tell() + nBofSize <= rInStream.size()) ) { switch( nBofId ) { @@ -207,9 +207,8 @@ OUString SAL_CALL BiffDetector::detect( Sequence< PropertyValue >& rDescriptor ) MediaDescriptor aDescriptor( rDescriptor ); aDescriptor.addInputStream(); - Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW ); Reference< XInputStream > xInStrm( aDescriptor[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY_THROW ); - StorageRef xStorage( new ::oox::ole::OleStorage( xFactory, xInStrm, true ) ); + StorageRef xStorage( new ::oox::ole::OleStorage( mxContext, xInStrm, true ) ); OUString aWorkbookName; switch( detectStorageBiffVersion( aWorkbookName, xStorage ) ) diff --git a/oox/source/xls/biffhelper.cxx b/oox/source/xls/biffhelper.cxx index 4612c77ad..bf730e217 100644 --- a/oox/source/xls/biffhelper.cxx +++ b/oox/source/xls/biffhelper.cxx @@ -269,7 +269,7 @@ void lclImportImgDataDib( StreamDataSequence& orDataSeq, BiffInputStream& rStrm, // BIFF12 import -------------------------------------------------------------- -/*static*/ OUString BiffHelper::readString( SequenceInputStream& rStrm, bool b32BitLen ) +/*static*/ OUString BiffHelper::readString( SequenceInputStream& rStrm, bool b32BitLen, bool bAllowNulChars ) { OUString aString; if( !rStrm.isEof() ) @@ -279,16 +279,9 @@ void lclImportImgDataDib( StreamDataSequence& orDataSeq, BiffInputStream& rStrm, OSL_ENSURE( !rStrm.isEof() && (nCharCount >= -1), "BiffHelper::readString - invalid string length" ); if( !rStrm.isEof() && (nCharCount > 0) ) { - ::std::vector< sal_Unicode > aBuffer; - aBuffer.reserve( getLimitedValue< size_t, sal_Int32 >( nCharCount + 1, 0, 0xFFFF ) ); - for( sal_Int32 nCharIdx = 0; !rStrm.isEof() && (nCharIdx < nCharCount); ++nCharIdx ) - { - sal_uInt16 nChar; - rStrm.readValue( nChar ); - aBuffer.push_back( static_cast< sal_Unicode >( nChar ) ); - } - aBuffer.push_back( 0 ); - aString = OUString( &aBuffer.front() ); + // SequenceInputStream always supports getRemaining() + nCharCount = ::std::min( nCharCount, static_cast< sal_Int32 >( rStrm.getRemaining() / 2 ) ); + aString = rStrm.readUnicodeArray( nCharCount, bAllowNulChars ); } } return aString; diff --git a/oox/source/xls/biffinputstream.cxx b/oox/source/xls/biffinputstream.cxx index 97acb2858..ab9a2bf0a 100644 --- a/oox/source/xls/biffinputstream.cxx +++ b/oox/source/xls/biffinputstream.cxx @@ -87,7 +87,7 @@ void BiffInputRecordBuffer::enableDecoder( bool bEnable ) bool BiffInputRecordBuffer::startRecord( sal_Int64 nHeaderPos ) { - mbValidHeader = (0 <= nHeaderPos) && (nHeaderPos + 4 <= mrInStrm.getLength()); + mbValidHeader = (0 <= nHeaderPos) && (nHeaderPos + 4 <= mrInStrm.size()); if( mbValidHeader ) { mnHeaderPos = nHeaderPos; @@ -95,7 +95,7 @@ bool BiffInputRecordBuffer::startRecord( sal_Int64 nHeaderPos ) mrInStrm >> mnRecId >> mnRecSize; mnBodyPos = mrInStrm.tell(); mnNextHeaderPos = mnBodyPos + mnRecSize; - mbValidHeader = !mrInStrm.isEof() && (mnNextHeaderPos <= mrInStrm.getLength()); + mbValidHeader = !mrInStrm.isEof() && (mnNextHeaderPos <= mrInStrm.size()); } if( !mbValidHeader ) { @@ -116,7 +116,7 @@ bool BiffInputRecordBuffer::startNextRecord() sal_uInt16 BiffInputRecordBuffer::getNextRecId() { sal_uInt16 nRecId = BIFF_ID_UNKNOWN; - if( mbValidHeader && (mnNextHeaderPos + 4 <= mrInStrm.getLength()) ) + if( mbValidHeader && (mnNextHeaderPos + 4 <= mrInStrm.size()) ) { mrInStrm.seek( mnNextHeaderPos ); mrInStrm >> nRecId; @@ -169,6 +169,7 @@ void BiffInputRecordBuffer::updateDecoded() // ============================================================================ BiffInputStream::BiffInputStream( BinaryInputStream& rInStream, bool bContLookup ) : + BinaryStreamBase( true ), maRecBuffer( rInStream ), mnRecHandle( -1 ), mnRecId( BIFF_ID_UNKNOWN ), @@ -257,9 +258,11 @@ sal_uInt16 BiffInputStream::getNextRecId() // BinaryStreamBase interface (seeking) --------------------------------------- -bool BiffInputStream::isSeekable() const +sal_Int64 BiffInputStream::size() const { - return true; + if( !mbHasComplRec ) + const_cast< BiffInputStream* >( this )->calcRecordLength(); + return mnComplRecSize; } sal_Int64 BiffInputStream::tell() const @@ -267,13 +270,6 @@ sal_Int64 BiffInputStream::tell() const return mbEof ? -1 : (mnCurrRecSize - maRecBuffer.getRecLeft()); } -sal_Int64 BiffInputStream::getLength() const -{ - if( !mbHasComplRec ) - const_cast< BiffInputStream* >( this )->calcRecordLength(); - return mnComplRecSize; -} - void BiffInputStream::seek( sal_Int64 nRecPos ) { if( isInRecord() ) @@ -285,35 +281,35 @@ void BiffInputStream::seek( sal_Int64 nRecPos ) } } +void BiffInputStream::close() +{ +} + sal_Int64 BiffInputStream::tellBase() const { return maRecBuffer.getBaseStream().tell(); } -sal_Int64 BiffInputStream::getBaseLength() const +sal_Int64 BiffInputStream::sizeBase() const { - return maRecBuffer.getBaseStream().getLength(); + return maRecBuffer.getBaseStream().size(); } // BinaryInputStream interface (stream read access) --------------------------- -sal_Int32 BiffInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes ) +sal_Int32 BiffInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nRet = 0; if( !mbEof ) { orData.realloc( ::std::max< sal_Int32 >( nBytes, 0 ) ); if( nBytes > 0 ) - { - nRet = readMemory( orData.getArray(), nBytes ); - if( nRet < nBytes ) - orData.realloc( nRet ); - } + nRet = readMemory( orData.getArray(), nBytes, nAtomSize ); } return nRet; } -sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes ) +sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nRet = 0; if( !mbEof && opMem && (nBytes > 0) ) @@ -323,7 +319,7 @@ sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes ) while( !mbEof && (nBytesLeft > 0) ) { - sal_uInt16 nReadSize = getMaxRawReadSize( nBytesLeft ); + sal_uInt16 nReadSize = getMaxRawReadSize( nBytesLeft, nAtomSize ); // check nReadSize, stream may already be located at end of a raw record if( nReadSize > 0 ) { @@ -340,12 +336,12 @@ sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes ) return nRet; } -void BiffInputStream::skip( sal_Int32 nBytes ) +void BiffInputStream::skip( sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nBytesLeft = nBytes; while( !mbEof && (nBytesLeft > 0) ) { - sal_uInt16 nSkipSize = getMaxRawReadSize( nBytesLeft ); + sal_uInt16 nSkipSize = getMaxRawReadSize( nBytesLeft, nAtomSize ); // check nSkipSize, stream may already be located at end of a raw record if( nSkipSize > 0 ) { @@ -383,28 +379,22 @@ OUString BiffInputStream::readUniStringChars( sal_uInt16 nChars, bool b16BitChar OUStringBuffer aBuffer; aBuffer.ensureCapacity( nChars ); - /* This function has to react on CONTINUE records to read the repeated - flags field, so readUnicodeArray() cannot be used here. */ - sal_uInt16 nCharsLeft = nChars; + /* This function has to react on CONTINUE records which repeat the flags + field in their first byte and may change the 8bit/16bit character mode, + thus a plain call to readCompressedUnicodeArray() cannot be used here. */ + sal_Int32 nCharsLeft = nChars; while( !mbEof && (nCharsLeft > 0) ) { - sal_uInt16 nPortionCount = 0; - if( b16BitChars ) - { - nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 ); - OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0), - "BiffInputStream::readUniStringChars - missing a byte" ); - } - else - { - nPortionCount = getMaxRawReadSize( nCharsLeft ); - } - - // read the character array - appendUnicodeArray( aBuffer, nPortionCount, b16BitChars, bAllowNulChars ); - - // prepare for next CONTINUE record - nCharsLeft = nCharsLeft - nPortionCount; + /* Read the character array from the remaining part of the current raw + record. First, calculate the maximum number of characters that can + be read without triggering to start a following CONTINUE record. */ + sal_Int32 nRawChars = b16BitChars ? (getMaxRawReadSize( nCharsLeft * 2, 2 ) / 2) : getMaxRawReadSize( nCharsLeft, 1 ); + aBuffer.append( readCompressedUnicodeArray( nRawChars, !b16BitChars, bAllowNulChars ) ); + + /* Prepare for next CONTINUE record. Calling jumpToNextStringContinue() + reads the leading byte in the following CONTINUE record and updates + the b16BitChars flag. */ + nCharsLeft -= nRawChars; if( nCharsLeft > 0 ) jumpToNextStringContinue( b16BitChars ); } @@ -429,25 +419,15 @@ OUString BiffInputStream::readUniString( bool bAllowNulChars ) void BiffInputStream::skipUniStringChars( sal_uInt16 nChars, bool b16BitChars ) { - sal_uInt16 nCharsLeft = nChars; + sal_Int32 nCharsLeft = nChars; while( !mbEof && (nCharsLeft > 0) ) { - sal_uInt16 nPortionCount; - if( b16BitChars ) - { - nPortionCount = ::std::min< sal_uInt16 >( nCharsLeft, maRecBuffer.getRecLeft() / 2 ); - OSL_ENSURE( (nPortionCount <= nCharsLeft) || ((maRecBuffer.getRecLeft() & 1) == 0), - "BiffInputStream::skipUniStringChars - missing a byte" ); - skip( 2 * nPortionCount ); - } - else - { - nPortionCount = getMaxRawReadSize( nCharsLeft ); - skip( nPortionCount ); - } + // skip the character array + sal_Int32 nSkipSize = b16BitChars ? getMaxRawReadSize( 2 * nCharsLeft, 2 ) : getMaxRawReadSize( nCharsLeft, 1 ); + skip( nSkipSize ); // prepare for next CONTINUE record - nCharsLeft = nCharsLeft - nPortionCount; + nCharsLeft -= (b16BitChars ? (nSkipSize / 2) : nSkipSize); if( nCharsLeft > 0 ) jumpToNextStringContinue( b16BitChars ); } @@ -469,13 +449,6 @@ void BiffInputStream::skipUniString() // private -------------------------------------------------------------------- -void BiffInputStream::readAtom( void* opMem, sal_uInt8 nSize ) -{ - // byte swapping is done in calling BinaryInputStream::readValue() template function - if( ensureRawReadSize( nSize ) ) - maRecBuffer.read( opMem, nSize ); -} - void BiffInputStream::setupRecord() { // initialize class members @@ -529,7 +502,7 @@ bool BiffInputStream::jumpToNextContinue() bool BiffInputStream::jumpToNextStringContinue( bool& rb16BitChars ) { - OSL_ENSURE( maRecBuffer.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - unexpected garbage" ); + OSL_ENSURE( maRecBuffer.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - alignment error" ); if( mbCont && (getRemaining() > 0) ) { @@ -561,31 +534,17 @@ void BiffInputStream::calcRecordLength() seek( nCurrPos ); // restore position, seek() resets old mbValid state } -bool BiffInputStream::ensureRawReadSize( sal_uInt16 nBytes ) -{ - if( !mbEof && (nBytes > 0) ) - { - while( !mbEof && (maRecBuffer.getRecLeft() == 0) ) jumpToNextContinue(); - mbEof = mbEof || (nBytes > maRecBuffer.getRecLeft()); - OSL_ENSURE( !mbEof, "BiffInputStream::ensureRawReadSize - record overread" ); - } - return !mbEof; -} - -sal_uInt16 BiffInputStream::getMaxRawReadSize( sal_Int32 nBytes ) const -{ - return getLimitedValue< sal_uInt16, sal_Int32 >( nBytes, 0, maRecBuffer.getRecLeft() ); -} - -void BiffInputStream::appendUnicodeArray( OUStringBuffer& orBuffer, sal_uInt16 nChars, bool b16BitChars, bool bAllowNulChars ) +sal_uInt16 BiffInputStream::getMaxRawReadSize( sal_Int32 nBytes, size_t nAtomSize ) const { - orBuffer.ensureCapacity( orBuffer.getLength() + nChars ); - sal_uInt16 nChar; - for( sal_uInt16 nCharIdx = 0; !mbEof && (nCharIdx < nChars); ++nCharIdx ) + sal_uInt16 nMaxSize = getLimitedValue< sal_uInt16, sal_Int32 >( nBytes, 0, maRecBuffer.getRecLeft() ); + if( (0 < nMaxSize) && (nMaxSize < nBytes) && (nAtomSize > 1) ) { - if( b16BitChars ) readValue( nChar ); else nChar = readuInt8(); - orBuffer.append( static_cast< sal_Unicode >( (!bAllowNulChars && (nChar == 0)) ? '?' : nChar ) ); + // check that remaining data in record buffer is a multiple of the passed atom size + sal_uInt16 nPadding = static_cast< sal_uInt16 >( nMaxSize % nAtomSize ); + OSL_ENSURE( nPadding == 0, "BiffInputStream::getMaxRawReadSize - alignment error" ); + nMaxSize = nMaxSize - nPadding; } + return nMaxSize; } void BiffInputStream::readUniStringHeader( bool& orb16BitChars, sal_Int32& ornAddSize ) diff --git a/oox/source/xls/biffoutputstream.cxx b/oox/source/xls/biffoutputstream.cxx index d8275b510..c4ed227a6 100644 --- a/oox/source/xls/biffoutputstream.cxx +++ b/oox/source/xls/biffoutputstream.cxx @@ -85,6 +85,7 @@ void BiffOutputRecordBuffer::fill( sal_uInt8 nValue, sal_uInt16 nBytes ) // ============================================================================ BiffOutputStream::BiffOutputStream( BinaryOutputStream& rOutStream, sal_uInt16 nMaxRecSize ) : + BinaryStreamBase( true ), maRecBuffer( rOutStream, nMaxRecSize ), mnPortionSize( 0 ), mnPortionPos( 0 ) @@ -96,19 +97,19 @@ BiffOutputStream::BiffOutputStream( BinaryOutputStream& rOutStream, sal_uInt16 n void BiffOutputStream::startRecord( sal_uInt16 nRecId ) { maRecBuffer.startRecord( nRecId ); - setPortionSize( 0 ); + setPortionSize( 1 ); } void BiffOutputStream::endRecord() { - setPortionSize( 0 ); + setPortionSize( 1 ); maRecBuffer.endRecord(); } -void BiffOutputStream::setPortionSize( sal_uInt16 nSize ) +void BiffOutputStream::setPortionSize( sal_uInt8 nSize ) { OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::setPortionSize - block operation inside portion" ); - mnPortionSize = nSize; + mnPortionSize = ::std::max< sal_uInt8 >( nSize, 1 ); mnPortionPos = 0; } @@ -119,20 +120,20 @@ sal_Int64 BiffOutputStream::tellBase() const return maRecBuffer.getBaseStream().tell(); } -sal_Int64 BiffOutputStream::getBaseLength() const +sal_Int64 BiffOutputStream::sizeBase() const { - return maRecBuffer.getBaseStream().getLength(); + return maRecBuffer.getBaseStream().size(); } // BinaryOutputStream interface (stream write access) ------------------------- -void BiffOutputStream::writeData( const StreamDataSequence& rData ) +void BiffOutputStream::writeData( const StreamDataSequence& rData, size_t nAtomSize ) { if( rData.hasElements() ) - writeMemory( rData.getConstArray(), rData.getLength() ); + writeMemory( rData.getConstArray(), rData.getLength(), nAtomSize ); } -void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes ) +void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize ) { if( pMem && (nBytes > 0) ) { @@ -140,7 +141,7 @@ void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes ) sal_Int32 nBytesLeft = nBytes; while( nBytesLeft > 0 ) { - sal_uInt16 nBlockSize = prepareRawBlock( nBytesLeft ); + sal_uInt16 nBlockSize = prepareWriteBlock( nBytesLeft, nAtomSize ); maRecBuffer.write( pnBuffer, nBlockSize ); pnBuffer += nBlockSize; nBytesLeft -= nBlockSize; @@ -148,59 +149,60 @@ void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes ) } } -void BiffOutputStream::fill( sal_uInt8 nValue, sal_Int32 nBytes ) +void BiffOutputStream::fill( sal_uInt8 nValue, sal_Int32 nBytes, size_t nAtomSize ) { sal_Int32 nBytesLeft = nBytes; while( nBytesLeft > 0 ) { - sal_uInt16 nBlockSize = prepareRawBlock( nBytesLeft ); + sal_uInt16 nBlockSize = prepareWriteBlock( nBytesLeft, nAtomSize ); maRecBuffer.fill( nValue, nBlockSize ); nBytesLeft -= nBlockSize; } } -void BiffOutputStream::writeBlock( const void* pMem, sal_uInt16 nBytes ) -{ - ensureRawBlock( nBytes ); - maRecBuffer.write( pMem, nBytes ); -} - // private -------------------------------------------------------------------- -void BiffOutputStream::writeAtom( const void* pMem, sal_uInt8 nSize ) -{ - // byte swapping is done in calling BinaryOutputStream::writeValue() template function - writeBlock( pMem, nSize ); -} - -void BiffOutputStream::ensureRawBlock( sal_uInt16 nSize ) +sal_uInt16 BiffOutputStream::prepareWriteBlock( sal_Int32 nTotalSize, size_t nAtomSize ) { - if( (maRecBuffer.getRecLeft() < nSize) || - ((mnPortionSize > 0) && (mnPortionPos == 0) && (maRecBuffer.getRecLeft() < mnPortionSize)) ) + sal_uInt16 nRecLeft = maRecBuffer.getRecLeft(); + if( mnPortionSize <= 1 ) { - maRecBuffer.endRecord(); - maRecBuffer.startRecord( BIFF_ID_CONT ); + // no portions: restrict remaining record size to entire atoms + nRecLeft = static_cast< sal_uInt16 >( (nRecLeft / nAtomSize) * nAtomSize ); } - if( mnPortionSize > 0 ) + else { - OSL_ENSURE( mnPortionPos + nSize <= mnPortionSize, "BiffOutputStream::ensureRawBlock - portion overflow" ); - mnPortionPos = (mnPortionPos + nSize) % mnPortionSize; // prevent compiler warning, do not use operator+=, operator%= + sal_Int32 nPortionLeft = mnPortionSize - mnPortionPos; + if( nTotalSize <= nPortionLeft ) + { + // block fits into the current portion + OSL_ENSURE( nPortionLeft <= nRecLeft, "BiffOutputStream::prepareWriteBlock - portion exceeds record" ); + mnPortionPos = static_cast< sal_uInt8 >( (mnPortionPos + nTotalSize) % mnPortionSize ); + } + else + { + // restrict remaining record size to entire portions + OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::prepareWriteBlock - writing over multiple portions starts inside portion" ); + mnPortionPos = 0; + // check that atom size matches portion size + OSL_ENSURE( mnPortionSize % nAtomSize == 0, "BiffOutputStream::prepareWriteBlock - atom size does not match portion size" ); + sal_uInt8 nPortionSize = static_cast< sal_uInt8 >( (mnPortionSize / nAtomSize) * nAtomSize ); + // restrict remaining record size to entire portions + nRecLeft = (nRecLeft / nPortionSize) * nPortionSize; + } } -} -sal_uInt16 BiffOutputStream::prepareRawBlock( sal_Int32 nTotalSize ) -{ - sal_uInt16 nRecLeft = maRecBuffer.getRecLeft(); - if( mnPortionSize > 0 ) - { - OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::prepareRawBlock - block operation inside portion" ); - OSL_ENSURE( nTotalSize % mnPortionSize == 0, "BiffOutputStream::prepareRawBlock - portion size does not match block size" ); - nRecLeft = (nRecLeft / mnPortionSize) * mnPortionSize; - } - sal_uInt16 nSize = getLimitedValue< sal_uInt16, sal_Int32 >( nTotalSize, 0, nRecLeft ); - ensureRawBlock( nSize ); - return nSize; + // current record has space for some data: return size of available space + if( nRecLeft > 0 ) + return getLimitedValue< sal_uInt16, sal_Int32 >( nTotalSize, 0, nRecLeft ); + + // finish current record and start a new CONTINUE record + maRecBuffer.endRecord(); + maRecBuffer.startRecord( BIFF_ID_CONT ); + mnPortionPos = 0; + return prepareWriteBlock( nTotalSize, nAtomSize ); } + // ============================================================================ } // namespace xls diff --git a/oox/source/xls/chartsheetfragment.cxx b/oox/source/xls/chartsheetfragment.cxx index 0a5743cef..c49ec0ea7 100644 --- a/oox/source/xls/chartsheetfragment.cxx +++ b/oox/source/xls/chartsheetfragment.cxx @@ -45,9 +45,8 @@ using ::rtl::OUString; // ============================================================================ -ChartsheetFragment::ChartsheetFragment( const WorkbookHelper& rHelper, - const OUString& rFragmentPath, const ISegmentProgressBarRef& rxProgressBar, sal_Int16 nSheet ) : - WorksheetFragmentBase( rHelper, rFragmentPath, rxProgressBar, SHEETTYPE_CHARTSHEET, nSheet ) +ChartsheetFragment::ChartsheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : + WorksheetFragmentBase( rHelper, rFragmentPath ) { } @@ -179,9 +178,8 @@ void ChartsheetFragment::importDrawing( SequenceInputStream& rStrm ) // ============================================================================ -BiffChartsheetFragment::BiffChartsheetFragment( const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, sal_Int16 nSheet ) : - BiffWorksheetFragmentBase( rParent, rxProgressBar, SHEETTYPE_CHARTSHEET, nSheet ) +BiffChartsheetFragment::BiffChartsheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) : + BiffWorksheetFragmentBase( rHelper, rParent ) { } diff --git a/oox/source/xls/commentsbuffer.cxx b/oox/source/xls/commentsbuffer.cxx index d1ac93a9c..49dca529c 100644 --- a/oox/source/xls/commentsbuffer.cxx +++ b/oox/source/xls/commentsbuffer.cxx @@ -34,7 +34,9 @@ #include "oox/helper/attributelist.hxx" #include "oox/vml/vmlshape.hxx" #include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" #include "oox/xls/drawingfragment.hxx" +#include "oox/xls/drawingmanager.hxx" namespace oox { namespace xls { @@ -44,14 +46,25 @@ namespace xls { using namespace ::com::sun::star::drawing; using namespace ::com::sun::star::sheet; using namespace ::com::sun::star::table; +using namespace ::com::sun::star::text; using namespace ::com::sun::star::uno; using ::rtl::OUString; // ============================================================================ +namespace { + +const sal_uInt16 BIFF_NOTE_VISIBLE = 0x0002; + +} // namespace + +// ============================================================================ + CommentModel::CommentModel() : - mnAuthorId( -1 ) + mnAuthorId( -1 ), + mnObjId( BIFF_OBJ_INVALID_ID ), + mbVisible( false ) { } @@ -77,6 +90,35 @@ void Comment::importComment( SequenceInputStream& rStrm ) getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, aBinRange, getSheetIndex() ); } +void Comment::importNote( BiffInputStream& rStrm ) +{ + BinAddress aBinAddr; + rStrm >> aBinAddr; + // cell range will be checked while inserting the comment into the document + getAddressConverter().convertToCellRangeUnchecked( maModel.maRange, BinRange( aBinAddr ), getSheetIndex() ); + + // remaining record data is BIFF dependent + switch( getBiff() ) + { + case BIFF2: + case BIFF3: + importNoteBiff2( rStrm ); + break; + case BIFF4: + case BIFF5: + importNoteBiff2( rStrm ); + // in BIFF4 and BIFF5, comments can have an associated sound + if( (rStrm.getNextRecId() == BIFF_ID_NOTESOUND) && rStrm.startNextRecord() ) + importNoteSound( rStrm ); + break; + case BIFF8: + importNoteBiff8( rStrm ); + break; + case BIFF_UNKNOWN: + break; + } +} + RichStringRef Comment::createText() { maModel.mxText.reset( new RichString( *this ) ); @@ -92,35 +134,95 @@ void Comment::finalizeImport() CellAddress aNotePos( maModel.maRange.Sheet, maModel.maRange.StartColumn, maModel.maRange.StartRow ); if( getAddressConverter().checkCellAddress( aNotePos, true ) && maModel.mxText.get() ) try { - maModel.mxText->finalizeImport(); - OUString aNoteText = maModel.mxText->getPlainText(); - // non-empty string required by note implementation - if( aNoteText.getLength() > 0 ) + Reference< XSheetAnnotationsSupplier > xAnnosSupp( getSheet(), UNO_QUERY_THROW ); + Reference< XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), UNO_SET_THROW ); + // non-empty string required by note implementation (real text will be added below) + xAnnos->insertNew( aNotePos, OUString( sal_Unicode( ' ' ) ) ); + + // receive created note from cell (insertNew does not return the note) + Reference< XSheetAnnotationAnchor > xAnnoAnchor( getCell( aNotePos ), UNO_QUERY_THROW ); + Reference< XSheetAnnotation > xAnno( xAnnoAnchor->getAnnotation(), UNO_SET_THROW ); + Reference< XSheetAnnotationShapeSupplier > xAnnoShapeSupp( xAnno, UNO_QUERY_THROW ); + Reference< XShape > xAnnoShape( xAnnoShapeSupp->getAnnotationShape(), UNO_SET_THROW ); + + // convert shape formatting and visibility + sal_Bool bVisible = sal_True; + switch( getFilterType() ) { - Reference< XSheetAnnotationsSupplier > xAnnosSupp( getSheet(), UNO_QUERY_THROW ); - Reference< XSheetAnnotations > xAnnos( xAnnosSupp->getAnnotations(), UNO_SET_THROW ); - xAnnos->insertNew( aNotePos, aNoteText ); - // receive craeted note from cell (insertNew does not return the note) - Reference< XSheetAnnotationAnchor > xAnnoAnchor( getCell( aNotePos ), UNO_QUERY_THROW ); - Reference< XSheetAnnotation > xAnno( xAnnoAnchor->getAnnotation(), UNO_SET_THROW ); - Reference< XSheetAnnotationShapeSupplier > xAnnoShapeSupp( xAnno, UNO_QUERY_THROW ); - Reference< XShape > xAnnoShape( xAnnoShapeSupp->getAnnotationShape(), UNO_SET_THROW ); - // convert shape formatting - if( const ::oox::vml::ShapeBase* pNoteShape = getVmlDrawing().getNoteShape( aNotePos ) ) - { - // position and formatting - pNoteShape->convertFormatting( xAnnoShape ); - // visibility - const ::oox::vml::ClientData* pClientData = pNoteShape->getClientData(); - xAnno->setIsVisible( pClientData && pClientData->mbVisible ); - } + case FILTER_OOXML: + if( const ::oox::vml::ShapeBase* pNoteShape = getVmlDrawing().getNoteShape( aNotePos ) ) + { + // position and formatting + pNoteShape->convertFormatting( xAnnoShape ); + // visibility + const ::oox::vml::ClientData* pClientData = pNoteShape->getClientData(); + bVisible = pClientData && pClientData->mbVisible; + } + break; + case FILTER_BIFF: + bVisible = maModel.mbVisible; + break; + case FILTER_UNKNOWN: + break; } + xAnno->setIsVisible( bVisible ); + + // insert text and convert text formatting + maModel.mxText->finalizeImport(); + Reference< XText > xAnnoText( xAnnoShape, UNO_QUERY_THROW ); + maModel.mxText->convert( xAnnoText ); } catch( Exception& ) { } } +// private -------------------------------------------------------------------- + +void Comment::importNoteBiff2( BiffInputStream& rStrm ) +{ + sal_uInt16 nTotalLen; + rStrm >> nTotalLen; + sal_uInt16 nPartLen = ::std::min( nTotalLen, static_cast< sal_uInt16 >( rStrm.getRemaining() ) ); + RichStringRef xNoteText = createText(); + xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() ); + + nTotalLen = nTotalLen - nPartLen; // operator-=() gives compiler warning + while( (nTotalLen > 0) && (rStrm.getNextRecId() == BIFF_ID_NOTE) && rStrm.startNextRecord() ) + { + sal_uInt16 nMarker; + rStrm >> nMarker; + rStrm.skip( 2 ); + rStrm >> nPartLen; + OSL_ENSURE( nMarker == 0xFFFF, "Comment::importNoteBiff2 - missing continuation NOTE record" ); + if( nMarker == 0xFFFF ) + { + OSL_ENSURE( nPartLen <= nTotalLen, "Comment::importNoteBiff2 - string too long" ); + // call to RichString::importCharArray() appends new text portion + xNoteText->importCharArray( rStrm, nPartLen, getTextEncoding() ); + nTotalLen = nTotalLen - ::std::min( nTotalLen, nPartLen ); + } + else + { + // seems to be a new note, rewind record, so worksheet fragment loop will find it + rStrm.rewindRecord(); + nTotalLen = 0; + } + } +} + +void Comment::importNoteBiff8( BiffInputStream& rStrm ) +{ + sal_uInt16 nFlags; + rStrm >> nFlags >> maModel.mnObjId; + maModel.maAuthor = rStrm.readUniString(); + maModel.mbVisible = getFlag( nFlags, BIFF_NOTE_VISIBLE ); +} + +void Comment::importNoteSound( BiffInputStream& /*rStrm*/ ) +{ +} + // ============================================================================ CommentsBuffer::CommentsBuffer( const WorksheetHelper& rHelper ) : diff --git a/oox/source/xls/condformatbuffer.cxx b/oox/source/xls/condformatbuffer.cxx index 7ef2d848e..c310b053f 100644 --- a/oox/source/xls/condformatbuffer.cxx +++ b/oox/source/xls/condformatbuffer.cxx @@ -193,10 +193,9 @@ void CondFormatRule::importCfRule( const AttributeList& rAttribs ) void CondFormatRule::appendFormula( const OUString& rFormula ) { - TokensFormulaContext aContext( true, false ); - aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() ); - getFormulaParser().importFormula( aContext, rFormula ); - maModel.maFormulas.push_back( aContext ); + CellAddress aBaseAddr = mrCondFormat.getRanges().getBaseAddress(); + ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, rFormula ); + maModel.maFormulas.push_back( aTokens ); } void CondFormatRule::importCfRule( SequenceInputStream& rStrm ) @@ -216,25 +215,24 @@ void CondFormatRule::importCfRule( SequenceInputStream& rStrm ) OSL_ENSURE( (nFmla1Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" ); if( rStrm.getRemaining() >= 8 ) { - TokensFormulaContext aContext( true, false ); - aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() ); - getFormulaParser().importFormula( aContext, rStrm ); - maModel.maFormulas.push_back( aContext ); + CellAddress aBaseAddr = mrCondFormat.getRanges().getBaseAddress(); + ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm ); + maModel.maFormulas.push_back( aTokens ); // second formula OSL_ENSURE( (nFmla2Size >= 0) || (nFmla3Size == 0), "CondFormatRule::importCfRule - missing second formula" ); OSL_ENSURE( (nFmla2Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" ); if( rStrm.getRemaining() >= 8 ) { - getFormulaParser().importFormula( aContext, rStrm ); - maModel.maFormulas.push_back( aContext ); + aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm ); + maModel.maFormulas.push_back( aTokens ); // third formula OSL_ENSURE( (nFmla3Size > 0) == (rStrm.getRemaining() >= 8), "CondFormatRule::importCfRule - formula size mismatch" ); if( rStrm.getRemaining() >= 8 ) { - getFormulaParser().importFormula( aContext, rStrm ); - maModel.maFormulas.push_back( aContext ); + aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm ); + maModel.maFormulas.push_back( aTokens ); } } } @@ -419,21 +417,20 @@ void CondFormatRule::importCfRule( BiffInputStream& rStrm, sal_Int32 nPriority ) OSL_ENSURE( (nFmla1Size > 0) || (nFmla2Size == 0), "CondFormatRule::importCfRule - missing first formula" ); if( nFmla1Size > 0 ) { - TokensFormulaContext aContext( true, false ); - aContext.setBaseAddress( mrCondFormat.getRanges().getBaseAddress() ); - getFormulaParser().importFormula( aContext, rStrm, &nFmla1Size ); - maModel.maFormulas.push_back( aContext ); + CellAddress aBaseAddr = mrCondFormat.getRanges().getBaseAddress(); + ApiTokenSequence aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm, &nFmla1Size ); + maModel.maFormulas.push_back( aTokens ); if( nFmla2Size > 0 ) { - getFormulaParser().importFormula( aContext, rStrm, &nFmla2Size ); - maModel.maFormulas.push_back( aContext ); + aTokens = getFormulaParser().importFormula( aBaseAddr, FORMULATYPE_CONDFORMAT, rStrm, &nFmla2Size ); + maModel.maFormulas.push_back( aTokens ); } } } void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries >& rxEntries ) { - ConditionOperator eOperator = ::com::sun::star::sheet::ConditionOperator_NONE; + ConditionOperator eOperator = ConditionOperator_NONE; /* Replacement formula for unsupported rule types (text comparison rules, time period rules, cell type rules). The replacement formulas below may @@ -460,7 +457,7 @@ void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries > eOperator = CondFormatBuffer::convertToApiOperator( maModel.mnOperator ); break; case XML_expression: - eOperator = ::com::sun::star::sheet::ConditionOperator_FORMULA; + eOperator = ConditionOperator_FORMULA; break; case XML_containsText: OSL_ENSURE( maModel.mnOperator == XML_containsText, "CondFormatRule::finalizeImport - unexpected operator" ); @@ -591,17 +588,17 @@ void CondFormatRule::finalizeImport( const Reference< XSheetConditionalEntries > // set the replacement formula maModel.maFormulas.clear(); appendFormula( aReplaceFormula ); - eOperator = ::com::sun::star::sheet::ConditionOperator_FORMULA; + eOperator = ConditionOperator_FORMULA; } - if( rxEntries.is() && (eOperator != ::com::sun::star::sheet::ConditionOperator_NONE) && !maModel.maFormulas.empty() ) + if( rxEntries.is() && (eOperator != ConditionOperator_NONE) && !maModel.maFormulas.empty() ) { ::std::vector< PropertyValue > aProps; // create condition properties lclAppendProperty( aProps, CREATE_OUSTRING( "Operator" ), eOperator ); - lclAppendProperty( aProps, CREATE_OUSTRING( "Formula1" ), maModel.maFormulas[ 0 ].getTokens() ); + lclAppendProperty( aProps, CREATE_OUSTRING( "Formula1" ), maModel.maFormulas[ 0 ] ); if( maModel.maFormulas.size() >= 2 ) - lclAppendProperty( aProps, CREATE_OUSTRING( "Formula2" ), maModel.maFormulas[ 1 ].getTokens() ); + lclAppendProperty( aProps, CREATE_OUSTRING( "Formula2" ), maModel.maFormulas[ 1 ] ); // style name for the formatting attributes OUString aStyleName = getStyles().createDxfStyle( maModel.mnDxfId ); @@ -744,7 +741,6 @@ void CondFormatBuffer::finalizeImport() ConditionOperator CondFormatBuffer::convertToApiOperator( sal_Int32 nToken ) { - using namespace ::com::sun::star::sheet; switch( nToken ) { case XML_between: return ConditionOperator_BETWEEN; diff --git a/oox/source/xls/defnamesbuffer.cxx b/oox/source/xls/defnamesbuffer.cxx index a7a400ce6..2a8737163 100644 --- a/oox/source/xls/defnamesbuffer.cxx +++ b/oox/source/xls/defnamesbuffer.cxx @@ -189,32 +189,32 @@ void lclConvertRefFlags( sal_Int32& ornFlags, sal_Int32& ornAbsPos, sal_Int32& o } } -void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddress, bool bColRel, bool bRowRel ) +void lclConvertSingleRefFlags( SingleReference& orApiRef, const CellAddress& rBaseAddr, bool bColRel, bool bRowRel ) { using namespace ::com::sun::star::sheet::ReferenceFlags; lclConvertRefFlags( orApiRef.Flags, orApiRef.Column, orApiRef.RelativeColumn, - rBaseAddress.Column, COLUMN_RELATIVE, bColRel ); + rBaseAddr.Column, COLUMN_RELATIVE, bColRel ); lclConvertRefFlags( orApiRef.Flags, orApiRef.Row, orApiRef.RelativeRow, - rBaseAddress.Row, ROW_RELATIVE, bRowRel ); + rBaseAddr.Row, ROW_RELATIVE, bRowRel ); } -Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddress, sal_uInt16 nRelFlags ) +Any lclConvertReference( const Any& rRefAny, const CellAddress& rBaseAddr, sal_uInt16 nRelFlags ) { if( rRefAny.has< SingleReference >() && !getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ) && !getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) ) { SingleReference aApiRef; rRefAny >>= aApiRef; - lclConvertSingleRefFlags( aApiRef, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) ); + lclConvertSingleRefFlags( aApiRef, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) ); return Any( aApiRef ); } if( rRefAny.has< ComplexReference >() ) { ComplexReference aApiRef; rRefAny >>= aApiRef; - lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) ); - lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddress, getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) ); + lclConvertSingleRefFlags( aApiRef.Reference1, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL1REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW1REL ) ); + lclConvertSingleRefFlags( aApiRef.Reference2, rBaseAddr, getFlag( nRelFlags, BIFF_REFFLAG_COL2REL ), getFlag( nRelFlags, BIFF_REFFLAG_ROW2REL ) ); return Any( aApiRef ); } return Any(); @@ -248,7 +248,7 @@ const OUString& DefinedNameBase::getUpcaseModelName() const return maUpModelName; } -Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const +Any DefinedNameBase::getReference( const CellAddress& rBaseAddr ) const { if( maRefAny.hasValue() && (maModel.maName.getLength() >= 2) && (maModel.maName[ 0 ] == '\x01') ) { @@ -260,7 +260,7 @@ Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const { ExternalReference aApiExtRef; maRefAny >>= aApiExtRef; - Any aRefAny = lclConvertReference( aApiExtRef.Reference, rBaseAddress, nRelFlags ); + Any aRefAny = lclConvertReference( aApiExtRef.Reference, rBaseAddr, nRelFlags ); if( aRefAny.hasValue() ) { aApiExtRef.Reference <<= aRefAny; @@ -269,37 +269,30 @@ Any DefinedNameBase::getReference( const CellAddress& rBaseAddress ) const } else { - return lclConvertReference( maRefAny, rBaseAddress, nRelFlags ); + return lclConvertReference( maRefAny, rBaseAddr, nRelFlags ); } } } return Any(); } -void DefinedNameBase::importOoxFormula( FormulaContext& rContext, sal_Int16 nBaseSheet ) +ApiTokenSequence DefinedNameBase::importOoxFormula( sal_Int16 nBaseSheet ) { - if( maModel.maFormula.getLength() > 0 ) - { - rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) ); - getFormulaParser().importFormula( rContext, maModel.maFormula ); - } - else - getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME ); + return (maModel.maFormula.getLength() > 0) ? + getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), maModel.maFormula ) : + getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME ); } -void DefinedNameBase::importBiff12Formula( FormulaContext& rContext, sal_Int16 nBaseSheet, SequenceInputStream& rStrm ) +ApiTokenSequence DefinedNameBase::importBiff12Formula( sal_Int16 nBaseSheet, SequenceInputStream& rStrm ) { - rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) ); - getFormulaParser().importFormula( rContext, rStrm ); + return getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm ); } -void DefinedNameBase::importBiffFormula( FormulaContext& rContext, sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) +ApiTokenSequence DefinedNameBase::importBiffFormula( sal_Int16 nBaseSheet, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) { - rContext.setBaseAddress( CellAddress( nBaseSheet, 0, 0 ) ); - if( !pnFmlaSize || (*pnFmlaSize > 0) ) - getFormulaParser().importFormula( rContext, rStrm, pnFmlaSize ); - else - getFormulaParser().convertErrorToFormula( rContext, BIFF_ERR_NAME ); + return (!pnFmlaSize || (*pnFmlaSize > 0)) ? + getFormulaParser().importFormula( CellAddress( nBaseSheet, 0, 0 ), FORMULATYPE_DEFINEDNAME, rStrm, pnFmlaSize ) : + getFormulaParser().convertErrorToFormula( BIFF_ERR_NAME ); } void DefinedNameBase::extractReference( const ApiTokenSequence& rTokens ) @@ -467,9 +460,8 @@ void DefinedName::importDefinedName( BiffInputStream& rStrm, sal_Int16 nCalcShee these names contain a simple cell reference or range reference. Other regular defined names and external names rely on existence of this reference. */ - TokensFormulaContext aContext( true, true ); - importBiffFormula( aContext, mnCalcSheet, rStrm, &mnFmlaSize ); - extractReference( aContext.getTokens() ); + ApiTokenSequence aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize ); + extractReference( aTokens ); } else { @@ -488,6 +480,10 @@ void DefinedName::createNameObject() if( /*maModel.mbHidden ||*/ maModel.mbFunction || maModel.mbVBName ) return; + // skip BIFF names without stream position (e.g. BIFF3-BIFF4 internal 3D references) + if( (getFilterType() == FILTER_BIFF) && !mxBiffStrm.get() ) + return; + // convert original name to final Calc name (TODO: filter invalid characters from model name) maCalcName = isBuiltinName() ? lclGetPrefixedName( mcBuiltinId ) : maModel.maName; @@ -519,69 +515,83 @@ void DefinedName::createNameObject() void DefinedName::convertFormula() { Reference< XFormulaTokens > xTokens( mxNamedRange, UNO_QUERY ); - if( xTokens.is() ) + if( !xTokens.is() ) + return; + + // convert and set formula of the defined name + ApiTokenSequence aTokens; + switch( getFilterType() ) { - // convert and set formula of the defined name - switch( getFilterType() ) + case FILTER_OOXML: { - case FILTER_OOXML: + if( mxFormula.get() ) { - SimpleFormulaContext aContext( xTokens, true, false ); - implImportOoxFormula( aContext ); + SequenceInputStream aStrm( *mxFormula ); + aTokens = importBiff12Formula( mnCalcSheet, aStrm ); } - break; - case FILTER_BIFF: + else + aTokens = importOoxFormula( mnCalcSheet ); + } + break; + case FILTER_BIFF: + { + OSL_ENSURE( mxBiffStrm.get(), "DefinedName::convertFormula - missing BIFF stream" ); + if( mxBiffStrm.get() ) { - SimpleFormulaContext aContext( xTokens, true, getBiff() <= BIFF4 ); - implImportBiffFormula( aContext ); + BiffInputStream& rStrm = mxBiffStrm->getStream(); + BiffInputStreamPosGuard aStrmGuard( rStrm ); + if( mxBiffStrm->restorePosition() ) + aTokens = importBiffFormula( mnCalcSheet, rStrm, &mnFmlaSize ); } - break; - case FILTER_UNKNOWN: break; } + break; + case FILTER_UNKNOWN: + break; + } + xTokens->setTokens( aTokens ); - // set built-in names (print ranges, repeated titles, filter ranges) - if( !isGlobalName() ) switch( mcBuiltinId ) + // set built-in names (print ranges, repeated titles, filter ranges) + if( !isGlobalName() ) switch( mcBuiltinId ) + { + case BIFF_DEFNAME_PRINTAREA: { - case BIFF_DEFNAME_PRINTAREA: - { - Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY ); - ApiCellRangeList aPrintRanges; - getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), false, mnCalcSheet ); - if( xPrintAreas.is() && !aPrintRanges.empty() ) - xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) ); - } - break; - case BIFF_DEFNAME_PRINTTITLES: + Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY ); + ApiCellRangeList aPrintRanges; + getFormulaParser().extractCellRangeList( aPrintRanges, xTokens->getTokens(), false, mnCalcSheet ); + if( xPrintAreas.is() && !aPrintRanges.empty() ) + xPrintAreas->setPrintAreas( ContainerHelper::vectorToSequence( aPrintRanges ) ); + } + break; + case BIFF_DEFNAME_PRINTTITLES: + { + Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY ); + ApiCellRangeList aTitleRanges; + getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), false, mnCalcSheet ); + if( xPrintAreas.is() && !aTitleRanges.empty() ) { - Reference< XPrintAreas > xPrintAreas( getSheetFromDoc( mnCalcSheet ), UNO_QUERY ); - ApiCellRangeList aTitleRanges; - getFormulaParser().extractCellRangeList( aTitleRanges, xTokens->getTokens(), false, mnCalcSheet ); - if( xPrintAreas.is() && !aTitleRanges.empty() ) + bool bHasRowTitles = false; + bool bHasColTitles = false; + const CellAddress& rMaxPos = getAddressConverter().getMaxAddress(); + for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt ) { - bool bHasRowTitles = false; - bool bHasColTitles = false; - const CellAddress& rMaxPos = getAddressConverter().getMaxAddress(); - for( ApiCellRangeList::const_iterator aIt = aTitleRanges.begin(), aEnd = aTitleRanges.end(); (aIt != aEnd) && (!bHasRowTitles || !bHasColTitles); ++aIt ) + bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column); + bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row); + if( !bHasRowTitles && bFullRow && !bFullCol ) { - bool bFullRow = (aIt->StartColumn == 0) && (aIt->EndColumn >= rMaxPos.Column); - bool bFullCol = (aIt->StartRow == 0) && (aIt->EndRow >= rMaxPos.Row); - if( !bHasRowTitles && bFullRow && !bFullCol ) - { - xPrintAreas->setTitleRows( *aIt ); - xPrintAreas->setPrintTitleRows( sal_True ); - bHasRowTitles = true; - } - else if( !bHasColTitles && bFullCol && !bFullRow ) - { - xPrintAreas->setTitleColumns( *aIt ); - xPrintAreas->setPrintTitleColumns( sal_True ); - bHasColTitles = true; - } + xPrintAreas->setTitleRows( *aIt ); + xPrintAreas->setPrintTitleRows( sal_True ); + bHasRowTitles = true; + } + else if( !bHasColTitles && bFullCol && !bFullRow ) + { + xPrintAreas->setTitleColumns( *aIt ); + xPrintAreas->setPrintTitleColumns( sal_True ); + bHasColTitles = true; } } } - break; } + break; } } @@ -593,26 +603,6 @@ bool DefinedName::getAbsoluteRange( CellRangeAddress& orRange ) const return xTokens.is() && getFormulaParser().extractCellRange( orRange, xTokens->getTokens(), false ); } -void DefinedName::implImportOoxFormula( FormulaContext& rContext ) -{ - if( mxFormula.get() ) - { - SequenceInputStream aStrm( *mxFormula ); - importBiff12Formula( rContext, mnCalcSheet, aStrm ); - } - else - importOoxFormula( rContext, mnCalcSheet ); -} - -void DefinedName::implImportBiffFormula( FormulaContext& rContext ) -{ - OSL_ENSURE( mxBiffStrm.get(), "DefinedName::implImportBiffFormula - missing BIFF stream" ); - BiffInputStream& rStrm = mxBiffStrm->getStream(); - BiffInputStreamPosGuard aStrmGuard( rStrm ); - if( mxBiffStrm->restorePosition() ) - importBiffFormula( rContext, mnCalcSheet, rStrm, &mnFmlaSize ); -} - // ============================================================================ DefinedNamesBuffer::DefinedNamesBuffer( const WorkbookHelper& rHelper ) : diff --git a/oox/source/xls/drawingbase.cxx b/oox/source/xls/drawingbase.cxx new file mode 100755 index 000000000..920c16629 --- /dev/null +++ b/oox/source/xls/drawingbase.cxx @@ -0,0 +1,324 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "oox/xls/drawingbase.hxx" + +#include <com/sun/star/awt/Rectangle.hpp> +#include "oox/helper/attributelist.hxx" +#include "oox/helper/binaryinputstream.hxx" +#include "oox/xls/unitconverter.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::table; +using namespace ::oox::drawingml; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +/** Converts the passed 32-bit integer value from 1/100 mm to EMUs. */ +inline sal_Int64 lclHmmToEmu( sal_Int32 nValue ) +{ + return (nValue < 0) ? -1 : convertHmmToEmu( nValue ); +} + +/** Converts the passed 64-bit integer value from EMUs to 1/100 mm. */ +inline sal_Int32 lclEmuToHmm( sal_Int64 nValue ) +{ + return (nValue < 0) ? -1 : convertEmuToHmm( nValue ); +} + +/** Reads the cell anchor model from a BIFF or DFF stream. */ +BinaryInputStream& operator>>( BinaryInputStream& rStrm, CellAnchorModel& rModel ) +{ + // all members are given as 16-bit unsigned values + rModel.mnCol = rStrm.readuInt16(); + rModel.mnColOffset = rStrm.readuInt16(); + rModel.mnRow = rStrm.readuInt16(); + rModel.mnRowOffset = rStrm.readuInt16(); + return rStrm; +} + +} // namespace + +// ============================================================================ + +CellAnchorModel::CellAnchorModel() : + mnCol( -1 ), + mnRow( -1 ), + mnColOffset( 0 ), + mnRowOffset( 0 ) +{ +} + +// ---------------------------------------------------------------------------- + +AnchorClientDataModel::AnchorClientDataModel() : + mbLocksWithSheet( true ), + mbPrintsWithSheet( true ) +{ +} + +// ============================================================================ + +ShapeAnchor::ShapeAnchor( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ), + meAnchorType( ANCHOR_INVALID ), + meCellAnchorType( CELLANCHOR_EMU ), + mnEditAs( XML_twoCell ) +{ +} + +void ShapeAnchor::importAnchor( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( nElement ) + { + case XDR_TOKEN( absoluteAnchor ): + meAnchorType = ANCHOR_ABSOLUTE; + break; + case XDR_TOKEN( oneCellAnchor ): + meAnchorType = ANCHOR_ONECELL; + break; + case XDR_TOKEN( twoCellAnchor ): + meAnchorType = ANCHOR_TWOCELL; + mnEditAs = rAttribs.getToken( XML_editAs, XML_twoCell ); + break; + default: + OSL_ENSURE( false, "ShapeAnchor::importAnchor - unexpected element" ); + } + meCellAnchorType = CELLANCHOR_EMU; +} + +void ShapeAnchor::importPos( const AttributeList& rAttribs ) +{ + OSL_ENSURE( meAnchorType == ANCHOR_ABSOLUTE, "ShapeAnchor::importPos - unexpected 'xdr:pos' element" ); + maPos.X = rAttribs.getHyper( XML_x, 0 ); + maPos.Y = rAttribs.getHyper( XML_y, 0 ); +} + +void ShapeAnchor::importExt( const AttributeList& rAttribs ) +{ + OSL_ENSURE( (meAnchorType == ANCHOR_ABSOLUTE) || (meAnchorType == ANCHOR_ONECELL), "ShapeAnchor::importExt - unexpected 'xdr:ext' element" ); + maSize.Width = rAttribs.getHyper( XML_cx, 0 ); + maSize.Height = rAttribs.getHyper( XML_cy, 0 ); +} + +void ShapeAnchor::importClientData( const AttributeList& rAttribs ) +{ + maClientData.mbLocksWithSheet = rAttribs.getBool( XML_fLocksWithSheet, true ); + maClientData.mbPrintsWithSheet = rAttribs.getBool( XML_fPrintsWithSheet, true ); +} + +void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue ) +{ + CellAnchorModel* pCellAnchor = 0; + switch( nParentContext ) + { + case XDR_TOKEN( from ): + OSL_ENSURE( (meAnchorType == ANCHOR_ONECELL) || (meAnchorType == ANCHOR_TWOCELL), "ShapeAnchor::setCellPos - unexpected 'xdr:from' element" ); + pCellAnchor = &maFrom; + break; + case XDR_TOKEN( to ): + OSL_ENSURE( meAnchorType == ANCHOR_TWOCELL, "ShapeAnchor::setCellPos - unexpected 'xdr:to' element" ); + pCellAnchor = &maTo; + break; + default: + OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected parent element" ); + } + if( pCellAnchor ) switch( nElement ) + { + case XDR_TOKEN( col ): pCellAnchor->mnCol = rValue.toInt32(); break; + case XDR_TOKEN( row ): pCellAnchor->mnRow = rValue.toInt32(); break; + case XDR_TOKEN( colOff ): pCellAnchor->mnColOffset = rValue.toInt64(); break; + case XDR_TOKEN( rowOff ): pCellAnchor->mnRowOffset = rValue.toInt64(); break; + default: OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected element" ); + } +} + +void ShapeAnchor::importVmlAnchor( const OUString& rAnchor ) +{ + meAnchorType = ANCHOR_TWOCELL; /// VML uses two-cell anchors only + meCellAnchorType = CELLANCHOR_PIXEL; /// VML uses screen pixels for offset values + + ::std::vector< OUString > aTokens; + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + aTokens.push_back( rAnchor.getToken( 0, ',', nIndex ).trim() ); + + OSL_ENSURE( aTokens.size() >= 8, "ShapeAnchor::importVmlAnchor - missing anchor tokens" ); + if( aTokens.size() >= 8 ) + { + maFrom.mnCol = aTokens[ 0 ].toInt32(); + maFrom.mnColOffset = aTokens[ 1 ].toInt32(); + maFrom.mnRow = aTokens[ 2 ].toInt32(); + maFrom.mnRowOffset = aTokens[ 3 ].toInt32(); + maTo.mnCol = aTokens[ 4 ].toInt32(); + maTo.mnColOffset = aTokens[ 5 ].toInt32(); + maTo.mnRow = aTokens[ 6 ].toInt32(); + maTo.mnRowOffset = aTokens[ 7 ].toInt32(); + } +} + +void ShapeAnchor::importBiffAnchor( BinaryInputStream& rStrm ) +{ + meAnchorType = ANCHOR_TWOCELL; /// BIFF/DFF use two-cell anchors only + meCellAnchorType = CELLANCHOR_COLROW; /// BIFF/DFF use fraction of column/row for offset values + rStrm >> maFrom >> maTo; +} + +EmuRectangle ShapeAnchor::calcAnchorRectEmu( const Size& rPageSizeHmm ) const +{ + AddressConverter& rAddrConv = getAddressConverter(); + EmuSize aPageSize( lclHmmToEmu( rPageSizeHmm.Width ), lclHmmToEmu( rPageSizeHmm.Height ) ); + EmuRectangle aAnchorRect( -1, -1, -1, -1 ); + + // calculate shape position + switch( meAnchorType ) + { + case ANCHOR_ABSOLUTE: + OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" ); + if( maPos.isValid() && (maPos.X < aPageSize.Width) && (maPos.Y < aPageSize.Height) ) + aAnchorRect.setPos( maPos ); + break; + case ANCHOR_ONECELL: + case ANCHOR_TWOCELL: + OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" ); + if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) + { + EmuPoint aPoint = calcCellAnchorEmu( maFrom ); + if( (aPoint.X < aPageSize.Width) && (aPoint.Y < aPageSize.Height) ) + aAnchorRect.setPos( aPoint ); + } + break; + case ANCHOR_INVALID: + OSL_ENSURE( false, "ShapeAnchor::calcAnchorRectEmu - invalid anchor" ); + break; + } + + // calculate shape size + if( (aAnchorRect.X >= 0) && (aAnchorRect.Y >= 0) ) switch( meAnchorType ) + { + case ANCHOR_ABSOLUTE: + case ANCHOR_ONECELL: + OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid size" ); + if( maSize.isValid() ) + { + aAnchorRect.Width = ::std::min< sal_Int64 >( maSize.Width, aPageSize.Width - aAnchorRect.X ); + aAnchorRect.Height = ::std::min< sal_Int64 >( maSize.Height, aPageSize.Height - aAnchorRect.Y ); + } + break; + case ANCHOR_TWOCELL: + OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcAnchorRectEmu - invalid position" ); + if( maTo.isValid() ) + { + /* Pass a valid cell address to calcCellAnchorEmu(), otherwise + nothing useful is returned, even if either row or column is valid. */ + CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true ); + CellAnchorModel aValidTo = maTo; + aValidTo.mnCol = aToCell.Column; + aValidTo.mnRow = aToCell.Row; + EmuPoint aPoint = calcCellAnchorEmu( aValidTo ); + // width (if column index is valid, use the calculated offset, otherwise stretch to maximum available X position) + aAnchorRect.Width = aPageSize.Width - aAnchorRect.X; + if( aToCell.Column == maTo.mnCol ) + aAnchorRect.Width = ::std::min< sal_Int64 >( aPoint.X - aAnchorRect.X + 1, aAnchorRect.Width ); + // height (if row index is valid, use the calculated offset, otherwise stretch to maximum available Y position) + aAnchorRect.Height = aPageSize.Height - aAnchorRect.Y; + if( aToCell.Row == maTo.mnRow ) + aAnchorRect.Height = ::std::min< sal_Int64 >( aPoint.Y - aAnchorRect.Y + 1, aAnchorRect.Height ); + } + break; + case ANCHOR_INVALID: + break; + } + + // add 0.75 mm (27,000 EMUs) in X direction to correct display error + if( aAnchorRect.X >= 0 ) + aAnchorRect.X += 27000; + // remove 0.25 mm (9,000 EMUs) in Y direction to correct display error + if( aAnchorRect.Y >= 9000 ) + aAnchorRect.Y -= 9000; + + return aAnchorRect; +} + +Rectangle ShapeAnchor::calcAnchorRectHmm( const Size& rPageSizeHmm ) const +{ + EmuRectangle aAnchorRect = calcAnchorRectEmu( rPageSizeHmm ); + return Rectangle( lclEmuToHmm( aAnchorRect.X ), lclEmuToHmm( aAnchorRect.Y ), lclEmuToHmm( aAnchorRect.Width ), lclEmuToHmm( aAnchorRect.Height ) ); +} + +// private -------------------------------------------------------------------- + +EmuPoint ShapeAnchor::calcCellAnchorEmu( const CellAnchorModel& rModel ) const +{ + // calculate position of top-left edge of the cell + Point aPoint = getCellPosition( rModel.mnCol, rModel.mnRow ); + EmuPoint aEmuPoint( lclHmmToEmu( aPoint.X ), lclHmmToEmu( aPoint.Y ) ); + + // add the offset inside the cell + switch( meCellAnchorType ) + { + case CELLANCHOR_EMU: + aEmuPoint.X += rModel.mnColOffset; + aEmuPoint.Y += rModel.mnRowOffset; + break; + + case CELLANCHOR_PIXEL: + { + const UnitConverter& rUnitConv = getUnitConverter(); + aEmuPoint.X += static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( rModel.mnColOffset ), UNIT_SCREENX, UNIT_EMU ) ); + aEmuPoint.Y += static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( rModel.mnRowOffset ), UNIT_SCREENY, UNIT_EMU ) ); + } + break; + + case CELLANCHOR_COLROW: + { + Size aCellSize = getCellSize( rModel.mnCol, rModel.mnRow ); + EmuSize aEmuSize( lclHmmToEmu( aCellSize.Width ), lclHmmToEmu( aCellSize.Height ) ); + // X offset is given in 1/1024 of column width + aEmuPoint.X += static_cast< sal_Int64 >( aEmuSize.Width * getLimitedValue< double >( static_cast< double >( rModel.mnColOffset ) / 1024.0, 0.0, 1.0 ) + 0.5 ); + // Y offset is given in 1/256 of row height + aEmuPoint.Y += static_cast< sal_Int64 >( aEmuSize.Height * getLimitedValue< double >( static_cast< double >( rModel.mnRowOffset ) / 256.0, 0.0, 1.0 ) + 0.5 ); + } + break; + } + + return aEmuPoint; +} + +// ============================================================================ + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/drawingfragment.cxx b/oox/source/xls/drawingfragment.cxx index b1d029050..c577a774a 100644 --- a/oox/source/xls/drawingfragment.cxx +++ b/oox/source/xls/drawingfragment.cxx @@ -72,344 +72,6 @@ using ::rtl::OUStringToOString; // DrawingML // ============================================================================ -namespace { - -/** Converts the passed 64-bit integer value from the passed unit to EMUs. */ -sal_Int64 lclCalcEmu( const UnitConverter& rUnitConv, sal_Int64 nValue, Unit eFromUnit ) -{ - return (eFromUnit == UNIT_EMU) ? nValue : - static_cast< sal_Int64 >( rUnitConv.scaleValue( static_cast< double >( nValue ), eFromUnit, UNIT_EMU ) + 0.5 ); -} - -} // namespace - -// ============================================================================ - -AnchorCellModel::AnchorCellModel() : - mnCol( -1 ), - mnRow( -1 ), - mnColOffset( 0 ), - mnRowOffset( 0 ) -{ -} - -// ---------------------------------------------------------------------------- - -AnchorClientDataModel::AnchorClientDataModel() : - mbLocksWithSheet( true ), - mbPrintsWithSheet( true ) -{ -} - -// ============================================================================ - -ShapeAnchor::ShapeAnchor( const WorksheetHelper& rHelper ) : - WorksheetHelper( rHelper ), - meType( ANCHOR_INVALID ), - mnEditAs( XML_twoCell ) -{ -} - -void ShapeAnchor::importAnchor( sal_Int32 nElement, const AttributeList& rAttribs ) -{ - switch( nElement ) - { - case XDR_TOKEN( absoluteAnchor ): - meType = ANCHOR_ABSOLUTE; - break; - case XDR_TOKEN( oneCellAnchor ): - meType = ANCHOR_ONECELL; - break; - case XDR_TOKEN( twoCellAnchor ): - meType = ANCHOR_TWOCELL; - mnEditAs = rAttribs.getToken( XML_editAs, XML_twoCell ); - break; - default: - OSL_ENSURE( false, "ShapeAnchor::importAnchor - unexpected element" ); - } -} - -void ShapeAnchor::importPos( const AttributeList& rAttribs ) -{ - OSL_ENSURE( meType == ANCHOR_ABSOLUTE, "ShapeAnchor::importPos - unexpected 'xdr:pos' element" ); - maPos.X = rAttribs.getHyper( XML_x, 0 ); - maPos.Y = rAttribs.getHyper( XML_y, 0 ); -} - -void ShapeAnchor::importExt( const AttributeList& rAttribs ) -{ - OSL_ENSURE( (meType == ANCHOR_ABSOLUTE) || (meType == ANCHOR_ONECELL), "ShapeAnchor::importExt - unexpected 'xdr:ext' element" ); - maSize.Width = rAttribs.getHyper( XML_cx, 0 ); - maSize.Height = rAttribs.getHyper( XML_cy, 0 ); -} - -void ShapeAnchor::importClientData( const AttributeList& rAttribs ) -{ - maClientData.mbLocksWithSheet = rAttribs.getBool( XML_fLocksWithSheet, true ); - maClientData.mbPrintsWithSheet = rAttribs.getBool( XML_fPrintsWithSheet, true ); -} - -void ShapeAnchor::setCellPos( sal_Int32 nElement, sal_Int32 nParentContext, const OUString& rValue ) -{ - AnchorCellModel* pAnchorCell = 0; - switch( nParentContext ) - { - case XDR_TOKEN( from ): - OSL_ENSURE( (meType == ANCHOR_ONECELL) || (meType == ANCHOR_TWOCELL), "ShapeAnchor::setCellPos - unexpected 'xdr:from' element" ); - pAnchorCell = &maFrom; - break; - case XDR_TOKEN( to ): - OSL_ENSURE( meType == ANCHOR_TWOCELL, "ShapeAnchor::setCellPos - unexpected 'xdr:to' element" ); - pAnchorCell = &maTo; - break; - default: - OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected parent element" ); - } - if( pAnchorCell ) switch( nElement ) - { - case XDR_TOKEN( col ): pAnchorCell->mnCol = rValue.toInt32(); break; - case XDR_TOKEN( row ): pAnchorCell->mnRow = rValue.toInt32(); break; - case XDR_TOKEN( colOff ): pAnchorCell->mnColOffset = rValue.toInt64(); break; - case XDR_TOKEN( rowOff ): pAnchorCell->mnRowOffset = rValue.toInt64(); break; - default: OSL_ENSURE( false, "ShapeAnchor::setCellPos - unexpected element" ); - } -} - -void ShapeAnchor::importVmlAnchor( const OUString& rAnchor ) -{ - meType = ANCHOR_VML; - - ::std::vector< OUString > aTokens; - sal_Int32 nIndex = 0; - while( nIndex >= 0 ) - aTokens.push_back( rAnchor.getToken( 0, ',', nIndex ).trim() ); - - OSL_ENSURE( aTokens.size() >= 8, "ShapeAnchor::importVmlAnchor - missing anchor tokens" ); - if( aTokens.size() >= 8 ) - { - maFrom.mnCol = aTokens[ 0 ].toInt32(); - maFrom.mnColOffset = aTokens[ 1 ].toInt32(); - maFrom.mnRow = aTokens[ 2 ].toInt32(); - maFrom.mnRowOffset = aTokens[ 3 ].toInt32(); - maTo.mnCol = aTokens[ 4 ].toInt32(); - maTo.mnColOffset = aTokens[ 5 ].toInt32(); - maTo.mnRow = aTokens[ 6 ].toInt32(); - maTo.mnRowOffset = aTokens[ 7 ].toInt32(); - } -} - -bool ShapeAnchor::isValidAnchor() const -{ - bool bValid = false; - switch( meType ) - { - case ANCHOR_ABSOLUTE: - OSL_ENSURE( maPos.isValid(), "ShapeAnchor::isValidAnchor - invalid position" ); - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::isValidAnchor - invalid size" ); - bValid = maPos.isValid() && maSize.isValid() && (maSize.Width > 0) && (maSize.Height > 0); - break; - case ANCHOR_ONECELL: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::isValidAnchor - invalid from position" ); - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::isValidAnchor - invalid size" ); - bValid = maFrom.isValid() && maSize.isValid() && (maSize.Width > 0) && (maSize.Height > 0); - break; - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::isValidAnchor - invalid from position" ); - OSL_ENSURE( maTo.isValid(), "ShapeAnchor::isValidAnchor - invalid to position" ); - bValid = maFrom.isValid() && maTo.isValid() && - ((maFrom.mnCol < maTo.mnCol) || ((maFrom.mnCol == maTo.mnCol) && (maFrom.mnColOffset < maTo.mnColOffset))) && - ((maFrom.mnRow < maTo.mnRow) || ((maFrom.mnRow == maTo.mnRow) && (maFrom.mnRowOffset < maTo.mnRowOffset))); - break; - case ANCHOR_INVALID: - OSL_ENSURE( false, "ShapeAnchor::isValidAnchor - invalid anchor" ); - break; - } - return bValid; -} - -Rectangle ShapeAnchor::calcApiLocation( const Size& rApiSheetSize, const AnchorSizeModel& rEmuSheetSize ) const -{ - AddressConverter& rAddrConv = getAddressConverter(); - UnitConverter& rUnitConv = getUnitConverter(); - Rectangle aApiLoc( -1, -1, -1, -1 ); - Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU; - Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU; - - // calculate shape position - switch( meType ) - { - case ANCHOR_ABSOLUTE: - OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); - if( maPos.isValid() && (maPos.X < rEmuSheetSize.Width) && (maPos.Y < rEmuSheetSize.Height) ) - { - aApiLoc.X = rUnitConv.scaleToMm100( static_cast< double >( maPos.X ), UNIT_EMU ); - aApiLoc.Y = rUnitConv.scaleToMm100( static_cast< double >( maPos.Y ), UNIT_EMU ); - } - break; - case ANCHOR_ONECELL: - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); - if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) - { - Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow ); - aApiLoc.X = aPoint.X + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnColOffset ), eUnitX ); - aApiLoc.Y = aPoint.Y + rUnitConv.scaleToMm100( static_cast< double >( maFrom.mnRowOffset ), eUnitY ); - } - break; - case ANCHOR_INVALID: - OSL_ENSURE( false, "ShapeAnchor::calcApiLocation - invalid anchor" ); - break; - } - - // calculate shape size - if( (aApiLoc.X >= 0) && (aApiLoc.Y >= 0) ) switch( meType ) - { - case ANCHOR_ABSOLUTE: - case ANCHOR_ONECELL: - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcApiLocation - invalid size" ); - if( maSize.isValid() ) - { - aApiLoc.Width = ::std::min< sal_Int32 >( - rUnitConv.scaleToMm100( static_cast< double >( maSize.Width ), UNIT_EMU ), - rApiSheetSize.Width - aApiLoc.X ); - aApiLoc.Height = ::std::min< sal_Int32 >( - rUnitConv.scaleToMm100( static_cast< double >( maSize.Height ), UNIT_EMU ), - rApiSheetSize.Height - aApiLoc.Y ); - } - break; - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcApiLocation - invalid position" ); - if( maTo.isValid() ) - { - /* Pass a valid cell address to getCellPosition(), otherwise - nothing is returned, even if either row or column is valid. */ - CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true ); - Point aPoint = getCellPosition( aToCell.Column, aToCell.Row ); - // width - aApiLoc.Width = rApiSheetSize.Width - aApiLoc.X; - if( aToCell.Column == maTo.mnCol ) - { - aPoint.X += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnColOffset ), eUnitX ); - aApiLoc.Width = ::std::min< sal_Int32 >( aPoint.X - aApiLoc.X + 1, aApiLoc.Width ); - } - // height - aApiLoc.Height = rApiSheetSize.Height - aApiLoc.Y; - if( aToCell.Row == maTo.mnRow ) - { - aPoint.Y += rUnitConv.scaleToMm100( static_cast< double >( maTo.mnRowOffset ), eUnitY ); - aApiLoc.Height = ::std::min< sal_Int32 >( aPoint.Y - aApiLoc.Y + 1, aApiLoc.Height ); - } - } - break; - case ANCHOR_INVALID: - break; - } - - return aApiLoc; -} - -Rectangle ShapeAnchor::calcEmuLocation( const AnchorSizeModel& rEmuSheetSize ) const -{ - AddressConverter& rAddrConv = getAddressConverter(); - UnitConverter& rUnitConv = getUnitConverter(); - - Size aSheetSize( - getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Width, 0, SAL_MAX_INT32 ), - getLimitedValue< sal_Int32, sal_Int64 >( rEmuSheetSize.Height, 0, SAL_MAX_INT32 ) ); - Rectangle aLoc( -1, -1, -1, -1 ); - Unit eUnitX = (meType == ANCHOR_VML) ? UNIT_SCREENX : UNIT_EMU; - Unit eUnitY = (meType == ANCHOR_VML) ? UNIT_SCREENY : UNIT_EMU; - - // calculate shape position - switch( meType ) - { - case ANCHOR_ABSOLUTE: - OSL_ENSURE( maPos.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); - if( maPos.isValid() && (maPos.X < aSheetSize.Width) && (maPos.Y < aSheetSize.Height) ) - { - aLoc.X = static_cast< sal_Int32 >( maPos.X ); - aLoc.Y = static_cast< sal_Int32 >( maPos.Y ); - } - break; - case ANCHOR_ONECELL: - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maFrom.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); - if( maFrom.isValid() && rAddrConv.checkCol( maFrom.mnCol, true ) && rAddrConv.checkRow( maFrom.mnRow, true ) ) - { - Point aPoint = getCellPosition( maFrom.mnCol, maFrom.mnRow ); - sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnColOffset, eUnitX ); - sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) ) + lclCalcEmu( rUnitConv, maFrom.mnRowOffset, eUnitY ); - if( (nX < aSheetSize.Width) && (nY < aSheetSize.Height) ) - { - aLoc.X = static_cast< sal_Int32 >( nX ); - aLoc.Y = static_cast< sal_Int32 >( nY ); - } - } - break; - case ANCHOR_INVALID: - OSL_ENSURE( false, "ShapeAnchor::calcEmuLocation - invalid anchor" ); - break; - } - - // calculate shape size - if( (aLoc.X >= 0) && (aLoc.Y >= 0) ) switch( meType ) - { - case ANCHOR_ABSOLUTE: - case ANCHOR_ONECELL: - OSL_ENSURE( maSize.isValid(), "ShapeAnchor::calcEmuLocation - invalid size" ); - if( maSize.isValid() ) - { - aLoc.Width = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( maSize.Width, aSheetSize.Width - aLoc.X ) ); - aLoc.Height = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( maSize.Height, aSheetSize.Height - aLoc.Y ) ); - } - break; - case ANCHOR_TWOCELL: - case ANCHOR_VML: - OSL_ENSURE( maTo.isValid(), "ShapeAnchor::calcEmuLocation - invalid position" ); - if( maTo.isValid() ) - { - /* Pass a valid cell address to getCellPosition(), otherwise - nothing is returned, even if either row or column is valid. */ - CellAddress aToCell = rAddrConv.createValidCellAddress( BinAddress( maTo.mnCol, maTo.mnRow ), getSheetIndex(), true ); - Point aPoint = getCellPosition( aToCell.Column, aToCell.Row ); - sal_Int64 nX = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.X, UNIT_EMU ) ); - sal_Int64 nY = static_cast< sal_Int64 >( rUnitConv.scaleFromMm100( aPoint.Y, UNIT_EMU ) ); - // width - aLoc.Width = aSheetSize.Width - aLoc.X; - if( aToCell.Column == maTo.mnCol ) - { - nX += lclCalcEmu( rUnitConv, maTo.mnColOffset, eUnitX ); - aLoc.Width = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nX - aLoc.X + 1, aLoc.Width ) ); - } - // height - aLoc.Height = aSheetSize.Height - aLoc.Y; - if( aToCell.Row == maTo.mnRow ) - { - nY += lclCalcEmu( rUnitConv, maTo.mnRowOffset, eUnitY ); - aLoc.Height = static_cast< sal_Int32 >( ::std::min< sal_Int64 >( nY - aLoc.Y + 1, aLoc.Height ) ); - } - } - break; - case ANCHOR_INVALID: - break; - } - - // add 0.75 mm (27,000 EMUs) in X direction to correct display error - if( aLoc.X >= 0 ) - aLoc.X += 27000; - // remove 0.25 mm (9,000 EMUs) in Y direction to correct display error - if( aLoc.Y >= 9000 ) - aLoc.Y -= 9000; - - return aLoc; -} - -// ============================================================================ - ShapeMacroAttacher::ShapeMacroAttacher( const OUString& rMacroName, const Reference< XShape >& rxShape ) : VbaMacroAttacherBase( rMacroName ), mxShape( rxShape ) @@ -518,9 +180,6 @@ DrawingFragment::DrawingFragment( const WorksheetHelper& rHelper, const OUString mxDrawPage( rHelper.getDrawPage(), UNO_QUERY ) { OSL_ENSURE( mxDrawPage.is(), "DrawingFragment::DrawingFragment - missing drawing page" ); - maApiSheetSize = getDrawPageSize(); - maEmuSheetSize.Width = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Width, UNIT_EMU ) ); - maEmuSheetSize.Height = static_cast< sal_Int64 >( getUnitConverter().scaleFromMm100( maApiSheetSize.Height, UNIT_EMU ) ); } ContextHandlerRef DrawingFragment::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) @@ -595,20 +254,23 @@ void DrawingFragment::onEndElement() case XDR_TOKEN( absoluteAnchor ): case XDR_TOKEN( oneCellAnchor ): case XDR_TOKEN( twoCellAnchor ): - if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() && mxAnchor->isValidAnchor() ) + if( mxDrawPage.is() && mxShape.get() && mxAnchor.get() ) { - Rectangle aShapeRect = mxAnchor->calcEmuLocation( maEmuSheetSize ); - if( (aShapeRect.X >= 0) && (aShapeRect.Y >= 0) && (aShapeRect.Width >= 0) && (aShapeRect.Height >= 0) ) + EmuRectangle aShapeRectEmu = mxAnchor->calcAnchorRectEmu( getDrawPageSize() ); + if( (aShapeRectEmu.X >= 0) && (aShapeRectEmu.Y >= 0) && (aShapeRectEmu.Width >= 0) && (aShapeRectEmu.Height >= 0) ) { - mxShape->addShape( getOoxFilter(), &getTheme(), mxDrawPage, &aShapeRect ); + // TODO: DrawingML implementation expects 32-bit coordinates for EMU rectangles (change that to EmuRectangle) + Rectangle aShapeRectEmu32( + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.X, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Y, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Width, 0, SAL_MAX_INT32 ), + getLimitedValue< sal_Int32, sal_Int64 >( aShapeRectEmu.Height, 0, SAL_MAX_INT32 ) ); + mxShape->addShape( getOoxFilter(), &getTheme(), mxDrawPage, &aShapeRectEmu32 ); /* Collect all shape positions in the WorksheetHelper base class. But first, scale EMUs to 1/100 mm. */ - const UnitConverter& rUnitConv = getUnitConverter(); Rectangle aShapeRectHmm( - rUnitConv.scaleToMm100( aShapeRect.X, UNIT_EMU ), - rUnitConv.scaleToMm100( aShapeRect.Y, UNIT_EMU ), - rUnitConv.scaleToMm100( aShapeRect.Width, UNIT_EMU ), - rUnitConv.scaleToMm100( aShapeRect.Height, UNIT_EMU ) ); + convertEmuToHmm( aShapeRectEmu.X ), convertEmuToHmm( aShapeRectEmu.Y ), + convertEmuToHmm( aShapeRectEmu.Width ), convertEmuToHmm( aShapeRectEmu.Height ) ); extendShapeBoundingBox( aShapeRectHmm ); } } @@ -770,7 +432,7 @@ bool VmlDrawing::convertClientAnchor( Rectangle& orShapeRect, const OUString& rS return false; ShapeAnchor aAnchor( *this ); aAnchor.importVmlAnchor( rShapeAnchor ); - orShapeRect = aAnchor.calcApiLocation( getDrawPageSize(), AnchorSizeModel() ); + orShapeRect = aAnchor.calcAnchorRectHmm( getDrawPageSize() ); return (orShapeRect.Width >= 0) && (orShapeRect.Height >= 0); } diff --git a/oox/source/xls/drawingmanager.cxx b/oox/source/xls/drawingmanager.cxx new file mode 100755 index 000000000..bc0200817 --- /dev/null +++ b/oox/source/xls/drawingmanager.cxx @@ -0,0 +1,1414 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "oox/xls/drawingmanager.hxx" + +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/drawing/CircleKind.hpp> +#include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <com/sun/star/drawing/PolygonKind.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include "oox/core/filterbase.hxx" +#include "oox/drawingml/fillproperties.hxx" +#include "oox/drawingml/lineproperties.hxx" +#include "oox/drawingml/shapepropertymap.hxx" +#include "oox/helper/containerhelper.hxx" +#include "oox/token/tokens.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/unitconverter.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::drawing; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::oox::drawingml; + +using ::rtl::OUString; + +// ============================================================================ + +namespace { + +// OBJ record ----------------------------------------------------------------- + +const sal_uInt16 BIFF_OBJTYPE_GROUP = 0; +const sal_uInt16 BIFF_OBJTYPE_LINE = 1; +const sal_uInt16 BIFF_OBJTYPE_RECTANGLE = 2; +const sal_uInt16 BIFF_OBJTYPE_OVAL = 3; +const sal_uInt16 BIFF_OBJTYPE_ARC = 4; +const sal_uInt16 BIFF_OBJTYPE_CHART = 5; +const sal_uInt16 BIFF_OBJTYPE_TEXT = 6; +const sal_uInt16 BIFF_OBJTYPE_BUTTON = 7; +const sal_uInt16 BIFF_OBJTYPE_PICTURE = 8; +const sal_uInt16 BIFF_OBJTYPE_POLYGON = 9; // new in BIFF4 +const sal_uInt16 BIFF_OBJTYPE_CHECKBOX = 11; // new in BIFF5 +const sal_uInt16 BIFF_OBJTYPE_OPTIONBUTTON = 12; +const sal_uInt16 BIFF_OBJTYPE_EDIT = 13; +const sal_uInt16 BIFF_OBJTYPE_LABEL = 14; +const sal_uInt16 BIFF_OBJTYPE_DIALOG = 15; +const sal_uInt16 BIFF_OBJTYPE_SPIN = 16; +const sal_uInt16 BIFF_OBJTYPE_SCROLLBAR = 17; +const sal_uInt16 BIFF_OBJTYPE_LISTBOX = 18; +const sal_uInt16 BIFF_OBJTYPE_GROUPBOX = 19; +const sal_uInt16 BIFF_OBJTYPE_DROPDOWN = 20; +const sal_uInt16 BIFF_OBJTYPE_NOTE = 25; // new in BIFF8 +const sal_uInt16 BIFF_OBJTYPE_DRAWING = 30; +const sal_uInt16 BIFF_OBJTYPE_UNKNOWN = 0xFFFF; // for internal use only + +const sal_uInt16 BIFF_OBJ_HIDDEN = 0x0100; +const sal_uInt16 BIFF_OBJ_VISIBLE = 0x0200; +const sal_uInt16 BIFF_OBJ_PRINTABLE = 0x0400; + +// line formatting ------------------------------------------------------------ + +const sal_uInt8 BIFF_OBJ_LINE_AUTOCOLOR = 64; + +const sal_uInt8 BIFF_OBJ_LINE_SOLID = 0; +const sal_uInt8 BIFF_OBJ_LINE_DASH = 1; +const sal_uInt8 BIFF_OBJ_LINE_DOT = 2; +const sal_uInt8 BIFF_OBJ_LINE_DASHDOT = 3; +const sal_uInt8 BIFF_OBJ_LINE_DASHDOTDOT = 4; +const sal_uInt8 BIFF_OBJ_LINE_MEDTRANS = 5; +const sal_uInt8 BIFF_OBJ_LINE_DARKTRANS = 6; +const sal_uInt8 BIFF_OBJ_LINE_LIGHTTRANS = 7; +const sal_uInt8 BIFF_OBJ_LINE_NONE = 255; + +const sal_uInt8 BIFF_OBJ_LINE_HAIR = 0; +const sal_uInt8 BIFF_OBJ_LINE_THIN = 1; +const sal_uInt8 BIFF_OBJ_LINE_MEDIUM = 2; +const sal_uInt8 BIFF_OBJ_LINE_THICK = 3; + +const sal_uInt8 BIFF_OBJ_LINE_AUTO = 0x01; + +const sal_uInt8 BIFF_OBJ_ARROW_NONE = 0; +const sal_uInt8 BIFF_OBJ_ARROW_OPEN = 1; +const sal_uInt8 BIFF_OBJ_ARROW_FILLED = 2; +const sal_uInt8 BIFF_OBJ_ARROW_OPENBOTH = 3; +const sal_uInt8 BIFF_OBJ_ARROW_FILLEDBOTH = 4; + +const sal_uInt8 BIFF_OBJ_ARROW_NARROW = 0; +const sal_uInt8 BIFF_OBJ_ARROW_MEDIUM = 1; +const sal_uInt8 BIFF_OBJ_ARROW_WIDE = 2; + +const sal_uInt8 BIFF_OBJ_LINE_TL = 0; +const sal_uInt8 BIFF_OBJ_LINE_TR = 1; +const sal_uInt8 BIFF_OBJ_LINE_BR = 2; +const sal_uInt8 BIFF_OBJ_LINE_BL = 3; + +const sal_uInt8 BIFF_OBJ_ARC_TR = 0; +const sal_uInt8 BIFF_OBJ_ARC_TL = 1; +const sal_uInt8 BIFF_OBJ_ARC_BL = 2; +const sal_uInt8 BIFF_OBJ_ARC_BR = 3; + +const sal_uInt16 BIFF_OBJ_POLY_CLOSED = 0x0100; + +// fill formatting ------------------------------------------------------------ + +const sal_uInt8 BIFF_OBJ_FILL_AUTOCOLOR = 65; + +const sal_uInt8 BIFF_OBJ_PATT_NONE = 0; +const sal_uInt8 BIFF_OBJ_PATT_SOLID = 1; + +const sal_uInt8 BIFF_OBJ_FILL_AUTO = 0x01; + +// text formatting ------------------------------------------------------------ + +const sal_uInt8 BIFF_OBJ_HOR_LEFT = 1; +const sal_uInt8 BIFF_OBJ_HOR_CENTER = 2; +const sal_uInt8 BIFF_OBJ_HOR_RIGHT = 3; +const sal_uInt8 BIFF_OBJ_HOR_JUSTIFY = 4; + +const sal_uInt8 BIFF_OBJ_VER_TOP = 1; +const sal_uInt8 BIFF_OBJ_VER_CENTER = 2; +const sal_uInt8 BIFF_OBJ_VER_BOTTOM = 3; +const sal_uInt8 BIFF_OBJ_VER_JUSTIFY = 4; + +const sal_uInt16 BIFF_OBJ_ORIENT_NONE = 0; +const sal_uInt16 BIFF_OBJ_ORIENT_STACKED = 1; /// Stacked top to bottom. +const sal_uInt16 BIFF_OBJ_ORIENT_90CCW = 2; /// 90 degr. counterclockwise. +const sal_uInt16 BIFF_OBJ_ORIENT_90CW = 3; /// 90 degr. clockwise. + +const sal_uInt16 BIFF_OBJ_TEXT_AUTOSIZE = 0x0080; +const sal_uInt16 BIFF_OBJ_TEXT_LOCKED = 0x0200; + +const sal_Int32 BIFF_OBJ_TEXT_MARGIN = 20000; /// Automatic text margin (EMUs). + +// BIFF8 OBJ sub records ------------------------------------------------------ + +const sal_uInt16 BIFF_OBJCMO_PRINTABLE = 0x0010; /// Object printable. +const sal_uInt16 BIFF_OBJCMO_AUTOLINE = 0x2000; /// Automatic line formatting. +const sal_uInt16 BIFF_OBJCMO_AUTOFILL = 0x4000; /// Automatic fill formatting. + +// ---------------------------------------------------------------------------- + +inline BiffInputStream& operator>>( BiffInputStream& rStrm, ShapeAnchor& rAnchor ) +{ + rAnchor.importBiffAnchor( rStrm ); + return rStrm; +} + +} // namespace + +// ============================================================================ +// Model structures for BIFF OBJ record data +// ============================================================================ + +BiffObjLineModel::BiffObjLineModel() : + mnColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ), + mnStyle( BIFF_OBJ_LINE_SOLID ), + mnWidth( BIFF_OBJ_LINE_HAIR ), + mbAuto( true ) +{ +} + +bool BiffObjLineModel::isVisible() const +{ + return mbAuto || (mnStyle != BIFF_OBJ_LINE_NONE); +} + +BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjLineModel& rModel ) +{ + sal_uInt8 nFlags; + rStrm >> rModel.mnColorIdx >> rModel.mnStyle >> rModel.mnWidth >> nFlags; + rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_LINE_AUTO ); + return rStrm; +} + +// ============================================================================ + +BiffObjFillModel::BiffObjFillModel() : + mnBackColorIdx( BIFF_OBJ_LINE_AUTOCOLOR ), + mnPattColorIdx( BIFF_OBJ_FILL_AUTOCOLOR ), + mnPattern( BIFF_OBJ_PATT_SOLID ), + mbAuto( true ) +{ +} + +bool BiffObjFillModel::isFilled() const +{ + return mbAuto || (mnPattern != BIFF_OBJ_PATT_NONE); +} + +BiffInputStream& operator>>( BiffInputStream& rStrm, BiffObjFillModel& rModel ) +{ + sal_uInt8 nFlags; + rStrm >> rModel.mnBackColorIdx >> rModel.mnPattColorIdx >> rModel.mnPattern >> nFlags; + rModel.mbAuto = getFlag( nFlags, BIFF_OBJ_FILL_AUTO ); + return rStrm; +} + +// ============================================================================ + +BiffObjTextModel::BiffObjTextModel() : + mnTextLen( 0 ), + mnFormatSize( 0 ), + mnLinkSize( 0 ), + mnDefFontId( 0 ), + mnFlags( 0 ), + mnOrientation( BIFF_OBJ_ORIENT_NONE ), + mnButtonFlags( 0 ), + mnShortcut( 0 ), + mnShortcutEA( 0 ) +{ +} + +void BiffObjTextModel::readObj3( BiffInputStream& rStrm ) +{ + rStrm >> mnTextLen; + rStrm.skip( 2 ); + rStrm >> mnFormatSize >> mnDefFontId; + rStrm.skip( 2 ); + rStrm >> mnFlags >> mnOrientation; + rStrm.skip( 8 ); +} + +void BiffObjTextModel::readObj5( BiffInputStream& rStrm ) +{ + rStrm >> mnTextLen; + rStrm.skip( 2 ); + rStrm >> mnFormatSize >> mnDefFontId; + rStrm.skip( 2 ); + rStrm >> mnFlags >> mnOrientation; + rStrm.skip( 2 ); + rStrm >> mnLinkSize; + rStrm.skip( 2 ); + rStrm >> mnButtonFlags >> mnShortcut >> mnShortcutEA; +} + +void BiffObjTextModel::readTxo8( BiffInputStream& rStrm ) +{ + rStrm >> mnFlags >> mnOrientation >> mnButtonFlags >> mnShortcut >> mnShortcutEA >> mnTextLen >> mnFormatSize; +} + +sal_uInt8 BiffObjTextModel::getHorAlign() const +{ + return extractValue< sal_uInt8 >( mnFlags, 1, 3 ); +} + +sal_uInt8 BiffObjTextModel::getVerAlign() const +{ + return extractValue< sal_uInt8 >( mnFlags, 4, 3 ); +} + +// ============================================================================ +// BIFF drawing objects +// ============================================================================ + +BiffDrawingObjectContainer::BiffDrawingObjectContainer() +{ +} + +void BiffDrawingObjectContainer::append( const BiffDrawingObjectRef& rxDrawingObj ) +{ + maObjects.push_back( rxDrawingObj ); +} + +void BiffDrawingObjectContainer::insertGrouped( const BiffDrawingObjectRef& rxDrawingObj ) +{ + if( !maObjects.empty() ) + if( BiffGroupObject* pGroupObj = dynamic_cast< BiffGroupObject* >( maObjects.back().get() ) ) + if( pGroupObj->tryInsert( rxDrawingObj ) ) + return; + maObjects.push_back( rxDrawingObj ); +} + +void BiffDrawingObjectContainer::convertAndInsert( BiffDrawingBase& rDrawing, const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const +{ + maObjects.forEachMem( &BiffDrawingObjectBase::convertAndInsert, ::boost::ref( rDrawing ), ::boost::cref( rxShapes ), pParentRect ); +} + +// ============================================================================ + +BiffDrawingObjectBase::BiffDrawingObjectBase( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ), + maAnchor( rHelper ), + mnDffShapeId( 0 ), + mnDffFlags( 0 ), + mnObjId( BIFF_OBJ_INVALID_ID ), + mnObjType( BIFF_OBJTYPE_UNKNOWN ), + mbHasAnchor( false ), + mbHidden( false ), + mbVisible( true ), + mbPrintable( true ), + mbAreaObj( false ), + mbAutoMargin( true ), + mbSimpleMacro( true ), + mbProcessShape( true ), + mbInsertShape( true ), + mbCustomDff( false ) +{ +} + +BiffDrawingObjectBase::~BiffDrawingObjectBase() +{ +} + +/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff3( const WorksheetHelper& rHelper, BiffInputStream& rStrm ) +{ + BiffDrawingObjectRef xDrawingObj; + + if( rStrm.getRemaining() >= 30 ) + { + sal_uInt16 nObjType; + rStrm.skip( 4 ); + rStrm >> nObjType; + switch( nObjType ) + { + case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break; + case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break; + case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break; + case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break; + case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break; +#if 0 + case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break; + case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break; + case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break; +#endif + default: +#if 0 + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff3 - unknown object type" ); +#endif + xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) ); + } + } + + xDrawingObj->importObjBiff3( rStrm ); + return xDrawingObj; +} + +/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff4( const WorksheetHelper& rHelper, BiffInputStream& rStrm ) +{ + BiffDrawingObjectRef xDrawingObj; + + if( rStrm.getRemaining() >= 30 ) + { + sal_uInt16 nObjType; + rStrm.skip( 4 ); + rStrm >> nObjType; + switch( nObjType ) + { + case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break; + case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break; + case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break; + case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break; + case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break; + case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break; +#if 0 + case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break; + case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break; + case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break; +#endif + default: +#if 0 + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff4 - unknown object type" ); +#endif + xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) ); + } + } + + xDrawingObj->importObjBiff4( rStrm ); + return xDrawingObj; +} + +/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff5( const WorksheetHelper& rHelper, BiffInputStream& rStrm ) +{ + BiffDrawingObjectRef xDrawingObj; + + if( rStrm.getRemaining() >= 34 ) + { + sal_uInt16 nObjType; + rStrm.skip( 4 ); + rStrm >> nObjType; + switch( nObjType ) + { + case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break; + case BIFF_OBJTYPE_LINE: xDrawingObj.reset( new BiffLineObject( rHelper ) ); break; + case BIFF_OBJTYPE_RECTANGLE: xDrawingObj.reset( new BiffRectObject( rHelper ) ); break; + case BIFF_OBJTYPE_OVAL: xDrawingObj.reset( new BiffOvalObject( rHelper ) ); break; + case BIFF_OBJTYPE_ARC: xDrawingObj.reset( new BiffArcObject( rHelper ) ); break; + case BIFF_OBJTYPE_POLYGON: xDrawingObj.reset( new BiffPolygonObject( rHelper ) ); break; +#if 0 + case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break; + case BIFF_OBJTYPE_TEXT: xDrawingObj.reset( new XclImpTextObj( rHelper ) ); break; + case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break; + case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break; + case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break; + case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break; + case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break; + case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break; + case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break; + case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break; + case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break; +#endif + default: +#if 0 + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff5 - unknown object type" ); +#endif + xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) ); + } + } + + xDrawingObj->importObjBiff5( rStrm ); + return xDrawingObj; +} + +/*static*/ BiffDrawingObjectRef BiffDrawingObjectBase::importObjBiff8( const WorksheetHelper& rHelper, BiffInputStream& rStrm ) +{ + BiffDrawingObjectRef xDrawingObj; + + if( rStrm.getRemaining() >= 10 ) + { + sal_uInt16 nSubRecId, nSubRecSize, nObjType; + rStrm >> nSubRecId >> nSubRecSize >> nObjType; + OSL_ENSURE( nSubRecId == BIFF_ID_OBJCMO, "BiffDrawingObjectBase::importObjBiff8 - OBJCMO subrecord expected" ); + if( (nSubRecId == BIFF_ID_OBJCMO) && (nSubRecSize >= 6) ) + { + switch( nObjType ) + { +#if 0 + // in BIFF8, all simple objects support text + case BIFF_OBJTYPE_LINE: + case BIFF_OBJTYPE_ARC: + xDrawingObj.reset( new XclImpTextObj( rHelper ) ); + // lines and arcs may be 2-dimensional + xDrawingObj->setAreaObj( false ); + break; + + // in BIFF8, all simple objects support text + case BIFF_OBJTYPE_RECTANGLE: + case BIFF_OBJTYPE_OVAL: + case BIFF_OBJTYPE_POLYGON: + case BIFF_OBJTYPE_DRAWING: + case BIFF_OBJTYPE_TEXT: + xDrawingObj.reset( new XclImpTextObj( rHelper ) ); + break; +#endif + + case BIFF_OBJTYPE_GROUP: xDrawingObj.reset( new BiffGroupObject( rHelper ) ); break; +#if 0 + case BIFF_OBJTYPE_CHART: xDrawingObj.reset( new XclImpChartObj( rHelper ) ); break; + case BIFF_OBJTYPE_BUTTON: xDrawingObj.reset( new XclImpButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_PICTURE: xDrawingObj.reset( new XclImpPictureObj( rHelper ) ); break; + case BIFF_OBJTYPE_CHECKBOX: xDrawingObj.reset( new XclImpCheckBoxObj( rHelper ) ); break; + case BIFF_OBJTYPE_OPTIONBUTTON: xDrawingObj.reset( new XclImpOptionButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_EDIT: xDrawingObj.reset( new XclImpEditObj( rHelper ) ); break; + case BIFF_OBJTYPE_LABEL: xDrawingObj.reset( new XclImpLabelObj( rHelper ) ); break; + case BIFF_OBJTYPE_DIALOG: xDrawingObj.reset( new XclImpDialogObj( rHelper ) ); break; + case BIFF_OBJTYPE_SPIN: xDrawingObj.reset( new XclImpSpinButtonObj( rHelper ) ); break; + case BIFF_OBJTYPE_SCROLLBAR: xDrawingObj.reset( new XclImpScrollBarObj( rHelper ) ); break; + case BIFF_OBJTYPE_LISTBOX: xDrawingObj.reset( new XclImpListBoxObj( rHelper ) ); break; + case BIFF_OBJTYPE_GROUPBOX: xDrawingObj.reset( new XclImpGroupBoxObj( rHelper ) ); break; + case BIFF_OBJTYPE_DROPDOWN: xDrawingObj.reset( new XclImpDropDownObj( rHelper ) ); break; + case BIFF_OBJTYPE_NOTE: xDrawingObj.reset( new XclImpNoteObj( rHelper ) ); break; +#endif + + default: +#if 0 + OSL_ENSURE( false, "BiffDrawingObjectBase::importObjBiff8 - unknown object type" ); +#endif + xDrawingObj.reset( new BiffPlaceholderObject( rHelper ) ); + } + } + } + + xDrawingObj->importObjBiff8( rStrm ); + return xDrawingObj; +} + +Reference< XShape > BiffDrawingObjectBase::convertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle* pParentRect ) const +{ + Reference< XShape > xShape; + if( rxShapes.is() && mbProcessShape && !mbHidden ) // TODO: support for hidden objects? + { + // base class 'ShapeAnchor' calculates the shape rectangle in 1/100 mm + // in BIFF3-BIFF5, all shapes have absolute anchor (also children of group shapes) + Rectangle aShapeRect = maAnchor.calcAnchorRectHmm( getDrawPageSize() ); + + // convert the shape, if the calculated rectangle is not empty + bool bHasWidth = aShapeRect.Width > 0; + bool bHasHeight = aShapeRect.Height > 0; + if( mbAreaObj ? (bHasWidth && bHasHeight) : (bHasWidth || bHasHeight) ) + { + xShape = implConvertAndInsert( rDrawing, rxShapes, aShapeRect ); + /* Notify the drawing that a new shape has been inserted (but not + for children of group shapes). For convenience, pass the + rectangle that contains position and size of the shape. */ + if( !pParentRect && xShape.is() ) + rDrawing.notifyShapeInserted( xShape, aShapeRect ); + } + } + return xShape; +} + +// protected ------------------------------------------------------------------ + +void BiffDrawingObjectBase::readNameBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen ) +{ + maObjName = OUString(); + if( nNameLen > 0 ) + { + // name length field is repeated before the name + maObjName = rStrm.readByteStringUC( false, getTextEncoding() ); + // skip padding byte for word boundaries + rStrm.alignToBlock( 2 ); + } +} + +void BiffDrawingObjectBase::readMacroBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + maMacroName = OUString(); + rStrm.skip( nMacroSize ); + // skip padding byte for word boundaries, not contained in nMacroSize + rStrm.alignToBlock( 2 ); +} + +void BiffDrawingObjectBase::readMacroBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + maMacroName = OUString(); + rStrm.skip( nMacroSize ); +} + +void BiffDrawingObjectBase::readMacroBiff5( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + maMacroName = OUString(); + rStrm.skip( nMacroSize ); +} + +void BiffDrawingObjectBase::readMacroBiff8( BiffInputStream& rStrm ) +{ + maMacroName = OUString(); + if( rStrm.getRemaining() > 6 ) + { + // macro is stored in a tNameXR token containing a link to a defined name + sal_uInt16 nFmlaSize; + rStrm >> nFmlaSize; + rStrm.skip( 4 ); + OSL_ENSURE( nFmlaSize == 7, "BiffDrawingObjectBase::readMacroBiff8 - unexpected formula size" ); + if( nFmlaSize == 7 ) + { + sal_uInt8 nTokenId; + sal_uInt16 nExtLinkId, nExtNameId; + rStrm >> nTokenId >> nExtLinkId >> nExtNameId; +#if 0 + OSL_ENSURE( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ), + "BiffDrawingObjectBase::readMacroBiff8 - tNameXR token expected" ); + if( nTokenId == XclTokenArrayHelper::GetTokenId( EXC_TOKID_NAMEX, EXC_TOKCLASS_REF ) ) + maMacroName = GetLinkManager().GetMacroName( nExtLinkId, nExtNameId ); +#endif + } + } +} + +void BiffDrawingObjectBase::convertLineProperties( ShapePropertyMap& rPropMap, const BiffObjLineModel& rLineModel, sal_uInt16 nArrows ) const +{ + if( rLineModel.mbAuto ) + { + BiffObjLineModel aAutoModel; + aAutoModel.mbAuto = false; + convertLineProperties( rPropMap, aAutoModel, nArrows ); + return; + } + + /* Convert line formatting to DrawingML line formatting and let the + DrawingML code do the hard work. */ + LineProperties aLineProps; + + if( rLineModel.mnStyle == BIFF_OBJ_LINE_NONE ) + { + aLineProps.maLineFill.moFillType = XML_noFill; + } + else + { + aLineProps.maLineFill.moFillType = XML_solidFill; + aLineProps.maLineFill.maFillColor.setPaletteClr( rLineModel.mnColorIdx ); + aLineProps.moLineCompound = XML_sng; + aLineProps.moLineCap = XML_flat; + aLineProps.moLineJoint = XML_round; + + // line width: use 0.35 mm per BIFF line width step + sal_Int32 nLineWidth = 0; + switch( rLineModel.mnWidth ) + { + default: + case BIFF_OBJ_LINE_HAIR: nLineWidth = 0; break; + case BIFF_OBJ_LINE_THIN: nLineWidth = 20; break; + case BIFF_OBJ_LINE_MEDIUM: nLineWidth = 40; break; + case BIFF_OBJ_LINE_THICK: nLineWidth = 60; break; + } + aLineProps.moLineWidth = getLimitedValue< sal_Int32, sal_Int64 >( convertHmmToEmu( nLineWidth ), 0, SAL_MAX_INT32 ); + + // dash style and transparency + switch( rLineModel.mnStyle ) + { + default: + case BIFF_OBJ_LINE_SOLID: + aLineProps.moPresetDash = XML_solid; + break; + case BIFF_OBJ_LINE_DASH: + aLineProps.moPresetDash = XML_lgDash; + break; + case BIFF_OBJ_LINE_DOT: + aLineProps.moPresetDash = XML_dot; + break; + case BIFF_OBJ_LINE_DASHDOT: + aLineProps.moPresetDash = XML_lgDashDot; + break; + case BIFF_OBJ_LINE_DASHDOTDOT: + aLineProps.moPresetDash = XML_lgDashDotDot; + break; + case BIFF_OBJ_LINE_MEDTRANS: + aLineProps.moPresetDash = XML_solid; + aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 50 * PER_PERCENT ); + break; + case BIFF_OBJ_LINE_DARKTRANS: + aLineProps.moPresetDash = XML_solid; + aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 75 * PER_PERCENT ); + break; + case BIFF_OBJ_LINE_LIGHTTRANS: + aLineProps.moPresetDash = XML_solid; + aLineProps.maLineFill.maFillColor.addTransformation( XML_alpha, 25 * PER_PERCENT ); + break; + } + + // line ends + bool bLineStart = false; + bool bLineEnd = false; + bool bFilled = false; + switch( extractValue< sal_uInt8 >( nArrows, 0, 4 ) ) + { + case BIFF_OBJ_ARROW_OPEN: bLineStart = false; bLineEnd = true; bFilled = false; break; + case BIFF_OBJ_ARROW_OPENBOTH: bLineStart = true; bLineEnd = true; bFilled = false; break; + case BIFF_OBJ_ARROW_FILLED: bLineStart = false; bLineEnd = true; bFilled = true; break; + case BIFF_OBJ_ARROW_FILLEDBOTH: bLineStart = true; bLineEnd = true; bFilled = true; break; + } + if( bLineStart || bLineEnd ) + { + // arrow type (open or closed) + sal_Int32 nArrowType = bFilled ? XML_triangle : XML_arrow; + aLineProps.maStartArrow.moArrowType = bLineStart ? nArrowType : XML_none; + aLineProps.maEndArrow.moArrowType = bLineEnd ? nArrowType : XML_none; + + // arrow width + sal_Int32 nArrowWidth = XML_med; + switch( extractValue< sal_uInt8 >( nArrows, 4, 4 ) ) + { + case BIFF_OBJ_ARROW_NARROW: nArrowWidth = XML_sm; break; + case BIFF_OBJ_ARROW_MEDIUM: nArrowWidth = XML_med; break; + case BIFF_OBJ_ARROW_WIDE: nArrowWidth = XML_lg; break; + } + aLineProps.maStartArrow.moArrowWidth = aLineProps.maEndArrow.moArrowWidth = nArrowWidth; + + // arrow length + sal_Int32 nArrowLength = XML_med; + switch( extractValue< sal_uInt8 >( nArrows, 8, 4 ) ) + { + case BIFF_OBJ_ARROW_NARROW: nArrowLength = XML_sm; break; + case BIFF_OBJ_ARROW_MEDIUM: nArrowLength = XML_med; break; + case BIFF_OBJ_ARROW_WIDE: nArrowLength = XML_lg; break; + } + aLineProps.maStartArrow.moArrowLength = aLineProps.maEndArrow.moArrowLength = nArrowLength; + } + } + + aLineProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() ); +} + +void BiffDrawingObjectBase::convertFillProperties( ShapePropertyMap& rPropMap, const BiffObjFillModel& rFillModel ) const +{ + if( rFillModel.mbAuto ) + { + BiffObjFillModel aAutoModel; + aAutoModel.mbAuto = false; + convertFillProperties( rPropMap, aAutoModel ); + return; + } + + /* Convert fill formatting to DrawingML fill formatting and let the + DrawingML code do the hard work. */ + FillProperties aFillProps; + + if( rFillModel.mnPattern == BIFF_OBJ_PATT_NONE ) + { + aFillProps.moFillType = XML_noFill; + } + else + { + const sal_Int32 spnPatternPresets[] = { + XML_TOKEN_INVALID, XML_TOKEN_INVALID, XML_pct50, XML_pct50, XML_pct25, + XML_dkHorz, XML_dkVert, XML_dkDnDiag, XML_dkUpDiag, XML_smCheck, XML_trellis, + XML_ltHorz, XML_ltVert, XML_ltDnDiag, XML_ltUpDiag, XML_smGrid, XML_diagCross, + XML_pct20, XML_pct10 }; + sal_Int32 nPatternPreset = STATIC_ARRAY_SELECT( spnPatternPresets, rFillModel.mnPattern, XML_TOKEN_INVALID ); + if( nPatternPreset == XML_TOKEN_INVALID ) + { + aFillProps.moFillType = XML_solidFill; + aFillProps.maFillColor.setPaletteClr( rFillModel.mnPattColorIdx ); + } + else + { + aFillProps.moFillType = XML_pattFill; + aFillProps.maPatternProps.maPattFgColor.setPaletteClr( rFillModel.mnPattColorIdx ); + aFillProps.maPatternProps.maPattBgColor.setPaletteClr( rFillModel.mnBackColorIdx ); + aFillProps.maPatternProps.moPattPreset = nPatternPreset; + } +#if 0 + static const sal_uInt8 sppnPatterns[][ 8 ] = + { + { 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }, + { 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD }, + { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }, + { 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00 }, + { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }, + { 0x33, 0x66, 0xCC, 0x99, 0x33, 0x66, 0xCC, 0x99 }, + { 0xCC, 0x66, 0x33, 0x99, 0xCC, 0x66, 0x33, 0x99 }, + { 0xCC, 0xCC, 0x33, 0x33, 0xCC, 0xCC, 0x33, 0x33 }, + { 0xCC, 0xFF, 0x33, 0xFF, 0xCC, 0xFF, 0x33, 0xFF }, + { 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, + { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }, + { 0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88 }, + { 0x88, 0x44, 0x22, 0x11, 0x88, 0x44, 0x22, 0x11 }, + { 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x11, 0x11, 0x11 }, + { 0xAA, 0x44, 0xAA, 0x11, 0xAA, 0x44, 0xAA, 0x11 }, + { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 }, + { 0x80, 0x00, 0x08, 0x00, 0x80, 0x00, 0x08, 0x00 } + }; + const sal_uInt8* const pnPattern = sppnPatterns[ ::std::min< size_t >( rFillData.mnPattern - 2, STATIC_ARRAY_SIZE( sppnPatterns ) ) ]; + // create 2-colored 8x8 DIB + SvMemoryStream aMemStrm; +// { 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 } + aMemStrm << sal_uInt32( 12 ) << sal_Int16( 8 ) << sal_Int16( 8 ) << sal_uInt16( 1 ) << sal_uInt16( 1 ); + aMemStrm << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF ) << sal_uInt8( 0xFF ); + aMemStrm << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 ) << sal_uInt8( 0x00 ); + for( size_t nIdx = 0; nIdx < 8; ++nIdx ) + aMemStrm << sal_uInt32( pnPattern[ nIdx ] ); // 32-bit little-endian + aMemStrm.Seek( STREAM_SEEK_TO_BEGIN ); + Bitmap aBitmap; + aBitmap.Read( aMemStrm, FALSE ); + XOBitmap aXOBitmap( aBitmap ); + aXOBitmap.Bitmap2Array(); + aXOBitmap.SetBitmapType( XBITMAP_8X8 ); + if( aXOBitmap.GetBackgroundColor().GetColor() == COL_BLACK ) + ::std::swap( aPattColor, aBackColor ); + aXOBitmap.SetPixelColor( aPattColor ); + aXOBitmap.SetBackgroundColor( aBackColor ); + rSdrObj.SetMergedItem( XFillStyleItem( XFILL_BITMAP ) ); + rSdrObj.SetMergedItem( XFillBitmapItem( EMPTY_STRING, aXOBitmap ) ); +#endif + } + + aFillProps.pushToPropMap( rPropMap, getBaseFilter().getGraphicHelper() ); +} + +void BiffDrawingObjectBase::convertFrameProperties( ShapePropertyMap& /*rPropMap*/, sal_uInt16 /*nFrameFlags*/ ) const +{ +} + +void BiffDrawingObjectBase::implReadObjBiff3( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ ) +{ +} + +void BiffDrawingObjectBase::implReadObjBiff4( BiffInputStream& /*rStrm*/, sal_uInt16 /*nMacroSize*/ ) +{ +} + +void BiffDrawingObjectBase::implReadObjBiff5( BiffInputStream& /*rStrm*/, sal_uInt16 /*nNameLen*/, sal_uInt16 /*nMacroSize*/ ) +{ +} + +void BiffDrawingObjectBase::implReadObjBiff8SubRec( BiffInputStream& /*rStrm*/, sal_uInt16 /*nSubRecId*/, sal_uInt16 /*nSubRecSize*/ ) +{ +} + +// private -------------------------------------------------------------------- + +void BiffDrawingObjectBase::importObjBiff3( BiffInputStream& rStrm ) +{ + // back to offset 4 (ignore object count field) + rStrm.seek( 4 ); + + sal_uInt16 nObjFlags, nMacroSize; + rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize; + rStrm.skip( 2 ); + + mbHasAnchor = true; + mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN ); + mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE ); + implReadObjBiff3( rStrm, nMacroSize ); +} + +void BiffDrawingObjectBase::importObjBiff4( BiffInputStream& rStrm ) +{ + // back to offset 4 (ignore object count field) + rStrm.seek( 4 ); + + sal_uInt16 nObjFlags, nMacroSize; + rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize; + rStrm.skip( 2 ); + + mbHasAnchor = true; + mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN ); + mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE ); + mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE ); + implReadObjBiff4( rStrm, nMacroSize ); +} + +void BiffDrawingObjectBase::importObjBiff5( BiffInputStream& rStrm ) +{ + // back to offset 4 (ignore object count field) + rStrm.seek( 4 ); + + sal_uInt16 nObjFlags, nMacroSize, nNameLen; + rStrm >> mnObjType >> mnObjId >> nObjFlags >> maAnchor >> nMacroSize; + rStrm.skip( 2 ); + rStrm >> nNameLen; + rStrm.skip( 2 ); + + mbHasAnchor = true; + mbHidden = getFlag( nObjFlags, BIFF_OBJ_HIDDEN ); + mbVisible = getFlag( nObjFlags, BIFF_OBJ_VISIBLE ); + mbPrintable = getFlag( nObjFlags, BIFF_OBJ_PRINTABLE ); + implReadObjBiff5( rStrm, nNameLen, nMacroSize ); +} + +void BiffDrawingObjectBase::importObjBiff8( BiffInputStream& rStrm ) +{ + // back to beginning + rStrm.seekToStart(); + + bool bLoop = true; + while( bLoop && (rStrm.getRemaining() >= 4) ) + { + sal_uInt16 nSubRecId, nSubRecSize; + rStrm >> nSubRecId >> nSubRecSize; + sal_Int64 nStrmPos = rStrm.tell(); + // sometimes the last subrecord has an invalid length (OBJLBSDATA) -> min() + nSubRecSize = static_cast< sal_uInt16 >( ::std::min< sal_Int64 >( nSubRecSize, rStrm.getRemaining() ) ); + + switch( nSubRecId ) + { + case BIFF_ID_OBJCMO: + OSL_ENSURE( rStrm.tell() == 4, "BiffDrawingObjectBase::importObjBiff8 - unexpected OBJCMO subrecord" ); + if( (rStrm.tell() == 4) && (nSubRecSize >= 6) ) + { + sal_uInt16 nObjFlags; + rStrm >> mnObjType >> mnObjId >> nObjFlags; + mbPrintable = getFlag( nObjFlags, BIFF_OBJCMO_PRINTABLE ); + } + break; + case BIFF_ID_OBJMACRO: + readMacroBiff8( rStrm ); + break; + case BIFF_ID_OBJEND: + bLoop = false; + break; + default: + implReadObjBiff8SubRec( rStrm, nSubRecId, nSubRecSize ); + } + + // seek to end of subrecord + rStrm.seek( nStrmPos + nSubRecSize ); + } + + /* Call doReadObj8SubRec() with BIFF_ID_OBJEND for further stream + processing (e.g. charts), even if the OBJEND subrecord is missing. */ + implReadObjBiff8SubRec( rStrm, BIFF_ID_OBJEND, 0 ); + + /* Pictures that Excel reads from BIFF5 and writes to BIFF8 still have the + IMGDATA record following the OBJ record (but they use the image data + stored in DFF). The IMGDATA record may be continued by several CONTINUE + records. But the last CONTINUE record may be in fact an MSODRAWING + record that contains the DFF data of the next drawing object! So we + have to skip just enough CONTINUE records to look at the next + MSODRAWING/CONTINUE record. */ + if( (rStrm.getNextRecId() == BIFF3_ID_IMGDATA) && rStrm.startNextRecord() ) + { + rStrm.skip( 4 ); + sal_Int64 nDataSize = rStrm.readuInt32(); + nDataSize -= rStrm.getRemaining(); + // skip following CONTINUE records until IMGDATA ends + while( (nDataSize > 0) && (rStrm.getNextRecId() == BIFF_ID_CONT) && rStrm.startNextRecord() ) + { + OSL_ENSURE( nDataSize >= rStrm.getRemaining(), "BiffDrawingObjectBase::importObjBiff8 - CONTINUE too long" ); + nDataSize -= ::std::min( rStrm.getRemaining(), nDataSize ); + } + OSL_ENSURE( nDataSize == 0, "BiffDrawingObjectBase::importObjBiff8 - missing CONTINUE records" ); + // next record may be MSODRAWING or CONTINUE or anything else + } +} + +// ============================================================================ + +BiffPlaceholderObject::BiffPlaceholderObject( const WorksheetHelper& rHelper ) : + BiffDrawingObjectBase( rHelper ) +{ + setProcessShape( false ); +} + +Reference< XShape > BiffPlaceholderObject::implConvertAndInsert( BiffDrawingBase& /*rDrawing*/, + const Reference< XShapes >& /*rxShapes*/, const Rectangle& /*rShapeRect*/ ) const +{ + return Reference< XShape >(); +} + +// ============================================================================ + +BiffGroupObject::BiffGroupObject( const WorksheetHelper& rHelper ) : + BiffDrawingObjectBase( rHelper ), + mnFirstUngrouped( BIFF_OBJ_INVALID_ID ) +{ +} + +bool BiffGroupObject::tryInsert( const BiffDrawingObjectRef& rxDrawingObj ) +{ + if( rxDrawingObj->getObjId() == mnFirstUngrouped ) + return false; + // insert into own list or into nested group + maChildren.insertGrouped( rxDrawingObj ); + return true; +} + +void BiffGroupObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + rStrm.skip( 4 ); + rStrm >> mnFirstUngrouped; + rStrm.skip( 16 ); + readMacroBiff3( rStrm, nMacroSize ); +} + +void BiffGroupObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + rStrm.skip( 4 ); + rStrm >> mnFirstUngrouped; + rStrm.skip( 16 ); + readMacroBiff4( rStrm, nMacroSize ); +} + +void BiffGroupObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) +{ + rStrm.skip( 4 ); + rStrm >> mnFirstUngrouped; + rStrm.skip( 16 ); + readNameBiff5( rStrm, nNameLen ); + readMacroBiff5( rStrm, nMacroSize ); +} + +Reference< XShape > BiffGroupObject::implConvertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xGroupShape; + if( !maChildren.empty() ) try + { + xGroupShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rxShapes, rShapeRect ); + Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW ); + maChildren.convertAndInsert( rDrawing, xChildShapes, &rShapeRect ); + // no child shape has been created - delete the group shape + if( !xChildShapes->hasElements() ) + { + rxShapes->remove( xGroupShape ); + xGroupShape.clear(); + } + } + catch( Exception& ) + { + } + return xGroupShape; +} + +// ============================================================================ + +BiffLineObject::BiffLineObject( const WorksheetHelper& rHelper ) : + BiffDrawingObjectBase( rHelper ), + mnArrows( 0 ), + mnStartPoint( BIFF_OBJ_LINE_TL ) +{ + setAreaObj( false ); +} + +void BiffLineObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + rStrm >> maLineModel >> mnArrows >> mnStartPoint; + rStrm.skip( 1 ); + readMacroBiff3( rStrm, nMacroSize ); +} + +void BiffLineObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + rStrm >> maLineModel >> mnArrows >> mnStartPoint; + rStrm.skip( 1 ); + readMacroBiff4( rStrm, nMacroSize ); +} + +void BiffLineObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) +{ + rStrm >> maLineModel >> mnArrows >> mnStartPoint; + rStrm.skip( 1 ); + readNameBiff5( rStrm, nNameLen ); + readMacroBiff5( rStrm, nMacroSize ); +} + +Reference< XShape > BiffLineObject::implConvertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() ); + convertLineProperties( aPropMap, maLineModel, mnArrows ); + + // create the line polygon + PointSequenceSequence aPoints( 1 ); + aPoints[ 0 ].realloc( 2 ); + Point& rBeg = aPoints[ 0 ][ 0 ]; + Point& rEnd = aPoints[ 0 ][ 1 ]; + sal_Int32 nL = rShapeRect.X; + sal_Int32 nT = rShapeRect.Y; + sal_Int32 nR = rShapeRect.X + ::std::max< sal_Int32 >( rShapeRect.Width - 1, 0 ); + sal_Int32 nB = rShapeRect.Y + ::std::max< sal_Int32 >( rShapeRect.Height - 1, 0 ); + switch( mnStartPoint ) + { + default: + case BIFF_OBJ_LINE_TL: rBeg.X = nL; rBeg.Y = nT; rEnd.X = nR; rEnd.Y = nB; break; + case BIFF_OBJ_LINE_TR: rBeg.X = nR; rBeg.Y = nT; rEnd.X = nL; rEnd.Y = nB; break; + case BIFF_OBJ_LINE_BR: rBeg.X = nR; rBeg.Y = nB; rEnd.X = nL; rEnd.Y = nT; break; + case BIFF_OBJ_LINE_BL: rBeg.X = nL; rBeg.Y = nB; rEnd.X = nR; rEnd.Y = nT; break; + } + aPropMap.setProperty( PROP_PolyPolygon, aPoints ); + aPropMap.setProperty( PROP_PolygonKind, PolygonKind_LINE ); + + // create the shape + Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.LineShape" ), rxShapes, rShapeRect ); + PropertySet( xShape ).setProperties( aPropMap ); + return xShape; +} + +// ============================================================================ + +BiffRectObject::BiffRectObject( const WorksheetHelper& rHelper ) : + BiffDrawingObjectBase( rHelper ), + mnFrameFlags( 0 ) +{ + setAreaObj( true ); +} + +void BiffRectObject::readFrameData( BiffInputStream& rStrm ) +{ + rStrm >> maFillModel >> maLineModel >> mnFrameFlags; +} + +void BiffRectObject::convertRectProperties( ShapePropertyMap& rPropMap ) const +{ + convertLineProperties( rPropMap, maLineModel ); + convertFillProperties( rPropMap, maFillModel ); + convertFrameProperties( rPropMap, mnFrameFlags ); +} + +void BiffRectObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + readFrameData( rStrm ); + readMacroBiff3( rStrm, nMacroSize ); +} + +void BiffRectObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + readFrameData( rStrm ); + readMacroBiff4( rStrm, nMacroSize ); +} + +void BiffRectObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) +{ + readFrameData( rStrm ); + readNameBiff5( rStrm, nNameLen ); + readMacroBiff5( rStrm, nMacroSize ); +} + +Reference< XShape > BiffRectObject::implConvertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() ); + convertRectProperties( aPropMap ); + + Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ), rxShapes, rShapeRect ); + PropertySet( xShape ).setProperties( aPropMap ); + return xShape; +} + +// ============================================================================ + +BiffOvalObject::BiffOvalObject( const WorksheetHelper& rHelper ) : + BiffRectObject( rHelper ) +{ +} + +Reference< XShape > BiffOvalObject::implConvertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() ); + convertRectProperties( aPropMap ); + + Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, rShapeRect ); + PropertySet( xShape ).setProperties( aPropMap ); + return xShape; +} + +// ============================================================================ + +BiffArcObject::BiffArcObject( const WorksheetHelper& rHelper ) : + BiffDrawingObjectBase( rHelper ), + mnQuadrant( BIFF_OBJ_ARC_TR ) +{ + setAreaObj( false ); // arc may be 2-dimensional +} + +void BiffArcObject::implReadObjBiff3( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + rStrm >> maFillModel >> maLineModel >> mnQuadrant; + rStrm.skip( 1 ); + readMacroBiff3( rStrm, nMacroSize ); +} + +void BiffArcObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + rStrm >> maFillModel >> maLineModel >> mnQuadrant; + rStrm.skip( 1 ); + readMacroBiff4( rStrm, nMacroSize ); +} + +void BiffArcObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) +{ + rStrm >> maFillModel >> maLineModel >> mnQuadrant; + rStrm.skip( 1 ); + readNameBiff5( rStrm, nNameLen ); + readMacroBiff5( rStrm, nMacroSize ); +} + +Reference< XShape > BiffArcObject::implConvertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() ); + convertLineProperties( aPropMap, maLineModel ); + convertFillProperties( aPropMap, maFillModel ); + + /* Simulate arc objects with ellipse sections. While the original arc + object uses the entire object rectangle, only one quarter of the + ellipse shape will be visible. Thus, the size of the ellipse shape + needs to be extended and its position adjusted according to the visible + quadrant. */ + Rectangle aNewRect( rShapeRect.X, rShapeRect.Y, rShapeRect.Width * 2, rShapeRect.Height * 2 ); + long nStartAngle = 0; + switch( mnQuadrant ) + { + default: + case BIFF_OBJ_ARC_TR: nStartAngle = 0; aNewRect.X -= rShapeRect.Width; break; + case BIFF_OBJ_ARC_TL: nStartAngle = 9000; break; + case BIFF_OBJ_ARC_BL: nStartAngle = 18000; aNewRect.Y -= rShapeRect.Height; break; + case BIFF_OBJ_ARC_BR: nStartAngle = 27000; aNewRect.X -= rShapeRect.Width; aNewRect.Y -= rShapeRect.Height; break; + } + long nEndAngle = (nStartAngle + 9000) % 36000; + aPropMap.setProperty( PROP_CircleKind, maFillModel.isFilled() ? CircleKind_SECTION : CircleKind_ARC ); + aPropMap.setProperty( PROP_CircleStartAngle, nStartAngle ); + aPropMap.setProperty( PROP_CircleEndAngle, nEndAngle ); + + // create the shape + Reference< XShape > xShape = rDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ), rxShapes, aNewRect ); + PropertySet( xShape ).setProperties( aPropMap ); + return xShape; +} + +// ============================================================================ + +BiffPolygonObject::BiffPolygonObject( const WorksheetHelper& rHelper ) : + BiffRectObject( rHelper ), + mnPolyFlags( 0 ), + mnPointCount( 0 ) +{ + setAreaObj( false ); // polygon may be 2-dimensional +} + +void BiffPolygonObject::implReadObjBiff4( BiffInputStream& rStrm, sal_uInt16 nMacroSize ) +{ + readFrameData( rStrm ); + rStrm >> mnPolyFlags; + rStrm.skip( 10 ); + rStrm >> mnPointCount; + rStrm.skip( 8 ); + readMacroBiff4( rStrm, nMacroSize ); + importCoordList( rStrm ); +} + +void BiffPolygonObject::implReadObjBiff5( BiffInputStream& rStrm, sal_uInt16 nNameLen, sal_uInt16 nMacroSize ) +{ + readFrameData( rStrm ); + rStrm >> mnPolyFlags; + rStrm.skip( 10 ); + rStrm >> mnPointCount; + rStrm.skip( 8 ); + readNameBiff5( rStrm, nNameLen ); + readMacroBiff5( rStrm, nMacroSize ); + importCoordList( rStrm ); +} + +namespace { + +Point lclGetPolyPoint( const Rectangle& rAnchorRect, const Point& rPoint ) +{ + // polygon coordinates are given in 1/16384 of shape size + return Point( + rAnchorRect.X + static_cast< sal_Int32 >( rAnchorRect.Width * getLimitedValue< double >( static_cast< double >( rPoint.X ) / 16384.0, 0.0, 1.0 ) + 0.5 ), + rAnchorRect.Y + static_cast< sal_Int32 >( rAnchorRect.Height * getLimitedValue< double >( static_cast< double >( rPoint.Y ) / 16384.0, 0.0, 1.0 ) + 0.5 ) ); +} + +} // namespace + +Reference< XShape > BiffPolygonObject::implConvertAndInsert( BiffDrawingBase& rDrawing, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + Reference< XShape > xShape; + if( maCoords.size() >= 2 ) + { + ShapePropertyMap aPropMap( getBaseFilter().getModelObjectHelper() ); + convertRectProperties( aPropMap ); + + // create the polygon + PointVector aPolygon; + for( PointVector::const_iterator aIt = maCoords.begin(), aEnd = maCoords.end(); aIt != aEnd; ++aIt ) + aPolygon.push_back( lclGetPolyPoint( rShapeRect, *aIt ) ); + // close polygon if specified + if( getFlag( mnPolyFlags, BIFF_OBJ_POLY_CLOSED ) && ((maCoords.front().X != maCoords.back().X) || (maCoords.front().Y != maCoords.back().Y)) ) + aPolygon.push_back( aPolygon.front() ); + PointSequenceSequence aPoints( 1 ); + aPoints[ 0 ] = ContainerHelper::vectorToSequence( aPolygon ); + aPropMap.setProperty( PROP_PolyPolygon, aPoints ); + + // create the shape + OUString aService = maFillModel.isFilled() ? + CREATE_OUSTRING( "com.sun.star.drawing.PolyPolygonShape" ) : + CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" ); + xShape = rDrawing.createAndInsertXShape( aService, rxShapes, rShapeRect ); + PropertySet( xShape ).setProperties( aPropMap ); + } + return xShape; +} + +void BiffPolygonObject::importCoordList( BiffInputStream& rStrm ) +{ + if( (rStrm.getNextRecId() == BIFF_ID_COORDLIST) && rStrm.startNextRecord() ) + { + OSL_ENSURE( rStrm.getRemaining() / 4 == mnPointCount, "BiffPolygonObject::importCoordList - wrong polygon point count" ); + while( rStrm.getRemaining() >= 4 ) + { + sal_uInt16 nX, nY; + rStrm >> nX >> nY; + maCoords.push_back( Point( nX, nY ) ); + } + } +} + +// ============================================================================ +// BIFF drawing page +// ============================================================================ + +BiffDrawingBase::BiffDrawingBase( const WorksheetHelper& rHelper, const Reference< XDrawPage >& rxDrawPage ) : + WorksheetHelper( rHelper ), + mxDrawPage( rxDrawPage ) +{ +} + +void BiffDrawingBase::importObj( BiffInputStream& rStrm ) +{ + BiffDrawingObjectRef xDrawingObj; + +#if 0 + /* #i61786# In BIFF8 streams, OBJ records may occur without MSODRAWING + records. In this case, the OBJ records are in BIFF5 format. Do a sanity + check here that there is no DFF data loaded before. */ + DBG_ASSERT( maDffStrm.Tell() == 0, "BiffDrawingBase::importObj - unexpected DFF stream data, OBJ will be ignored" ); + if( maDffStrm.Tell() == 0 ) switch( GetBiff() ) +#else + switch( getBiff() ) +#endif + { + case BIFF3: + xDrawingObj = BiffDrawingObjectBase::importObjBiff3( *this, rStrm ); + break; + case BIFF4: + xDrawingObj = BiffDrawingObjectBase::importObjBiff4( *this, rStrm ); + break; + case BIFF5: +// TODO: add BIFF8 when DFF is supported +// case BIFF8: + xDrawingObj = BiffDrawingObjectBase::importObjBiff5( *this, rStrm ); + break; + default:; + } + + if( xDrawingObj.get() ) + { + // insert into maRawObjs or into the last open group object + maRawObjs.insertGrouped( xDrawingObj ); + // to be able to find objects by ID + maObjMapId[ xDrawingObj->getObjId() ] = xDrawingObj; + } +} + +void BiffDrawingBase::setSkipObj( sal_uInt16 nObjId ) +{ + /* Store identifiers of objects to be skipped in a separate list (the OBJ + record may not be read yet). In the finalization phase, all objects + registered here will be skipped. */ + maSkipObjs.push_back( nObjId ); +} + +void BiffDrawingBase::finalizeImport() +{ + Reference< XShapes > xShapes( mxDrawPage, UNO_QUERY ); + OSL_ENSURE( xShapes.is(), "BiffDrawingBase::finalizeImport - no shapes container" ); + if( !xShapes.is() ) + return; + + // process list of objects to be skipped + for( BiffObjIdVector::const_iterator aIt = maSkipObjs.begin(), aEnd = maSkipObjs.end(); aIt != aEnd; ++aIt ) + if( BiffDrawingObjectBase* pDrawingObj = maObjMapId.get( *aIt ).get() ) + pDrawingObj->setProcessShape( false ); + + // process drawing objects without DFF data + maRawObjs.convertAndInsert( *this, xShapes ); +} + +Reference< XShape > BiffDrawingBase::createAndInsertXShape( const OUString& rService, + const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const +{ + OSL_ENSURE( rService.getLength() > 0, "BiffDrawingBase::createAndInsertXShape - missing UNO shape service name" ); + OSL_ENSURE( rxShapes.is(), "BiffDrawingBase::createAndInsertXShape - missing XShapes container" ); + Reference< XShape > xShape; + if( (rService.getLength() > 0) && rxShapes.is() ) try + { + xShape.set( getBaseFilter().getModelFactory()->createInstance( rService ), UNO_QUERY_THROW ); + // insert shape into passed shape collection (maybe drawpage or group shape) + rxShapes->add( xShape ); + xShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) ); + xShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) ); + } + catch( Exception& ) + { + } + OSL_ENSURE( xShape.is(), "BiffDrawingBase::createAndInsertXShape - cannot instanciate shape object" ); + return xShape; +} + +// protected ------------------------------------------------------------------ + +void BiffDrawingBase::appendRawObject( const BiffDrawingObjectRef& rxDrawingObj ) +{ + OSL_ENSURE( rxDrawingObj.get(), "BiffDrawingBase::appendRawObject - unexpected empty object reference" ); + maRawObjs.append( rxDrawingObj ); +} + +// ============================================================================ + +BiffSheetDrawing::BiffSheetDrawing( const WorksheetHelper& rHelper ) : + BiffDrawingBase( rHelper, rHelper.getDrawPage() ) +{ +} + +void BiffSheetDrawing::notifyShapeInserted( const Reference< XShape >& /*rxShape*/, const Rectangle& rShapeRect ) +{ + // collect all shape positions in the WorksheetHelper base class + extendShapeBoundingBox( rShapeRect ); +} + +// ============================================================================ + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/excelchartconverter.cxx b/oox/source/xls/excelchartconverter.cxx index 670139d26..10947e564 100644 --- a/oox/source/xls/excelchartconverter.cxx +++ b/oox/source/xls/excelchartconverter.cxx @@ -30,6 +30,7 @@ #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/chart2/data/XDataProvider.hpp> #include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include "oox/core/filterbase.hxx" #include "oox/drawingml/chart/datasourcemodel.hxx" #include "oox/helper/containerhelper.hxx" #include "oox/xls/formulaparser.hxx" @@ -64,8 +65,7 @@ void ExcelChartConverter::createDataProvider( const Reference< XChartDocument >& try { Reference< XDataReceiver > xDataRec( rxChartDoc, UNO_QUERY_THROW ); - Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); - Reference< XDataProvider > xDataProv( xFactory->createInstance( + Reference< XDataProvider > xDataProv( getBaseFilter().getModelFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.chart2.data.DataProvider" ) ), UNO_QUERY_THROW ); xDataRec->attachDataProvider( xDataProv ); } @@ -85,13 +85,12 @@ Reference< XDataSequence > ExcelChartConverter::createDataSequence( { // parse the formula string, create a token sequence FormulaParser& rParser = getFormulaParser(); - TokensFormulaContext aContext( true, true ); - aContext.setBaseAddress( CellAddress( getCurrentSheetIndex(), 0, 0 ) ); - rParser.importFormula( aContext, rDataSeq.maFormula ); + CellAddress aBaseAddr( getCurrentSheetIndex(), 0, 0 ); + ApiTokenSequence aTokens = rParser.importFormula( aBaseAddr, rDataSeq.maFormula ); // create a range list from the token sequence ApiCellRangeList aRanges; - rParser.extractCellRangeList( aRanges, aContext.getTokens(), false ); + rParser.extractCellRangeList( aRanges, aTokens, false ); aRangeRep = rParser.generateApiRangeListString( aRanges ); } else if( !rDataSeq.maData.empty() ) diff --git a/oox/source/xls/excelfilter.cxx b/oox/source/xls/excelfilter.cxx index 4dbf7884e..2dfb6f4cc 100644 --- a/oox/source/xls/excelfilter.cxx +++ b/oox/source/xls/excelfilter.cxx @@ -56,29 +56,29 @@ using ::oox::drawingml::table::TableStyleListPtr; // ============================================================================ ExcelFilterBase::ExcelFilterBase() : - mpData( 0 ) + mpBookGlob( 0 ) { } ExcelFilterBase::~ExcelFilterBase() { - OSL_ENSURE( !mpData, "ExcelFilterBase::~ExcelFilterBase - workbook data not cleared" ); + OSL_ENSURE( !mpBookGlob, "ExcelFilterBase::~ExcelFilterBase - workbook data not cleared" ); } -void ExcelFilterBase::registerWorkbookData( WorkbookData& rData ) +void ExcelFilterBase::registerWorkbookGlobals( WorkbookGlobals& rBookGlob ) { - mpData = &rData; + mpBookGlob = &rBookGlob; } -WorkbookData& ExcelFilterBase::getWorkbookData() const +WorkbookGlobals& ExcelFilterBase::getWorkbookGlobals() const { - OSL_ENSURE( mpData, "ExcelFilterBase::getWorkbookData - missing workbook data" ); - return *mpData; + OSL_ENSURE( mpBookGlob, "ExcelFilterBase::getWorkbookGlobals - missing workbook data" ); + return *mpBookGlob; } -void ExcelFilterBase::unregisterWorkbookData() +void ExcelFilterBase::unregisterWorkbookGlobals() { - mpData = 0; + mpBookGlob = 0; } // ============================================================================ @@ -124,9 +124,12 @@ bool ExcelFilter::importDocument() throw() OUString aWorkbookPath = getFragmentPathFromFirstType( CREATE_OFFICEDOC_RELATION_TYPE( "officeDocument" ) ); if( aWorkbookPath.getLength() == 0 ) return false; - - WorkbookHelperRoot aHelper( *this ); - return aHelper.isValid() && importFragment( new WorkbookFragment( aHelper, aWorkbookPath ) ); + + /* Construct the WorkbookGlobals object referred to by every instance of + the class WorkbookHelper, and execute the import filter by constructing + an instance of WorkbookFragment and loading the file. */ + WorkbookGlobalsRef xBookGlob = WorkbookHelper::constructGlobals( *this ); + return xBookGlob.get() && importFragment( new WorkbookFragment( *xBookGlob, aWorkbookPath ) ); } bool ExcelFilter::exportDocument() throw() @@ -136,7 +139,7 @@ bool ExcelFilter::exportDocument() throw() const ::oox::drawingml::Theme* ExcelFilter::getCurrentTheme() const { - return &WorkbookHelper( getWorkbookData() ).getTheme(); + return &WorkbookHelper( getWorkbookGlobals() ).getTheme(); } ::oox::vml::Drawing* ExcelFilter::getVmlDrawing() @@ -151,12 +154,12 @@ const TableStyleListPtr ExcelFilter::getTableStyles() ::oox::drawingml::chart::ChartConverter& ExcelFilter::getChartConverter() { - return WorkbookHelper( getWorkbookData() ).getChartConverter(); + return WorkbookHelper( getWorkbookGlobals() ).getChartConverter(); } GraphicHelper* ExcelFilter::implCreateGraphicHelper() const { - return new ExcelGraphicHelper( getWorkbookData() ); + return new ExcelGraphicHelper( getWorkbookGlobals() ); } ::oox::ole::VbaProject* ExcelFilter::implCreateVbaProject() const @@ -225,8 +228,11 @@ bool ExcelBiffFilter::importDocument() throw() if( eBiff == BIFF_UNKNOWN ) return false; - WorkbookHelperRoot aHelper( *this, eBiff ); - return aHelper.isValid() && BiffWorkbookFragment( aHelper, aWorkbookName ).importFragment(); + /* Construct the WorkbookGlobals object referred to by every instance of + the class WorkbookHelper, and execute the import filter by constructing + an instance of BiffWorkbookFragment and loading the file. */ + WorkbookGlobalsRef xBookGlob = WorkbookHelper::constructGlobals( *this, eBiff ); + return xBookGlob.get() && BiffWorkbookFragment( *xBookGlob, aWorkbookName ).importFragment(); } bool ExcelBiffFilter::exportDocument() throw() @@ -236,7 +242,7 @@ bool ExcelBiffFilter::exportDocument() throw() GraphicHelper* ExcelBiffFilter::implCreateGraphicHelper() const { - return new ExcelGraphicHelper( getWorkbookData() ); + return new ExcelGraphicHelper( getWorkbookGlobals() ); } ::oox::ole::VbaProject* ExcelBiffFilter::implCreateVbaProject() const @@ -289,11 +295,16 @@ bool ExcelVbaProjectFilter::importDocument() throw() if( !xVbaPrjStrg || !xVbaPrjStrg->isStorage() ) return false; - WorkbookHelperRoot aHelper( *this, eBiff ); + /* Construct the WorkbookGlobals object referred to by every instance of + the class WorkbookHelper. */ + WorkbookGlobalsRef xBookGlob = WorkbookHelper::constructGlobals( *this, eBiff ); + if( !xBookGlob.get() ) + return false; + // set palette colors passed in service constructor Any aPalette = getArgument( CREATE_OUSTRING( "ColorPalette" ) ); - aHelper.getStyles().importPalette( aPalette ); - // import the VBA project + WorkbookHelper( *xBookGlob ).getStyles().importPalette( aPalette ); + // import the VBA project (getVbaProject() implemented in base class) getVbaProject().importVbaProject( *xVbaPrjStrg, getGraphicHelper() ); return true; } diff --git a/oox/source/xls/excelhandlers.cxx b/oox/source/xls/excelhandlers.cxx index e82e0578b..1030659bf 100644 --- a/oox/source/xls/excelhandlers.cxx +++ b/oox/source/xls/excelhandlers.cxx @@ -51,17 +51,10 @@ WorkbookFragmentBase::WorkbookFragmentBase( // ============================================================================ -WorksheetFragmentBase::WorksheetFragmentBase( const WorkbookHelper& rHelper, - const OUString& rFragmentPath, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : - FragmentHandler2( rHelper.getOoxFilter(), rFragmentPath ), - WorksheetHelperRoot( rHelper, rxProgressBar, eSheetType, nSheet ) -{ -} - WorksheetFragmentBase::WorksheetFragmentBase( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : FragmentHandler2( rHelper.getOoxFilter(), rFragmentPath ), - WorksheetHelperRoot( rHelper ) + WorksheetHelper( rHelper ) { } @@ -81,14 +74,8 @@ BiffWorkbookContextBase::BiffWorkbookContextBase( const WorkbookHelper& rHelper // ---------------------------------------------------------------------------- -BiffWorksheetContextBase::BiffWorksheetContextBase( const WorkbookHelper& rHelper, - const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : - WorksheetHelperRoot( rHelper, rxProgressBar, eSheetType, nSheet ) -{ -} - BiffWorksheetContextBase::BiffWorksheetContextBase( const WorksheetHelper& rHelper ) : - WorksheetHelperRoot( rHelper ) + WorksheetHelper( rHelper ) { } @@ -103,17 +90,33 @@ const sal_uInt16 BIFF_BOF_CHART = 0x0020; /// BIFF2-BIFF8 chart sh const sal_uInt16 BIFF_BOF_MACRO = 0x0040; /// BIFF4-BIFF8 macro sheet. const sal_uInt16 BIFF_BOF_WORKSPACE = 0x0100; /// BIFF3-BIFF8 workspace. -BiffFragmentType lclStartFragment( BiffInputStream& rStrm, BiffType eBiff ) +} // namespace + +// ---------------------------------------------------------------------------- + +BiffFragmentHandler::BiffFragmentHandler( const FilterBase& rFilter, const OUString& rStrmName ) +{ + // do not automatically close the root stream (indicated by empty stream name) + bool bRootStrm = rStrmName.getLength() == 0; + mxXInStrm.reset( new BinaryXInputStream( rFilter.openInputStream( rStrmName ), !bRootStrm ) ); + mxBiffStrm.reset( new BiffInputStream( *mxXInStrm ) ); +} + +BiffFragmentHandler::~BiffFragmentHandler() +{ +} + +BiffFragmentType BiffFragmentHandler::startFragment( BiffType eBiff ) { BiffFragmentType eFragment = BIFF_FRAGMENT_UNKNOWN; /* #i23425# Don't rely on BOF record ID to read BOF contents, but on the detected BIFF version. */ - if( BiffHelper::isBofRecord( rStrm ) ) + if( mxBiffStrm->startNextRecord() && BiffHelper::isBofRecord( *mxBiffStrm ) ) { // BOF is always written unencrypted - rStrm.enableDecoder( false ); - rStrm.skip( 2 ); - sal_uInt16 nType = rStrm.readuInt16(); + mxBiffStrm->enableDecoder( false ); + mxBiffStrm->skip( 2 ); + sal_uInt16 nType = mxBiffStrm->readuInt16(); // decide which fragment types are valid for current BIFF version switch( eBiff ) @@ -166,32 +169,6 @@ BiffFragmentType lclStartFragment( BiffInputStream& rStrm, BiffType eBiff ) return eFragment; } -} // namespace - -// ---------------------------------------------------------------------------- - -BiffFragmentHandler::BiffFragmentHandler( const FilterBase& rFilter, const OUString& rStrmName ) -{ - // do not automatically close the root stream (indicated by empty stream name) - bool bRootStrm = rStrmName.getLength() == 0; - mxXInStrm.reset( new BinaryXInputStream( rFilter.openInputStream( rStrmName ), !bRootStrm ) ); - mxBiffStrm.reset( new BiffInputStream( *mxXInStrm ) ); -} - -BiffFragmentHandler::~BiffFragmentHandler() -{ -} - -BiffFragmentType BiffFragmentHandler::startFragment( BiffType eBiff ) -{ - return mxBiffStrm->startNextRecord() ? lclStartFragment( *mxBiffStrm, eBiff ) : BIFF_FRAGMENT_UNKNOWN; -} - -BiffFragmentType BiffFragmentHandler::startFragment( BiffType eBiff, sal_Int64 nRecHandle ) -{ - return mxBiffStrm->startRecordByHandle( nRecHandle ) ? lclStartFragment( *mxBiffStrm, eBiff ) : BIFF_FRAGMENT_UNKNOWN; -} - bool BiffFragmentHandler::skipFragment() { while( mxBiffStrm->startNextRecord() && (mxBiffStrm->getRecId() != BIFF_ID_EOF) ) @@ -200,7 +177,7 @@ bool BiffFragmentHandler::skipFragment() return !mxBiffStrm->isEof() && (mxBiffStrm->getRecId() == BIFF_ID_EOF); } -// ---------------------------------------------------------------------------- +// ============================================================================ BiffWorkbookFragmentBase::BiffWorkbookFragmentBase( const WorkbookHelper& rHelper, const OUString& rStrmName, bool bCloneDecoder ) : BiffFragmentHandler( rHelper.getBaseFilter(), rStrmName ), @@ -212,18 +189,16 @@ BiffWorkbookFragmentBase::BiffWorkbookFragmentBase( const WorkbookHelper& rHelpe // ---------------------------------------------------------------------------- -BiffWorksheetFragmentBase::BiffWorksheetFragmentBase( const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : +BiffWorksheetFragmentBase::BiffWorksheetFragmentBase( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) : BiffFragmentHandler( rParent ), - WorksheetHelperRoot( rParent, rxProgressBar, eSheetType, nSheet ) + WorksheetHelper( rHelper ) { } // ---------------------------------------------------------------------------- -BiffSkipWorksheetFragment::BiffSkipWorksheetFragment( const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, sal_Int16 nSheet ) : - BiffWorksheetFragmentBase( rParent, rxProgressBar, SHEETTYPE_EMPTYSHEET, nSheet ) +BiffSkipWorksheetFragment::BiffSkipWorksheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) : + BiffWorksheetFragmentBase( rHelper, rParent ) { } diff --git a/oox/source/xls/externallinkbuffer.cxx b/oox/source/xls/externallinkbuffer.cxx index b212c9b69..ee5e4fb72 100644 --- a/oox/source/xls/externallinkbuffer.cxx +++ b/oox/source/xls/externallinkbuffer.cxx @@ -242,9 +242,8 @@ void ExternalName::importExternalName( BiffInputStream& rStrm ) // cell references to other internal sheets are stored in hidden external names if( bHiddenRef && (getBiff() == BIFF4) && isWorkbookFile() ) { - TokensFormulaContext aContext( true, true ); - importBiffFormula( aContext, mrParentLink.getCalcSheetIndex(), rStrm ); - extractReference( aContext.getTokens() ); + ApiTokenSequence aTokens = importBiffFormula( mrParentLink.getCalcSheetIndex(), rStrm ); + extractReference( aTokens ); } break; @@ -252,9 +251,8 @@ void ExternalName::importExternalName( BiffInputStream& rStrm ) // cell references to other documents are stored in hidden external names if( bHiddenRef ) { - TokensFormulaContext aContext( true, true ); - importBiffFormula( aContext, 0, rStrm ); - extractExternalReference( aContext.getTokens() ); + ApiTokenSequence aTokens = importBiffFormula( 0, rStrm ); + extractExternalReference( aTokens ); } break; diff --git a/oox/source/xls/formulabase.cxx b/oox/source/xls/formulabase.cxx index 7349b7673..1439bdc80 100755 --- a/oox/source/xls/formulabase.cxx +++ b/oox/source/xls/formulabase.cxx @@ -39,7 +39,6 @@ #include <com/sun/star/sheet/FormulaMapGroupSpecialOffset.hpp> #include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp> #include <com/sun/star/sheet/XFormulaParser.hpp> -#include <com/sun/star/sheet/XFormulaTokens.hpp> #include <rtl/strbuf.hxx> #include <rtl/ustrbuf.hxx> #include "oox/core/filterbase.hxx" @@ -227,8 +226,10 @@ const sal_uInt16 FUNCFLAG_MACROCMD = 0x0080; /// Function is a macro- const sal_uInt16 FUNCFLAG_ALWAYSVAR = 0x0100; /// Function is always represented by a tFuncVar token. const sal_uInt16 FUNCFLAG_PARAMPAIRS = 0x0200; /// Optional parameters are expected to appear in pairs. -const sal_uInt16 FUNCFLAG_FUNCLIBMASK = 0xF000; /// Mask for function library bits. -const sal_uInt16 FUNCFLAG_EUROTOOL = 0x1000; /// Function is part of the EuroTool add-in. +/// Converts a function library index (value of enum FunctionLibraryType) to function flags. +#define FUNCLIB_TO_FUNCFLAGS( funclib_index ) static_cast< sal_uInt16 >( static_cast< sal_uInt8 >( funclib_index ) << 12 ) +/// Extracts a function library index (value of enum FunctionLibraryType) from function flags. +#define FUNCFLAGS_TO_FUNCLIB( func_flags ) extractValue< FunctionLibraryType >( func_flags, 12, 4 ) typedef ::boost::shared_ptr< FunctionInfo > FunctionInfoRef; @@ -298,7 +299,9 @@ static const FunctionData saFuncTableBiff2[] = { "DOLLAR", "DOLLAR", 13, 13, 1, 2, V, { VR }, 0 }, { "FIXED", "FIXED", 14, 14, 1, 2, V, { VR, VR, C }, 0 }, { "SIN", "SIN", 15, 15, 1, 1, V, { VR }, 0 }, + { "CSC", "SIN", 15, 15, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, { "COS", "COS", 16, 16, 1, 1, V, { VR }, 0 }, + { "SEC", "COS", 16, 16, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, { "TAN", "TAN", 17, 17, 1, 1, V, { VR }, 0 }, { "COT", "TAN", 17, 17, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, { "ATAN", "ATAN", 18, 18, 1, 1, V, { VR }, 0 }, @@ -458,7 +461,9 @@ static const FunctionData saFuncTableBiff3[] = { "MEDIAN", "MEDIAN", 227, 227, 1, MX, V, { RX }, 0 }, { "SUMPRODUCT", "SUMPRODUCT", 228, 228, 1, MX, V, { VA }, 0 }, { "SINH", "SINH", 229, 229, 1, 1, V, { VR }, 0 }, + { "CSCH", "SINH", 229, 229, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, { "COSH", "COSH", 230, 230, 1, 1, V, { VR }, 0 }, + { "SECH", "COSH", 230, 230, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, { "TANH", "TANH", 231, 231, 1, 1, V, { VR }, 0 }, { "COTH", "TANH", 231, 231, 1, 1, V, { VR }, FUNCFLAG_EXPORTONLY }, { "ASINH", "ASINH", 232, 232, 1, 1, V, { VR }, 0 }, @@ -674,7 +679,7 @@ static const FunctionData saFuncTableBiff5[] = // *** EuroTool add-in *** - { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { VR }, FUNCFLAG_EUROTOOL }, + { "EUROCONVERT", "EUROCONVERT", NOID, NOID, 3, 5, V, { VR }, FUNCLIB_TO_FUNCFLAGS( FUNCLIB_EUROTOOL ) }, // *** macro sheet commands *** @@ -911,12 +916,7 @@ void FunctionProviderImpl::initFunc( const FunctionData& rFuncData, sal_uInt8 nM xFuncInfo->maBiffMacroName = CREATE_OUSTRING( "_xlfnodf." ) + xFuncInfo->maOdfFuncName; } - switch( rFuncData.mnFlags & FUNCFLAG_FUNCLIBMASK ) - { - case FUNCFLAG_EUROTOOL: xFuncInfo->meFuncLibType = FUNCLIB_EUROTOOL; break; - default: xFuncInfo->meFuncLibType = FUNCLIB_UNKNOWN; - } - + xFuncInfo->meFuncLibType = FUNCFLAGS_TO_FUNCLIB( rFuncData.mnFlags ); xFuncInfo->mnApiOpCode = -1; xFuncInfo->mnBiff12FuncId = rFuncData.mnBiff12FuncId; xFuncInfo->mnBiffFuncId = rFuncData.mnBiffFuncId; @@ -1024,7 +1024,7 @@ struct OpCodeProviderImpl : public ApiOpCodes explicit OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos, - const Reference< XMultiServiceFactory >& rxFactory ); + const Reference< XMultiServiceFactory >& rxModelFactory ); private: typedef ::std::map< OUString, ApiToken > ApiTokenMap; @@ -1046,11 +1046,11 @@ private: // ---------------------------------------------------------------------------- OpCodeProviderImpl::OpCodeProviderImpl( const FunctionInfoVector& rFuncInfos, - const Reference< XMultiServiceFactory >& rxFactory ) + const Reference< XMultiServiceFactory >& rxModelFactory ) { - if( rxFactory.is() ) try + if( rxModelFactory.is() ) try { - Reference< XFormulaOpCodeMapper > xMapper( rxFactory->createInstance( + Reference< XFormulaOpCodeMapper > xMapper( rxModelFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaOpCodeMapper" ) ), UNO_QUERY_THROW ); // op-codes provided as attributes @@ -1296,10 +1296,10 @@ bool OpCodeProviderImpl::initFuncOpCodes( const ApiTokenMap& rIntFuncTokenMap, c // ---------------------------------------------------------------------------- -OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxFactory, +OpCodeProvider::OpCodeProvider( const Reference< XMultiServiceFactory >& rxModelFactory, FilterType eFilter, BiffType eBiff, bool bImportFilter ) : FunctionProvider( eFilter, eBiff, bImportFilter ), - mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxFactory ) ) + mxOpCodeImpl( new OpCodeProviderImpl( getFuncs(), rxModelFactory ) ) { } @@ -1334,12 +1334,12 @@ Sequence< FormulaOpCodeMapEntry > OpCodeProvider::getOoxParserMap() const // API formula parser wrapper ================================================= ApiParserWrapper::ApiParserWrapper( - const Reference< XMultiServiceFactory >& rxFactory, const OpCodeProvider& rOpCodeProv ) : + const Reference< XMultiServiceFactory >& rxModelFactory, const OpCodeProvider& rOpCodeProv ) : OpCodeProvider( rOpCodeProv ) { - if( rxFactory.is() ) try + if( rxModelFactory.is() ) try { - mxParser.set( rxFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW ); + mxParser.set( rxModelFactory->createInstance( CREATE_OUSTRING( "com.sun.star.sheet.FormulaParser" ) ), UNO_QUERY_THROW ); } catch( Exception& ) { @@ -1365,51 +1365,6 @@ ApiTokenSequence ApiParserWrapper::parseFormula( const OUString& rFormula, const return aTokenSeq; } -// formula contexts =========================================================== - -FormulaContext::FormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) : - maBaseAddress( 0, 0, 0 ), - mbRelativeAsOffset( bRelativeAsOffset ), - mb2dRefsAs3dRefs( b2dRefsAs3dRefs ), - mbAllowNulChars( bAllowNulChars ) -{ -} - -FormulaContext::~FormulaContext() -{ -} - -void FormulaContext::setSharedFormula( const CellAddress& ) -{ -} - -// ---------------------------------------------------------------------------- - -TokensFormulaContext::TokensFormulaContext( bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) : - FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs, bAllowNulChars ) -{ -} - -void TokensFormulaContext::setTokens( const ApiTokenSequence& rTokens ) -{ - maTokens = rTokens; -} - -// ---------------------------------------------------------------------------- - -SimpleFormulaContext::SimpleFormulaContext( const Reference< XFormulaTokens >& rxTokens, - bool bRelativeAsOffset, bool b2dRefsAs3dRefs, bool bAllowNulChars ) : - FormulaContext( bRelativeAsOffset, b2dRefsAs3dRefs, bAllowNulChars ), - mxTokens( rxTokens ) -{ - OSL_ENSURE( mxTokens.is(), "SimpleFormulaContext::SimpleFormulaContext - missing XFormulaTokens interface" ); -} - -void SimpleFormulaContext::setTokens( const ApiTokenSequence& rTokens ) -{ - mxTokens->setTokens( rTokens ); -} - // formula parser/printer base class for filters ============================== namespace { @@ -1482,7 +1437,7 @@ TokenToRangeListState lclProcessClose( sal_Int32& ornParenLevel ) // ---------------------------------------------------------------------------- FormulaProcessorBase::FormulaProcessorBase( const WorkbookHelper& rHelper ) : - OpCodeProvider( rHelper.getDocumentFactory(), rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ), + OpCodeProvider( rHelper.getBaseFilter().getModelFactory(), rHelper.getFilterType(), rHelper.getBiff(), rHelper.getBaseFilter().isImportFilter() ), ApiOpCodes( getOpCodes() ), WorkbookHelper( rHelper ) { @@ -1707,6 +1662,12 @@ bool FormulaProcessorBase::extractString( OUString& orString, const ApiTokenSequ return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_PUSH) && (aTokenIt->Data >>= orString) && !(++aTokenIt).is(); } +bool FormulaProcessorBase::extractSpecialTokenInfo( ApiSpecialTokenInfo& orTokenInfo, const ApiTokenSequence& rTokens ) const +{ + ApiTokenIterator aTokenIt( rTokens, OPCODE_SPACES, true ); + return aTokenIt.is() && (aTokenIt->OpCode == OPCODE_BAD) && (aTokenIt->Data >>= orTokenInfo); +} + void FormulaProcessorBase::convertStringToStringList( ApiTokenSequence& orTokens, sal_Unicode cStringSep, bool bTrimLeadingSpaces ) const { diff --git a/oox/source/xls/formulaparser.cxx b/oox/source/xls/formulaparser.cxx index 39bb8c3b9..7da4a9f9a 100644 --- a/oox/source/xls/formulaparser.cxx +++ b/oox/source/xls/formulaparser.cxx @@ -119,7 +119,6 @@ const FunctionInfo* FormulaFinalizer::getFunctionInfo( ApiToken& orFuncToken ) // no success - return null return 0; - } const FunctionInfo* FormulaFinalizer::getExternCallInfo( ApiToken& orFuncToken, const ApiToken& rECToken ) @@ -241,17 +240,29 @@ const ApiToken* FormulaFinalizer::processParameters( if( !aParamInfoIt.isExcelOnlyParam() ) { - // replace empty second and third parameter in IF function with zeros - if( (pRealFuncInfo->mnBiff12FuncId == BIFF_FUNC_IF) && ((nParam == 1) || (nParam == 2)) && bIsEmpty ) + // handle empty parameters + if( bIsEmpty ) { - maTokens.append< double >( OPCODE_PUSH, 0.0 ); - bIsEmpty = false; + // append leading space tokens from original token array + while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) ) + maTokens.push_back( *pParamBegin++ ); + // add default values for some empty parameters, or the OPCODE_MISSING token + appendEmptyParameter( *pRealFuncInfo, nParam ); + // reset bIsEmpty flag, if something has been appended in appendEmptyParameter() + bIsEmpty = maTokens.back().OpCode == OPCODE_MISSING; + // skip OPCODE_MISSING token in the original token array + OSL_ENSURE( (pParamBegin == pParamEnd) || (pParamBegin->OpCode == OPCODE_MISSING), "FormulaFinalizer::processParameters - OPCODE_MISSING expected" ); + if( pParamBegin < pParamEnd ) ++pParamBegin; + // append trailing space tokens from original token array + while( (pParamBegin < pParamEnd) && (pParamBegin->OpCode == OPCODE_SPACES) ) + maTokens.push_back( *pParamBegin++ ); } else { - // process all tokens of the parameter + // if parameter is not empty, process all tokens of the parameter processTokens( pParamBegin, pParamEnd ); } + // append parameter separator token maTokens.append( OPCODE_SEP ); } @@ -358,6 +369,25 @@ const ApiToken* FormulaFinalizer::findParameters( ParameterPosVector& rParams, return (pToken < pTokenEnd) ? (pToken + 1) : pTokenEnd; } +void FormulaFinalizer::appendEmptyParameter( const FunctionInfo& rFuncInfo, size_t nParam ) +{ + // remeber old size of the token array + size_t nTokenArraySize = maTokens.size(); + + switch( rFuncInfo.mnBiff12FuncId ) + { + case BIFF_FUNC_IF: + if( (nParam == 1) || (nParam == 2) ) + maTokens.append< double >( OPCODE_PUSH, 0.0 ); + break; + default:; + } + + // if no token has been added, append a OPCODE_MISSING token + if( nTokenArraySize == maTokens.size() ) + maTokens.append( OPCODE_MISSING ); +} + void FormulaFinalizer::appendCalcOnlyParameter( const FunctionInfo& rFuncInfo, size_t nParam ) { (void)nParam; // prevent 'unused' warning @@ -410,27 +440,23 @@ class FormulaParserImpl : public FormulaFinalizer, public WorkbookHelper public: explicit FormulaParserImpl( const FormulaParser& rParent ); - /** Converts an XML formula string. */ - virtual void importOoxFormula( - FormulaContext& rContext, + /** Converts an OOXML formula string. */ + virtual ApiTokenSequence importOoxFormula( + const CellAddress& rBaseAddress, const OUString& rFormulaString ); /** Imports and converts a BIFF12 token array from the passed stream. */ - virtual void importBiff12Formula( - FormulaContext& rContext, + virtual ApiTokenSequence importBiff12Formula( + const CellAddress& rBaseAddress, + FormulaType eType, SequenceInputStream& rStrm ); /** Imports and converts a BIFF2-BIFF8 token array from the passed stream. */ - virtual void importBiffFormula( - FormulaContext& rContext, + virtual ApiTokenSequence importBiffFormula( + const CellAddress& rBaseAddress, + FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ); - /** Finalizes the passed token array after import (e.g. adjusts function - parameters) and sets the formula using the passed context. */ - void setFormula( - FormulaContext& rContext, - const ApiTokenSequence& rTokens ); - /** Tries to resolve the passed ref-id to an OLE target URL. */ OUString resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const; @@ -438,18 +464,10 @@ protected: typedef ::std::pair< sal_Int32, bool > WhiteSpace; typedef ::std::vector< WhiteSpace > WhiteSpaceVec; - /** Sets the current formula context used for import. */ - inline FormulaContext& getFormulaContext() const { return *mpContext; } - - /** Sets the current formula context used for import. */ - void initializeImport( FormulaContext& rContext ); - /** Finalizes the passed token array after import. */ - void finalizeImport( const ApiTokenSequence& rTokens ); + /** Initializes the formula parser before importing a formula. */ + void initializeImport( const CellAddress& rBaseAddress, FormulaType eType ); /** Finalizes the internal token storage after import. */ - void finalizeImport(); - - /** Inserts a shared formula using the current formula context and passed base address. */ - void setSharedFormula( const BinAddress& rBaseAddr ); + ApiTokenSequence finalizeImport(); // token array ------------------------------------------------------------ @@ -512,6 +530,7 @@ protected: bool pushExternalFuncOperand( const FunctionInfo& rFuncInfo ); bool pushDdeLinkOperand( const OUString& rDdeServer, const OUString& rDdeTopic, const OUString& rDdeItem ); bool pushExternalNameOperand( const ExternalNameRef& rxExtName, const ExternalLink& rExtLink ); + bool pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable ); bool pushUnaryPreOperator( sal_Int32 nOpCode ); bool pushUnaryPostOperator( sal_Int32 nOpCode ); @@ -545,6 +564,12 @@ protected: const sal_Int32 mnMaxXlsCol; /// Maximum column index in imported document. const sal_Int32 mnMaxXlsRow; /// Maximum row index in imported document. + CellAddress maBaseAddr; /// Base address for relative references. + bool mbRelativeAsOffset; /// True = relative row/column index is (signed) offset, false = explicit index. + bool mb2dRefsAs3dRefs; /// True = convert all 2D references to 3D references in sheet specified by base address. + bool mbSpecialTokens; /// True = special handling for tExp and tTbl tokens, false = exit with error. + bool mbAllowNulChars; /// True = keep NUL characters in string tokens. + private: typedef ::std::vector< size_t > SizeTypeVector; @@ -554,7 +579,6 @@ private: WhiteSpaceVec maLeadingSpaces; /// List of whitespaces before next token. WhiteSpaceVec maOpeningSpaces; /// List of whitespaces before opening parenthesis. WhiteSpaceVec maClosingSpaces; /// List of whitespaces before closing parenthesis. - FormulaContext* mpContext; /// Current formula context. }; // ---------------------------------------------------------------------------- @@ -566,7 +590,9 @@ FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) : mnMaxApiRow( rParent.getAddressConverter().getMaxApiAddress().Row ), mnMaxXlsCol( rParent.getAddressConverter().getMaxXlsAddress().Column ), mnMaxXlsRow( rParent.getAddressConverter().getMaxXlsAddress().Row ), - mpContext( 0 ) + mbRelativeAsOffset( false ), + mb2dRefsAs3dRefs( false ), + mbAllowNulChars( false ) { // reserve enough space to make resize(), push_back() etc. cheap maTokenStorage.reserve( 0x2000 ); @@ -577,25 +603,22 @@ FormulaParserImpl::FormulaParserImpl( const FormulaParser& rParent ) : maClosingSpaces.reserve( 256 ); } -void FormulaParserImpl::importOoxFormula( FormulaContext&, const OUString& ) +ApiTokenSequence FormulaParserImpl::importOoxFormula( const CellAddress&, const OUString& ) { OSL_ENSURE( false, "FormulaParserImpl::importOoxFormula - not implemented" ); + return ApiTokenSequence(); } -void FormulaParserImpl::importBiff12Formula( FormulaContext&, SequenceInputStream& ) +ApiTokenSequence FormulaParserImpl::importBiff12Formula( const CellAddress&, FormulaType, SequenceInputStream& ) { OSL_ENSURE( false, "FormulaParserImpl::importBiff12Formula - not implemented" ); + return ApiTokenSequence(); } -void FormulaParserImpl::importBiffFormula( FormulaContext&, BiffInputStream&, const sal_uInt16* ) +ApiTokenSequence FormulaParserImpl::importBiffFormula( const CellAddress&, FormulaType, BiffInputStream&, const sal_uInt16* ) { OSL_ENSURE( false, "FormulaParserImpl::importBiffFormula - not implemented" ); -} - -void FormulaParserImpl::setFormula( FormulaContext& rContext, const ApiTokenSequence& rTokens ) -{ - initializeImport( rContext ); - finalizeImport( rTokens ); + return ApiTokenSequence(); } OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId, bool bUseRefSheets ) const @@ -607,22 +630,41 @@ OUString FormulaParserImpl::resolveOleTarget( sal_Int32 nRefId, bool bUseRefShee return OUString(); } -void FormulaParserImpl::initializeImport( FormulaContext& rContext ) +void FormulaParserImpl::initializeImport( const CellAddress& rBaseAddr, FormulaType eType ) { + maBaseAddr = rBaseAddr; + mbRelativeAsOffset = mb2dRefsAs3dRefs = mbSpecialTokens = mbAllowNulChars = false; + switch( eType ) + { + case FORMULATYPE_CELL: + mbSpecialTokens = true; + break; + case FORMULATYPE_ARRAY: + break; + case FORMULATYPE_SHAREDFORMULA: + mbRelativeAsOffset = true; + break; + case FORMULATYPE_CONDFORMAT: + mbRelativeAsOffset = true; + break; + case FORMULATYPE_VALIDATION: + mbRelativeAsOffset = true; + // enable NUL characters in BIFF import, string list is single tStr token with NUL separators + mbAllowNulChars = getFilterType() == FILTER_BIFF; + break; + case FORMULATYPE_DEFINEDNAME: + mbRelativeAsOffset = true; + // BIFF2-BIFF4: convert 2D referebces to absolute 3D references + mb2dRefsAs3dRefs = (getFilterType() == FILTER_BIFF) && (getBiff() <= BIFF4); + break; + } + maTokenStorage.clear(); maTokenIndexes.clear(); maOperandSizeStack.clear(); - mpContext = &rContext; -} - -void FormulaParserImpl::finalizeImport( const ApiTokenSequence& rTokens ) -{ - ApiTokenSequence aFinalTokens = finalizeTokenArray( rTokens ); - if( aFinalTokens.hasElements() ) - mpContext->setTokens( aFinalTokens ); } -void FormulaParserImpl::finalizeImport() +ApiTokenSequence FormulaParserImpl::finalizeImport() { ApiTokenSequence aTokens( static_cast< sal_Int32 >( maTokenIndexes.size() ) ); if( aTokens.hasElements() ) @@ -631,14 +673,7 @@ void FormulaParserImpl::finalizeImport() for( SizeTypeVector::const_iterator aIt = maTokenIndexes.begin(), aEnd = maTokenIndexes.end(); aIt != aEnd; ++aIt, ++pToken ) *pToken = maTokenStorage[ *aIt ]; } - finalizeImport( aTokens ); -} - -void FormulaParserImpl::setSharedFormula( const BinAddress& rBaseAddr ) -{ - CellAddress aApiBaseAddr; - if( getAddressConverter().convertToCellAddress( aApiBaseAddr, rBaseAddr, mpContext->getBaseAddress().Sheet, false ) ) - mpContext->setSharedFormula( aApiBaseAddr ); + return finalizeTokenArray( aTokens ); } // token array ---------------------------------------------------------------- @@ -988,7 +1023,7 @@ bool FormulaParserImpl::pushNlrOperand( const BinSingleRef2d& rRef ) bool FormulaParserImpl::pushEmbeddedRefOperand( const DefinedNameBase& rName, bool bPushBadToken ) { - Any aRefAny = rName.getReference( mpContext->getBaseAddress() ); + Any aRefAny = rName.getReference( maBaseAddr ); if( aRefAny.hasValue() ) return pushAnyOperand( aRefAny, OPCODE_PUSH ); if( bPushBadToken && (rName.getModelName().getLength() > 0) && (rName.getModelName()[ 0 ] >= ' ') ) @@ -1058,6 +1093,13 @@ bool FormulaParserImpl::pushExternalNameOperand( const ExternalNameRef& rxExtNam return pushBiffErrorOperand( BIFF_ERR_NAME ); } +bool FormulaParserImpl::pushSpecialTokenOperand( const BinAddress& rBaseAddr, bool bTable ) +{ + CellAddress aBaseAddr( maBaseAddr.Sheet, rBaseAddr.mnCol, rBaseAddr.mnRow ); + ApiSpecialTokenInfo aTokenInfo( aBaseAddr, bTable ); + return mbSpecialTokens && (getFormulaSize() == 0) && pushValueOperand( aTokenInfo, OPCODE_BAD ); +} + bool FormulaParserImpl::pushUnaryPreOperator( sal_Int32 nOpCode ) { return pushUnaryPreOperatorToken( nOpCode, &maLeadingSpaces ) && resetSpaces(); @@ -1092,15 +1134,15 @@ bool FormulaParserImpl::pushFunctionOperator( const FunctionInfo& rFuncInfo, siz void FormulaParserImpl::initReference2d( SingleReference& orApiRef ) const { - if( mpContext->is2dRefsAs3dRefs() ) + if( mb2dRefsAs3dRefs ) { - initReference3d( orApiRef, mpContext->getBaseAddress().Sheet, false ); + initReference3d( orApiRef, maBaseAddr.Sheet, false ); } else { orApiRef.Flags = SHEET_RELATIVE; // #i10184# absolute sheet index needed for relative references in shared formulas - orApiRef.Sheet = mpContext->getBaseAddress().Sheet; + orApiRef.Sheet = maBaseAddr.Sheet; orApiRef.RelativeSheet = 0; } } @@ -1145,9 +1187,9 @@ void FormulaParserImpl::convertReference( SingleReference& orApiRef, const BinSi if( !bRelativeAsOffset ) { if( rRef.mbColRel ) - orApiRef.RelativeColumn -= mpContext->getBaseAddress().Column; + orApiRef.RelativeColumn -= maBaseAddr.Column; if( rRef.mbRowRel ) - orApiRef.RelativeRow -= mpContext->getBaseAddress().Row; + orApiRef.RelativeRow -= maBaseAddr.Row; } } } @@ -1234,12 +1276,13 @@ class OoxFormulaParserImpl : public FormulaParserImpl public: explicit OoxFormulaParserImpl( const FormulaParser& rParent ); - virtual void importOoxFormula( - FormulaContext& rContext, + virtual ApiTokenSequence importOoxFormula( + const CellAddress& rBaseAddr, const OUString& rFormulaString ); - virtual void importBiff12Formula( - FormulaContext& rContext, + virtual ApiTokenSequence importBiff12Formula( + const CellAddress& rBaseAddr, + FormulaType eType, SequenceInputStream& rStrm ); private: @@ -1283,26 +1326,25 @@ private: OoxFormulaParserImpl::OoxFormulaParserImpl( const FormulaParser& rParent ) : FormulaParserImpl( rParent ), - maApiParser( rParent.getDocumentFactory(), rParent ), + maApiParser( rParent.getBaseFilter().getModelFactory(), rParent ), mnAddDataPos( 0 ), mbNeedExtRefs( true ) { } -void OoxFormulaParserImpl::importOoxFormula( FormulaContext& rContext, const OUString& rFormulaString ) +ApiTokenSequence OoxFormulaParserImpl::importOoxFormula( const CellAddress& rBaseAddr, const OUString& rFormulaString ) { if( mbNeedExtRefs ) { maApiParser.getParserProperties().setProperty( PROP_ExternalLinks, getExternalLinks().getLinkInfos() ); mbNeedExtRefs = false; } - initializeImport( rContext ); - finalizeImport( maApiParser.parseFormula( rFormulaString, rContext.getBaseAddress() ) ); + return finalizeTokenArray( maApiParser.parseFormula( rFormulaString, rBaseAddr ) ); } -void OoxFormulaParserImpl::importBiff12Formula( FormulaContext& rContext, SequenceInputStream& rStrm ) +ApiTokenSequence OoxFormulaParserImpl::importBiff12Formula( const CellAddress& rBaseAddr, FormulaType eType, SequenceInputStream& rStrm ) { - initializeImport( rContext ); + initializeImport( rBaseAddr, eType ); sal_Int32 nFmlaSize = rStrm.readInt32(); sal_Int64 nFmlaPos = rStrm.tell(); @@ -1315,7 +1357,7 @@ void OoxFormulaParserImpl::importBiff12Formula( FormulaContext& rContext, Sequen rStrm.seek( nFmlaPos ); bool bOk = (nFmlaSize >= 0) && (nAddDataSize >= 0); - bool bRelativeAsOffset = getFormulaContext().isRelativeAsOffset(); + bool bRelativeAsOffset = mbRelativeAsOffset; while( bOk && !rStrm.isEof() && (rStrm.tell() < nFmlaEndPos) ) { @@ -1392,12 +1434,16 @@ void OoxFormulaParserImpl::importBiff12Formula( FormulaContext& rContext, Sequen } // build and finalize the token sequence + ApiTokenSequence aFinalTokens; if( bOk && (rStrm.tell() == nFmlaEndPos) && (mnAddDataPos == nAddDataEndPos) ) - finalizeImport(); + aFinalTokens = finalizeImport(); // seek behind token array if( (nFmlaSize >= 0) && (nAddDataSize >= 0) ) rStrm.seek( nAddDataEndPos ); + + // return the final token sequence + return aFinalTokens; } // import token contents and create API formula token ------------------------- @@ -1541,7 +1587,7 @@ bool OoxFormulaParserImpl::importTableToken( SequenceInputStream& rStrm ) } else if( bThisRow ) { - nStartRow = nEndRow = getFormulaContext().getBaseAddress().Row - xTable->getRange().StartRow; + nStartRow = nEndRow = maBaseAddr.Row - xTable->getRange().StartRow; bFixedHeight = true; } else @@ -1720,9 +1766,7 @@ bool OoxFormulaParserImpl::importExpToken( SequenceInputStream& rStrm ) swapStreamPosition( rStrm ); rStrm >> aBaseAddr.mnCol; swapStreamPosition( rStrm ); - setSharedFormula( aBaseAddr ); - // formula has been set, exit parser by returning false - return false; + return pushSpecialTokenOperand( aBaseAddr, false ); } LinkSheetRange OoxFormulaParserImpl::readSheetRange( SequenceInputStream& rStrm ) @@ -1837,8 +1881,9 @@ class BiffFormulaParserImpl : public FormulaParserImpl public: explicit BiffFormulaParserImpl( const FormulaParser& rParent ); - virtual void importBiffFormula( - FormulaContext& rContext, + virtual ApiTokenSequence importBiffFormula( + const CellAddress& rBaseAddr, + FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ); private: @@ -1874,7 +1919,8 @@ private: bool importFuncVarToken2( BiffInputStream& rStrm ); bool importFuncVarToken4( BiffInputStream& rStrm ); bool importFuncCEToken( BiffInputStream& rStrm ); - bool importExpToken5( BiffInputStream& rStrm ); + bool importExpToken( BiffInputStream& rStrm ); + bool importTblToken( BiffInputStream& rStrm ); bool importNlrAddrToken( BiffInputStream& rStrm, bool bRow ); bool importNlrRangeToken( BiffInputStream& rStrm ); @@ -1923,7 +1969,6 @@ private: ImportTokenFunc mpImportFuncToken; /// Pointer to tFunc import function (function with fixed parameter count). ImportTokenFunc mpImportFuncVarToken; /// Pointer to tFuncVar import function (function with variable parameter count). ImportTokenFunc mpImportFuncCEToken; /// Pointer to tFuncCE import function (command macro call). - ImportTokenFunc mpImportExpToken; /// Pointer to tExp import function (array/shared formula). sal_Int64 mnAddDataPos; /// Current stream position for additional data (tArray, tMemArea, tNlr). sal_Int32 mnCurrRefId; /// Current ref-id from tSheet token (BIFF2-BIFF4 only). sal_uInt16 mnAttrDataSize; /// Size of one tAttr data element. @@ -1957,7 +2002,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2; mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2; mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken; - mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable; mnAttrDataSize = 1; mnArraySize = 6; mnNameSize = 5; @@ -1979,7 +2023,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken2; mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken2; mpImportFuncCEToken = &BiffFormulaParserImpl::importFuncCEToken; - mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable; mnAttrDataSize = 2; mnArraySize = 7; mnNameSize = 8; @@ -2001,7 +2044,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; - mpImportExpToken = &BiffFormulaParserImpl::importTokenNotAvailable; mnAttrDataSize = 2; mnArraySize = 7; mnNameSize = 8; @@ -2023,7 +2065,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; - mpImportExpToken = &BiffFormulaParserImpl::importExpToken5; mnAttrDataSize = 2; mnArraySize = 7; mnNameSize = 12; @@ -2045,7 +2086,6 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : mpImportFuncToken = &BiffFormulaParserImpl::importFuncToken4; mpImportFuncVarToken = &BiffFormulaParserImpl::importFuncVarToken4; mpImportFuncCEToken = &BiffFormulaParserImpl::importTokenNotAvailable; - mpImportExpToken = &BiffFormulaParserImpl::importExpToken5; mnAttrDataSize = 2; mnArraySize = 7; mnNameSize = 2; @@ -2057,15 +2097,14 @@ BiffFormulaParserImpl::BiffFormulaParserImpl( const FormulaParser& rParent ) : } } -void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext, - BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) +ApiTokenSequence BiffFormulaParserImpl::importBiffFormula( const CellAddress& rBaseAddr, + FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) { - initializeImport( rContext ); + initializeImport( rBaseAddr, eType ); mnCurrRefId = 0; sal_uInt16 nFmlaSize = lclReadFmlaSize( rStrm, getBiff(), pnFmlaSize ); sal_Int64 nEndPos = mnAddDataPos = rStrm.tell() + nFmlaSize; - bool bRelativeAsOffset = getFormulaContext().isRelativeAsOffset(); bool bOk = true; while( bOk && !rStrm.isEof() && (rStrm.tell() < nEndPos) ) @@ -2083,8 +2122,8 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext, // base tokens switch( nBaseId ) { - case BIFF_TOKID_EXP: bOk = (this->*mpImportExpToken)( rStrm ); break; - case BIFF_TOKID_TBL: bOk = false; /* multiple op. will be set externally */ break; + case BIFF_TOKID_EXP: bOk = importExpToken( rStrm ); break; + case BIFF_TOKID_TBL: bOk = importTblToken( rStrm ); break; case BIFF_TOKID_ADD: bOk = pushBinaryOperator( OPCODE_ADD ); break; case BIFF_TOKID_SUB: bOk = pushBinaryOperator( OPCODE_SUB ); break; case BIFF_TOKID_MUL: bOk = pushBinaryOperator( OPCODE_MULT ); break; @@ -2140,10 +2179,10 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext, case BIFF_TOKID_MEMNOMEMN: bOk = importMemFuncToken( rStrm ); break; case BIFF_TOKID_FUNCCE: bOk = (this->*mpImportFuncCEToken)( rStrm ); break; case BIFF_TOKID_NAMEX: bOk = (this->*mpImportNameXToken)( rStrm ); break; - case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, bRelativeAsOffset ); break; - case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, bRelativeAsOffset ); break; - case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, bRelativeAsOffset ); break; - case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, bRelativeAsOffset ); break; + case BIFF_TOKID_REF3D: bOk = (this->*mpImportRef3dToken)( rStrm, false, mbRelativeAsOffset ); break; + case BIFF_TOKID_AREA3D: bOk = (this->*mpImportArea3dToken)( rStrm, false, mbRelativeAsOffset ); break; + case BIFF_TOKID_REFERR3D: bOk = (this->*mpImportRef3dToken)( rStrm, true, mbRelativeAsOffset ); break; + case BIFF_TOKID_AREAERR3D: bOk = (this->*mpImportArea3dToken)( rStrm, true, mbRelativeAsOffset ); break; default: bOk = false; } } @@ -2151,11 +2190,15 @@ void BiffFormulaParserImpl::importBiffFormula( FormulaContext& rContext, } // build and finalize the token sequence + ApiTokenSequence aFinalTokens; if( bOk && (rStrm.tell() == nEndPos) ) - finalizeImport(); + aFinalTokens = finalizeImport(); // seek behind additional token data of tArray, tMemArea, tNlr tokens rStrm.seek( mnAddDataPos ); + + // return the final token sequence + return aFinalTokens; } // import token contents and create API formula token ------------------------- @@ -2174,13 +2217,13 @@ bool BiffFormulaParserImpl::importRefTokenNotAvailable( BiffInputStream&, bool, bool BiffFormulaParserImpl::importStrToken2( BiffInputStream& rStrm ) { - return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), getFormulaContext().isNulCharsAllowed() ) ); + return pushValueOperand( rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars ) ); } bool BiffFormulaParserImpl::importStrToken8( BiffInputStream& rStrm ) { // read flags field for empty strings also - return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), getFormulaContext().isNulCharsAllowed() ) ); + return pushValueOperand( rStrm.readUniStringBody( rStrm.readuInt8(), mbAllowNulChars ) ); } bool BiffFormulaParserImpl::importAttrToken( BiffInputStream& rStrm ) @@ -2310,7 +2353,6 @@ bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm ) size_t nOpSize = popOperandSize(); size_t nOldArraySize = getFormulaSize(); bool bBiff8 = getBiff() == BIFF8; - bool bNulChars = getFormulaContext().isNulCharsAllowed(); // read array size swapStreamPosition( rStrm ); @@ -2339,8 +2381,8 @@ bool BiffFormulaParserImpl::importArrayToken( BiffInputStream& rStrm ) break; case BIFF_DATATYPE_STRING: appendRawToken( OPCODE_PUSH ) <<= bBiff8 ? - rStrm.readUniString( bNulChars ) : - rStrm.readByteStringUC( false, getTextEncoding(), bNulChars ); + rStrm.readUniString( mbAllowNulChars ) : + rStrm.readByteStringUC( false, getTextEncoding(), mbAllowNulChars ); break; case BIFF_DATATYPE_BOOL: appendRawToken( OPCODE_PUSH ) <<= static_cast< double >( (rStrm.readuInt8() == BIFF_TOK_BOOL_FALSE) ? 0.0 : 1.0 ); @@ -2489,13 +2531,18 @@ bool BiffFormulaParserImpl::importFuncCEToken( BiffInputStream& rStrm ) return pushBiffFunction( nCmdId, nParamCount ); } -bool BiffFormulaParserImpl::importExpToken5( BiffInputStream& rStrm ) +bool BiffFormulaParserImpl::importExpToken( BiffInputStream& rStrm ) { BinAddress aBaseAddr; aBaseAddr.read( rStrm ); - setSharedFormula( aBaseAddr ); - // formula has been set, exit parser by returning false - return false; + return pushSpecialTokenOperand( aBaseAddr, false ); +} + +bool BiffFormulaParserImpl::importTblToken( BiffInputStream& rStrm ) +{ + BinAddress aBaseAddr; + aBaseAddr.read( rStrm ); + return pushSpecialTokenOperand( aBaseAddr, true ); } bool BiffFormulaParserImpl::importNlrAddrToken( BiffInputStream& rStrm, bool bRow ) @@ -2765,22 +2812,35 @@ FormulaParser::~FormulaParser() { } -void FormulaParser::importFormula( FormulaContext& rContext, const OUString& rFormulaString ) const +ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, const OUString& rFormulaString ) const { - mxImpl->importOoxFormula( rContext, rFormulaString ); + return mxImpl->importOoxFormula( rBaseAddress, rFormulaString ); } -void FormulaParser::importFormula( FormulaContext& rContext, SequenceInputStream& rStrm ) const +ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, SequenceInputStream& rStrm ) const { - mxImpl->importBiff12Formula( rContext, rStrm ); + return mxImpl->importBiff12Formula( rBaseAddress, eType, rStrm ); } -void FormulaParser::importFormula( FormulaContext& rContext, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const +ApiTokenSequence FormulaParser::importFormula( const CellAddress& rBaseAddress, FormulaType eType, BiffInputStream& rStrm, const sal_uInt16* pnFmlaSize ) const { - mxImpl->importBiffFormula( rContext, rStrm, pnFmlaSize ); + return mxImpl->importBiffFormula( rBaseAddress, eType, rStrm, pnFmlaSize ); +} + +ApiTokenSequence FormulaParser::convertBoolToFormula( bool bValue ) const +{ + if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( bValue ? BIFF_FUNC_TRUE : BIFF_FUNC_FALSE ) ) + { + ApiTokenSequence aTokens( 3 ); + aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode; + aTokens[ 1 ].OpCode = OPCODE_OPEN; + aTokens[ 2 ].OpCode = OPCODE_CLOSE; + return aTokens; + } + return ApiTokenSequence(); } -void FormulaParser::convertErrorToFormula( FormulaContext& rContext, sal_uInt8 nErrorCode ) const +ApiTokenSequence FormulaParser::convertErrorToFormula( sal_uInt8 nErrorCode ) const { ApiTokenSequence aTokens( 3 ); // HACK: enclose all error codes into an 1x1 matrix @@ -2788,26 +2848,24 @@ void FormulaParser::convertErrorToFormula( FormulaContext& rContext, sal_uInt8 n aTokens[ 1 ].OpCode = OPCODE_PUSH; aTokens[ 1 ].Data <<= BiffHelper::calcDoubleFromError( nErrorCode ); aTokens[ 2 ].OpCode = OPCODE_ARRAY_CLOSE; - mxImpl->setFormula( rContext, aTokens ); + return aTokens; } -void FormulaParser::convertNameToFormula( FormulaContext& rContext, sal_Int32 nTokenIndex ) const +ApiTokenSequence FormulaParser::convertNameToFormula( sal_Int32 nTokenIndex ) const { - if( nTokenIndex >= 0 ) - { - ApiTokenSequence aTokens( 1 ); - aTokens[ 0 ].OpCode = OPCODE_NAME; - aTokens[ 0 ].Data <<= nTokenIndex; - mxImpl->setFormula( rContext, aTokens ); - } - else - convertErrorToFormula( rContext, BIFF_ERR_REF ); + if( nTokenIndex < 0 ) + return convertErrorToFormula( BIFF_ERR_REF ); + + ApiTokenSequence aTokens( 1 ); + aTokens[ 0 ].OpCode = OPCODE_NAME; + aTokens[ 0 ].Data <<= nTokenIndex; + return aTokens; } -void FormulaParser::convertNumberToHyperlink( FormulaContext& rContext, const OUString& rUrl, double fValue ) const +ApiTokenSequence FormulaParser::convertNumberToHyperlink( const OUString& rUrl, double fValue ) const { OSL_ENSURE( rUrl.getLength() > 0, "FormulaParser::convertNumberToHyperlink - missing URL" ); - if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiff12FuncId( BIFF_FUNC_HYPERLINK ) ) + if( const FunctionInfo* pFuncInfo = getFuncInfoFromBiffFuncId( BIFF_FUNC_HYPERLINK ) ) { ApiTokenSequence aTokens( 6 ); aTokens[ 0 ].OpCode = pFuncInfo->mnApiOpCode; @@ -2818,8 +2876,9 @@ void FormulaParser::convertNumberToHyperlink( FormulaContext& rContext, const OU aTokens[ 4 ].OpCode = OPCODE_PUSH; aTokens[ 4 ].Data <<= fValue; aTokens[ 5 ].OpCode = OPCODE_CLOSE; - mxImpl->setFormula( rContext, aTokens ); + return aTokens; } + return ApiTokenSequence(); } OUString FormulaParser::importOleTargetLink( const OUString& rFormulaString ) diff --git a/oox/source/xls/makefile.mk b/oox/source/xls/makefile.mk index 6ca6e6a27..bcd539a70 100644..100755 --- a/oox/source/xls/makefile.mk +++ b/oox/source/xls/makefile.mk @@ -57,7 +57,9 @@ SLOFILES = \ $(SLO)$/connectionsbuffer.obj \ $(SLO)$/connectionsfragment.obj \ $(SLO)$/defnamesbuffer.obj \ + $(SLO)$/drawingbase.obj \ $(SLO)$/drawingfragment.obj \ + $(SLO)$/drawingmanager.obj \ $(SLO)$/excelchartconverter.obj \ $(SLO)$/excelfilter.obj \ $(SLO)$/excelhandlers.obj \ @@ -79,9 +81,9 @@ SLOFILES = \ $(SLO)$/richstringcontext.obj \ $(SLO)$/scenariobuffer.obj \ $(SLO)$/scenariocontext.obj \ - $(SLO)$/sharedformulabuffer.obj \ $(SLO)$/sharedstringsbuffer.obj \ $(SLO)$/sharedstringsfragment.obj \ + $(SLO)$/sheetdatabuffer.obj \ $(SLO)$/sheetdatacontext.obj \ $(SLO)$/stylesbuffer.obj \ $(SLO)$/stylesfragment.obj \ diff --git a/oox/source/xls/numberformatsbuffer.cxx b/oox/source/xls/numberformatsbuffer.cxx index 2b72f4a97..b971b9004 100644 --- a/oox/source/xls/numberformatsbuffer.cxx +++ b/oox/source/xls/numberformatsbuffer.cxx @@ -1950,7 +1950,7 @@ NumberFormatsBuffer::NumberFormatsBuffer( const WorkbookHelper& rHelper ) : // get the current locale try { - Reference< XMultiServiceFactory > xConfigProv( getGlobalFactory()->createInstance( + Reference< XMultiServiceFactory > xConfigProv( getBaseFilter().getServiceFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.configuration.ConfigurationProvider" ) ), UNO_QUERY_THROW ); // try user-defined locale setting diff --git a/oox/source/xls/ooxformulaparser.cxx b/oox/source/xls/ooxformulaparser.cxx index b2c5bea84..ea54be315 100644 --- a/oox/source/xls/ooxformulaparser.cxx +++ b/oox/source/xls/ooxformulaparser.cxx @@ -47,7 +47,7 @@ using ::rtl::OUString; class OOXMLFormulaParserImpl : private FormulaFinalizer { public: - explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxFactory ); + explicit OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ); Sequence< FormulaToken > parseFormula( const OUString& rFormula, const CellAddress& rReferencePos ); @@ -60,9 +60,9 @@ private: // ---------------------------------------------------------------------------- -OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxFactory ) : - FormulaFinalizer( OpCodeProvider( rxFactory, FILTER_OOXML, BIFF_UNKNOWN, true ) ), - maApiParser( rxFactory, *this ) +OOXMLFormulaParserImpl::OOXMLFormulaParserImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) : + FormulaFinalizer( OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, true ) ), + maApiParser( rxModelFactory, *this ) { } @@ -115,7 +115,7 @@ const FunctionInfo* OOXMLFormulaParserImpl::resolveBadFuncName( const OUString& class OOXMLFormulaPrinterImpl : public OpCodeProvider { public: - explicit OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxFactory ); + explicit OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory ); private: ApiParserWrapper maApiParser; @@ -123,9 +123,9 @@ private: // ---------------------------------------------------------------------------- -OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxFactory ) : - OpCodeProvider( rxFactory, FILTER_OOXML, BIFF_UNKNOWN, false ), - maApiParser( rxFactory, *this ) +OOXMLFormulaPrinterImpl::OOXMLFormulaPrinterImpl( const Reference< XMultiServiceFactory >& rxModelFactory ) : + OpCodeProvider( rxModelFactory, FILTER_OOXML, BIFF_UNKNOWN, false ), + maApiParser( rxModelFactory, *this ) { } @@ -202,8 +202,8 @@ Sequence< FormulaToken > SAL_CALL OOXMLFormulaParser::parseFormula( { if( !mxParserImpl ) { - Reference< XMultiServiceFactory > xFactory( mxComponent, UNO_QUERY_THROW ); - mxParserImpl.reset( new OOXMLFormulaParserImpl( xFactory ) ); + Reference< XMultiServiceFactory > xModelFactory( mxComponent, UNO_QUERY_THROW ); + mxParserImpl.reset( new OOXMLFormulaParserImpl( xModelFactory ) ); } return mxParserImpl->parseFormula( rFormula, rReferencePos ); } diff --git a/oox/source/xls/pagesettings.cxx b/oox/source/xls/pagesettings.cxx index f878eb26a..cc8cfcd59 100644 --- a/oox/source/xls/pagesettings.cxx +++ b/oox/source/xls/pagesettings.cxx @@ -903,8 +903,7 @@ Reference< XTextContent > HeaderFooterParser::createField( const OUString& rServ Reference< XTextContent > xContent; try { - Reference< XMultiServiceFactory > xFactory( getDocument(), UNO_QUERY_THROW ); - xContent.set( xFactory->createInstance( rServiceName ), UNO_QUERY_THROW ); + xContent.set( getBaseFilter().getModelFactory()->createInstance( rServiceName ), UNO_QUERY_THROW ); } catch( Exception& ) { diff --git a/oox/source/xls/pivotcachebuffer.cxx b/oox/source/xls/pivotcachebuffer.cxx index f5d7559dc..7b2a37300 100644 --- a/oox/source/xls/pivotcachebuffer.cxx +++ b/oox/source/xls/pivotcachebuffer.cxx @@ -34,7 +34,6 @@ #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> #include <com/sun/star/sheet/DataPilotFieldGroupInfo.hpp> #include <com/sun/star/sheet/XDataPilotFieldGrouping.hpp> -#include <com/sun/star/table/XCell.hpp> #include <rtl/ustrbuf.hxx> #include "oox/core/filterbase.hxx" #include "oox/helper/attributelist.hxx" @@ -44,6 +43,7 @@ #include "oox/xls/defnamesbuffer.hxx" #include "oox/xls/excelhandlers.hxx" #include "oox/xls/pivotcachefragment.hxx" +#include "oox/xls/sheetdatabuffer.hxx" #include "oox/xls/tablebuffer.hxx" #include "oox/xls/unitconverter.hxx" #include "oox/xls/worksheetbuffer.hxx" @@ -737,7 +737,7 @@ void PivotCacheField::importPCDFRangePr( BiffInputStream& rStrm ) void PivotCacheField::importPCDFDiscretePr( BiffInputStream& rStrm ) { - sal_Int32 nCount = static_cast< sal_Int32 >( rStrm.getLength() / 2 ); + sal_Int32 nCount = static_cast< sal_Int32 >( rStrm.size() / 2 ); for( sal_Int32 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex ) maDiscreteItems.push_back( rStrm.readuInt16() ); } @@ -936,7 +936,9 @@ OUString PivotCacheField::createParentGroupField( const Reference< XDataPilotFie void PivotCacheField::writeSourceHeaderCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow ) const { - rSheetHelper.setStringCell( rSheetHelper.getCell( CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow ) ), maFieldModel.maName ); + CellModel aModel; + aModel.maCellAddr = CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow ); + rSheetHelper.getSheetData().setStringCell( aModel, maFieldModel.maName ); } void PivotCacheField::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ) const @@ -982,15 +984,17 @@ void PivotCacheField::writeItemToSourceDataCell( WorksheetHelper& rSheetHelper, { if( rItem.getType() != XML_m ) { - Reference< XCell > xCell = rSheetHelper.getCell( CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow ) ); - if( xCell.is() ) switch( rItem.getType() ) + CellModel aModel; + aModel.maCellAddr = CellAddress( rSheetHelper.getSheetIndex(), nCol, nRow ); + SheetDataBuffer& rSheetData = rSheetHelper.getSheetData(); + switch( rItem.getType() ) { - case XML_s: rSheetHelper.setStringCell( xCell, rItem.getValue().get< OUString >() ); break; - case XML_n: xCell->setValue( rItem.getValue().get< double >() ); break; - case XML_i: xCell->setValue( rItem.getValue().get< sal_Int16 >() ); break; - case XML_d: rSheetHelper.setDateTimeCell( xCell, rItem.getValue().get< DateTime >() ); break; - case XML_b: rSheetHelper.setBooleanCell( xCell, rItem.getValue().get< bool >() ); break; - case XML_e: rSheetHelper.setErrorCell( xCell, static_cast< sal_uInt8 >( rItem.getValue().get< sal_Int32 >() ) ); break; + case XML_s: rSheetData.setStringCell( aModel, rItem.getValue().get< OUString >() ); break; + case XML_n: rSheetData.setValueCell( aModel, rItem.getValue().get< double >() ); break; + case XML_i: rSheetData.setValueCell( aModel, rItem.getValue().get< sal_Int16 >() ); break; + case XML_d: rSheetData.setDateTimeCell( aModel, rItem.getValue().get< DateTime >() ); break; + case XML_b: rSheetData.setBooleanCell( aModel, rItem.getValue().get< bool >() ); break; + case XML_e: rSheetData.setErrorCell( aModel, static_cast< sal_uInt8 >( rItem.getValue().get< sal_Int32 >() ) ); break; default: OSL_ENSURE( false, "PivotCacheField::writeItemToSourceDataCell - unexpected item data type" ); } } @@ -1042,6 +1046,7 @@ PCWorksheetSourceModel::PCWorksheetSourceModel() PivotCache::PivotCache( const WorkbookHelper& rHelper ) : WorkbookHelper( rHelper ), + mnCurrRow( -1 ), mbValidSource( false ), mbDummySheet( false ) { @@ -1274,34 +1279,39 @@ void PivotCache::writeSourceHeaderCells( WorksheetHelper& rSheetHelper ) const sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn; sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column; sal_Int32 nRow = maSheetSrcModel.maRange.StartRow; + mnCurrRow = -1; + updateSourceDataRow( rSheetHelper, nRow ); for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol ) (*aIt)->writeSourceHeaderCell( rSheetHelper, nCol, nRow ); } -void PivotCache::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nCol, sal_Int32 nRow, const PivotCacheItem& rItem ) const +void PivotCache::writeSourceDataCell( WorksheetHelper& rSheetHelper, sal_Int32 nColIdx, sal_Int32 nRowIdx, const PivotCacheItem& rItem ) const { - OSL_ENSURE( (0 <= nCol) && (nCol <= maSheetSrcModel.maRange.EndColumn - maSheetSrcModel.maRange.StartColumn), "PivotCache::writeSourceDataCell - invalid column index" ); - OSL_ENSURE( (0 < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow - maSheetSrcModel.maRange.StartRow), "PivotCache::writeSourceDataCell - invalid row index" ); - if( const PivotCacheField* pCacheField = maDatabaseFields.get( nCol ).get() ) - pCacheField->writeSourceDataCell( rSheetHelper, maSheetSrcModel.maRange.StartColumn + nCol, maSheetSrcModel.maRange.StartRow + nRow, rItem ); + sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn + nColIdx; + OSL_ENSURE( (maSheetSrcModel.maRange.StartColumn <= nCol) && (nCol <= maSheetSrcModel.maRange.EndColumn), "PivotCache::writeSourceDataCell - invalid column index" ); + sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx; + OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::writeSourceDataCell - invalid row index" ); + updateSourceDataRow( rSheetHelper, nRow ); + if( const PivotCacheField* pCacheField = maDatabaseFields.get( nColIdx ).get() ) + pCacheField->writeSourceDataCell( rSheetHelper, nCol, nRow, rItem ); } -void PivotCache::importPCRecord( SequenceInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const +void PivotCache::importPCRecord( SequenceInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const { - OSL_ENSURE( (0 < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow - maSheetSrcModel.maRange.StartRow), "PivotCache::importPCRecord - invalid row index" ); + sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx; + OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::importPCRecord - invalid row index" ); sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn; sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column; - nRow += maSheetSrcModel.maRange.StartRow; for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); !rStrm.isEof() && (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol ) (*aIt)->importPCRecordItem( rStrm, rSheetHelper, nCol, nRow ); } -void PivotCache::importPCItemIndexList( BiffInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const +void PivotCache::importPCItemIndexList( BiffInputStream& rStrm, WorksheetHelper& rSheetHelper, sal_Int32 nRowIdx ) const { - OSL_ENSURE( (0 < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow - maSheetSrcModel.maRange.StartRow), "PivotCache::importPCItemIndexList - invalid row index" ); + sal_Int32 nRow = maSheetSrcModel.maRange.StartRow + nRowIdx; + OSL_ENSURE( (maSheetSrcModel.maRange.StartRow < nRow) && (nRow <= maSheetSrcModel.maRange.EndRow), "PivotCache::importPCItemIndexList - invalid row index" ); sal_Int32 nCol = maSheetSrcModel.maRange.StartColumn; sal_Int32 nMaxCol = getAddressConverter().getMaxApiAddress().Column; - nRow += maSheetSrcModel.maRange.StartRow; for( PivotCacheFieldVector::const_iterator aIt = maDatabaseFields.begin(), aEnd = maDatabaseFields.end(); !rStrm.isEof() && (aIt != aEnd) && (nCol <= nMaxCol); ++aIt, ++nCol ) if( (*aIt)->hasSharedItems() ) (*aIt)->importPCItemIndex( rStrm, rSheetHelper, nCol, nRow ); @@ -1415,17 +1425,28 @@ void PivotCache::finalizeExternalSheetSource() void PivotCache::prepareSourceDataSheet() { + CellRangeAddress& rRange = maSheetSrcModel.maRange; // data will be inserted in top-left cell, sheet index is still set to 0 (will be set below) - maSheetSrcModel.maRange.EndColumn -= maSheetSrcModel.maRange.StartColumn; - maSheetSrcModel.maRange.StartColumn = 0; - maSheetSrcModel.maRange.EndRow -= maSheetSrcModel.maRange.StartRow; - maSheetSrcModel.maRange.StartRow = 0; + rRange.EndColumn -= rRange.StartColumn; + rRange.StartColumn = 0; + rRange.EndRow -= rRange.StartRow; + rRange.StartRow = 0; // check range location, do not allow ranges that overflow the sheet partly - if( getAddressConverter().checkCellRange( maSheetSrcModel.maRange, false, true ) ) + if( getAddressConverter().checkCellRange( rRange, false, true ) ) { + maColSpans.insert( ValueRange( rRange.StartColumn, rRange.EndColumn ) ); OUString aSheetName = CREATE_OUSTRING( "DPCache_" ) + maSheetSrcModel.maSheet; - maSheetSrcModel.maRange.Sheet = getWorksheets().insertEmptySheet( aSheetName, false ); - mbValidSource = mbDummySheet = maSheetSrcModel.maRange.Sheet >= 0; + rRange.Sheet = getWorksheets().insertEmptySheet( aSheetName, false ); + mbValidSource = mbDummySheet = rRange.Sheet >= 0; + } +} + +void PivotCache::updateSourceDataRow( WorksheetHelper& rSheetHelper, sal_Int32 nRow ) const +{ + if( mnCurrRow != nRow ) + { + rSheetHelper.getSheetData().setColSpans( nRow, maColSpans ); + mnCurrRow = nRow; } } diff --git a/oox/source/xls/pivotcachefragment.cxx b/oox/source/xls/pivotcachefragment.cxx index 3ec829f76..35ad3144f 100644 --- a/oox/source/xls/pivotcachefragment.cxx +++ b/oox/source/xls/pivotcachefragment.cxx @@ -208,18 +208,23 @@ void PivotCacheDefinitionFragment::finalizeImport() { OUString aRecFragmentPath = getRelations().getFragmentPathFromRelId( mrPivotCache.getRecordsRelId() ); if( aRecFragmentPath.getLength() > 0 ) - importOoxFragment( new PivotCacheRecordsFragment( *this, aRecFragmentPath, mrPivotCache ) ); + { + sal_Int16 nSheet = mrPivotCache.getSourceRange().Sheet; + WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, nSheet ); + if( xSheetGlob.get() ) + importOoxFragment( new PivotCacheRecordsFragment( *xSheetGlob, aRecFragmentPath, mrPivotCache ) ); + } } } // ============================================================================ -PivotCacheRecordsFragment::PivotCacheRecordsFragment( const WorkbookHelper& rHelper, +PivotCacheRecordsFragment::PivotCacheRecordsFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath, const PivotCache& rPivotCache ) : - WorksheetFragmentBase( rHelper, rFragmentPath, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, rPivotCache.getSourceRange().Sheet ), + WorksheetFragmentBase( rHelper, rFragmentPath ), mrPivotCache( rPivotCache ), - mnCol( 0 ), - mnRow( 0 ), + mnColIdx( 0 ), + mnRowIdx( 0 ), mbInRecord( false ) { // prepare sheet: insert column header names into top row @@ -252,8 +257,8 @@ ContextHandlerRef PivotCacheRecordsFragment::onCreateContext( sal_Int32 nElement case XLS_TOKEN( x ): aItem.readIndex( rAttribs ); break; default: OSL_ENSURE( false, "PivotCacheRecordsFragment::onCreateContext - unexpected element" ); } - mrPivotCache.writeSourceDataCell( *this, mnCol, mnRow, aItem ); - ++mnCol; + mrPivotCache.writeSourceDataCell( *this, mnColIdx, mnRowIdx, aItem ); + ++mnColIdx; } break; } @@ -294,15 +299,15 @@ const RecordInfo* PivotCacheRecordsFragment::getRecordInfos() const void PivotCacheRecordsFragment::startCacheRecord() { - mnCol = 0; - ++mnRow; + mnColIdx = 0; + ++mnRowIdx; mbInRecord = true; } void PivotCacheRecordsFragment::importPCRecord( SequenceInputStream& rStrm ) { startCacheRecord(); - mrPivotCache.importPCRecord( rStrm, *this, mnRow ); + mrPivotCache.importPCRecord( rStrm, *this, mnRowIdx ); mbInRecord = false; } @@ -322,8 +327,8 @@ void PivotCacheRecordsFragment::importPCRecordItem( sal_Int32 nRecId, SequenceIn case BIFF12_ID_PCITEM_INDEX: aItem.readIndex( rStrm ); break; default: OSL_ENSURE( false, "PivotCacheRecordsFragment::importPCRecordItem - unexpected record" ); } - mrPivotCache.writeSourceDataCell( *this, mnCol, mnRow, aItem ); - ++mnCol; + mrPivotCache.writeSourceDataCell( *this, mnColIdx, mnRowIdx, aItem ); + ++mnColIdx; } } @@ -373,10 +378,14 @@ bool BiffPivotCacheFragment::importFragment() { /* Last call of lclSeekToPCDField() failed and kept stream position unchanged. Stream should point to source data table now. */ - BiffPivotCacheRecordsContext aContext( *this, mrPivotCache ); - if( aContext.isValidSheet() ) + sal_Int16 nSheet = mrPivotCache.getSourceRange().Sheet; + WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, nSheet ); + if( xSheetGlob.get() ) + { + BiffPivotCacheRecordsContext aContext( *xSheetGlob, mrPivotCache ); while( rStrm.startNextRecord() && (rStrm.getRecId() != BIFF_ID_EOF) ) aContext.importRecord( rStrm ); + } } } @@ -385,11 +394,11 @@ bool BiffPivotCacheFragment::importFragment() // ============================================================================ -BiffPivotCacheRecordsContext::BiffPivotCacheRecordsContext( const WorkbookHelper& rHelper, const PivotCache& rPivotCache ) : - BiffWorksheetContextBase( rHelper, ISegmentProgressBarRef(), SHEETTYPE_WORKSHEET, rPivotCache.getSourceRange().Sheet ), +BiffPivotCacheRecordsContext::BiffPivotCacheRecordsContext( const WorksheetHelper& rHelper, const PivotCache& rPivotCache ) : + BiffWorksheetContextBase( rHelper ), mrPivotCache( rPivotCache ), mnColIdx( 0 ), - mnRow( 0 ), + mnRowIdx( 0 ), mbHasShared( false ), mbInRow( false ) { @@ -418,7 +427,7 @@ void BiffPivotCacheRecordsContext::importRecord( BiffInputStream& rStrm ) OSL_ENSURE( mbHasShared, "BiffPivotCacheRecordsContext::importRecord - unexpected PCITEM_INDEXLIST record" ); // PCITEM_INDEXLIST record always in front of a new data row startNextRow(); - mrPivotCache.importPCItemIndexList( rStrm, *this, mnRow ); + mrPivotCache.importPCItemIndexList( rStrm, *this, mnRowIdx ); mbInRow = !maUnsharedCols.empty(); // mbInRow remains true, if unshared items are expected return; } @@ -449,14 +458,14 @@ void BiffPivotCacheRecordsContext::importRecord( BiffInputStream& rStrm ) // write the item data to the sheet cell OSL_ENSURE( mnColIdx < maUnsharedCols.size(), "BiffPivotCacheRecordsContext::importRecord - invalid column index" ); if( mnColIdx < maUnsharedCols.size() ) - mrPivotCache.writeSourceDataCell( *this, maUnsharedCols[ mnColIdx ], mnRow, aItem ); + mrPivotCache.writeSourceDataCell( *this, maUnsharedCols[ mnColIdx ], mnRowIdx, aItem ); ++mnColIdx; } void BiffPivotCacheRecordsContext::startNextRow() { mnColIdx = 0; - ++mnRow; + ++mnRowIdx; mbInRow = true; } diff --git a/oox/source/xls/richstring.cxx b/oox/source/xls/richstring.cxx index 049aa85e2..05b7ddbc5 100644 --- a/oox/source/xls/richstring.cxx +++ b/oox/source/xls/richstring.cxx @@ -52,6 +52,11 @@ namespace { const sal_uInt8 BIFF12_STRINGFLAG_FONTS = 0x01; const sal_uInt8 BIFF12_STRINGFLAG_PHONETICS = 0x02; +inline bool lclNeedsRichTextFormat( const Font* pFont ) +{ + return pFont && pFont->needsRichTextFormat(); +} + } // namespace // ============================================================================ @@ -86,18 +91,27 @@ void RichStringPortion::finalizeImport() mxFont = getStyles().getFont( mnFontId ); } -void RichStringPortion::convert( const Reference< XText >& rxText, sal_Int32 nXfId ) +void RichStringPortion::convert( const Reference< XText >& rxText, const Font* pFont, bool bReplace ) { - Reference< XTextRange > xRange = rxText->getEnd(); - xRange->setString( maText ); - if( mxFont.get() ) - { - PropertySet aPropSet( xRange ); - mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT ); - } - if( const Font* pFont = getStyles().getFontFromCellXf( nXfId ).get() ) + Reference< XTextRange > xRange; + if( bReplace ) + xRange.set( rxText, UNO_QUERY ); + else + xRange = rxText->getEnd(); + OSL_ENSURE( xRange.is(), "RichStringPortion::convert - cannot get text range interface" ); + + if( xRange.is() ) { - if( pFont->needsRichTextFormat() ) + xRange->setString( maText ); + if( mxFont.get() ) + { + PropertySet aPropSet( xRange ); + mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT ); + } + + /* Some font attributes cannot be set to cell formattiing in Calc but + require to use rich formatting, e.g. font escapement. */ + if( lclNeedsRichTextFormat( pFont ) ) { PropertySet aPropSet( xRange ); pFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT ); @@ -391,7 +405,7 @@ void RichString::importString( SequenceInputStream& rStrm, bool bRich ) { FontPortionModelList aPortions; aPortions.importPortions( rStrm ); - createFontPortions( aBaseText, aPortions ); + createTextPortions( aBaseText, aPortions ); } else { @@ -408,7 +422,12 @@ void RichString::importString( SequenceInputStream& rStrm, bool bRich ) } } -void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eDefaultTextEnc, BiffStringFlags nFlags ) +void RichString::importCharArray( BiffInputStream& rStrm, sal_uInt16 nChars, rtl_TextEncoding eTextEnc ) +{ + createPortion()->setText( rStrm.readCharArrayUC( nChars, eTextEnc ) ); +} + +void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eTextEnc, BiffStringFlags nFlags ) { OSL_ENSURE( !getFlag( nFlags, BIFF_STR_KEEPFONTS ), "RichString::importString - keep fonts not implemented" ); OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_EXTRAFONTS) ) ), "RichString::importByteString - unknown flag" ); @@ -420,11 +439,11 @@ void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eDef { FontPortionModelList aPortions; aPortions.importPortions( rStrm, false ); - createFontPortions( aBaseText, eDefaultTextEnc, aPortions ); + createTextPortions( aBaseText, eTextEnc, aPortions ); } else { - createPortion()->setText( OStringToOUString( aBaseText, eDefaultTextEnc ) ); + createPortion()->setText( OStringToOUString( aBaseText, eTextEnc ) ); } } @@ -454,7 +473,7 @@ void RichString::importUniString( BiffInputStream& rStrm, BiffStringFlags nFlags { FontPortionModelList aPortions; aPortions.importPortions( rStrm, nFontCount, BIFF_FONTPORTION_16BIT ); - createFontPortions( aBaseText, aPortions ); + createTextPortions( aBaseText, aPortions ); } else { @@ -488,23 +507,34 @@ void RichString::importUniString( BiffInputStream& rStrm, BiffStringFlags nFlags void RichString::finalizeImport() { - maFontPortions.forEachMem( &RichStringPortion::finalizeImport ); + maTextPortions.forEachMem( &RichStringPortion::finalizeImport ); } -OUString RichString::getPlainText() const +bool RichString::extractPlainString( OUString& orString, const Font* pFirstPortionFont ) const { - OUStringBuffer aBuffer; - for( PortionVec::const_iterator aIt = maFontPortions.begin(), aEnd = maFontPortions.end(); aIt != aEnd; ++aIt ) - aBuffer.append( (*aIt)->getText() ); - return aBuffer.makeStringAndClear(); + if( !maPhonPortions.empty() ) + return false; + if( maTextPortions.empty() ) + { + orString = OUString(); + return true; + } + if( (maTextPortions.size() == 1) && !maTextPortions.front()->hasFont() && !lclNeedsRichTextFormat( pFirstPortionFont ) ) + { + orString = maTextPortions.front()->getText(); + return true; + } + return false; } -void RichString::convert( const Reference< XText >& rxText, sal_Int32 nXfId ) const +void RichString::convert( const Reference< XText >& rxText, const Font* pFirstPortionFont ) const { - for( PortionVec::const_iterator aIt = maFontPortions.begin(), aEnd = maFontPortions.end(); aIt != aEnd; ++aIt ) + bool bReplace = true; + for( PortionVector::const_iterator aIt = maTextPortions.begin(), aEnd = maTextPortions.end(); aIt != aEnd; ++aIt ) { - (*aIt)->convert( rxText, nXfId ); - nXfId = -1; // use passed XF identifier for first portion only + (*aIt)->convert( rxText, pFirstPortionFont, bReplace ); + pFirstPortionFont = 0; // use passed font for first portion only + bReplace = false; // do not replace first portion text with following portions } } @@ -513,7 +543,7 @@ void RichString::convert( const Reference< XText >& rxText, sal_Int32 nXfId ) co RichStringPortionRef RichString::createPortion() { RichStringPortionRef xPortion( new RichStringPortion( *this ) ); - maFontPortions.push_back( xPortion ); + maTextPortions.push_back( xPortion ); return xPortion; } @@ -524,9 +554,9 @@ RichStringPhoneticRef RichString::createPhonetic() return xPhonetic; } -void RichString::createFontPortions( const OString& rText, rtl_TextEncoding eDefaultTextEnc, FontPortionModelList& rPortions ) +void RichString::createTextPortions( const OString& rText, rtl_TextEncoding eTextEnc, FontPortionModelList& rPortions ) { - maFontPortions.clear(); + maTextPortions.clear(); sal_Int32 nStrLen = rText.getLength(); if( nStrLen > 0 ) { @@ -544,8 +574,8 @@ void RichString::createFontPortions( const OString& rText, rtl_TextEncoding eDef { // convert byte string to unicode string, using current font encoding FontRef xFont = getStyles().getFont( aIt->mnFontId ); - rtl_TextEncoding eTextEnc = xFont.get() ? xFont->getFontEncoding() : eDefaultTextEnc; - OUString aUniStr = OStringToOUString( rText.copy( aIt->mnPos, nPortionLen ), eTextEnc ); + rtl_TextEncoding eFontEnc = xFont.get() ? xFont->getFontEncoding() : eTextEnc; + OUString aUniStr = OStringToOUString( rText.copy( aIt->mnPos, nPortionLen ), eFontEnc ); // create string portion RichStringPortionRef xPortion = createPortion(); xPortion->setText( aUniStr ); @@ -555,9 +585,9 @@ void RichString::createFontPortions( const OString& rText, rtl_TextEncoding eDef } } -void RichString::createFontPortions( const OUString& rText, FontPortionModelList& rPortions ) +void RichString::createTextPortions( const OUString& rText, FontPortionModelList& rPortions ) { - maFontPortions.clear(); + maTextPortions.clear(); sal_Int32 nStrLen = rText.getLength(); if( nStrLen > 0 ) { diff --git a/oox/source/xls/sharedformulabuffer.cxx b/oox/source/xls/sharedformulabuffer.cxx deleted file mode 100644 index 8a433ff98..000000000 --- a/oox/source/xls/sharedformulabuffer.cxx +++ /dev/null @@ -1,212 +0,0 @@ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -#include "oox/xls/sharedformulabuffer.hxx" - -#include <com/sun/star/sheet/XFormulaTokens.hpp> -#include <rtl/ustrbuf.hxx> -#include "oox/helper/propertyset.hxx" -#include "oox/xls/addressconverter.hxx" -#include "oox/xls/biffinputstream.hxx" -#include "oox/xls/formulaparser.hxx" - -namespace oox { -namespace xls { - -// ============================================================================ - -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::sheet; -using namespace ::com::sun::star::table; - -using ::rtl::OUString; -using ::rtl::OUStringBuffer; - -// ============================================================================ - -namespace { - -bool operator==( const CellAddress& rAddr1, const CellAddress& rAddr2 ) -{ - return - (rAddr1.Sheet == rAddr2.Sheet) && - (rAddr1.Column == rAddr2.Column) && - (rAddr1.Row == rAddr2.Row); -} - -bool lclContains( const CellRangeAddress& rRange, const CellAddress& rAddr ) -{ - return - (rRange.Sheet == rAddr.Sheet) && - (rRange.StartColumn <= rAddr.Column) && (rAddr.Column <= rRange.EndColumn) && - (rRange.StartRow <= rAddr.Row) && (rAddr.Row <= rRange.EndRow); -} - -} // namespace - -// ============================================================================ - -ExtCellFormulaContext::ExtCellFormulaContext( const WorksheetHelper& rHelper, - const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) : - SimpleFormulaContext( rxTokens, false, false ), - WorksheetHelper( rHelper ) -{ - setBaseAddress( rCellPos ); -} - -void ExtCellFormulaContext::setSharedFormula( const CellAddress& rBaseAddr ) -{ - getSharedFormulas().setSharedFormulaCell( *this, rBaseAddr ); -} - -// ============================================================================ - -SharedFormulaBuffer::SharedFormulaBuffer( const WorksheetHelper& rHelper ) : - WorksheetHelper( rHelper ) -{ -} - -void SharedFormulaBuffer::importSharedFmla( const OUString& rFormula, const OUString& rSharedRange, sal_Int32 nSharedId, const CellAddress& rBaseAddr ) -{ - CellRangeAddress aFmlaRange; - if( getAddressConverter().convertToCellRange( aFmlaRange, rSharedRange, getSheetIndex(), true, true ) ) - { - // create the defined name representing the shared formula - OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" ); - BinAddress aMapKey( nSharedId, 0 ); - Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey ); - // convert the formula definition - Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY ); - if( xTokens.is() ) - { - SimpleFormulaContext aContext( xTokens, true, false ); - aContext.setBaseAddress( rBaseAddr ); - getFormulaParser().importFormula( aContext, rFormula ); - updateCachedCell( rBaseAddr, aMapKey ); - } - } -} - -void SharedFormulaBuffer::importSharedFmla( SequenceInputStream& rStrm, const CellAddress& rBaseAddr ) -{ - BinRange aRange; - rStrm >> aRange; - CellRangeAddress aFmlaRange; - if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true, true ) ) - { - // create the defined name representing the shared formula - OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" ); - BinAddress aMapKey( rBaseAddr ); - Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey ); - // load the formula definition - Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY ); - if( xTokens.is() ) - { - SimpleFormulaContext aContext( xTokens, true, false ); - aContext.setBaseAddress( rBaseAddr ); - getFormulaParser().importFormula( aContext, rStrm ); - updateCachedCell( rBaseAddr, aMapKey ); - } - } -} - -void SharedFormulaBuffer::importSharedFmla( BiffInputStream& rStrm, const CellAddress& rBaseAddr ) -{ - BinRange aRange; - aRange.read( rStrm, false ); // always 8bit column indexes - CellRangeAddress aFmlaRange; - if( getAddressConverter().convertToCellRange( aFmlaRange, aRange, getSheetIndex(), true, true ) ) - { - // create the defined name representing the shared formula - OSL_ENSURE( lclContains( aFmlaRange, rBaseAddr ), "SharedFormulaBuffer::importSharedFmla - invalid range for shared formula" ); - BinAddress aMapKey( rBaseAddr ); - Reference< XNamedRange > xNamedRange = createDefinedName( aMapKey ); - // load the formula definition - Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY ); - if( xTokens.is() ) - { - rStrm.skip( 2 ); // flags - SimpleFormulaContext aContext( xTokens, true, false ); - aContext.setBaseAddress( rBaseAddr ); - getFormulaParser().importFormula( aContext, rStrm ); - updateCachedCell( rBaseAddr, aMapKey ); - } - } -} - -void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, const CellAddress& rBaseAddr ) -{ - if( !implSetSharedFormulaCell( rContext, BinAddress( rBaseAddr ) ) ) - if( rContext.getBaseAddress() == rBaseAddr ) - mxLastContext.reset( new ExtCellFormulaContext( rContext ) ); -} - -void SharedFormulaBuffer::setSharedFormulaCell( ExtCellFormulaContext& rContext, sal_Int32 nSharedId ) -{ - implSetSharedFormulaCell( rContext, BinAddress( nSharedId, 0 ) ); -} - -Reference< XNamedRange > SharedFormulaBuffer::createDefinedName( const BinAddress& rMapKey ) -{ - OSL_ENSURE( maIndexMap.count( rMapKey ) == 0, "SharedFormulaBuffer::createDefinedName - shared formula exists already" ); - // create the defined name representing the shared formula - OUString aName = OUStringBuffer().appendAscii( "__shared_" ). - append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ). - append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ). - append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear(); - Reference< XNamedRange > xNamedRange = createNamedRangeObject( aName ); - PropertySet aNameProps( xNamedRange ); - aNameProps.setProperty( PROP_IsSharedFormula, true ); - sal_Int32 nTokenIndex = -1; - if( aNameProps.getProperty( nTokenIndex, PROP_TokenIndex ) && (nTokenIndex >= 0) ) - maIndexMap[ rMapKey ] = nTokenIndex; - return xNamedRange; -} - -bool SharedFormulaBuffer::implSetSharedFormulaCell( ExtCellFormulaContext& rContext, const BinAddress& rMapKey ) -{ - TokenIndexMap::const_iterator aIt = maIndexMap.find( rMapKey ); - sal_Int32 nTokenIndex = (aIt == maIndexMap.end()) ? -1 : aIt->second; - if( nTokenIndex >= 0 ) - { - getFormulaParser().convertNameToFormula( rContext, nTokenIndex ); - return true; - } - return false; -} - -void SharedFormulaBuffer::updateCachedCell( const CellAddress& rBaseAddr, const BinAddress& rMapKey ) -{ - if( mxLastContext.get() && (mxLastContext->getBaseAddress() == rBaseAddr) ) - implSetSharedFormulaCell( *mxLastContext, rMapKey ); - mxLastContext.reset(); -} - -// ============================================================================ - -} // namespace xls -} // namespace oox diff --git a/oox/source/xls/sharedstringsbuffer.cxx b/oox/source/xls/sharedstringsbuffer.cxx index 9d6a587cc..101e5b58b 100644 --- a/oox/source/xls/sharedstringsbuffer.cxx +++ b/oox/source/xls/sharedstringsbuffer.cxx @@ -73,11 +73,9 @@ void SharedStringsBuffer::finalizeImport() maStrings.forEachMem( &RichString::finalizeImport ); } -void SharedStringsBuffer::convertString( const Reference< XText >& rxText, sal_Int32 nStringId, sal_Int32 nXfId ) const +RichStringRef SharedStringsBuffer::getString( sal_Int32 nStringId ) const { - if( rxText.is() ) - if( const RichString* pString = maStrings.get( nStringId ).get() ) - pString->convert( rxText, nXfId ); + return maStrings.get( nStringId ); } // ============================================================================ diff --git a/oox/source/xls/sheetdatabuffer.cxx b/oox/source/xls/sheetdatabuffer.cxx new file mode 100755 index 000000000..76790d675 --- /dev/null +++ b/oox/source/xls/sheetdatabuffer.cxx @@ -0,0 +1,935 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "oox/xls/sheetdatabuffer.hxx" + +#include <algorithm> +#include <com/sun/star/sheet/XArrayFormulaTokens.hpp> +#include <com/sun/star/sheet/XCellRangeData.hpp> +#include <com/sun/star/sheet/XFormulaTokens.hpp> +#include <com/sun/star/sheet/XMultipleOperation.hpp> +#include <com/sun/star/table/XCell.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/util/DateTime.hpp> +#include <com/sun/star/util/NumberFormat.hpp> +#include <com/sun/star/util/XMergeable.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <rtl/ustrbuf.hxx> +#include "oox/helper/containerhelper.hxx" +#include "oox/helper/propertymap.hxx" +#include "oox/helper/propertyset.hxx" +#include "oox/token/tokens.hxx" +#include "oox/xls/addressconverter.hxx" +#include "oox/xls/biffinputstream.hxx" +#include "oox/xls/formulaparser.hxx" +#include "oox/xls/sharedstringsbuffer.hxx" +#include "oox/xls/unitconverter.hxx" + +namespace oox { +namespace xls { + +// ============================================================================ + +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sheet; +using namespace ::com::sun::star::table; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +// ============================================================================ + +CellModel::CellModel() : + mnCellType( XML_TOKEN_INVALID ), + mnXfId( -1 ), + mbShowPhonetic( false ) +{ +} + +// ---------------------------------------------------------------------------- + +CellFormulaModel::CellFormulaModel() : + mnFormulaType( XML_TOKEN_INVALID ), + mnSharedId( -1 ) +{ +} + +bool CellFormulaModel::isValidArrayRef( const CellAddress& rCellAddr ) +{ + return + (maFormulaRef.Sheet == rCellAddr.Sheet) && + (maFormulaRef.StartColumn == rCellAddr.Column) && + (maFormulaRef.StartRow == rCellAddr.Row); +} + +bool CellFormulaModel::isValidSharedRef( const CellAddress& rCellAddr ) +{ + return + (maFormulaRef.Sheet == rCellAddr.Sheet) && + (maFormulaRef.StartColumn <= rCellAddr.Column) && (rCellAddr.Column <= maFormulaRef.EndColumn) && + (maFormulaRef.StartRow <= rCellAddr.Row) && (rCellAddr.Row <= maFormulaRef.EndRow); +} + +// ---------------------------------------------------------------------------- + +DataTableModel::DataTableModel() : + mb2dTable( false ), + mbRowTable( false ), + mbRef1Deleted( false ), + mbRef2Deleted( false ) +{ +} + +// ============================================================================ + +namespace { + +const sal_Int32 CELLBLOCK_MAXROWS = 16; /// Number of rows in a cell block. + +} // namespace + +CellBlock::CellBlock( const WorksheetHelper& rHelper, const ValueRange& rColSpan, sal_Int32 nRow ) : + WorksheetHelper( rHelper ), + maRange( rHelper.getSheetIndex(), rColSpan.mnFirst, nRow, rColSpan.mnLast, nRow ), + mnRowLength( rColSpan.mnLast - rColSpan.mnFirst + 1 ), + mnFirstFreeIndex( 0 ) +{ + maCellArray.realloc( 1 ); + maCellArray[ 0 ].realloc( mnRowLength ); + mpCurrCellRow = maCellArray[ 0 ].getArray(); +} + +bool CellBlock::isExpandable( const ValueRange& rColSpan ) const +{ + return (maRange.StartColumn == rColSpan.mnFirst) && (maRange.EndColumn == rColSpan.mnLast); +} + +bool CellBlock::isBefore( const ValueRange& rColSpan ) const +{ + return (maRange.EndColumn < rColSpan.mnLast) || + ((maRange.EndColumn == rColSpan.mnLast) && (maRange.StartColumn != rColSpan.mnFirst)); +} + +bool CellBlock::contains( sal_Int32 nCol ) const +{ + return (maRange.StartColumn <= nCol) && (nCol <= maRange.EndColumn); +} + +void CellBlock::insertRichString( const CellAddress& rAddress, const RichStringRef& rxString, const Font* pFirstPortionFont ) +{ + maRichStrings.push_back( RichStringCell( rAddress, rxString, pFirstPortionFont ) ); +} + +void CellBlock::startNextRow() +{ + // fill last cells in current row with empty strings (placeholder for empty cells) + fillUnusedCells( mnRowLength ); + // flush if the cell block reaches maximum size + if( maCellArray.getLength() == CELLBLOCK_MAXROWS ) + { + finalizeImport(); + maRange.StartRow = ++maRange.EndRow; + maCellArray.realloc( 1 ); + mpCurrCellRow = maCellArray[ 0 ].getArray(); + } + else + { + // prepare next row + ++maRange.EndRow; + sal_Int32 nRowCount = maCellArray.getLength(); + maCellArray.realloc( nRowCount + 1 ); + maCellArray[ nRowCount ].realloc( mnRowLength ); + mpCurrCellRow = maCellArray[ nRowCount ].getArray(); + } + mnFirstFreeIndex = 0; +} + +Any& CellBlock::getCellAny( sal_Int32 nCol ) +{ + OSL_ENSURE( contains( nCol ), "CellBlock::getCellAny - invalid column" ); + // fill cells before passed column with empty strings (the placeholder for empty cells) + sal_Int32 nIndex = nCol - maRange.StartColumn; + fillUnusedCells( nIndex ); + mnFirstFreeIndex = nIndex + 1; + return mpCurrCellRow[ nIndex ]; +} + +void CellBlock::finalizeImport() +{ + // fill last cells in last row with empty strings (placeholder for empty cells) + fillUnusedCells( mnRowLength ); + // insert all buffered cells into the Calc sheet + try + { + Reference< XCellRangeData > xRangeData( getCellRange( maRange ), UNO_QUERY_THROW ); + xRangeData->setDataArray( maCellArray ); + } + catch( Exception& ) + { + } + // insert uncacheable cells separately + for( RichStringCellList::const_iterator aIt = maRichStrings.begin(), aEnd = maRichStrings.end(); aIt != aEnd; ++aIt ) + putRichString( aIt->maCellAddr, *aIt->mxString, aIt->mpFirstPortionFont ); +} + +// private -------------------------------------------------------------------- + +CellBlock::RichStringCell::RichStringCell( const CellAddress& rCellAddr, const RichStringRef& rxString, const Font* pFirstPortionFont ) : + maCellAddr( rCellAddr ), + mxString( rxString ), + mpFirstPortionFont( pFirstPortionFont ) +{ +} + +void CellBlock::fillUnusedCells( sal_Int32 nIndex ) +{ + if( mnFirstFreeIndex < nIndex ) + { + Any* pCellEnd = mpCurrCellRow + nIndex; + for( Any* pCell = mpCurrCellRow + mnFirstFreeIndex; pCell < pCellEnd; ++pCell ) + *pCell <<= OUString(); + } +} + +// ============================================================================ + +CellBlockBuffer::CellBlockBuffer( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ), + mnCurrRow( -1 ) +{ + maCellBlockIt = maCellBlocks.end(); +} + +void CellBlockBuffer::setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans ) +{ + OSL_ENSURE( maColSpans.count( nRow ) == 0, "CellBlockBuffer::setColSpans - multiple column spans for the same row" ); + OSL_ENSURE( (mnCurrRow < nRow) && (maColSpans.empty() || (maColSpans.rbegin()->first < nRow)), "CellBlockBuffer::setColSpans - rows are unsorted" ); + if( (mnCurrRow < nRow) && (maColSpans.count( nRow ) == 0) ) + maColSpans[ nRow ] = rColSpans.getRanges(); +} + +CellBlock* CellBlockBuffer::getCellBlock( const CellAddress& rCellAddr ) +{ + OSL_ENSURE( rCellAddr.Row >= mnCurrRow, "CellBlockBuffer::getCellBlock - passed row out of order" ); + // prepare cell blocks, if row changes + if( rCellAddr.Row != mnCurrRow ) + { + // find colspans for the new row + ColSpanVectorMap::iterator aIt = maColSpans.find( rCellAddr.Row ); + + /* Gap between rows, or rows out of order, or no colspan + information for the new row found: flush all open cell blocks. */ + if( (aIt == maColSpans.end()) || (rCellAddr.Row != mnCurrRow + 1) ) + { + finalizeImport(); + maCellBlocks.clear(); + maCellBlockIt = maCellBlocks.end(); + } + + /* Prepare matching cell blocks, create new cell blocks, finalize + unmatching cell blocks, if colspan information is available. */ + if( aIt != maColSpans.end() ) + { + /* The colspan vector aIt points to is sorted by columns, as well + as the cell block map. In the folloing, this vector and the + list of cell blocks can be iterated simultanously. */ + CellBlockMap::iterator aMIt = maCellBlocks.begin(); + const ValueRangeVector& rColRanges = aIt->second; + for( ValueRangeVector::const_iterator aVIt = rColRanges.begin(), aVEnd = rColRanges.end(); aVIt != aVEnd; ++aVIt, ++aMIt ) + { + const ValueRange& rColSpan = *aVIt; + /* Finalize and remove all cell blocks up to end of the column + range (cell blocks are keyed by end column index). + CellBlock::isBefore() returns true, if the end index of the + passed colspan is greater than the column end index of the + cell block, or if the passed range has the same end index + but the start indexes do not match. */ + while( (aMIt != maCellBlocks.end()) && aMIt->second->isBefore( rColSpan ) ) + { + aMIt->second->finalizeImport(); + maCellBlocks.erase( aMIt++ ); + } + /* If the current cell block (aMIt) fits to the colspan, start + a new row there, otherwise create and insert a new cell block. */ + if( (aMIt != maCellBlocks.end()) && aMIt->second->isExpandable( rColSpan ) ) + aMIt->second->startNextRow(); + else + aMIt = maCellBlocks.insert( aMIt, CellBlockMap::value_type( rColSpan.mnLast, + CellBlockMap::mapped_type( new CellBlock( *this, rColSpan, rCellAddr.Row ) ) ) ); + } + // finalize and remove all remaining cell blocks + CellBlockMap::iterator aMEnd = maCellBlocks.end(); + for( CellBlockMap::iterator aMIt2 = aMIt; aMIt2 != aMEnd; ++aMIt2 ) + aMIt2->second->finalizeImport(); + maCellBlocks.erase( aMIt, aMEnd ); + + // remove cached colspan information (including current one aIt points to) + maColSpans.erase( maColSpans.begin(), ++aIt ); + } + maCellBlockIt = maCellBlocks.begin(); + mnCurrRow = rCellAddr.Row; + } + + // try to find a valid cell block (update maCellBlockIt) + if( ((maCellBlockIt != maCellBlocks.end()) && maCellBlockIt->second->contains( rCellAddr.Column )) || + (((maCellBlockIt = maCellBlocks.lower_bound( rCellAddr.Column )) != maCellBlocks.end()) && maCellBlockIt->second->contains( rCellAddr.Column )) ) + { + // maCellBlockIt points to valid cell block + return maCellBlockIt->second.get(); + } + + // no valid cell block found + return 0; +} + +void CellBlockBuffer::finalizeImport() +{ + maCellBlocks.forEachMem( &CellBlock::finalizeImport ); +} + +// ============================================================================ + +SheetDataBuffer::SheetDataBuffer( const WorksheetHelper& rHelper ) : + WorksheetHelper( rHelper ), + maCellBlocks( rHelper ), + mbPendingSharedFmla( false ) +{ +} + +void SheetDataBuffer::setColSpans( sal_Int32 nRow, const ValueRangeSet& rColSpans ) +{ + maCellBlocks.setColSpans( nRow, rColSpans ); +} + +void SheetDataBuffer::setBlankCell( const CellModel& rModel ) +{ + setCellFormat( rModel ); +} + +void SheetDataBuffer::setValueCell( const CellModel& rModel, double fValue ) +{ + if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rModel.maCellAddr ) ) + pCellBlock->getCellAny( rModel.maCellAddr.Column ) <<= fValue; + else + putValue( rModel.maCellAddr, fValue ); + setCellFormat( rModel ); +} + +void SheetDataBuffer::setStringCell( const CellModel& rModel, const OUString& rText ) +{ + if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rModel.maCellAddr ) ) + pCellBlock->getCellAny( rModel.maCellAddr.Column ) <<= rText; + else + putString( rModel.maCellAddr, rText ); + setCellFormat( rModel ); +} + +void SheetDataBuffer::setStringCell( const CellModel& rModel, const RichStringRef& rxString ) +{ + OSL_ENSURE( rxString.get(), "SheetDataBuffer::setStringCell - missing rich string object" ); + const Font* pFirstPortionFont = getStyles().getFontFromCellXf( rModel.mnXfId ).get(); + OUString aText; + if( rxString->extractPlainString( aText, pFirstPortionFont ) ) + { + setStringCell( rModel, aText ); + } + else + { + if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rModel.maCellAddr ) ) + pCellBlock->insertRichString( rModel.maCellAddr, rxString, pFirstPortionFont ); + else + putRichString( rModel.maCellAddr, *rxString, pFirstPortionFont ); + setCellFormat( rModel ); + } +} + +void SheetDataBuffer::setStringCell( const CellModel& rModel, sal_Int32 nStringId ) +{ + RichStringRef xString = getSharedStrings().getString( nStringId ); + if( xString.get() ) + setStringCell( rModel, xString ); + else + setBlankCell( rModel ); +} + +void SheetDataBuffer::setDateTimeCell( const CellModel& rModel, const DateTime& rDateTime ) +{ + // write serial date/time value into the cell + double fSerial = getUnitConverter().calcSerialFromDateTime( rDateTime ); + setValueCell( rModel, fSerial ); + // set appropriate number format + using namespace ::com::sun::star::util::NumberFormat; + sal_Int16 nStdFmt = (fSerial < 1.0) ? TIME : (((rDateTime.Hours > 0) || (rDateTime.Minutes > 0) || (rDateTime.Seconds > 0)) ? DATETIME : DATE); + setStandardNumFmt( rModel.maCellAddr, nStdFmt ); +} + +void SheetDataBuffer::setBooleanCell( const CellModel& rModel, bool bValue ) +{ + setCellFormula( rModel.maCellAddr, getFormulaParser().convertBoolToFormula( bValue ) ); + // #108770# set 'Standard' number format for all Boolean cells + setCellFormat( rModel, 0 ); +} + +void SheetDataBuffer::setErrorCell( const CellModel& rModel, const OUString& rErrorCode ) +{ + setErrorCell( rModel, getUnitConverter().calcBiffErrorCode( rErrorCode ) ); +} + +void SheetDataBuffer::setErrorCell( const CellModel& rModel, sal_uInt8 nErrorCode ) +{ + setCellFormula( rModel.maCellAddr, getFormulaParser().convertErrorToFormula( nErrorCode ) ); + setCellFormat( rModel ); +} + +void SheetDataBuffer::setFormulaCell( const CellModel& rModel, const ApiTokenSequence& rTokens ) +{ + mbPendingSharedFmla = false; + ApiTokenSequence aTokens; + + /* Detect special token passed as placeholder for array formulas, shared + formulas, and table operations. In BIFF, these formulas are represented + by a single tExp resp. tTbl token. If the formula parser finds these + tokens, it puts a single OPCODE_BAD token with the base address and + formula type into the token sequence. This information will be + extracted here, and in case of a shared formula, the shared formula + buffer will generate the resulting formula token array. */ + ApiSpecialTokenInfo aTokenInfo; + if( rTokens.hasElements() && getFormulaParser().extractSpecialTokenInfo( aTokenInfo, rTokens ) ) + { + /* The second member of the token info is set to true, if the formula + represents a table operation, which will be skipped. In BIFF12 it + is not possible to distinguish array and shared formulas + (BIFF5/BIFF8 provide this information with a special flag in the + FORMULA record). */ + if( !aTokenInfo.Second ) + { + /* Construct the token array representing the shared formula. If + the returned sequence is empty, the definition of the shared + formula has not been loaded yet, or the cell is part of an + array formula. In this case, the cell will be remembered. After + reading the formula definition it will be retried to insert the + formula via retryPendingSharedFormulaCell(). */ + BinAddress aBaseAddr( aTokenInfo.First ); + aTokens = resolveSharedFormula( aBaseAddr ); + if( !aTokens.hasElements() ) + { + maSharedFmlaAddr = rModel.maCellAddr; + maSharedBaseAddr = aBaseAddr; + mbPendingSharedFmla = true; + } + } + } + else + { + // simple formula, use the passed token array + aTokens = rTokens; + } + + setCellFormula( rModel.maCellAddr, aTokens ); + setCellFormat( rModel ); +} + +void SheetDataBuffer::setFormulaCell( const CellModel& rModel, sal_Int32 nSharedId ) +{ + setCellFormula( rModel.maCellAddr, resolveSharedFormula( BinAddress( nSharedId, 0 ) ) ); + setCellFormat( rModel ); +} + +void SheetDataBuffer::createArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens ) +{ + /* Array formulas will be inserted later in finalizeImport(). This is + needed to not disturb collecting all the cells, which will be put into + the sheet in large blocks to increase performance. */ + maArrayFormulas.push_back( ArrayFormula( rRange, rTokens ) ); +} + +void SheetDataBuffer::createTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) +{ + /* Table operations will be inserted later in finalizeImport(). This is + needed to not disturb collecting all the cells, which will be put into + the sheet in large blocks to increase performance. */ + maTableOperations.push_back( TableOperation( rRange, rModel ) ); +} + +void SheetDataBuffer::createSharedFormula( sal_Int32 nSharedId, const ApiTokenSequence& rTokens ) +{ + createSharedFormula( BinAddress( nSharedId, 0 ), rTokens ); +} + +void SheetDataBuffer::createSharedFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens ) +{ + createSharedFormula( BinAddress( rCellAddr ), rTokens ); +} + +void SheetDataBuffer::setRowFormat( sal_Int32 nRow, sal_Int32 nXfId, bool bCustomFormat ) +{ + // set row formatting + if( bCustomFormat ) + { + // try to expand cached row range, if formatting is equal + if( (maXfIdRowRange.maRowRange.mnLast < 0) || !maXfIdRowRange.tryExpand( nRow, nXfId ) ) + { + writeXfIdRowRangeProperties( maXfIdRowRange ); + maXfIdRowRange.set( nRow, nXfId ); + } + } + else if( maXfIdRowRange.maRowRange.mnLast >= 0 ) + { + // finish last cached row range + writeXfIdRowRangeProperties( maXfIdRowRange ); + maXfIdRowRange.set( -1, -1 ); + } +} + +void SheetDataBuffer::setMergedRange( const CellRangeAddress& rRange ) +{ + maMergedRanges.push_back( MergedRange( rRange ) ); +} + +void SheetDataBuffer::setStandardNumFmt( const CellAddress& rCellAddr, sal_Int16 nStdNumFmt ) +{ + try + { + Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY_THROW ); + Reference< XNumberFormatTypes > xNumFmtTypes( xNumFmtsSupp->getNumberFormats(), UNO_QUERY_THROW ); + sal_Int32 nIndex = xNumFmtTypes->getStandardFormat( nStdNumFmt, Locale() ); + PropertySet aPropSet( getCell( rCellAddr ) ); + aPropSet.setProperty( PROP_NumberFormat, nIndex ); + } + catch( Exception& ) + { + } +} + +void SheetDataBuffer::finalizeImport() +{ + // insert all cells of all open cell blocks + maCellBlocks.finalizeImport(); + + // create all array formulas + for( ArrayFormulaList::iterator aIt = maArrayFormulas.begin(), aEnd = maArrayFormulas.end(); aIt != aEnd; ++aIt ) + finalizeArrayFormula( aIt->first, aIt->second ); + + // create all table operations + for( TableOperationList::iterator aIt = maTableOperations.begin(), aEnd = maTableOperations.end(); aIt != aEnd; ++aIt ) + finalizeTableOperation( aIt->first, aIt->second ); + + // write default formatting of remaining row range + writeXfIdRowRangeProperties( maXfIdRowRange ); + + // try to merge remaining inserted ranges + mergeXfIdRanges(); + // write all formatting + for( XfIdRangeMap::const_iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); aIt != aEnd; ++aIt ) + writeXfIdRangeProperties( aIt->second ); + + // merge all cached merged ranges and update right/bottom cell borders + for( MergedRangeList::iterator aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt ) + finalizeMergedRange( aIt->maRange ); + for( MergedRangeList::iterator aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt ) + finalizeMergedRange( aIt->maRange ); +} + +// private -------------------------------------------------------------------- + +SheetDataBuffer::XfIdRowRange::XfIdRowRange() : + maRowRange( -1 ), + mnXfId( -1 ) +{ +} + +bool SheetDataBuffer::XfIdRowRange::intersects( const CellRangeAddress& rRange ) const +{ + return (rRange.StartRow <= maRowRange.mnLast) && (maRowRange.mnFirst <= rRange.EndRow); +} + +void SheetDataBuffer::XfIdRowRange::set( sal_Int32 nRow, sal_Int32 nXfId ) +{ + maRowRange = ValueRange( nRow ); + mnXfId = nXfId; +} + +bool SheetDataBuffer::XfIdRowRange::tryExpand( sal_Int32 nRow, sal_Int32 nXfId ) +{ + if( mnXfId == nXfId ) + { + if( maRowRange.mnLast + 1 == nRow ) + { + ++maRowRange.mnLast; + return true; + } + if( maRowRange.mnFirst == nRow + 1 ) + { + --maRowRange.mnFirst; + return true; + } + } + return false; +} + +void SheetDataBuffer::XfIdRange::set( const CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId ) +{ + maRange.Sheet = rCellAddr.Sheet; + maRange.StartColumn = maRange.EndColumn = rCellAddr.Column; + maRange.StartRow = maRange.EndRow = rCellAddr.Row; + mnXfId = nXfId; + mnNumFmtId = nNumFmtId; +} + +bool SheetDataBuffer::XfIdRange::tryExpand( const CellAddress& rCellAddr, sal_Int32 nXfId, sal_Int32 nNumFmtId ) +{ + if( (mnXfId == nXfId) && (mnNumFmtId == nNumFmtId) && + (maRange.StartRow == rCellAddr.Row) && + (maRange.EndRow == rCellAddr.Row) && + (maRange.EndColumn + 1 == rCellAddr.Column) ) + { + ++maRange.EndColumn; + return true; + } + return false; +} + +bool SheetDataBuffer::XfIdRange::tryMerge( const XfIdRange& rXfIdRange ) +{ + if( (mnXfId == rXfIdRange.mnXfId) && + (mnNumFmtId == rXfIdRange.mnNumFmtId) && + (maRange.EndRow + 1 == rXfIdRange.maRange.StartRow) && + (maRange.StartColumn == rXfIdRange.maRange.StartColumn) && + (maRange.EndColumn == rXfIdRange.maRange.EndColumn) ) + { + maRange.EndRow = rXfIdRange.maRange.EndRow; + return true; + } + return false; +} + + +SheetDataBuffer::MergedRange::MergedRange( const CellRangeAddress& rRange ) : + maRange( rRange ), + mnHorAlign( XML_TOKEN_INVALID ) +{ +} + +SheetDataBuffer::MergedRange::MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ) : + maRange( rAddress.Sheet, rAddress.Column, rAddress.Row, rAddress.Column, rAddress.Row ), + mnHorAlign( nHorAlign ) +{ +} + +bool SheetDataBuffer::MergedRange::tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign ) +{ + if( (mnHorAlign == nHorAlign) && (maRange.StartRow == rAddress.Row) && + (maRange.EndRow == rAddress.Row) && (maRange.EndColumn + 1 == rAddress.Column) ) + { + ++maRange.EndColumn; + return true; + } + return false; +} + +// ---------------------------------------------------------------------------- + +void SheetDataBuffer::setCellFormula( const CellAddress& rCellAddr, const ApiTokenSequence& rTokens ) +{ + if( rTokens.hasElements() ) + { + if( CellBlock* pCellBlock = maCellBlocks.getCellBlock( rCellAddr ) ) + pCellBlock->getCellAny( rCellAddr.Column ) <<= rTokens; + else + putFormulaTokens( rCellAddr, rTokens ); + } +} + +void SheetDataBuffer::createSharedFormula( const BinAddress& rMapKey, const ApiTokenSequence& rTokens ) +{ + // create the defined name that will represent the shared formula + OUString aName = OUStringBuffer().appendAscii( RTL_CONSTASCII_STRINGPARAM( "__shared_" ) ). + append( static_cast< sal_Int32 >( getSheetIndex() + 1 ) ). + append( sal_Unicode( '_' ) ).append( rMapKey.mnRow ). + append( sal_Unicode( '_' ) ).append( rMapKey.mnCol ).makeStringAndClear(); + Reference< XNamedRange > xNamedRange = createNamedRangeObject( aName ); + OSL_ENSURE( xNamedRange.is(), "SheetDataBuffer::createSharedFormula - cannot create shared formula" ); + PropertySet aNameProps( xNamedRange ); + aNameProps.setProperty( PROP_IsSharedFormula, true ); + + // get and store the token index of the defined name + OSL_ENSURE( maSharedFormulas.count( rMapKey ) == 0, "SheetDataBuffer::createSharedFormula - shared formula exists already" ); + sal_Int32 nTokenIndex = 0; + if( aNameProps.getProperty( nTokenIndex, PROP_TokenIndex ) && (nTokenIndex >= 0) ) try + { + // store the token index in the map + maSharedFormulas[ rMapKey ] = nTokenIndex; + // set the formula definition + Reference< XFormulaTokens > xTokens( xNamedRange, UNO_QUERY_THROW ); + xTokens->setTokens( rTokens ); + // retry to insert a pending shared formula cell + if( mbPendingSharedFmla ) + setCellFormula( maSharedFmlaAddr, resolveSharedFormula( maSharedBaseAddr ) ); + } + catch( Exception& ) + { + } + mbPendingSharedFmla = false; +} + +ApiTokenSequence SheetDataBuffer::resolveSharedFormula( const BinAddress& rMapKey ) const +{ + sal_Int32 nTokenIndex = ContainerHelper::getMapElement( maSharedFormulas, rMapKey, -1 ); + return (nTokenIndex >= 0) ? getFormulaParser().convertNameToFormula( nTokenIndex ) : ApiTokenSequence(); +} + +void SheetDataBuffer::finalizeArrayFormula( const CellRangeAddress& rRange, const ApiTokenSequence& rTokens ) const +{ + Reference< XArrayFormulaTokens > xTokens( getCellRange( rRange ), UNO_QUERY ); + OSL_ENSURE( xTokens.is(), "SheetDataBuffer::finalizeArrayFormula - missing formula token interface" ); + if( xTokens.is() ) + xTokens->setArrayTokens( rTokens ); +} + +void SheetDataBuffer::finalizeTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) const +{ + sal_Int16 nSheet = getSheetIndex(); + bool bOk = false; + if( !rModel.mbRef1Deleted && (rModel.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) ) + { + CellRangeAddress aOpRange = rRange; + CellAddress aRef1; + if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, nSheet, true ) ) try + { + if( rModel.mb2dTable ) + { + CellAddress aRef2; + if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, nSheet, true ) ) + { + // API call expects input values inside operation range + --aOpRange.StartColumn; + --aOpRange.StartRow; + // formula range is top-left cell of operation range + CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow ); + // set multiple operation + Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW ); + xMultOp->setTableOperation( aFormulaRange, TableOperationMode_BOTH, aRef2, aRef1 ); + bOk = true; + } + } + else if( rModel.mbRowTable ) + { + // formula range is column to the left of operation range + CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow ); + // API call expects input values (top row) inside operation range + --aOpRange.StartRow; + // set multiple operation + Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW ); + xMultOp->setTableOperation( aFormulaRange, TableOperationMode_ROW, aRef1, aRef1 ); + bOk = true; + } + else + { + // formula range is row above operation range + CellRangeAddress aFormulaRange( nSheet, aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 ); + // API call expects input values (left column) inside operation range + --aOpRange.StartColumn; + // set multiple operation + Reference< XMultipleOperation > xMultOp( getCellRange( aOpRange ), UNO_QUERY_THROW ); + xMultOp->setTableOperation( aFormulaRange, TableOperationMode_COLUMN, aRef1, aRef1 ); + bOk = true; + } + } + catch( Exception& ) + { + } + } + + // on error: fill cell range with #REF! error codes + if( !bOk ) try + { + Reference< XCellRangeData > xCellRangeData( getCellRange( rRange ), UNO_QUERY_THROW ); + size_t nWidth = static_cast< size_t >( rRange.EndColumn - rRange.StartColumn + 1 ); + size_t nHeight = static_cast< size_t >( rRange.EndRow - rRange.StartRow + 1 ); + Matrix< Any > aErrorCells( nWidth, nHeight, Any( getFormulaParser().convertErrorToFormula( BIFF_ERR_REF ) ) ); + xCellRangeData->setDataArray( ContainerHelper::matrixToSequenceSequence( aErrorCells ) ); + } + catch( Exception& ) + { + } +} + +void SheetDataBuffer::setCellFormat( const CellModel& rModel, sal_Int32 nNumFmtId ) +{ + if( (rModel.mnXfId >= 0) || (nNumFmtId >= 0) ) + { + // try to merge existing ranges and to write some formatting properties + if( !maXfIdRanges.empty() ) + { + // get row index of last inserted cell + sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow; + // row changed - try to merge ranges of last row with existing ranges + if( rModel.maCellAddr.Row != nLastRow ) + { + mergeXfIdRanges(); + // write format properties of all ranges above last row and remove them + XfIdRangeMap::iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); + while( aIt != aEnd ) + { + // check that range cannot be merged with current row, and that range is not in cached row range + if( (aIt->second.maRange.EndRow < nLastRow) && !maXfIdRowRange.intersects( aIt->second.maRange ) ) + { + writeXfIdRangeProperties( aIt->second ); + maXfIdRanges.erase( aIt++ ); + } + else + ++aIt; + } + } + } + + // try to expand last existing range, or create new range entry + if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rModel.maCellAddr, rModel.mnXfId, nNumFmtId ) ) + maXfIdRanges[ BinAddress( rModel.maCellAddr ) ].set( rModel.maCellAddr, rModel.mnXfId, nNumFmtId ); + + // update merged ranges for 'center across selection' and 'fill' + if( const Xf* pXf = getStyles().getCellXf( rModel.mnXfId ).get() ) + { + sal_Int32 nHorAlign = pXf->getAlignment().getModel().mnHorAlign; + if( (nHorAlign == XML_centerContinuous) || (nHorAlign == XML_fill) ) + { + /* start new merged range, if cell is not empty (#108781#), + or try to expand last range with empty cell */ + if( rModel.mnCellType != XML_TOKEN_INVALID ) + maCenterFillRanges.push_back( MergedRange( rModel.maCellAddr, nHorAlign ) ); + else if( !maCenterFillRanges.empty() ) + maCenterFillRanges.rbegin()->tryExpand( rModel.maCellAddr, nHorAlign ); + } + } + } +} + +void SheetDataBuffer::writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const +{ + if( (rXfIdRowRange.maRowRange.mnLast >= 0) && (rXfIdRowRange.mnXfId >= 0) ) + { + AddressConverter& rAddrConv = getAddressConverter(); + CellRangeAddress aRange( getSheetIndex(), 0, rXfIdRowRange.maRowRange.mnFirst, rAddrConv.getMaxApiAddress().Column, rXfIdRowRange.maRowRange.mnLast ); + if( rAddrConv.validateCellRange( aRange, true, false ) ) + { + PropertySet aPropSet( getCellRange( aRange ) ); + getStyles().writeCellXfToPropertySet( aPropSet, rXfIdRowRange.mnXfId ); + } + } +} + +void SheetDataBuffer::writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const +{ + StylesBuffer& rStyles = getStyles(); + PropertyMap aPropMap; + if( rXfIdRange.mnXfId >= 0 ) + rStyles.writeCellXfToPropertyMap( aPropMap, rXfIdRange.mnXfId ); + if( rXfIdRange.mnNumFmtId >= 0 ) + rStyles.writeNumFmtToPropertyMap( aPropMap, rXfIdRange.mnNumFmtId ); + PropertySet aPropSet( getCellRange( rXfIdRange.maRange ) ); + aPropSet.setProperties( aPropMap ); +} + +void SheetDataBuffer::mergeXfIdRanges() +{ + if( !maXfIdRanges.empty() ) + { + // get row index of last range + sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow; + // process all ranges located in the same row of the last range + XfIdRangeMap::iterator aMergeIt = maXfIdRanges.end(); + while( (aMergeIt != maXfIdRanges.begin()) && ((--aMergeIt)->second.maRange.StartRow == nLastRow) ) + { + const XfIdRange& rMergeXfIdRange = aMergeIt->second; + // try to find a range that can be merged with rMergeRange + bool bFound = false; + for( XfIdRangeMap::iterator aIt = maXfIdRanges.begin(); !bFound && (aIt != aMergeIt); ++aIt ) + if( (bFound = aIt->second.tryMerge( rMergeXfIdRange )) == true ) + maXfIdRanges.erase( aMergeIt++ ); + } + } +} + +void SheetDataBuffer::finalizeMergedRange( const CellRangeAddress& rRange ) +{ + bool bMultiCol = rRange.StartColumn < rRange.EndColumn; + bool bMultiRow = rRange.StartRow < rRange.EndRow; + + if( bMultiCol || bMultiRow ) try + { + // merge the cell range + Reference< XMergeable > xMerge( getCellRange( rRange ), UNO_QUERY_THROW ); + xMerge->merge( sal_True ); + + // if merging this range worked (no overlapping merged ranges), update cell borders + Reference< XCell > xTopLeft( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.StartRow ) ), UNO_SET_THROW ); + PropertySet aTopLeftProp( xTopLeft ); + + // copy right border of top-right cell to right border of top-left cell + if( bMultiCol ) + { + PropertySet aTopRightProp( getCell( CellAddress( getSheetIndex(), rRange.EndColumn, rRange.StartRow ) ) ); + BorderLine aLine; + if( aTopRightProp.getProperty( aLine, PROP_RightBorder ) ) + aTopLeftProp.setProperty( PROP_RightBorder, aLine ); + } + + // copy bottom border of bottom-left cell to bottom border of top-left cell + if( bMultiRow ) + { + PropertySet aBottomLeftProp( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.EndRow ) ) ); + BorderLine aLine; + if( aBottomLeftProp.getProperty( aLine, PROP_BottomBorder ) ) + aTopLeftProp.setProperty( PROP_BottomBorder, aLine ); + } + + // #i93609# merged range in a single row: test if manual row height is needed + if( !bMultiRow ) + { + bool bTextWrap = aTopLeftProp.getBoolProperty( PROP_IsTextWrapped ); + if( !bTextWrap && (xTopLeft->getType() == CellContentType_TEXT) ) + { + Reference< XText > xText( xTopLeft, UNO_QUERY ); + bTextWrap = xText.is() && (xText->getString().indexOf( '\x0A' ) >= 0); + } + if( bTextWrap ) + setManualRowHeight( rRange.StartRow ); + } + } + catch( Exception& ) + { + } +} + +// ============================================================================ + +} // namespace xls +} // namespace oox diff --git a/oox/source/xls/sheetdatacontext.cxx b/oox/source/xls/sheetdatacontext.cxx index 0e95677d7..bedf61f5c 100644 --- a/oox/source/xls/sheetdatacontext.cxx +++ b/oox/source/xls/sheetdatacontext.cxx @@ -27,8 +27,6 @@ #include "oox/xls/sheetdatacontext.hxx" -#include <com/sun/star/sheet/XArrayFormulaTokens.hpp> -#include <com/sun/star/sheet/XFormulaTokens.hpp> #include <com/sun/star/table/CellContentType.hpp> #include <com/sun/star/table/XCell.hpp> #include <com/sun/star/table/XCellRange.hpp> @@ -39,7 +37,6 @@ #include "oox/xls/biffinputstream.hxx" #include "oox/xls/formulaparser.hxx" #include "oox/xls/richstringcontext.hxx" -#include "oox/xls/sharedformulabuffer.hxx" #include "oox/xls/unitconverter.hxx" namespace oox { @@ -98,64 +95,31 @@ const sal_uInt32 BIFF_ROW_THICKTOP = 0x10000000; const sal_uInt32 BIFF_ROW_THICKBOTTOM = 0x20000000; const sal_uInt32 BIFF_ROW_SHOWPHONETIC = 0x40000000; -const sal_Int32 BIFF2_XF_EXTENDED_IDS = 63; -const sal_uInt8 BIFF2_XF_MASK = 0x3F; +const sal_Int32 BIFF2_CELL_USEIXFE = 63; -// ---------------------------------------------------------------------------- - -/** Formula context for cell formulas. */ -class CellFormulaContext : public SimpleFormulaContext -{ -public: - explicit CellFormulaContext( - const Reference< XFormulaTokens >& rxTokens, - const CellAddress& rCellPos ); -}; - -CellFormulaContext::CellFormulaContext( const Reference< XFormulaTokens >& rxTokens, const CellAddress& rCellPos ) : - SimpleFormulaContext( rxTokens, false, false ) -{ - setBaseAddress( rCellPos ); -} - -// ---------------------------------------------------------------------------- - -/** Uses the XArrayFormulaTokens interface to set a token sequence. */ -class ArrayFormulaContext : public FormulaContext -{ -public: - explicit ArrayFormulaContext( - const Reference< XArrayFormulaTokens >& rxTokens, - const CellRangeAddress& rArrayRange ); - - virtual void setTokens( const ApiTokenSequence& rTokens ); +} // namespace -private: - Reference< XArrayFormulaTokens > mxTokens; -}; +// ============================================================================ -ArrayFormulaContext::ArrayFormulaContext( - const Reference< XArrayFormulaTokens >& rxTokens, const CellRangeAddress& rArrayRange ) : - FormulaContext( false, false ), - mxTokens( rxTokens ) +SheetDataContextBase::SheetDataContextBase( const WorksheetHelper& rHelper ) : + mrAddressConv( rHelper.getAddressConverter() ), + mrFormulaParser( rHelper.getFormulaParser() ), + mrSheetData( rHelper.getSheetData() ), + mnSheet( rHelper.getSheetIndex() ) { - OSL_ENSURE( mxTokens.is(), "ArrayFormulaContext::ArrayFormulaContext - missing XArrayFormulaTokens interface" ); - setBaseAddress( CellAddress( rArrayRange.Sheet, rArrayRange.StartColumn, rArrayRange.StartRow ) ); } -void ArrayFormulaContext::setTokens( const ApiTokenSequence& rTokens ) +SheetDataContextBase::~SheetDataContextBase() { - mxTokens->setArrayTokens( rTokens ); } -// ---------------------------------------------------------------------------- - -} // namespace - // ============================================================================ SheetDataContext::SheetDataContext( WorksheetFragmentBase& rFragment ) : - WorksheetContextBase( rFragment ) + WorksheetContextBase( rFragment ), + SheetDataContextBase( rFragment ), + mbHasFormula( false ), + mbValidRange( false ) { } @@ -168,20 +132,22 @@ ContextHandlerRef SheetDataContext::onCreateContext( sal_Int32 nElement, const A break; case XLS_TOKEN( row ): - if( nElement == XLS_TOKEN( c ) ) { importCell( rAttribs ); return this; } + // do not process cell elements with invalid (out-of-range) address + if( nElement == XLS_TOKEN( c ) && importCell( rAttribs ) ) + return this; break; case XLS_TOKEN( c ): - if( maCurrCell.mxCell.is() ) switch( nElement ) + switch( nElement ) { case XLS_TOKEN( is ): mxInlineStr.reset( new RichString( *this ) ); return new RichStringContext( *this, mxInlineStr ); case XLS_TOKEN( v ): - return this; + return this; // characters contain cell value case XLS_TOKEN( f ): importFormula( rAttribs ); - return this; + return this; // characters contain formula string } break; } @@ -193,94 +159,86 @@ void SheetDataContext::onCharacters( const OUString& rChars ) switch( getCurrentElement() ) { case XLS_TOKEN( v ): - maCurrCell.maValueStr = rChars; - maCurrCell.mbHasValueStr = true; + maCellValue = rChars; break; - case XLS_TOKEN( f ): - if( maCurrCell.mxCell.is() ) try - { - switch( maCurrCell.mnFormulaType ) - { - case XML_normal: - if( rChars.getLength() > 0 ) - { - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW ); - CellFormulaContext aContext( xTokens, maCurrCell.maAddress ); - getFormulaParser().importFormula( aContext, rChars ); - } - break; - - case XML_array: - if( (maCurrCell.maFormulaRef.getLength() > 0) && (rChars.getLength() > 0) ) - { - CellRangeAddress aArrayRange; - Reference< XArrayFormulaTokens > xTokens( getCellRange( maCurrCell.maFormulaRef, &aArrayRange ), UNO_QUERY_THROW ); - ArrayFormulaContext aContext( xTokens, aArrayRange ); - getFormulaParser().importFormula( aContext, rChars ); - } - break; - - case XML_shared: - if( maCurrCell.mnSharedId >= 0 ) - { - if( rChars.getLength() > 0 ) - getSharedFormulas().importSharedFmla( rChars, maCurrCell.maFormulaRef, maCurrCell.mnSharedId, maCurrCell.maAddress ); - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY_THROW ); - ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); - getSharedFormulas().setSharedFormulaCell( aContext, maCurrCell.mnSharedId ); - } - break; - - case XML_dataTable: - if( maCurrCell.maFormulaRef.getLength() > 0 ) - { - CellRangeAddress aTableRange; - if( getAddressConverter().convertToCellRange( aTableRange, maCurrCell.maFormulaRef, getSheetIndex(), true, true ) ) - setTableOperation( aTableRange, maTableData ); - } - break; - - default: - OSL_ENSURE( false, "SheetDataContext::onCharacters - unknown formula type" ); - } - } - catch( Exception& ) - { - } + if( maFmlaData.mnFormulaType != XML_TOKEN_INVALID ) + maTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, rChars ); break; } } void SheetDataContext::onEndElement() { - if( isCurrentElement( XLS_TOKEN( c ) ) && maCurrCell.mxCell.is() ) + if( getCurrentElement() == XLS_TOKEN( c ) ) { - if( maCurrCell.mxCell->getType() == CellContentType_EMPTY ) + // try to create a formula cell + if( mbHasFormula ) switch( maFmlaData.mnFormulaType ) + { + case XML_normal: + mrSheetData.setFormulaCell( maCellData, maTokens ); + break; + case XML_shared: + if( maFmlaData.mnSharedId >= 0 ) + { + if( mbValidRange && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) + mrSheetData.createSharedFormula( maFmlaData.mnSharedId, maTokens ); + mrSheetData.setFormulaCell( maCellData, maFmlaData.mnSharedId ); + } + else + // no success, set plain cell value and formatting below + mbHasFormula = false; + break; + case XML_array: + if( mbValidRange && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) + mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, maTokens ); + // set cell formatting, but do not set result as cell value + mrSheetData.setBlankCell( maCellData ); + break; + case XML_dataTable: + if( mbValidRange ) + mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData ); + // set cell formatting, but do not set result as cell value + mrSheetData.setBlankCell( maCellData ); + break; + default: + OSL_ENSURE( maFmlaData.mnFormulaType == XML_TOKEN_INVALID, "SheetDataContext::onEndElement - unknown formula type" ); + mbHasFormula = false; + } + + if( !mbHasFormula ) { - if( maCurrCell.mbHasValueStr ) + // no formula created: try to set the cell value + if( maCellValue.getLength() > 0 ) switch( maCellData.mnCellType ) { - // implemented in WorksheetHelper class - setCell( maCurrCell ); + case XML_n: + mrSheetData.setValueCell( maCellData, maCellValue.toDouble() ); + break; + case XML_b: + mrSheetData.setBooleanCell( maCellData, maCellValue.toDouble() != 0.0 ); + break; + case XML_e: + mrSheetData.setErrorCell( maCellData, maCellValue ); + break; + case XML_str: + mrSheetData.setStringCell( maCellData, maCellValue ); + break; + case XML_s: + mrSheetData.setStringCell( maCellData, maCellValue.toInt32() ); + break; } - else if( (maCurrCell.mnCellType == XML_inlineStr) && mxInlineStr.get() ) + else if( (maCellData.mnCellType == XML_inlineStr) && mxInlineStr.get() ) { - // convert font settings mxInlineStr->finalizeImport(); - // write string to cell - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() ) - mxInlineStr->convert( xText, maCurrCell.mnXfId ); + mrSheetData.setStringCell( maCellData, mxInlineStr ); } else { // empty cell, update cell type - maCurrCell.mnCellType = XML_TOKEN_INVALID; + maCellData.mnCellType = XML_TOKEN_INVALID; + mrSheetData.setBlankCell( maCellData ); } } - - // store the cell formatting data - setCellFormat( maCurrCell ); } } @@ -289,10 +247,7 @@ ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, Seq switch( getCurrentElement() ) { case BIFF12_ID_SHEETDATA: - switch( nRecId ) - { - case BIFF12_ID_ROW: importRow( rStrm ); return this; - } + if( nRecId == BIFF12_ID_ROW ) { importRow( rStrm ); return this; } break; case BIFF12_ID_ROW: @@ -332,7 +287,7 @@ ContextHandlerRef SheetDataContext::onCreateRecordContext( sal_Int32 nRecId, Seq void SheetDataContext::importRow( const AttributeList& rAttribs ) { RowModel aModel; - aModel.mnFirstRow = aModel.mnLastRow = rAttribs.getInteger( XML_r, -1 ); + aModel.mnRow = rAttribs.getInteger( XML_r, -1 ); aModel.mfHeight = rAttribs.getDouble( XML_ht, -1.0 ); aModel.mnXfId = rAttribs.getInteger( XML_s, -1 ); aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); @@ -343,41 +298,106 @@ void SheetDataContext::importRow( const AttributeList& rAttribs ) aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); aModel.mbThickTop = rAttribs.getBool( XML_thickTop, false ); aModel.mbThickBottom = rAttribs.getBool( XML_thickBot, false ); + + // decode the column spans (space-separated list of colon-separated integer pairs) + OUString aColSpansText = rAttribs.getString( XML_spans, OUString() ); + sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Column; + sal_Int32 nIndex = 0; + while( nIndex >= 0 ) + { + OUString aColSpanToken = aColSpansText.getToken( 0, ' ', nIndex ); + sal_Int32 nSepPos = aColSpanToken.indexOf( ':' ); + if( (0 < nSepPos) && (nSepPos + 1 < aColSpanToken.getLength()) ) + { + // OOXML uses 1-based integer column indexes, row model expects 0-based colspans + sal_Int32 nLastCol = ::std::min( aColSpanToken.copy( nSepPos + 1 ).toInt32() - 1, nMaxCol ); + aModel.insertColSpan( ValueRange( aColSpanToken.copy( 0, nSepPos ).toInt32() - 1, nLastCol ) ); + } + } + // set row properties in the current sheet setRowModel( aModel ); } -void SheetDataContext::importCell( const AttributeList& rAttribs ) +bool SheetDataContext::importCell( const AttributeList& rAttribs ) { - maCurrCell.reset(); - maCurrCell.mxCell = getCell( rAttribs.getString( XML_r, OUString() ), &maCurrCell.maAddress ); - maCurrCell.mnCellType = rAttribs.getToken( XML_t, XML_n ); - maCurrCell.mnXfId = rAttribs.getInteger( XML_s, -1 ); - maCurrCell.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); - mxInlineStr.reset(); + bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAttribs.getString( XML_r, OUString() ), mnSheet, true ); + if( bValidAddr ) + { + maCellData.mnCellType = rAttribs.getToken( XML_t, XML_n ); + maCellData.mnXfId = rAttribs.getInteger( XML_s, -1 ); + maCellData.mbShowPhonetic = rAttribs.getBool( XML_ph, false ); - // update used area of the sheet - if( maCurrCell.mxCell.is() ) - extendUsedArea( maCurrCell.maAddress ); + // reset cell value, formula settings, and inline string + maCellValue = OUString(); + mxInlineStr.reset(); + mbHasFormula = false; + + // update used area of the sheet + extendUsedArea( maCellData.maCellAddr ); + } + return bValidAddr; } void SheetDataContext::importFormula( const AttributeList& rAttribs ) { - maCurrCell.maFormulaRef = rAttribs.getString( XML_ref, OUString() ); - maCurrCell.mnFormulaType = rAttribs.getToken( XML_t, XML_normal ); - maCurrCell.mnSharedId = rAttribs.getInteger( XML_si, -1 ); - maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() ); - maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() ); - maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false ); - maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false ); - maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false ); - maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false ); + mbHasFormula = true; + mbValidRange = mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, rAttribs.getString( XML_ref, OUString() ), mnSheet, true, true ); + + maFmlaData.mnFormulaType = rAttribs.getToken( XML_t, XML_normal ); + maFmlaData.mnSharedId = rAttribs.getInteger( XML_si, -1 ); + + if( maFmlaData.mnFormulaType == XML_dataTable ) + { + maTableData.maRef1 = rAttribs.getString( XML_r1, OUString() ); + maTableData.maRef2 = rAttribs.getString( XML_r2, OUString() ); + maTableData.mb2dTable = rAttribs.getBool( XML_dt2D, false ); + maTableData.mbRowTable = rAttribs.getBool( XML_dtr, false ); + maTableData.mbRef1Deleted = rAttribs.getBool( XML_del1, false ); + maTableData.mbRef2Deleted = rAttribs.getBool( XML_del2, false ); + } + + // clear token array, will be regenerated from element text + maTokens = ApiTokenSequence(); } -void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eCellType ) +void SheetDataContext::importRow( SequenceInputStream& rStrm ) { - maCurrCell.reset(); + RowModel aModel; + sal_Int32 nSpanCount; + sal_uInt16 nHeight, nFlags1; + sal_uInt8 nFlags2; + rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2 >> nSpanCount; + maCurrPos.mnCol = 0; + // row index is 0-based in BIFF12, but RowModel expects 1-based + aModel.mnRow = maCurrPos.mnRow + 1; + // row height is in twips in BIFF12, convert to points + aModel.mfHeight = nHeight / 20.0; + aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 ); + aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT ); + aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT ); + aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC ); + aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN ); + aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED ); + aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP ); + aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM ); + + // read the column spans + sal_Int32 nMaxCol = mrAddressConv.getMaxApiAddress().Column; + for( sal_Int32 nSpanIdx = 0; (nSpanIdx < nSpanCount) && !rStrm.isEof(); ++nSpanIdx ) + { + sal_Int32 nFirstCol, nLastCol; + rStrm >> nFirstCol >> nLastCol; + aModel.insertColSpan( ValueRange( nFirstCol, ::std::min( nLastCol, nMaxCol ) ) ); + } + + // set row properties in the current sheet + setRowModel( aModel ); +} + +bool SheetDataContext::readCellHeader( SequenceInputStream& rStrm, CellType eCellType ) +{ switch( eCellType ) { case CELLTYPE_VALUE: @@ -388,200 +408,157 @@ void SheetDataContext::importCellHeader( SequenceInputStream& rStrm, CellType eC sal_uInt32 nXfId; rStrm >> nXfId; - maCurrCell.mxCell = getCell( maCurrPos, &maCurrCell.maAddress ); - maCurrCell.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 ); - maCurrCell.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC ); + bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, maCurrPos, mnSheet, true ); + maCellData.mnXfId = extractValue< sal_Int32 >( nXfId, 0, 24 ); + maCellData.mbShowPhonetic = getFlag( nXfId, BIFF12_CELL_SHOWPHONETIC ); // update used area of the sheet - if( maCurrCell.mxCell.is() ) - extendUsedArea( maCurrCell.maAddress ); + if( bValidAddr ) + extendUsedArea( maCellData.maCellAddr ); + return bValidAddr; +} + +ApiTokenSequence SheetDataContext::readCellFormula( SequenceInputStream& rStrm ) +{ + rStrm.skip( 2 ); + return mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm ); +} + +bool SheetDataContext::readFormulaRef( SequenceInputStream& rStrm ) +{ + BinRange aRange; + rStrm >> aRange; + return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true ); } void SheetDataContext::importCellBool( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_b; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { + maCellData.mnCellType = XML_b; bool bValue = rStrm.readuInt8() != 0; if( eCellType == CELLTYPE_FORMULA ) - { - importCellFormula( rStrm ); - } + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - { - setBooleanCell( maCurrCell.mxCell, bValue ); - // #108770# set 'Standard' number format for all Boolean cells - maCurrCell.mnNumFmtId = 0; - } + mrSheetData.setBooleanCell( maCellData, bValue ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellBlank( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellBlank - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, eCellType ) ) + mrSheetData.setBlankCell( maCellData ); } void SheetDataContext::importCellDouble( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { + maCellData.mnCellType = XML_n; double fValue = rStrm.readDouble(); if( eCellType == CELLTYPE_FORMULA ) - importCellFormula( rStrm ); + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - maCurrCell.mxCell->setValue( fValue ); + mrSheetData.setValueCell( maCellData, fValue ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellError( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_e; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { + maCellData.mnCellType = XML_e; sal_uInt8 nErrorCode = rStrm.readuInt8(); if( eCellType == CELLTYPE_FORMULA ) - importCellFormula( rStrm ); + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - setErrorCell( maCurrCell.mxCell, nErrorCode ); + mrSheetData.setErrorCell( maCellData, nErrorCode ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellRk( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRk - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) - maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); + } } void SheetDataContext::importCellRString( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellRString - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_inlineStr; - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { - RichString aString( *this ); - aString.importString( rStrm, true ); - aString.finalizeImport(); - aString.convert( xText, maCurrCell.mnXfId ); + maCellData.mnCellType = XML_inlineStr; + RichStringRef xString( new RichString( *this ) ); + xString->importString( rStrm, true ); + xString->finalizeImport(); + mrSheetData.setStringCell( maCellData, xString ); } - setCellFormat( maCurrCell ); } void SheetDataContext::importCellSi( SequenceInputStream& rStrm, CellType eCellType ) { OSL_ENSURE( eCellType != CELLTYPE_FORMULA, "SheetDataContext::importCellSi - no formula cells supported" ); - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_s; - if( maCurrCell.mxCell.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) - setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, eCellType ) ) + { + maCellData.mnCellType = XML_s; + mrSheetData.setStringCell( maCellData, rStrm.readInt32() ); + } } void SheetDataContext::importCellString( SequenceInputStream& rStrm, CellType eCellType ) { - importCellHeader( rStrm, eCellType ); - maCurrCell.mnCellType = XML_inlineStr; - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() && (maCurrCell.mxCell->getType() == CellContentType_EMPTY) ) + if( readCellHeader( rStrm, eCellType ) ) { - RichString aString( *this ); - aString.importString( rStrm, false ); - aString.finalizeImport(); + maCellData.mnCellType = XML_inlineStr; + // always import the string, stream will point to formula afterwards, if existing + RichStringRef xString( new RichString( *this ) ); + xString->importString( rStrm, false ); + xString->finalizeImport(); if( eCellType == CELLTYPE_FORMULA ) - importCellFormula( rStrm ); + mrSheetData.setFormulaCell( maCellData, readCellFormula( rStrm ) ); else - aString.convert( xText, maCurrCell.mnXfId ); - } - setCellFormat( maCurrCell ); -} - -void SheetDataContext::importCellFormula( SequenceInputStream& rStrm ) -{ - rStrm.skip( 2 ); - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY ); - if( xTokens.is() ) - { - ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); - getFormulaParser().importFormula( aContext, rStrm ); + mrSheetData.setStringCell( maCellData, xString ); } } -void SheetDataContext::importRow( SequenceInputStream& rStrm ) -{ - RowModel aModel; - - sal_uInt16 nHeight, nFlags1; - sal_uInt8 nFlags2; - rStrm >> maCurrPos.mnRow >> aModel.mnXfId >> nHeight >> nFlags1 >> nFlags2; - - // row index is 0-based in BIFF12, but RowModel expects 1-based - aModel.mnFirstRow = aModel.mnLastRow = maCurrPos.mnRow + 1; - // row height is in twips in BIFF12, convert to points - aModel.mfHeight = nHeight / 20.0; - aModel.mnLevel = extractValue< sal_Int32 >( nFlags1, 8, 3 ); - aModel.mbCustomHeight = getFlag( nFlags1, BIFF12_ROW_CUSTOMHEIGHT ); - aModel.mbCustomFormat = getFlag( nFlags1, BIFF12_ROW_CUSTOMFORMAT ); - aModel.mbShowPhonetic = getFlag( nFlags2, BIFF12_ROW_SHOWPHONETIC ); - aModel.mbHidden = getFlag( nFlags1, BIFF12_ROW_HIDDEN ); - aModel.mbCollapsed = getFlag( nFlags1, BIFF12_ROW_COLLAPSED ); - aModel.mbThickTop = getFlag( nFlags1, BIFF12_ROW_THICKTOP ); - aModel.mbThickBottom = getFlag( nFlags1, BIFF12_ROW_THICKBOTTOM ); - // set row properties in the current sheet - setRowModel( aModel ); -} - void SheetDataContext::importArray( SequenceInputStream& rStrm ) { - BinRange aRange; - rStrm >> aRange; - CellRangeAddress aArrayRange; - Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange ); - Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY ); - if( xRange.is() && xTokens.is() ) + if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) { rStrm.skip( 1 ); - ArrayFormulaContext aContext( xTokens, aArrayRange ); - getFormulaParser().importFormula( aContext, rStrm ); + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm ); + mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens ); } } -void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm ) -{ - getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress ); -} - void SheetDataContext::importDataTable( SequenceInputStream& rStrm ) { - BinRange aRange; - rStrm >> aRange; - CellRangeAddress aTableRange; - if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) ) + if( readFormulaRef( rStrm ) ) { - DataTableModel aModel; BinAddress aRef1, aRef2; sal_uInt8 nFlags; rStrm >> aRef1 >> aRef2 >> nFlags; - aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); - aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); - aModel.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW ); - aModel.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D ); - aModel.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL ); - aModel.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL ); - setTableOperation( aTableRange, aModel ); + maTableData.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); + maTableData.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); + maTableData.mbRowTable = getFlag( nFlags, BIFF12_DATATABLE_ROW ); + maTableData.mb2dTable = getFlag( nFlags, BIFF12_DATATABLE_2D ); + maTableData.mbRef1Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF1DEL ); + maTableData.mbRef2Deleted = getFlag( nFlags, BIFF12_DATATABLE_REF2DEL ); + mrSheetData.createTableOperation( maFmlaData.maFormulaRef, maTableData ); + } +} + +void SheetDataContext::importSharedFmla( SequenceInputStream& rStrm ) +{ + if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) + { + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm ); + mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens ); } } @@ -589,26 +566,27 @@ void SheetDataContext::importDataTable( SequenceInputStream& rStrm ) BiffSheetDataContext::BiffSheetDataContext( const WorksheetHelper& rHelper ) : BiffWorksheetContextBase( rHelper ), + SheetDataContextBase( rHelper ), mnBiff2XfId( 0 ) { - mnArrayIgnoreSize = (getBiff() == BIFF2) ? 1 : ((getBiff() <= BIFF4) ? 2 : 6); switch( getBiff() ) { case BIFF2: - mnFormulaIgnoreSize = 9; // double formula result, 1 byte flags - mnArrayIgnoreSize = 1; // recalc-always flag + mnFormulaSkipSize = 9; // double formula result, 1 byte flags + mnArraySkipSize = 1; // recalc-always flag break; case BIFF3: case BIFF4: - mnFormulaIgnoreSize = 10; // double formula result, 2 byte flags - mnArrayIgnoreSize = 2; // 2 byte flags + mnFormulaSkipSize = 10; // double formula result, 2 byte flags + mnArraySkipSize = 2; // 2 byte flags break; case BIFF5: case BIFF8: - mnFormulaIgnoreSize = 14; // double formula result, 2 byte flags, 4 bytes nothing - mnArrayIgnoreSize = 6; // 2 byte flags, 4 bytes nothing + mnFormulaSkipSize = 14; // double formula result, 2 byte flags, 4 bytes nothing + mnArraySkipSize = 6; // 2 byte flags, 4 bytes nothing + break; + case BIFF_UNKNOWN: break; - case BIFF_UNKNOWN: break; } } @@ -689,258 +667,284 @@ void BiffSheetDataContext::importRecord( BiffInputStream& rStrm ) } break; - case BIFF_UNKNOWN: break; + case BIFF_UNKNOWN: + break; } } } // private -------------------------------------------------------------------- -void BiffSheetDataContext::setCurrCell( const BinAddress& rAddr ) -{ - maCurrCell.reset(); - maCurrCell.mxCell = getCell( rAddr, &maCurrCell.maAddress ); - // update used area of the sheet - if( maCurrCell.mxCell.is() ) - extendUsedArea( maCurrCell.maAddress ); -} - -void BiffSheetDataContext::importXfId( BiffInputStream& rStrm, bool bBiff2 ) +void BiffSheetDataContext::importRow( BiffInputStream& rStrm ) { - if( bBiff2 ) + RowModel aModel; + sal_uInt16 nRow, nFirstUsedCol, nFirstFreeCol, nHeight; + rStrm >> nRow >> nFirstUsedCol >> nFirstFreeCol >> nHeight; + if( getBiff() == BIFF2 ) { - sal_uInt8 nBiff2XfId; - rStrm >> nBiff2XfId; rStrm.skip( 2 ); - maCurrCell.mnXfId = nBiff2XfId & BIFF2_XF_MASK; - if( maCurrCell.mnXfId == BIFF2_XF_EXTENDED_IDS ) - maCurrCell.mnXfId = mnBiff2XfId; + aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT; + if( aModel.mbCustomFormat ) + { + rStrm.skip( 5 ); + aModel.mnXfId = rStrm.readuInt16(); + } } else { - maCurrCell.mnXfId = rStrm.readuInt16(); + rStrm.skip( 4 ); + sal_uInt32 nFlags = rStrm.readuInt32(); + aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 ); + aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 ); + aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT ); + aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT ); + aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC ); + aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN ); + aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED ); + aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP ); + aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM ); } + + // row index is 0-based in BIFF, but RowModel expects 1-based + aModel.mnRow = static_cast< sal_Int32 >( nRow ) + 1; + // row height is in twips in BIFF, convert to points + aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0; + // set column spans + if( nFirstUsedCol < nFirstFreeCol ) + { + sal_Int32 nLastCol = ::std::min< sal_Int32 >( nFirstFreeCol - 1, mrAddressConv.getMaxApiAddress().Column ); + aModel.insertColSpan( ValueRange( nFirstUsedCol, nLastCol ) ); + } + + // set row properties in the current sheet + setRowModel( aModel ); } -void BiffSheetDataContext::importCellHeader( BiffInputStream& rStrm, bool bBiff2 ) +bool BiffSheetDataContext::readCellXfId( BiffInputStream& rStrm, const BinAddress& rAddr, bool bBiff2 ) +{ + bool bValidAddr = mrAddressConv.convertToCellAddress( maCellData.maCellAddr, rAddr, mnSheet, true ); + if( bValidAddr ) + { + // update used area of the sheet + extendUsedArea( maCellData.maCellAddr ); + + // load the XF identifier according to current BIFF version + if( bBiff2 ) + { + /* #i71453# On first call, check if the file contains XF records + (by trying to access the first XF with index 0). If there are + no XFs, the explicit formatting information contained in each + cell record will be used instead. */ + if( !mobBiff2HasXfs ) + mobBiff2HasXfs = getStyles().getCellXf( 0 ).get() != 0; + // read formatting information (includes the XF identifier) + sal_uInt8 nFlags1, nFlags2, nFlags3; + rStrm >> nFlags1 >> nFlags2 >> nFlags3; + /* If the file contains XFs, extract and set the XF identifier, + otherwise get the explicit formatting. */ + if( mobBiff2HasXfs.get() ) + { + maCellData.mnXfId = extractValue< sal_Int32 >( nFlags1, 0, 6 ); + /* If the identifier is equal to 63, then the real identifier + is contained in the preceding IXFE record (stored in the + class member mnBiff2XfId). */ + if( maCellData.mnXfId == BIFF2_CELL_USEIXFE ) + maCellData.mnXfId = mnBiff2XfId; + } + else + { + /* Let the Xf class do the API conversion. Keeping the member + maCellData.mnXfId untouched will prevent to trigger the + usual XF formatting conversion later on. */ + PropertySet aPropSet( getCell( maCellData.maCellAddr ) ); + Xf::writeBiff2CellFormatToPropertySet( *this, aPropSet, nFlags1, nFlags2, nFlags3 ); + } + } + else + { + // BIFF3-BIFF8: 16-bit XF identifier + maCellData.mnXfId = rStrm.readuInt16(); + } + } + return bValidAddr; +} + +bool BiffSheetDataContext::readCellHeader( BiffInputStream& rStrm, bool bBiff2 ) { BinAddress aAddr; rStrm >> aAddr; - setCurrCell( aAddr ); - importXfId( rStrm, bBiff2 ); + return readCellXfId( rStrm, aAddr, bBiff2 ); +} + +bool BiffSheetDataContext::readFormulaRef( BiffInputStream& rStrm ) +{ + BinRange aRange; + aRange.read( rStrm, false ); // columns always 8-bit + return mrAddressConv.convertToCellRange( maFmlaData.maFormulaRef, aRange, mnSheet, true, true ); } void BiffSheetDataContext::importBlank( BiffInputStream& rStrm ) { - importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BLANK ) ) + mrSheetData.setBlankCell( maCellData ); } void BiffSheetDataContext::importBoolErr( BiffInputStream& rStrm ) { - importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR ); - if( maCurrCell.mxCell.is() ) + if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_BOOLERR ) ) { sal_uInt8 nValue, nType; rStrm >> nValue >> nType; switch( nType ) { case BIFF_BOOLERR_BOOL: - maCurrCell.mnCellType = XML_b; - setBooleanCell( maCurrCell.mxCell, nValue != 0 ); - // #108770# set 'Standard' number format for all Boolean cells - maCurrCell.mnNumFmtId = 0; + maCellData.mnCellType = XML_b; + mrSheetData.setBooleanCell( maCellData, nValue != 0 ); break; case BIFF_BOOLERR_ERROR: - maCurrCell.mnCellType = XML_e; - setErrorCell( maCurrCell.mxCell, nValue ); + maCellData.mnCellType = XML_e; + mrSheetData.setErrorCell( maCellData, nValue ); break; default: OSL_ENSURE( false, "BiffSheetDataContext::importBoolErr - unknown cell type" ); + maCellData.mnCellType = XML_TOKEN_INVALID; + mrSheetData.setBlankCell( maCellData ); } } - setCellFormat( maCurrCell ); } void BiffSheetDataContext::importFormula( BiffInputStream& rStrm ) { - importCellHeader( rStrm, getBiff() == BIFF2 ); - maCurrCell.mnCellType = XML_n; - Reference< XFormulaTokens > xTokens( maCurrCell.mxCell, UNO_QUERY ); - if( xTokens.is() ) + if( readCellHeader( rStrm, getBiff() == BIFF2 ) ) { - rStrm.skip( mnFormulaIgnoreSize ); - ExtCellFormulaContext aContext( *this, xTokens, maCurrCell.maAddress ); - getFormulaParser().importFormula( aContext, rStrm ); + maCellData.mnCellType = XML_n; + rStrm.skip( mnFormulaSkipSize ); + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_CELL, rStrm ); + mrSheetData.setFormulaCell( maCellData, aTokens ); } - setCellFormat( maCurrCell ); } void BiffSheetDataContext::importInteger( BiffInputStream& rStrm ) { - importCellHeader( rStrm, true ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( rStrm.readuInt16() ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, true ) ) + { + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, rStrm.readuInt16() ); + } } void BiffSheetDataContext::importLabel( BiffInputStream& rStrm ) { + /* the deep secrets of BIFF type and record identifier... + record id BIFF -> XF type String type + 0x0004 2-7 -> 3 byte 8-bit length, byte string + 0x0004 8 -> 3 byte 16-bit length, unicode string + 0x0204 2-7 -> 2 byte 16-bit length, byte string + 0x0204 8 -> 2 byte 16-bit length, unicode string + */ bool bBiff2Xf = rStrm.getRecId() == BIFF2_ID_LABEL; - importCellHeader( rStrm, bBiff2Xf ); - maCurrCell.mnCellType = XML_inlineStr; - Reference< XText > xText( maCurrCell.mxCell, UNO_QUERY ); - if( xText.is() ) - { - /* the deep secrets of BIFF type and record identifier... - record id BIFF -> XF type String type - 0x0004 2-7 -> 3 byte 8-bit length, byte string - 0x0004 8 -> 3 byte 16-bit length, unicode string - 0x0204 2-7 -> 2 byte 16-bit length, byte string - 0x0204 8 -> 2 byte 16-bit length, unicode string */ - - RichString aString( *this ); + if( readCellHeader( rStrm, bBiff2Xf ) ) + { + maCellData.mnCellType = XML_inlineStr; if( getBiff() == BIFF8 ) { - aString.importUniString( rStrm ); + // string may contain rich-text formatting + RichStringRef xString( new RichString( *this ) ); + xString->importUniString( rStrm ); + xString->finalizeImport(); + mrSheetData.setStringCell( maCellData, xString ); } else { // #i63105# use text encoding from FONT record rtl_TextEncoding eTextEnc = getTextEncoding(); - if( const Font* pFont = getStyles().getFontFromCellXf( maCurrCell.mnXfId ).get() ) + if( const Font* pFont = getStyles().getFontFromCellXf( maCellData.mnXfId ).get() ) eTextEnc = pFont->getFontEncoding(); - BiffStringFlags nFlags = bBiff2Xf ? BIFF_STR_8BITLENGTH : BIFF_STR_DEFAULT; - setFlag( nFlags, BIFF_STR_EXTRAFONTS, rStrm.getRecId() == BIFF_ID_RSTRING ); - aString.importByteString( rStrm, eTextEnc, nFlags ); + // RSTRING record contains rich-text formatting + if( rStrm.getRecId() == BIFF_ID_RSTRING ) + { + BiffStringFlags nFlags = BIFF_STR_EXTRAFONTS; + // BIFF2 record identifier: 8-bit string length (see above) + setFlag( nFlags, BIFF_STR_8BITLENGTH, bBiff2Xf ); + RichStringRef xString( new RichString( *this ) ); + xString->importByteString( rStrm, eTextEnc, nFlags ); + xString->finalizeImport(); + mrSheetData.setStringCell( maCellData, xString ); + } + else + { + // BIFF2 record identifier: 8-bit string length (see above) + OUString aText = rStrm.readByteStringUC( !bBiff2Xf, eTextEnc ); + mrSheetData.setStringCell( maCellData, aText ); + } } - aString.finalizeImport(); - aString.convert( xText, maCurrCell.mnXfId ); } - setCellFormat( maCurrCell ); } void BiffSheetDataContext::importLabelSst( BiffInputStream& rStrm ) { - importCellHeader( rStrm, false ); - maCurrCell.mnCellType = XML_s; - if( maCurrCell.mxCell.is() ) - setSharedStringCell( maCurrCell.mxCell, rStrm.readInt32(), maCurrCell.mnXfId ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, false ) ) + { + maCellData.mnCellType = XML_s; + mrSheetData.setStringCell( maCellData, rStrm.readInt32() ); + } } void BiffSheetDataContext::importMultBlank( BiffInputStream& rStrm ) { BinAddress aAddr; - for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol ) - { - setCurrCell( aAddr ); - importXfId( rStrm, false ); - setCellFormat( maCurrCell ); - } + bool bValidAddr = true; + for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol ) + if( (bValidAddr = readCellXfId( rStrm, aAddr, false )) == true ) + mrSheetData.setBlankCell( maCellData ); } void BiffSheetDataContext::importMultRk( BiffInputStream& rStrm ) { BinAddress aAddr; - for( rStrm >> aAddr; rStrm.getRemaining() > 2; ++aAddr.mnCol ) + bool bValidAddr = true; + for( rStrm >> aAddr; bValidAddr && (rStrm.getRemaining() > 2); ++aAddr.mnCol ) { - setCurrCell( aAddr ); - maCurrCell.mnCellType = XML_n; - importXfId( rStrm, false ); - sal_Int32 nRkValue = rStrm.readInt32(); - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( nRkValue ) ); - setCellFormat( maCurrCell ); + if( (bValidAddr = readCellXfId( rStrm, aAddr, false )) == true ) + { + maCellData.mnCellType = XML_n; + sal_Int32 nRkValue = rStrm.readInt32(); + mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( nRkValue ) ); + } } } void BiffSheetDataContext::importNumber( BiffInputStream& rStrm ) { - importCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( rStrm.readDouble() ); - setCellFormat( maCurrCell ); + if( readCellHeader( rStrm, rStrm.getRecId() == BIFF2_ID_NUMBER ) ) + { + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, rStrm.readDouble() ); + } } void BiffSheetDataContext::importRk( BiffInputStream& rStrm ) { - importCellHeader( rStrm, false ); - maCurrCell.mnCellType = XML_n; - if( maCurrCell.mxCell.is() ) - maCurrCell.mxCell->setValue( BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); - setCellFormat( maCurrCell ); -} - -void BiffSheetDataContext::importRow( BiffInputStream& rStrm ) -{ - RowModel aModel; - - sal_uInt16 nRow, nHeight; - rStrm >> nRow; - rStrm.skip( 4 ); - rStrm >> nHeight; - if( getBiff() == BIFF2 ) + if( readCellHeader( rStrm, false ) ) { - rStrm.skip( 2 ); - aModel.mbCustomFormat = rStrm.readuInt8() == BIFF2_ROW_CUSTOMFORMAT; - if( aModel.mbCustomFormat ) - { - rStrm.skip( 5 ); - aModel.mnXfId = rStrm.readuInt16(); - } + maCellData.mnCellType = XML_n; + mrSheetData.setValueCell( maCellData, BiffHelper::calcDoubleFromRk( rStrm.readInt32() ) ); } - else - { - rStrm.skip( 4 ); - sal_uInt32 nFlags = rStrm.readuInt32(); - aModel.mnXfId = extractValue< sal_Int32 >( nFlags, 16, 12 ); - aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 0, 3 ); - aModel.mbCustomFormat = getFlag( nFlags, BIFF_ROW_CUSTOMFORMAT ); - aModel.mbCustomHeight = getFlag( nFlags, BIFF_ROW_CUSTOMHEIGHT ); - aModel.mbShowPhonetic = getFlag( nFlags, BIFF_ROW_SHOWPHONETIC ); - aModel.mbHidden = getFlag( nFlags, BIFF_ROW_HIDDEN ); - aModel.mbCollapsed = getFlag( nFlags, BIFF_ROW_COLLAPSED ); - aModel.mbThickTop = getFlag( nFlags, BIFF_ROW_THICKTOP ); - aModel.mbThickBottom = getFlag( nFlags, BIFF_ROW_THICKBOTTOM ); - } - - // row index is 0-based in BIFF, but RowModel expects 1-based - aModel.mnFirstRow = aModel.mnLastRow = nRow + 1; - // row height is in twips in BIFF, convert to points - aModel.mfHeight = (nHeight & BIFF_ROW_HEIGHTMASK) / 20.0; - // set row properties in the current sheet - setRowModel( aModel ); } void BiffSheetDataContext::importArray( BiffInputStream& rStrm ) { - BinRange aRange; - aRange.read( rStrm, false ); // columns always 8-bit - CellRangeAddress aArrayRange; - Reference< XCellRange > xRange = getCellRange( aRange, &aArrayRange ); - Reference< XArrayFormulaTokens > xTokens( xRange, UNO_QUERY ); - if( xRange.is() && xTokens.is() ) + if( readFormulaRef( rStrm ) && maFmlaData.isValidArrayRef( maCellData.maCellAddr ) ) { - rStrm.skip( mnArrayIgnoreSize ); - ArrayFormulaContext aContext( xTokens, aArrayRange ); - getFormulaParser().importFormula( aContext, rStrm ); + rStrm.skip( mnArraySkipSize ); + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_ARRAY, rStrm ); + mrSheetData.createArrayFormula( maFmlaData.maFormulaRef, aTokens ); } } -void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm ) -{ - getSharedFormulas().importSharedFmla( rStrm, maCurrCell.maAddress ); -} - void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm ) { - BinRange aRange; - aRange.read( rStrm, false ); // columns always 8-bit - CellRangeAddress aTableRange; - if( getAddressConverter().convertToCellRange( aTableRange, aRange, getSheetIndex(), true, true ) ) + if( readFormulaRef( rStrm ) ) { DataTableModel aModel; BinAddress aRef1, aRef2; @@ -972,7 +976,17 @@ void BiffSheetDataContext::importDataTable( BiffInputStream& rStrm ) } aModel.maRef1 = FormulaProcessorBase::generateAddress2dString( aRef1, false ); aModel.maRef2 = FormulaProcessorBase::generateAddress2dString( aRef2, false ); - setTableOperation( aTableRange, aModel ); + mrSheetData.createTableOperation( maFmlaData.maFormulaRef, aModel ); + } +} + +void BiffSheetDataContext::importSharedFmla( BiffInputStream& rStrm ) +{ + if( readFormulaRef( rStrm ) && maFmlaData.isValidSharedRef( maCellData.maCellAddr ) ) + { + rStrm.skip( 2 ); // flags + ApiTokenSequence aTokens = mrFormulaParser.importFormula( maCellData.maCellAddr, FORMULATYPE_SHAREDFORMULA, rStrm ); + mrSheetData.createSharedFormula( maCellData.maCellAddr, aTokens ); } } diff --git a/oox/source/xls/stylesbuffer.cxx b/oox/source/xls/stylesbuffer.cxx index 1ece7ec7c..c595fb57d 100644 --- a/oox/source/xls/stylesbuffer.cxx +++ b/oox/source/xls/stylesbuffer.cxx @@ -2484,6 +2484,41 @@ void Xf::writeToPropertySet( PropertySet& rPropSet ) const rPropSet.setProperties( aPropMap ); } +/*static*/ void Xf::writeBiff2CellFormatToPropertySet( const WorkbookHelper& rHelper, + PropertySet& rPropSet, sal_uInt8 nFlags1, sal_uInt8 nFlags2, sal_uInt8 nFlags3 ) +{ + /* Create an XF object and let it do the work. We will have access to its + private members here. Also, create temporary border and fill objects, + this prevents polluting the border and fill buffers with new temporary + objects per imported cell. */ + Xf aXf( rHelper ); + Border aBorder( rHelper, false ); + Fill aFill( rHelper, false ); + + // no used flags available in BIFF2 (always true) + aXf.setAllUsedFlags( true ); + + // set the attributes + aXf.maModel.mnFontId = extractValue< sal_Int32 >( nFlags2, 6, 2 ); + aXf.maModel.mnNumFmtId = extractValue< sal_Int32 >( nFlags2, 0, 6 ); + aXf.maAlignment.setBiff2Data( nFlags3 ); + aXf.maProtection.setBiff2Data( nFlags1 ); + aBorder.setBiff2Data( nFlags3 ); + aFill.setBiff2Data( nFlags3 ); + + // finalize the objects (convert model to API attributes) + aXf.finalizeImport(); + aBorder.finalizeImport(); + aFill.finalizeImport(); + + // write the properties to the property set + PropertyMap aPropMap; + aXf.writeToPropertyMap( aPropMap ); + aBorder.writeToPropertyMap( aPropMap ); + aFill.writeToPropertyMap( aPropMap ); + rPropSet.setProperties( aPropMap ); +} + void Xf::setBiffUsedFlags( sal_uInt8 nUsedFlags ) { /* Notes about finding the used flags: diff --git a/oox/source/xls/viewsettings.cxx b/oox/source/xls/viewsettings.cxx index c63b1c981..ec76f6e88 100644 --- a/oox/source/xls/viewsettings.cxx +++ b/oox/source/xls/viewsettings.cxx @@ -734,7 +734,7 @@ void ViewSettings::finalizeImport() sal_Int16 nShowMode = getWorkbookSettings().getApiShowObjectMode(); // view settings for all sheets - Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getGlobalFactory() ); + Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getBaseFilter().getComponentContext() ); if( !xSheetsNC.is() ) return; for( SheetPropertiesMap::const_iterator aIt = maSheetProps.begin(), aEnd = maSheetProps.end(); aIt != aEnd; ++aIt ) ContainerHelper::insertByName( xSheetsNC, rWorksheets.getCalcSheetName( aIt->first ), aIt->second ); @@ -746,7 +746,7 @@ void ViewSettings::finalizeImport() if( !rxActiveSheetView ) rxActiveSheetView.reset( new SheetViewModel ); - Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getGlobalFactory() ); + Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getBaseFilter().getComponentContext() ); if( xContainer.is() ) try { PropertyMap aPropMap; diff --git a/oox/source/xls/workbookfragment.cxx b/oox/source/xls/workbookfragment.cxx index d5f305511..4a1aa98b8 100644 --- a/oox/source/xls/workbookfragment.cxx +++ b/oox/source/xls/workbookfragment.cxx @@ -222,8 +222,10 @@ void WorkbookFragment::finalizeImport() /* Create fragments for all sheets, before importing them. Needed to do some preprocessing in the fragment constructors, e.g. loading the table fragments for all sheets that are needed before the cell formulas are - loaded. */ - typedef ::std::vector< FragmentHandlerRef > SheetFragmentVector; + loaded. Additionally, the instances of the WorkbookGlobals structures + have to be stored for every sheet. */ + typedef ::std::pair< WorksheetGlobalsRef, FragmentHandlerRef > SheetFragmentHandler; + typedef ::std::vector< SheetFragmentHandler > SheetFragmentVector; SheetFragmentVector aSheetFragments; WorksheetBuffer& rWorksheets = getWorksheets(); sal_Int32 nWorksheetCount = rWorksheets.getWorksheetCount(); @@ -238,34 +240,49 @@ void WorkbookFragment::finalizeImport() OSL_ENSURE( aFragmentPath.getLength() > 0, "WorkbookFragment::finalizeImport - cannot access sheet fragment" ); if( aFragmentPath.getLength() > 0 ) { - ::rtl::Reference< WorksheetFragmentBase > xFragment; double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - nWorksheet); ISegmentProgressBarRef xSheetSegment = getProgressBar().createSegment( fSegmentLength ); - // create the fragment according to the sheet type + // get the sheet type according to the relations type + WorksheetType eSheetType = SHEETTYPE_EMPTYSHEET; if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "worksheet" ) ) - { - xFragment.set( new WorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_WORKSHEET, nCalcSheet ) ); - } + eSheetType = SHEETTYPE_WORKSHEET; else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "chartsheet" ) ) - { - xFragment.set( new ChartsheetFragment( *this, aFragmentPath, xSheetSegment, nCalcSheet ) ); - } + eSheetType = SHEETTYPE_CHARTSHEET; else if( (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlMacrosheet" )) || (pRelation->maType == CREATE_MSOFFICE_RELATION_TYPE( "xlIntlMacrosheet" )) ) - { - xFragment.set( new WorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_MACROSHEET, nCalcSheet ) ); - } + eSheetType = SHEETTYPE_MACROSHEET; else if( pRelation->maType == CREATE_OFFICEDOC_RELATION_TYPE( "dialogsheet" ) ) + eSheetType = SHEETTYPE_DIALOGSHEET; + OSL_ENSURE( eSheetType != SHEETTYPE_EMPTYSHEET, "WorkbookFragment::finalizeImport - unknown sheet type" ); + if( eSheetType != SHEETTYPE_EMPTYSHEET ) { - xFragment.set( new WorksheetFragment( *this, aFragmentPath, xSheetSegment, SHEETTYPE_DIALOGSHEET, nCalcSheet ) ); + // create the WorksheetGlobals object + WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, xSheetSegment, eSheetType, nCalcSheet ); + OSL_ENSURE( xSheetGlob.get(), "WorkbookFragment::finalizeImport - missing sheet in document" ); + if( xSheetGlob.get() ) + { + // create the sheet fragment handler + ::rtl::Reference< WorksheetFragmentBase > xFragment; + switch( eSheetType ) + { + case SHEETTYPE_WORKSHEET: + case SHEETTYPE_MACROSHEET: + case SHEETTYPE_DIALOGSHEET: + xFragment.set( new WorksheetFragment( *xSheetGlob, aFragmentPath ) ); + break; + case SHEETTYPE_CHARTSHEET: + xFragment.set( new ChartsheetFragment( *xSheetGlob, aFragmentPath ) ); + break; + default: + OSL_ENSURE( false, "WorkbookFragment::finalizeImport - unexpected sheet type" ); + } + + // insert the fragment into the map + if( xFragment.is() ) + aSheetFragments.push_back( SheetFragmentHandler( xSheetGlob, xFragment.get() ) ); + } } - - // insert the fragment into the map - OSL_ENSURE( xFragment.is(), "WorkbookFragment::finalizeImport - unknown sheet type" ); - OSL_ENSURE( !xFragment.is() || xFragment->isValidSheet(), "WorkbookFragment::finalizeImport - missing sheet in document" ); - if( xFragment.is() && xFragment->isValidSheet() ) - aSheetFragments.push_back( xFragment.get() ); } } } @@ -278,9 +295,10 @@ void WorkbookFragment::finalizeImport() for( SheetFragmentVector::iterator aIt = aSheetFragments.begin(), aEnd = aSheetFragments.end(); aIt != aEnd; ++aIt ) { // import the sheet fragment - importOoxFragment( *aIt ); - // delete fragment object, will free all allocated sheet buffers - aIt->clear(); + importOoxFragment( aIt->second ); + // delete fragment object and WorkbookGlobals object, will free all allocated sheet buffers + aIt->second.clear(); + aIt->first.reset(); } // open the VBA project storage @@ -289,7 +307,7 @@ void WorkbookFragment::finalizeImport() { Reference< XInputStream > xInStrm = getBaseFilter().openInputStream( aVbaFragmentPath ); if( xInStrm.is() ) - setVbaProjectStorage( StorageRef( new ::oox::ole::OleStorage( getGlobalFactory(), xInStrm, false ) ) ); + setVbaProjectStorage( StorageRef( new ::oox::ole::OleStorage( getBaseFilter().getComponentContext(), xInStrm, false ) ) ); } // final conversions, e.g. calculation settings and view settings @@ -358,6 +376,7 @@ bool BiffWorkbookFragment::importFragment() { case BIFF_FRAGMENT_GLOBALS: { + BiffInputStream& rStrm = getInputStream(); // import workbook globals fragment and create sheets in document ISegmentProgressBarRef xGlobalsProgress = getProgressBar().createSegment( PROGRESS_LENGTH_GLOBALS ); bRet = importGlobalsFragment( *xGlobalsProgress ); @@ -366,10 +385,25 @@ bool BiffWorkbookFragment::importFragment() bool bNextSheet = bRet; for( sal_Int32 nWorksheet = 0, nWorksheetCount = rWorksheets.getWorksheetCount(); bNextSheet && (nWorksheet < nWorksheetCount); ++nWorksheet ) { - // try to start a new sheet fragment + // calculate progress size for the sheet double fSegmentLength = getProgressBar().getFreeLength() / (nWorksheetCount - nWorksheet); ISegmentProgressBarRef xSheetProgress = getProgressBar().createSegment( fSegmentLength ); - BiffFragmentType eSheetFragment = startFragment( getBiff(), rWorksheets.getBiffRecordHandle( nWorksheet ) ); + /* Try to start a new sheet fragment. The SHEET records point to the + first record of the sheet fragment which is usually a BOF record. */ + BiffFragmentType eSheetFragment = BIFF_FRAGMENT_UNKNOWN; + sal_Int64 nRecHandle = rWorksheets.getBiffRecordHandle( nWorksheet ); + if( rStrm.startRecordByHandle( nRecHandle ) ) + { + /* #i109800# Stream may point to any record of the sheet fragment. + Check the record identifier before calling startFragment(). */ + bool bIsBofRec = BiffHelper::isBofRecord( rStrm ); + /* Rewind the record. If it is the BOF record, it will be read in + startFragment(). In every case, stream will point before the + first available non-BOF record. */ + rStrm.rewindRecord(); + // if the BOF record is missing, a regular worksheet will be assumed + eSheetFragment = bIsBofRec ? startFragment( getBiff() ) : BIFF_FRAGMENT_WORKSHEET; + } sal_Int16 nCalcSheet = rWorksheets.getCalcSheetIndex( nWorksheet ); bNextSheet = importSheetFragment( *xSheetProgress, eSheetFragment, nCalcSheet ); } @@ -699,26 +733,32 @@ bool BiffWorkbookFragment::importSheetFragment( ISegmentProgressBar& rProgressBa break; } - // create the worksheet fragment + // create the WorksheetGlobals object ISegmentProgressBarRef xSheetProgress = rProgressBar.createSegment( rProgressBar.getFreeLength() ); + WorksheetGlobalsRef xSheetGlob = WorksheetHelper::constructGlobals( *this, xSheetProgress, eSheetType, nCalcSheet ); + OSL_ENSURE( xSheetGlob.get(), "BiffWorkbookFragment::importSheetFragment - missing sheet in document" ); + if( !xSheetGlob.get() ) + return false; + + // create the worksheet fragment ::boost::shared_ptr< BiffWorksheetFragmentBase > xFragment; switch( eSheetType ) { case SHEETTYPE_WORKSHEET: case SHEETTYPE_MACROSHEET: case SHEETTYPE_DIALOGSHEET: - xFragment.reset( new BiffWorksheetFragment( *this, xSheetProgress, eSheetType, nCalcSheet ) ); + xFragment.reset( new BiffWorksheetFragment( *xSheetGlob, *this ) ); break; case SHEETTYPE_CHARTSHEET: - xFragment.reset( new BiffChartsheetFragment( *this, xSheetProgress, nCalcSheet ) ); + xFragment.reset( new BiffChartsheetFragment( *xSheetGlob, *this ) ); break; case SHEETTYPE_MODULESHEET: case SHEETTYPE_EMPTYSHEET: - xFragment.reset( new BiffSkipWorksheetFragment( *this, xSheetProgress, nCalcSheet ) ); + xFragment.reset( new BiffSkipWorksheetFragment( *xSheetGlob, *this ) ); break; } // load the sheet fragment records - return xFragment->isValidSheet() && xFragment->importFragment(); + return xFragment.get() && xFragment->importFragment(); } // ============================================================================ diff --git a/oox/source/xls/workbookhelper.cxx b/oox/source/xls/workbookhelper.cxx index f72af4abc..ab11c886c 100644 --- a/oox/source/xls/workbookhelper.cxx +++ b/oox/source/xls/workbookhelper.cxx @@ -98,12 +98,12 @@ bool IgnoreCaseCompare::operator()( const OUString& rName1, const OUString& rNam // ============================================================================ -class WorkbookData +class WorkbookGlobals { public: - explicit WorkbookData( ExcelFilter& rFilter ); - explicit WorkbookData( ExcelBiffFilter& rFilter, BiffType eBiff ); - ~WorkbookData(); + explicit WorkbookGlobals( ExcelFilter& rFilter ); + explicit WorkbookGlobals( ExcelBiffFilter& rFilter, BiffType eBiff ); + ~WorkbookGlobals(); /** Returns true, if this helper refers to a valid document. */ inline bool isValid() const { return mxDoc.is(); } @@ -118,14 +118,15 @@ public: inline FilterType getFilterType() const { return meFilterType; } /** Returns true, if the file is a multi-sheet document, or false if single-sheet. */ inline bool isWorkbookFile() const { return mbWorkbook; } - /** Returns the index of the current sheet in the Calc document. */ - inline sal_Int16 getCurrentSheetIndex() const { return mnCurrSheet; } - /** Sets the index of the current sheet in the Calc document. */ - inline void setCurrentSheetIndex( sal_Int16 nSheet ) { mnCurrSheet = nSheet; } /** Returns the VBA project storage. */ inline StorageRef getVbaProjectStorage() const { return mxVbaPrjStrg; } - /** Sets the VBA project storage. */ + /** Returns the index of the current Calc sheet, if filter currently processes a sheet. */ + inline sal_Int16 getCurrentSheetIndex() const { return mnCurrSheet; } + + /** Sets the VBA project storage used to import VBA source code and forms. */ inline void setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ) { mxVbaPrjStrg = rxVbaPrjStrg; } + /** Sets the index of the current Calc sheet, if filter currently processes a sheet. */ + inline void setCurrentSheetIndex( sal_Int16 nSheet ) { mnCurrSheet = nSheet; } // document model --------------------------------------------------------- @@ -286,7 +287,7 @@ private: // ---------------------------------------------------------------------------- -WorkbookData::WorkbookData( ExcelFilter& rFilter ) : +WorkbookGlobals::WorkbookGlobals( ExcelFilter& rFilter ) : mrBaseFilter( rFilter ), mrExcelBase( rFilter ), meFilterType( FILTER_OOXML ), @@ -295,11 +296,11 @@ WorkbookData::WorkbookData( ExcelFilter& rFilter ) : meBiff( BIFF_UNKNOWN ) { // register at the filter, needed for virtual callbacks (even during construction) - mrExcelBase.registerWorkbookData( *this ); + mrExcelBase.registerWorkbookGlobals( *this ); initialize( true ); } -WorkbookData::WorkbookData( ExcelBiffFilter& rFilter, BiffType eBiff ) : +WorkbookGlobals::WorkbookGlobals( ExcelBiffFilter& rFilter, BiffType eBiff ) : mrBaseFilter( rFilter ), mrExcelBase( rFilter ), meFilterType( FILTER_BIFF ), @@ -308,19 +309,19 @@ WorkbookData::WorkbookData( ExcelBiffFilter& rFilter, BiffType eBiff ) : meBiff( eBiff ) { // register at the filter, needed for virtual callbacks (even during construction) - mrExcelBase.registerWorkbookData( *this ); + mrExcelBase.registerWorkbookGlobals( *this ); initialize( eBiff >= BIFF5 ); } -WorkbookData::~WorkbookData() +WorkbookGlobals::~WorkbookGlobals() { finalize(); - mrExcelBase.unregisterWorkbookData(); + mrExcelBase.unregisterWorkbookGlobals(); } // document model ------------------------------------------------------------- -Reference< XNameContainer > WorkbookData::getStyleFamily( bool bPageStyles ) const +Reference< XNameContainer > WorkbookGlobals::getStyleFamily( bool bPageStyles ) const { Reference< XNameContainer > xStylesNC; try @@ -332,11 +333,11 @@ Reference< XNameContainer > WorkbookData::getStyleFamily( bool bPageStyles ) con catch( Exception& ) { } - OSL_ENSURE( xStylesNC.is(), "WorkbookData::getStyleFamily - cannot access style family" ); + OSL_ENSURE( xStylesNC.is(), "WorkbookGlobals::getStyleFamily - cannot access style family" ); return xStylesNC; } -Reference< XStyle > WorkbookData::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const +Reference< XStyle > WorkbookGlobals::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const { Reference< XStyle > xStyle; try @@ -347,11 +348,11 @@ Reference< XStyle > WorkbookData::getStyleObject( const OUString& rStyleName, bo catch( Exception& ) { } - OSL_ENSURE( xStyle.is(), "WorkbookData::getStyleObject - cannot access style object" ); + OSL_ENSURE( xStyle.is(), "WorkbookGlobals::getStyleObject - cannot access style object" ); return xStyle; } -Reference< XNamedRange > WorkbookData::createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const +Reference< XNamedRange > WorkbookGlobals::createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const { // create the name and insert it into the Calc document Reference< XNamedRange > xNamedRange; @@ -369,11 +370,11 @@ Reference< XNamedRange > WorkbookData::createNamedRangeObject( OUString& orName, catch( Exception& ) { } - OSL_ENSURE( xNamedRange.is(), "WorkbookData::createNamedRangeObject - cannot create defined name" ); + OSL_ENSURE( xNamedRange.is(), "WorkbookGlobals::createNamedRangeObject - cannot create defined name" ); return xNamedRange; } -Reference< XDatabaseRange > WorkbookData::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const +Reference< XDatabaseRange > WorkbookGlobals::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const { // validate cell range CellRangeAddress aDestRange = rRangeAddr; @@ -395,11 +396,11 @@ Reference< XDatabaseRange > WorkbookData::createDatabaseRangeObject( OUString& o catch( Exception& ) { } - OSL_ENSURE( xDatabaseRange.is(), "WorkbookData::createDatabaseRangeObject - cannot create database range" ); + OSL_ENSURE( xDatabaseRange.is(), "WorkbookGlobals::createDatabaseRangeObject - cannot create database range" ); return xDatabaseRange; } -Reference< XStyle > WorkbookData::createStyleObject( OUString& orStyleName, bool bPageStyle ) const +Reference< XStyle > WorkbookGlobals::createStyleObject( OUString& orStyleName, bool bPageStyle ) const { Reference< XStyle > xStyle; try @@ -411,63 +412,62 @@ Reference< XStyle > WorkbookData::createStyleObject( OUString& orStyleName, bool catch( Exception& ) { } - OSL_ENSURE( xStyle.is(), "WorkbookData::createStyleObject - cannot create style" ); + OSL_ENSURE( xStyle.is(), "WorkbookGlobals::createStyleObject - cannot create style" ); return xStyle; } // BIFF specific -------------------------------------------------------------- -void WorkbookData::setTextEncoding( rtl_TextEncoding eTextEnc ) +void WorkbookGlobals::setTextEncoding( rtl_TextEncoding eTextEnc ) { if( eTextEnc != RTL_TEXTENCODING_DONTKNOW ) meTextEnc = eTextEnc; } -void WorkbookData::setCodePage( sal_uInt16 nCodePage ) +void WorkbookGlobals::setCodePage( sal_uInt16 nCodePage ) { setTextEncoding( BiffHelper::calcTextEncodingFromCodePage( nCodePage ) ); mbHasCodePage = true; } -void WorkbookData::setAppFontEncoding( rtl_TextEncoding eAppFontEnc ) +void WorkbookGlobals::setAppFontEncoding( rtl_TextEncoding eAppFontEnc ) { if( !mbHasCodePage ) setTextEncoding( eAppFontEnc ); } -void WorkbookData::setIsWorkbookFile() +void WorkbookGlobals::setIsWorkbookFile() { - OSL_ENSURE( meBiff == BIFF4, "WorkbookData::setIsWorkbookFile - invalid call" ); + OSL_ENSURE( meBiff == BIFF4, "WorkbookGlobals::setIsWorkbookFile - invalid call" ); mbWorkbook = true; } -void WorkbookData::createBuffersPerSheet( sal_Int16 nSheet ) +void WorkbookGlobals::createBuffersPerSheet( sal_Int16 nSheet ) { - // set mnCurrSheet to enable usage of WorkbookHelper::getCurrentSheetIndex() - mnCurrSheet = nSheet; switch( meBiff ) { case BIFF2: case BIFF3: - OSL_ENSURE( mnCurrSheet == 0, "WorkbookData::createBuffersPerSheet - unexpected sheet index" ); - mxDefNames->setLocalCalcSheet( mnCurrSheet ); + OSL_ENSURE( nSheet == 0, "WorkbookGlobals::createBuffersPerSheet - unexpected sheet index" ); + mxDefNames->setLocalCalcSheet( nSheet ); break; case BIFF4: - OSL_ENSURE( mbWorkbook || (mnCurrSheet == 0), "WorkbookData::createBuffersPerSheet - unexpected sheet index" ); + OSL_ENSURE( mbWorkbook || (nSheet == 0), "WorkbookGlobals::createBuffersPerSheet - unexpected sheet index" ); // #i11183# sheets in BIFF4W files have own styles and names - if( mbWorkbook && (mnCurrSheet > 0) ) + if( nSheet > 0 ) { mxStyles.reset( new StylesBuffer( *this ) ); mxDefNames.reset( new DefinedNamesBuffer( *this ) ); mxExtLinks.reset( new ExternalLinkBuffer( *this ) ); } - mxDefNames->setLocalCalcSheet( mnCurrSheet ); + mxDefNames->setLocalCalcSheet( nSheet ); break; case BIFF5: // BIFF5 stores external references per sheet - mxExtLinks.reset( new ExternalLinkBuffer( *this ) ); + if( nSheet > 0 ) + mxExtLinks.reset( new ExternalLinkBuffer( *this ) ); break; case BIFF8: @@ -476,12 +476,11 @@ void WorkbookData::createBuffersPerSheet( sal_Int16 nSheet ) case BIFF_UNKNOWN: break; } - mnCurrSheet = -1; } // private -------------------------------------------------------------------- -void WorkbookData::initialize( bool bWorkbookFile ) +void WorkbookGlobals::initialize( bool bWorkbookFile ) { maCellStyles = CREATE_OUSTRING( "CellStyles" ); maPageStyles = CREATE_OUSTRING( "PageStyles" ); @@ -494,7 +493,7 @@ void WorkbookData::initialize( bool bWorkbookFile ) // the spreadsheet document mxDoc.set( mrBaseFilter.getModel(), UNO_QUERY ); - OSL_ENSURE( mxDoc.is(), "WorkbookData::initialize - no spreadsheet document" ); + OSL_ENSURE( mxDoc.is(), "WorkbookGlobals::initialize - no spreadsheet document" ); mxWorkbookSettings.reset( new WorkbookSettings( *this ) ); mxViewSettings.reset( new ViewSettings( *this ) ); @@ -557,7 +556,7 @@ void WorkbookData::initialize( bool bWorkbookFile ) } } -void WorkbookData::finalize() +void WorkbookGlobals::finalize() { // set some document properties needed after import if( mrBaseFilter.isImportFilter() ) @@ -588,62 +587,73 @@ WorkbookHelper::~WorkbookHelper() { } -// filter --------------------------------------------------------------------- +/*static*/ WorkbookGlobalsRef WorkbookHelper::constructGlobals( ExcelFilter& rFilter ) +{ + WorkbookGlobalsRef xBookGlob( new WorkbookGlobals( rFilter ) ); + if( !xBookGlob->isValid() ) + xBookGlob.reset(); + return xBookGlob; +} -FilterBase& WorkbookHelper::getBaseFilter() const +/*static*/ WorkbookGlobalsRef WorkbookHelper::constructGlobals( ExcelBiffFilter& rFilter, BiffType eBiff ) { - return mrBookData.getBaseFilter(); + WorkbookGlobalsRef xBookGlob( new WorkbookGlobals( rFilter, eBiff ) ); + if( !xBookGlob->isValid() ) + xBookGlob.reset(); + return xBookGlob; } -Reference< XMultiServiceFactory > WorkbookHelper::getGlobalFactory() const +// filter --------------------------------------------------------------------- + +FilterBase& WorkbookHelper::getBaseFilter() const { - return mrBookData.getBaseFilter().getServiceFactory(); + return mrBookGlob.getBaseFilter(); } FilterType WorkbookHelper::getFilterType() const { - return mrBookData.getFilterType(); + return mrBookGlob.getFilterType(); } SegmentProgressBar& WorkbookHelper::getProgressBar() const { - return mrBookData.getProgressBar(); + return mrBookGlob.getProgressBar(); } bool WorkbookHelper::isWorkbookFile() const { - return mrBookData.isWorkbookFile(); + return mrBookGlob.isWorkbookFile(); } sal_Int16 WorkbookHelper::getCurrentSheetIndex() const { - return mrBookData.getCurrentSheetIndex(); + return mrBookGlob.getCurrentSheetIndex(); } -void WorkbookHelper::setCurrentSheetIndex( sal_Int16 nSheet ) +void WorkbookHelper::setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ) { - mrBookData.setCurrentSheetIndex( nSheet ); + mrBookGlob.setVbaProjectStorage( rxVbaPrjStrg ); } -void WorkbookHelper::setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ) +void WorkbookHelper::setCurrentSheetIndex( sal_Int16 nSheet ) { - mrBookData.setVbaProjectStorage( rxVbaPrjStrg ); + mrBookGlob.setCurrentSheetIndex( nSheet ); } void WorkbookHelper::finalizeWorkbookImport() { // workbook settings, document and sheet view settings - mrBookData.getWorkbookSettings().finalizeImport(); - mrBookData.getViewSettings().finalizeImport(); + mrBookGlob.getWorkbookSettings().finalizeImport(); + mrBookGlob.getViewSettings().finalizeImport(); /* Insert all pivot tables. Must be done after loading all sheets, because data pilots expect existing source data on creation. */ - mrBookData.getPivotTables().finalizeImport(); + mrBookGlob.getPivotTables().finalizeImport(); /* Insert scenarios after all sheet processing is done, because new hidden sheets are created for scenarios which would confuse code that relies on certain sheet indexes. Must be done after pivot tables too. */ - mrBookData.getScenarios().finalizeImport(); + mrBookGlob.getScenarios().finalizeImport(); /* Set 'Default' page style to automatic page numbering (default is manual number 1). Otherwise hidden sheets (e.g. for scenarios) which have @@ -654,7 +664,7 @@ void WorkbookHelper::finalizeWorkbookImport() /* Import the VBA project (after finalizing workbook settings which contains the workbook code name). */ - StorageRef xVbaPrjStrg = mrBookData.getVbaProjectStorage(); + StorageRef xVbaPrjStrg = mrBookGlob.getVbaProjectStorage(); if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() ) getBaseFilter().getVbaProject().importVbaProject( *xVbaPrjStrg, getBaseFilter().getGraphicHelper() ); } @@ -663,12 +673,7 @@ void WorkbookHelper::finalizeWorkbookImport() Reference< XSpreadsheetDocument > WorkbookHelper::getDocument() const { - return mrBookData.getDocument(); -} - -Reference< XMultiServiceFactory > WorkbookHelper::getDocumentFactory() const -{ - return mrBookData.getBaseFilter().getModelFactory(); + return mrBookGlob.getDocument(); } Reference< XSpreadsheet > WorkbookHelper::getSheetFromDoc( sal_Int16 nSheet ) const @@ -729,129 +734,129 @@ Reference< XCellRange > WorkbookHelper::getCellRangeFromDoc( const CellRangeAddr Reference< XNameContainer > WorkbookHelper::getStyleFamily( bool bPageStyles ) const { - return mrBookData.getStyleFamily( bPageStyles ); + return mrBookGlob.getStyleFamily( bPageStyles ); } Reference< XStyle > WorkbookHelper::getStyleObject( const OUString& rStyleName, bool bPageStyle ) const { - return mrBookData.getStyleObject( rStyleName, bPageStyle ); + return mrBookGlob.getStyleObject( rStyleName, bPageStyle ); } Reference< XNamedRange > WorkbookHelper::createNamedRangeObject( OUString& orName, sal_Int32 nNameFlags ) const { - return mrBookData.createNamedRangeObject( orName, nNameFlags ); + return mrBookGlob.createNamedRangeObject( orName, nNameFlags ); } Reference< XDatabaseRange > WorkbookHelper::createDatabaseRangeObject( OUString& orName, const CellRangeAddress& rRangeAddr ) const { - return mrBookData.createDatabaseRangeObject( orName, rRangeAddr ); + return mrBookGlob.createDatabaseRangeObject( orName, rRangeAddr ); } Reference< XStyle > WorkbookHelper::createStyleObject( OUString& orStyleName, bool bPageStyle ) const { - return mrBookData.createStyleObject( orStyleName, bPageStyle ); + return mrBookGlob.createStyleObject( orStyleName, bPageStyle ); } // buffers -------------------------------------------------------------------- WorkbookSettings& WorkbookHelper::getWorkbookSettings() const { - return mrBookData.getWorkbookSettings(); + return mrBookGlob.getWorkbookSettings(); } ViewSettings& WorkbookHelper::getViewSettings() const { - return mrBookData.getViewSettings(); + return mrBookGlob.getViewSettings(); } WorksheetBuffer& WorkbookHelper::getWorksheets() const { - return mrBookData.getWorksheets(); + return mrBookGlob.getWorksheets(); } ThemeBuffer& WorkbookHelper::getTheme() const { - return mrBookData.getTheme(); + return mrBookGlob.getTheme(); } StylesBuffer& WorkbookHelper::getStyles() const { - return mrBookData.getStyles(); + return mrBookGlob.getStyles(); } SharedStringsBuffer& WorkbookHelper::getSharedStrings() const { - return mrBookData.getSharedStrings(); + return mrBookGlob.getSharedStrings(); } ExternalLinkBuffer& WorkbookHelper::getExternalLinks() const { - return mrBookData.getExternalLinks(); + return mrBookGlob.getExternalLinks(); } DefinedNamesBuffer& WorkbookHelper::getDefinedNames() const { - return mrBookData.getDefinedNames(); + return mrBookGlob.getDefinedNames(); } TableBuffer& WorkbookHelper::getTables() const { - return mrBookData.getTables(); + return mrBookGlob.getTables(); } ScenarioBuffer& WorkbookHelper::getScenarios() const { - return mrBookData.getScenarios(); + return mrBookGlob.getScenarios(); } ConnectionsBuffer& WorkbookHelper::getConnections() const { - return mrBookData.getConnections(); + return mrBookGlob.getConnections(); } PivotCacheBuffer& WorkbookHelper::getPivotCaches() const { - return mrBookData.getPivotCaches(); + return mrBookGlob.getPivotCaches(); } PivotTableBuffer& WorkbookHelper::getPivotTables() const { - return mrBookData.getPivotTables(); + return mrBookGlob.getPivotTables(); } // converters ----------------------------------------------------------------- FormulaParser& WorkbookHelper::getFormulaParser() const { - return mrBookData.getFormulaParser(); + return mrBookGlob.getFormulaParser(); } UnitConverter& WorkbookHelper::getUnitConverter() const { - return mrBookData.getUnitConverter(); + return mrBookGlob.getUnitConverter(); } AddressConverter& WorkbookHelper::getAddressConverter() const { - return mrBookData.getAddressConverter(); + return mrBookGlob.getAddressConverter(); } ExcelChartConverter& WorkbookHelper::getChartConverter() const { - return mrBookData.getChartConverter(); + return mrBookGlob.getChartConverter(); } PageSettingsConverter& WorkbookHelper::getPageSettingsConverter() const { - return mrBookData.getPageSettingsConverter(); + return mrBookGlob.getPageSettingsConverter(); } // OOXML/BIFF12 specific ------------------------------------------------------ XmlFilterBase& WorkbookHelper::getOoxFilter() const { - OSL_ENSURE( mrBookData.getFilterType() == FILTER_OOXML, "WorkbookHelper::getOoxFilter - invalid call" ); - return mrBookData.getOoxFilter(); + OSL_ENSURE( mrBookGlob.getFilterType() == FILTER_OOXML, "WorkbookHelper::getOoxFilter - invalid call" ); + return mrBookGlob.getOoxFilter(); } bool WorkbookHelper::importOoxFragment( const ::rtl::Reference< FragmentHandler >& rxHandler ) @@ -863,82 +868,48 @@ bool WorkbookHelper::importOoxFragment( const ::rtl::Reference< FragmentHandler BinaryFilterBase& WorkbookHelper::getBiffFilter() const { - OSL_ENSURE( mrBookData.getFilterType() == FILTER_BIFF, "WorkbookHelper::getBiffFilter - invalid call" ); - return mrBookData.getBiffFilter(); + OSL_ENSURE( mrBookGlob.getFilterType() == FILTER_BIFF, "WorkbookHelper::getBiffFilter - invalid call" ); + return mrBookGlob.getBiffFilter(); } BiffType WorkbookHelper::getBiff() const { - return mrBookData.getBiff(); + return mrBookGlob.getBiff(); } rtl_TextEncoding WorkbookHelper::getTextEncoding() const { - return mrBookData.getTextEncoding(); + return mrBookGlob.getTextEncoding(); } void WorkbookHelper::setTextEncoding( rtl_TextEncoding eTextEnc ) { - mrBookData.setTextEncoding( eTextEnc ); + mrBookGlob.setTextEncoding( eTextEnc ); } void WorkbookHelper::setCodePage( sal_uInt16 nCodePage ) { - mrBookData.setCodePage( nCodePage ); + mrBookGlob.setCodePage( nCodePage ); } void WorkbookHelper::setAppFontEncoding( rtl_TextEncoding eAppFontEnc ) { - mrBookData.setAppFontEncoding( eAppFontEnc ); + mrBookGlob.setAppFontEncoding( eAppFontEnc ); } void WorkbookHelper::setIsWorkbookFile() { - mrBookData.setIsWorkbookFile(); + mrBookGlob.setIsWorkbookFile(); } void WorkbookHelper::createBuffersPerSheet( sal_Int16 nSheet ) { - mrBookData.createBuffersPerSheet( nSheet ); + mrBookGlob.createBuffersPerSheet( nSheet ); } BiffCodecHelper& WorkbookHelper::getCodecHelper() const { - return mrBookData.getCodecHelper(); -} - -// ============================================================================ - -namespace prv { - -WorkbookDataOwner::WorkbookDataOwner( WorkbookDataRef xBookData ) : - mxBookData( xBookData ) -{ -} - -WorkbookDataOwner::~WorkbookDataOwner() -{ -} - -} // namespace prv - -// ---------------------------------------------------------------------------- - -WorkbookHelperRoot::WorkbookHelperRoot( ExcelFilter& rFilter ) : - prv::WorkbookDataOwner( prv::WorkbookDataRef( new WorkbookData( rFilter ) ) ), - WorkbookHelper( *mxBookData ) -{ -} - -WorkbookHelperRoot::WorkbookHelperRoot( ExcelBiffFilter& rFilter, BiffType eBiff ) : - prv::WorkbookDataOwner( prv::WorkbookDataRef( new WorkbookData( rFilter, eBiff ) ) ), - WorkbookHelper( *mxBookData ) -{ -} - -bool WorkbookHelperRoot::isValid() const -{ - return mxBookData->isValid(); + return mrBookGlob.getCodecHelper(); } // ============================================================================ diff --git a/oox/source/xls/workbooksettings.cxx b/oox/source/xls/workbooksettings.cxx index 0d450c094..2710dd1ce 100644 --- a/oox/source/xls/workbooksettings.cxx +++ b/oox/source/xls/workbooksettings.cxx @@ -299,7 +299,7 @@ void WorkbookSettings::finalizeImport() { getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "ReadOnly" ) ] <<= true; - Reference< XPropertySet > xDocumentSettings( getDocumentFactory()->createInstance( + Reference< XPropertySet > xDocumentSettings( getBaseFilter().getModelFactory()->createInstance( CREATE_OUSTRING( "com.sun.star.document.Settings" ) ), UNO_QUERY_THROW ); PropertySet aSettingsProp( xDocumentSettings ); if( maFileSharing.mbRecommendReadOnly ) diff --git a/oox/source/xls/worksheetfragment.cxx b/oox/source/xls/worksheetfragment.cxx index b5d34855c..014fb4307 100644 --- a/oox/source/xls/worksheetfragment.cxx +++ b/oox/source/xls/worksheetfragment.cxx @@ -37,12 +37,14 @@ #include "oox/xls/commentsfragment.hxx" #include "oox/xls/condformatcontext.hxx" #include "oox/xls/drawingfragment.hxx" +#include "oox/xls/drawingmanager.hxx" #include "oox/xls/externallinkbuffer.hxx" #include "oox/xls/pagesettings.hxx" #include "oox/xls/pivottablefragment.hxx" #include "oox/xls/querytablefragment.hxx" #include "oox/xls/scenariobuffer.hxx" #include "oox/xls/scenariocontext.hxx" +#include "oox/xls/sheetdatabuffer.hxx" #include "oox/xls/sheetdatacontext.hxx" #include "oox/xls/tablefragment.hxx" #include "oox/xls/viewsettings.hxx" @@ -123,32 +125,18 @@ ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, c return 0; } -namespace { - -ApiTokenSequence lclImportDataValFormula( FormulaParser& rParser, const OUString& rFormula, const CellAddress& rBaseAddress ) -{ - TokensFormulaContext aContext( true, false ); - aContext.setBaseAddress( rBaseAddress ); - rParser.importFormula( aContext, rFormula ); - return aContext.getTokens(); -} - -} // namespace - void DataValidationsContext::onCharacters( const OUString& rChars ) { if( mxValModel.get() ) switch( getCurrentElement() ) { case XLS_TOKEN( formula1 ): - mxValModel->maTokens1 = lclImportDataValFormula( - getFormulaParser(), rChars, mxValModel->maRanges.getBaseAddress() ); + mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars ); // process string list of a list validation (convert to list of string tokens) if( mxValModel->mnType == XML_list ) getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true ); break; case XLS_TOKEN( formula2 ): - mxValModel->maTokens2 = lclImportDataValFormula( - getFormulaParser(), rChars, mxValModel->maRanges.getBaseAddress() ); + mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars ); break; } } @@ -212,12 +200,9 @@ void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm ) // condition formula(s) FormulaParser& rParser = getFormulaParser(); - TokensFormulaContext aContext( true, false ); - aContext.setBaseAddress( aModel.maRanges.getBaseAddress() ); - rParser.importFormula( aContext, rStrm ); - aModel.maTokens1 = aContext.getTokens(); - rParser.importFormula( aContext, rStrm ); - aModel.maTokens2 = aContext.getTokens(); + CellAddress aBaseAddr = aModel.maRanges.getBaseAddress(); + aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm ); + aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm ); // process string list of a list validation (convert to list of string tokens) if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) ) rParser.convertStringToStringList( aModel.maTokens1, ',', true ); @@ -228,9 +213,8 @@ void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm ) // ============================================================================ -WorksheetFragment::WorksheetFragment( const WorkbookHelper& rHelper, - const OUString& rFragmentPath, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : - WorksheetFragmentBase( rHelper, rFragmentPath, rxProgressBar, eSheetType, nSheet ) +WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) : + WorksheetFragmentBase( rHelper, rFragmentPath ) { // import data tables related to this worksheet RelationsRef xTableRels = getRelations().getRelationsFromType( CREATE_OFFICEDOC_RELATION_TYPE( "table" ) ); @@ -541,14 +525,14 @@ void WorksheetFragment::importSheetFormatPr( const AttributeList& rAttribs ) void WorksheetFragment::importCol( const AttributeList& rAttribs ) { ColumnModel aModel; - aModel.mnFirstCol = rAttribs.getInteger( XML_min, -1 ); - aModel.mnLastCol = rAttribs.getInteger( XML_max, -1 ); - aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 ); - aModel.mnXfId = rAttribs.getInteger( XML_style, -1 ); - aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); - aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false ); - aModel.mbHidden = rAttribs.getBool( XML_hidden, false ); - aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); + aModel.maRange.mnFirst = rAttribs.getInteger( XML_min, -1 ); + aModel.maRange.mnLast = rAttribs.getInteger( XML_max, -1 ); + aModel.mfWidth = rAttribs.getDouble( XML_width, 0.0 ); + aModel.mnXfId = rAttribs.getInteger( XML_style, -1 ); + aModel.mnLevel = rAttribs.getInteger( XML_outlineLevel, 0 ); + aModel.mbShowPhonetic = rAttribs.getBool( XML_phonetic, false ); + aModel.mbHidden = rAttribs.getBool( XML_hidden, false ); + aModel.mbCollapsed = rAttribs.getBool( XML_collapsed, false ); // set column properties in the current sheet setColumnModel( aModel ); } @@ -557,7 +541,7 @@ void WorksheetFragment::importMergeCell( const AttributeList& rAttribs ) { CellRangeAddress aRange; if( getAddressConverter().convertToCellRange( aRange, rAttribs.getString( XML_ref, OUString() ), getSheetIndex(), true, true ) ) - setMergedRange( aRange ); + getSheetData().setMergedRange( aRange ); } void WorksheetFragment::importHyperlink( const AttributeList& rAttribs ) @@ -659,11 +643,11 @@ void WorksheetFragment::importCol( SequenceInputStream& rStrm ) sal_Int32 nWidth; sal_uInt16 nFlags; - rStrm >> aModel.mnFirstCol >> aModel.mnLastCol >> nWidth >> aModel.mnXfId >> nFlags; + rStrm >> aModel.maRange.mnFirst >> aModel.maRange.mnLast >> nWidth >> aModel.mnXfId >> nFlags; // column indexes are 0-based in BIFF12, but ColumnModel expects 1-based - ++aModel.mnFirstCol; - ++aModel.mnLastCol; + ++aModel.maRange.mnFirst; + ++aModel.maRange.mnLast; // width is stored as 1/256th of a character in BIFF12, convert to entire character aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; // equal flags in all BIFFs @@ -681,7 +665,7 @@ void WorksheetFragment::importMergeCell( SequenceInputStream& rStrm ) rStrm >> aBinRange; CellRangeAddress aRange; if( getAddressConverter().convertToCellRange( aRange, aBinRange, getSheetIndex(), true, true ) ) - setMergedRange( aRange ); + getSheetData().setMergedRange( aRange ); } void WorksheetFragment::importHyperlink( SequenceInputStream& rStrm ) @@ -752,9 +736,8 @@ void WorksheetFragment::importEmbeddedOleData( StreamDataSequence& orEmbeddedDat // ============================================================================ -BiffWorksheetFragment::BiffWorksheetFragment( const BiffWorkbookFragmentBase& rParent, - const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : - BiffWorksheetFragmentBase( rParent, rxProgressBar, eSheetType, nSheet ) +BiffWorksheetFragment::BiffWorksheetFragment( const WorksheetHelper& rHelper, const BiffWorkbookFragmentBase& rParent ) : + BiffWorksheetFragmentBase( rHelper, rParent ) { } @@ -775,6 +758,7 @@ bool BiffWorksheetFragment::importFragment() SheetViewSettings& rSheetViewSett = getSheetViewSettings(); CondFormatBuffer& rCondFormats = getCondFormats(); PageSettings& rPageSett = getPageSettings(); + BiffSheetDrawing& rDrawing = getBiffDrawing(); // process all record in this sheet fragment BiffInputStream& rStrm = getInputStream(); @@ -806,6 +790,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_HORPAGEBREAKS: importPageBreaks( rStrm, true ); break; case BIFF_ID_ITERATION: rWorkbookSett.importIteration( rStrm ); break; case BIFF_ID_LEFTMARGIN: rPageSett.importLeftMargin( rStrm ); break; + case BIFF_ID_NOTE: importNote( rStrm ); break; case BIFF_ID_PANE: rSheetViewSett.importPane( rStrm ); break; case BIFF_ID_PASSWORD: rWorksheetSett.importPassword( rStrm ); break; case BIFF_ID_PRINTGRIDLINES: rPageSett.importPrintGridLines( rStrm ); break; @@ -835,13 +820,13 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_DEFCOLWIDTH: importDefColWidth( rStrm ); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; + case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; case BIFF_ID_SHEETPR: rWorksheetSett.importSheetPr( rStrm ); break; case BIFF_ID_UNCALCED: rWorkbookSett.importUncalced( rStrm ); break; case BIFF_ID_VCENTER: rPageSett.importVerCenter( rStrm ); break; case BIFF3_ID_WINDOW2: rSheetViewSett.importWindow2( rStrm ); break; - } break; @@ -850,6 +835,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_COLINFO: importColInfo( rStrm ); break; case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; + case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; case BIFF_ID_SAVERECALC: rWorkbookSett.importSaveRecalc( rStrm ); break; @@ -868,6 +854,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF3_ID_DEFROWHEIGHT: importDefRowHeight( rStrm ); break; case BIFF_ID_HCENTER: rPageSett.importHorCenter( rStrm ); break; case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; // #i62300# also in BIFF5 + case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; case BIFF_ID_PTDEFINITION: importPTDefinition( rStrm ); break; @@ -895,6 +882,7 @@ bool BiffWorksheetFragment::importFragment() case BIFF_ID_HYPERLINK: importHyperlink( rStrm ); break; case BIFF_ID_LABELRANGES: importLabelRanges( rStrm ); break; case BIFF_ID_MERGEDCELLS: importMergedCells( rStrm ); break; + case BIFF_ID_OBJ: rDrawing.importObj( rStrm ); break; case BIFF_ID_OBJECTPROTECT: rWorksheetSett.importObjectProtect( rStrm ); break; case BIFF_ID_PAGESETUP: rPageSett.importPageSetup( rStrm ); break; case BIFF_ID_PHONETICPR: rWorksheetSett.importPhoneticPr( rStrm ); break; @@ -957,15 +945,15 @@ void BiffWorksheetFragment::importColInfo( BiffInputStream& rStrm ) ColumnModel aModel; // column indexes are 0-based in BIFF, but ColumnModel expects 1-based - aModel.mnFirstCol = static_cast< sal_Int32 >( nFirstCol ) + 1; - aModel.mnLastCol = static_cast< sal_Int32 >( nLastCol ) + 1; + aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1; + aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1; // width is stored as 1/256th of a character in BIFF, convert to entire character - aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; - aModel.mnXfId = nXfId; - aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); - aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC ); - aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); - aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); + aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; + aModel.mnXfId = nXfId; + aModel.mnLevel = extractValue< sal_Int32 >( nFlags, 8, 3 ); + aModel.mbShowPhonetic = getFlag( nFlags, BIFF_COLINFO_SHOWPHONETIC ); + aModel.mbHidden = getFlag( nFlags, BIFF_COLINFO_HIDDEN ); + aModel.mbCollapsed = getFlag( nFlags, BIFF_COLINFO_COLLAPSED ); // set column properties in the current sheet setColumnModel( aModel ); } @@ -985,8 +973,8 @@ void BiffWorksheetFragment::importColWidth( BiffInputStream& rStrm ) ColumnModel aModel; // column indexes are 0-based in BIFF, but ColumnModel expects 1-based - aModel.mnFirstCol = static_cast< sal_Int32 >( nFirstCol ) + 1; - aModel.mnLastCol = static_cast< sal_Int32 >( nLastCol ) + 1; + aModel.maRange.mnFirst = static_cast< sal_Int32 >( nFirstCol ) + 1; + aModel.maRange.mnLast = static_cast< sal_Int32 >( nLastCol ) + 1; // width is stored as 1/256th of a character in BIFF, convert to entire character aModel.mfWidth = static_cast< double >( nWidth ) / 256.0; // set column properties in the current sheet @@ -1041,10 +1029,7 @@ ApiTokenSequence lclReadDataValFormula( BiffInputStream& rStrm, FormulaParser& r { sal_uInt16 nFmlaSize = rStrm.readuInt16(); rStrm.skip( 2 ); - // enable NUL characters, string list is single tStr token with NUL separators - TokensFormulaContext aContext( true, false, true ); - rParser.importFormula( aContext, rStrm, &nFmlaSize ); - return aContext.getTokens(); + return rParser.importFormula( CellAddress(), FORMULATYPE_VALIDATION, rStrm, &nFmlaSize ); } } // namespace @@ -1163,7 +1148,12 @@ void BiffWorksheetFragment::importMergedCells( BiffInputStream& rStrm ) ApiCellRangeList aRanges; getAddressConverter().convertToCellRangeList( aRanges, aBiffRanges, getSheetIndex(), true ); for( ApiCellRangeList::const_iterator aIt = aRanges.begin(), aEnd = aRanges.end(); aIt != aEnd; ++aIt ) - setMergedRange( *aIt ); + getSheetData().setMergedRange( *aIt ); +} + +void BiffWorksheetFragment::importNote( BiffInputStream& rStrm ) +{ + getComments().createComment()->importNote( rStrm ); } void BiffWorksheetFragment::importPageBreaks( BiffInputStream& rStrm, bool bRowBreak ) diff --git a/oox/source/xls/worksheethelper.cxx b/oox/source/xls/worksheethelper.cxx index 6b744618d..68f07d01a 100644 --- a/oox/source/xls/worksheethelper.cxx +++ b/oox/source/xls/worksheethelper.cxx @@ -42,7 +42,6 @@ #include <com/sun/star/sheet/XFormulaTokens.hpp> #include <com/sun/star/sheet/XLabelRanges.hpp> #include <com/sun/star/sheet/XMultiFormulaTokens.hpp> -#include <com/sun/star/sheet/XMultipleOperation.hpp> #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp> #include <com/sun/star/sheet/XSheetCondition.hpp> #include <com/sun/star/sheet/XSheetOutline.hpp> @@ -50,24 +49,20 @@ #include <com/sun/star/table/XColumnRowRange.hpp> #include <com/sun/star/text/WritingMode2.hpp> #include <com/sun/star/text/XText.hpp> -#include <com/sun/star/util/NumberFormat.hpp> -#include <com/sun/star/util/XMergeable.hpp> -#include <com/sun/star/util/XNumberFormatTypes.hpp> -#include <com/sun/star/util/XNumberFormatsSupplier.hpp> #include <rtl/ustrbuf.hxx> #include "oox/core/filterbase.hxx" -#include "oox/helper/containerhelper.hxx" #include "oox/helper/propertyset.hxx" #include "oox/xls/addressconverter.hxx" #include "oox/xls/autofilterbuffer.hxx" #include "oox/xls/commentsbuffer.hxx" #include "oox/xls/condformatbuffer.hxx" #include "oox/xls/drawingfragment.hxx" +#include "oox/xls/drawingmanager.hxx" #include "oox/xls/formulaparser.hxx" #include "oox/xls/pagesettings.hxx" #include "oox/xls/querytablebuffer.hxx" -#include "oox/xls/sharedformulabuffer.hxx" #include "oox/xls/sharedstringsbuffer.hxx" +#include "oox/xls/sheetdatabuffer.hxx" #include "oox/xls/stylesbuffer.hxx" #include "oox/xls/unitconverter.hxx" #include "oox/xls/viewsettings.hxx" @@ -113,107 +108,13 @@ void lclUpdateProgressBar( const ISegmentProgressBarRef& rxProgressBar, double f rxProgressBar->setPosition( fPosition ); } -// ---------------------------------------------------------------------------- - -struct ValueRange -{ - sal_Int32 mnFirst; - sal_Int32 mnLast; - - inline explicit ValueRange( sal_Int32 nValue ) : mnFirst( nValue ), mnLast( nValue ) {} - inline explicit ValueRange( sal_Int32 nFirst, sal_Int32 nLast ) : mnFirst( nFirst ), mnLast( nLast ) {} -}; - -typedef ::std::vector< ValueRange > ValueRangeVector; - -// ---------------------------------------------------------------------------- - -struct ValueRangeComp -{ - inline bool operator()( const ValueRange& rRange, sal_Int32 nValue ) const { return rRange.mnLast < nValue; } -}; - -typedef ::std::vector< ValueRange > ValueRangeVector; - -// ---------------------------------------------------------------------------- - -class ValueRangeSet -{ -public: - inline explicit ValueRangeSet() {} - - void insert( sal_Int32 nValue ); - void intersect( ValueRangeVector& orRanges, sal_Int32 nFirst, sal_Int32 nLast ) const; - -private: - ValueRangeVector maData; -}; - -void ValueRangeSet::insert( sal_Int32 nValue ) -{ - // find the first range that contains nValue or that follows nValue - ValueRangeVector::iterator aBeg = maData.begin(); - ValueRangeVector::iterator aEnd = maData.end(); - ValueRangeVector::iterator aNext = ::std::lower_bound( aBeg, aEnd, nValue, ValueRangeComp() ); - - // nothing to do if found range contains nValue - if( (aNext == aEnd) || (nValue < aNext->mnFirst) ) - { - ValueRangeVector::iterator aPrev = (aNext == aBeg) ? aEnd : (aNext - 1); - bool bJoinPrev = (aPrev != aEnd) && (aPrev->mnLast + 1 == nValue); - bool bJoinNext = (aNext != aEnd) && (aNext->mnFirst - 1 == nValue); - if( bJoinPrev && bJoinNext ) - { - aPrev->mnLast = aNext->mnLast; - maData.erase( aNext ); - } - else if( bJoinPrev ) - ++aPrev->mnLast; - else if( bJoinNext ) - --aNext->mnFirst; - else - maData.insert( aNext, ValueRange( nValue ) ); - } -} - -void ValueRangeSet::intersect( ValueRangeVector& orRanges, sal_Int32 nFirst, sal_Int32 nLast ) const -{ - orRanges.clear(); - // find the range that contains nFirst or the first range that follows nFirst - ValueRangeVector::const_iterator aIt = ::std::lower_bound( maData.begin(), maData.end(), nFirst, ValueRangeComp() ); - for( ValueRangeVector::const_iterator aEnd = maData.end(); (aIt != aEnd) && (aIt->mnFirst <= nLast); ++aIt ) - orRanges.push_back( ValueRange( ::std::max( aIt->mnFirst, nFirst ), ::std::min( aIt->mnLast, nLast ) ) ); -} - } // namespace // ============================================================================ // ============================================================================ -void CellModel::reset() -{ - mxCell.clear(); - maValueStr = maFormulaRef = OUString(); - mnCellType = mnFormulaType = XML_TOKEN_INVALID; - mnSharedId = mnXfId = mnNumFmtId = -1; - mbHasValueStr = mbShowPhonetic = false; -} - -// ---------------------------------------------------------------------------- - -DataTableModel::DataTableModel() : - mb2dTable( false ), - mbRowTable( false ), - mbRef1Deleted( false ), - mbRef2Deleted( false ) -{ -} - -// ---------------------------------------------------------------------------- - ColumnModel::ColumnModel() : - mnFirstCol( -1 ), - mnLastCol( -1 ), + maRange( -1 ), mfWidth( 0.0 ), mnXfId( -1 ), mnLevel( 0 ), @@ -223,27 +124,22 @@ ColumnModel::ColumnModel() : { } -bool ColumnModel::tryExpand( const ColumnModel& rModel ) +bool ColumnModel::isMergeable( const ColumnModel& rModel ) const { - bool bExpandable = - (mnFirstCol <= rModel.mnFirstCol) && - (rModel.mnFirstCol <= mnLastCol + 1) && - (mfWidth == rModel.mfWidth) && + return + (maRange.mnFirst <= rModel.maRange.mnFirst) && + (rModel.maRange.mnFirst <= maRange.mnLast + 1) && + (mfWidth == rModel.mfWidth) && // ignore mnXfId, cell formatting is always set directly - (mnLevel == rModel.mnLevel) && - (mbHidden == rModel.mbHidden) && - (mbCollapsed == rModel.mbCollapsed); - - if( bExpandable ) - mnLastCol = rModel.mnLastCol; - return bExpandable; + (mnLevel == rModel.mnLevel) && + (mbHidden == rModel.mbHidden) && + (mbCollapsed == rModel.mbCollapsed); } // ---------------------------------------------------------------------------- RowModel::RowModel() : - mnFirstRow( -1 ), - mnLastRow( -1 ), + mnRow( -1 ), mfHeight( 0.0 ), mnXfId( -1 ), mnLevel( 0 ), @@ -257,21 +153,22 @@ RowModel::RowModel() : { } -bool RowModel::tryExpand( const RowModel& rModel ) +void RowModel::insertColSpan( const ValueRange& rColSpan ) { - bool bExpandable = - (mnFirstRow <= rModel.mnFirstRow) && - (rModel.mnFirstRow <= mnLastRow + 1) && - (mfHeight == rModel.mfHeight) && - // ignore mnXfId, mbCustomFormat, mbShowPhonetic - cell formatting is always set directly - (mnLevel == rModel.mnLevel) && - (mbCustomHeight == rModel.mbCustomHeight) && - (mbHidden == rModel.mbHidden) && - (mbCollapsed == rModel.mbCollapsed); + if( (0 <= rColSpan.mnFirst) && (rColSpan.mnFirst <= rColSpan.mnLast) ) + maColSpans.insert( rColSpan ); +} - if( bExpandable ) - mnLastRow = rModel.mnLastRow; - return bExpandable; +bool RowModel::isMergeable( const RowModel& rModel ) const +{ + return + // ignore maColSpans - is handled separately in SheetDataBuffer class + (mfHeight == rModel.mfHeight) && + // ignore mnXfId, mbCustomFormat, mbShowPhonetic - cell formatting is always set directly + (mnLevel == rModel.mnLevel) && + (mbCustomHeight == rModel.mbCustomHeight) && + (mbHidden == rModel.mbHidden) && + (mbCollapsed == rModel.mbCollapsed); } // ---------------------------------------------------------------------------- @@ -325,10 +222,10 @@ void ValidationModel::setBiffErrorStyle( sal_uInt8 nErrorStyle ) // ============================================================================ // ============================================================================ -class WorksheetData : public WorkbookHelper +class WorksheetGlobals : public WorkbookHelper { public: - explicit WorksheetData( + explicit WorksheetGlobals( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, @@ -337,16 +234,12 @@ public: /** Returns true, if this helper refers to an existing Calc sheet. */ inline bool isValidSheet() const { return mxSheet.is(); } - /** Returns a cell formula simulating the passed boolean value. */ - const OUString& getBooleanFormula( bool bValue ) const; - /** Returns the type of this sheet. */ inline WorksheetType getSheetType() const { return meSheetType; } /** Returns the index of the current sheet. */ inline sal_Int16 getSheetIndex() const { return maUsedArea.Sheet; } /** Returns the XSpreadsheet interface of the current sheet. */ - inline const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheet >& - getSheet() const { return mxSheet; } + inline const Reference< XSpreadsheet >& getSheet() const { return mxSheet; } /** Returns the XCell interface for the passed cell address. */ Reference< XCell > getCell( const CellAddress& rAddress ) const; @@ -361,14 +254,14 @@ public: Reference< XCellRange > getRow( sal_Int32 nRow ) const; /** Returns the XTableColumns interface for a range of columns. */ - Reference< XTableColumns > getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const; + Reference< XTableColumns > getColumns( const ValueRange& rColRange ) const; /** Returns the XTableRows interface for a range of rows. */ - Reference< XTableRows > getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const; + Reference< XTableRows > getRows( const ValueRange& rRowRange ) const; /** Returns the XDrawPage interface of the draw page of the current sheet. */ Reference< XDrawPage > getDrawPage() const; /** Returns the size of the entire drawing page in 1/100 mm. */ - Size getDrawPageSize() const; + const Size& getDrawPageSize() const; /** Returns the absolute position of the top-left corner of the cell in 1/100 mm. */ Point getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const; @@ -376,14 +269,12 @@ public: Size getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const; /** Returns the address of the cell that contains the passed point in 1/100 mm. */ - CellAddress getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const; + CellAddress getCellAddressFromPosition( const Point& rPosition ) const; /** Returns the cell range address that contains the passed rectangle in 1/100 mm. */ CellRangeAddress getCellRangeFromRectangle( const Rectangle& rRect ) const; - /** Returns the worksheet settings object. */ - inline WorksheetSettings& getWorksheetSettings() { return maSheetSett; } - /** Returns the buffer containing all shared formulas in this sheet. */ - inline SharedFormulaBuffer& getSharedFormulas() { return maSharedFmlas; } + /** Returns the buffer for cell contents and cell formatting. */ + inline SheetDataBuffer& getSheetData() { return maSheetData; } /** Returns the conditional formattings in this sheet. */ inline CondFormatBuffer& getCondFormats() { return maCondFormats; } /** Returns the buffer for all cell comments in this sheet. */ @@ -392,19 +283,19 @@ public: inline AutoFilterBuffer& getAutoFilters() { return maAutoFilters; } /** Returns the buffer for all web query tables in this sheet. */ inline QueryTableBuffer& getQueryTables() { return maQueryTables; } + /** Returns the worksheet settings object. */ + inline WorksheetSettings& getWorksheetSettings() { return maSheetSett; } /** Returns the page/print settings for this sheet. */ inline PageSettings& getPageSettings() { return maPageSett; } /** Returns the view settings for this sheet. */ inline SheetViewSettings& getSheetViewSettings() { return maSheetViewSett; } - /** Returns the VML drawing page for this sheet (OOXML/BIFF12 only!). */ + /** Returns the VML drawing page for this sheet (OOXML/BIFF12 only). */ inline VmlDrawing& getVmlDrawing() { return *mxVmlDrawing; } + /** Returns the BIFF drawing page for this sheet (BIFF2-BIFF8 only). */ + inline BiffSheetDrawing& getBiffDrawing() const { return *mxBiffDrawing; } /** Changes the current sheet type. */ inline void setSheetType( WorksheetType eSheetType ) { meSheetType = eSheetType; } - /** Stores the cell format at the passed address. */ - void setCellFormat( const CellModel& rModel ); - /** Merges the cells in the passed cell range. */ - void setMergedRange( const CellRangeAddress& rRange ); /** Sets a column or row page break described in the passed struct. */ void setPageBreak( const PageBreakModel& rModel, bool bRowBreak ); /** Inserts the hyperlink URL into the spreadsheet. */ @@ -433,6 +324,8 @@ public: @descr Column default formatting is converted directly, other settings are cached and converted in the finalizeImport() call. */ void setColumnModel( const ColumnModel& rModel ); + /** Converts column default cell formatting. */ + void convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const; /** Sets default height and hidden state for all unused rows in the sheet. */ void setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ); @@ -440,11 +333,8 @@ public: @descr Row default formatting is converted directly, other settings are cached and converted in the finalizeImport() call. */ void setRowModel( const RowModel& rModel ); - - /** Converts column default cell formatting. */ - void convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const; - /** Converts row default cell formatting. */ - void convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) const; + /** Specifies that the passed row needs to set its height manually. */ + void setManualRowHeight( sal_Int32 nRow ); /** Initial conversion before importing the worksheet. */ void initializeWorksheetImport(); @@ -453,57 +343,13 @@ public: private: typedef ::std::vector< sal_Int32 > OutlineLevelVec; - typedef ::std::map< sal_Int32, ColumnModel > ColumnModelMap; - typedef ::std::map< sal_Int32, RowModel > RowModelMap; + typedef ::std::pair< ColumnModel, sal_Int32 > ColumnModelRange; + typedef ::std::map< sal_Int32, ColumnModelRange > ColumnModelRangeMap; + typedef ::std::pair< RowModel, sal_Int32 > RowModelRange; + typedef ::std::map< sal_Int32, RowModelRange > RowModelRangeMap; typedef ::std::list< HyperlinkModel > HyperlinkModelList; typedef ::std::list< ValidationModel > ValidationModelList; - struct XfIdRowRange - { - sal_Int32 mnFirstRow; /// Index of first row. - sal_Int32 mnLastRow; /// Index of last row. - sal_Int32 mnXfId; /// XF identifier for the row range. - - explicit XfIdRowRange(); - bool intersects( const CellRangeAddress& rRange ) const; - void set( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ); - bool tryExpand( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ); - }; - - struct XfIdRange - { - CellRangeAddress maRange; /// The formatted cell range. - sal_Int32 mnXfId; /// XF identifier for the range. - sal_Int32 mnNumFmtId; /// Number format id overriding the XF. - - void set( const CellModel& rModel ); - bool tryExpand( const CellModel& rModel ); - bool tryMerge( const XfIdRange& rXfIdRange ); - }; - - struct MergedRange - { - CellRangeAddress maRange; /// The formatted cell range. - sal_Int32 mnHorAlign; /// Horizontal alignment in the range. - - explicit MergedRange( const CellRangeAddress& rRange ); - explicit MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ); - bool tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign ); - }; - - typedef ::std::pair< sal_Int32, sal_Int32 > RowColKey; - typedef ::std::map< RowColKey, XfIdRange > XfIdRangeMap; - typedef ::std::list< MergedRange > MergedRangeList; - - /** Writes all cell formatting attributes to the passed row range. */ - void writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const; - /** Writes all cell formatting attributes to the passed cell range. */ - void writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const; - /** Tries to merge the ranges last inserted in maXfIdRanges with existing ranges. */ - void mergeXfIdRanges(); - /** Finalizes the remaining ranges in maXfIdRanges. */ - void finalizeXfIdRanges(); - /** Inserts all imported hyperlinks into their cell ranges. */ void finalizeHyperlinkRanges() const; /** Generates the final URL for the passed hyperlink. */ @@ -514,60 +360,52 @@ private: /** Inserts all imported data validations into their cell ranges. */ void finalizeValidationRanges() const; - /** Merges all cached merged ranges and updates right/bottom cell borders. */ - void finalizeMergedRanges(); - /** Merges the passed merged range and updates right/bottom cell borders. */ - void finalizeMergedRange( const CellRangeAddress& rRange ); - /** Converts column properties for all columns in the sheet. */ void convertColumns(); /** Converts column properties. */ - void convertColumns( OutlineLevelVec& orColLevels, sal_Int32 nFirstCol, sal_Int32 nLastCol, const ColumnModel& rModel ); + void convertColumns( OutlineLevelVec& orColLevels, const ValueRange& rColRange, const ColumnModel& rModel ); /** Converts row properties for all rows in the sheet. */ void convertRows(); /** Converts row properties. */ - void convertRows( OutlineLevelVec& orRowLevels, sal_Int32 nFirstRow, sal_Int32 nLastRow, const RowModel& rModel, double fDefHeight = -1.0 ); + void convertRows( OutlineLevelVec& orRowLevels, const ValueRange& rRowRange, const RowModel& rModel, double fDefHeight = -1.0 ); /** Converts outline grouping for the passed column or row. */ void convertOutlines( OutlineLevelVec& orLevels, sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows ); /** Groups columns or rows for the given range. */ void groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapsed, bool bRows ); - /** Imports the drawings of the sheet (DML, VML), and updates the used area. */ + /** Imports the drawings of the sheet (DML, VML, DFF) and updates the used area. */ void finalizeDrawings(); private: - typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr; + typedef ::std::auto_ptr< VmlDrawing > VmlDrawingPtr; + typedef ::std::auto_ptr< BiffSheetDrawing > BiffSheetDrawingPtr; - const OUString maTrueFormula; /// Replacement formula for TRUE boolean cells. - const OUString maFalseFormula; /// Replacement formula for FALSE boolean cells. const OUString maSheetCellRanges; /// Service name for a SheetCellRanges object. const OUString maUrlTextField; /// Service name for a URL text field. const CellAddress& mrMaxApiPos; /// Reference to maximum Calc cell address from address converter. CellRangeAddress maUsedArea; /// Used area of the sheet, and sheet index of the sheet. ColumnModel maDefColModel; /// Default column formatting. - ColumnModelMap maColModels; /// Columns sorted by first column index. + ColumnModelRangeMap maColModels; /// Ranges of columns sorted by first column index. RowModel maDefRowModel; /// Default row formatting. - RowModelMap maRowModels; /// Rows sorted by row index. + RowModelRangeMap maRowModels; /// Ranges of rows sorted by first row index. HyperlinkModelList maHyperlinks; /// Cell ranges containing hyperlinks. ValidationModelList maValidations; /// Cell ranges containing data validation settings. - XfIdRowRange maXfIdRowRange; /// Cached XF identifier for a range of rows. - XfIdRangeMap maXfIdRanges; /// Collected XF identifiers for cell ranges. - MergedRangeList maMergedRanges; /// Merged cell ranges. - MergedRangeList maCenterFillRanges; /// Merged cell ranges from 'center across' or 'fill' alignment. ValueRangeSet maManualRowHeights; /// Rows that need manual height independent from own settings. - WorksheetSettings maSheetSett; /// Global settings for this sheet. - SharedFormulaBuffer maSharedFmlas; /// Buffer for shared formulas in this sheet. + SheetDataBuffer maSheetData; /// Buffer for cell contents and cell formatting. CondFormatBuffer maCondFormats; /// Buffer for conditional formattings. CommentsBuffer maComments; /// Buffer for all cell comments in this sheet. AutoFilterBuffer maAutoFilters; /// Sheet auto filters (not associated to a table). QueryTableBuffer maQueryTables; /// Buffer for all web query tables in this sheet. + WorksheetSettings maSheetSett; /// Global settings for this sheet. PageSettings maPageSett; /// Page/print settings for this sheet. SheetViewSettings maSheetViewSett; /// View settings for this sheet. VmlDrawingPtr mxVmlDrawing; /// Collection of all VML shapes. + BiffSheetDrawingPtr mxBiffDrawing; /// Collection of all BIFF/DFF shapes. OUString maDrawingPath; /// Path to DrawingML fragment. OUString maVmlDrawingPath; /// Path to legacy VML drawing fragment. + Size maDrawPageSize; /// Current size of the drawing page in 1/100 mm. Rectangle maShapeBoundingBox; /// Bounding box for all shapes from all drawings. ISegmentProgressBarRef mxProgressBar; /// Sheet progress bar. ISegmentProgressBarRef mxRowProgress; /// Progress bar for row/cell processing. @@ -579,20 +417,18 @@ private: // ---------------------------------------------------------------------------- -WorksheetData::WorksheetData( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : +WorksheetGlobals::WorksheetGlobals( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : WorkbookHelper( rHelper ), - maTrueFormula( CREATE_OUSTRING( "=TRUE()" ) ), - maFalseFormula( CREATE_OUSTRING( "=FALSE()" ) ), maSheetCellRanges( CREATE_OUSTRING( "com.sun.star.sheet.SheetCellRanges" ) ), maUrlTextField( CREATE_OUSTRING( "com.sun.star.text.TextField.URL" ) ), mrMaxApiPos( rHelper.getAddressConverter().getMaxApiAddress() ), maUsedArea( nSheet, SAL_MAX_INT32, SAL_MAX_INT32, -1, -1 ), - maSheetSett( *this ), - maSharedFmlas( *this ), + maSheetData( *this ), maCondFormats( *this ), maComments( *this ), maAutoFilters( *this ), maQueryTables( *this ), + maSheetSett( *this ), maPageSett( *this ), maSheetViewSett( *this ), mxProgressBar( rxProgressBar ), @@ -621,8 +457,17 @@ WorksheetData::WorksheetData( const WorkbookHelper& rHelper, const ISegmentProgr maDefRowModel.mbCollapsed = false; // buffers - if( getFilterType() == FILTER_OOXML ) - mxVmlDrawing.reset( new VmlDrawing( *this ) ); + switch( getFilterType() ) + { + case FILTER_OOXML: + mxVmlDrawing.reset( new VmlDrawing( *this ) ); + break; + case FILTER_BIFF: + mxBiffDrawing.reset( new BiffSheetDrawing( *this ) ); + break; + case FILTER_UNKNOWN: + break; + } // prepare progress bars if( mxProgressBar.get() ) @@ -632,12 +477,7 @@ WorksheetData::WorksheetData( const WorkbookHelper& rHelper, const ISegmentProgr } } -const OUString& WorksheetData::getBooleanFormula( bool bValue ) const -{ - return bValue ? maTrueFormula : maFalseFormula; -} - -Reference< XCell > WorksheetData::getCell( const CellAddress& rAddress ) const +Reference< XCell > WorksheetGlobals::getCell( const CellAddress& rAddress ) const { Reference< XCell > xCell; if( mxSheet.is() ) try @@ -650,7 +490,7 @@ Reference< XCell > WorksheetData::getCell( const CellAddress& rAddress ) const return xCell; } -Reference< XCellRange > WorksheetData::getCellRange( const CellRangeAddress& rRange ) const +Reference< XCellRange > WorksheetGlobals::getCellRange( const CellRangeAddress& rRange ) const { Reference< XCellRange > xRange; if( mxSheet.is() ) try @@ -663,12 +503,12 @@ Reference< XCellRange > WorksheetData::getCellRange( const CellRangeAddress& rRa return xRange; } -Reference< XSheetCellRanges > WorksheetData::getCellRangeList( const ApiCellRangeList& rRanges ) const +Reference< XSheetCellRanges > WorksheetGlobals::getCellRangeList( const ApiCellRangeList& rRanges ) const { Reference< XSheetCellRanges > xRanges; if( mxSheet.is() && !rRanges.empty() ) try { - xRanges.set( getDocumentFactory()->createInstance( maSheetCellRanges ), UNO_QUERY_THROW ); + xRanges.set( getBaseFilter().getModelFactory()->createInstance( maSheetCellRanges ), UNO_QUERY_THROW ); Reference< XSheetCellRangeContainer > xRangeCont( xRanges, UNO_QUERY_THROW ); xRangeCont->addRangeAddresses( ContainerHelper::vectorToSequence( rRanges ), sal_False ); } @@ -678,7 +518,7 @@ Reference< XSheetCellRanges > WorksheetData::getCellRangeList( const ApiCellRang return xRanges; } -Reference< XCellRange > WorksheetData::getColumn( sal_Int32 nCol ) const +Reference< XCellRange > WorksheetGlobals::getColumn( sal_Int32 nCol ) const { Reference< XCellRange > xColumn; try @@ -693,7 +533,7 @@ Reference< XCellRange > WorksheetData::getColumn( sal_Int32 nCol ) const return xColumn; } -Reference< XCellRange > WorksheetData::getRow( sal_Int32 nRow ) const +Reference< XCellRange > WorksheetGlobals::getRow( sal_Int32 nRow ) const { Reference< XCellRange > xRow; try @@ -708,33 +548,33 @@ Reference< XCellRange > WorksheetData::getRow( sal_Int32 nRow ) const return xRow; } -Reference< XTableColumns > WorksheetData::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const +Reference< XTableColumns > WorksheetGlobals::getColumns( const ValueRange& rColRange ) const { Reference< XTableColumns > xColumns; - nLastCol = ::std::min( nLastCol, mrMaxApiPos.Column ); - if( (0 <= nFirstCol) && (nFirstCol <= nLastCol) ) + sal_Int32 nLastCol = ::std::min( rColRange.mnLast, mrMaxApiPos.Column ); + if( (0 <= rColRange.mnFirst) && (rColRange.mnFirst <= nLastCol) ) { - Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), nFirstCol, 0, nLastCol, 0 ) ), UNO_QUERY ); + Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), rColRange.mnFirst, 0, nLastCol, 0 ) ), UNO_QUERY ); if( xRange.is() ) xColumns = xRange->getColumns(); } return xColumns; } -Reference< XTableRows > WorksheetData::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const +Reference< XTableRows > WorksheetGlobals::getRows( const ValueRange& rRowRange ) const { Reference< XTableRows > xRows; - nLastRow = ::std::min( nLastRow, mrMaxApiPos.Row ); - if( (0 <= nFirstRow) && (nFirstRow <= nLastRow) ) + sal_Int32 nLastRow = ::std::min( rRowRange.mnLast, mrMaxApiPos.Row ); + if( (0 <= rRowRange.mnFirst) && (rRowRange.mnFirst <= nLastRow) ) { - Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), 0, nFirstRow, 0, nLastRow ) ), UNO_QUERY ); + Reference< XColumnRowRange > xRange( getCellRange( CellRangeAddress( getSheetIndex(), 0, rRowRange.mnFirst, 0, nLastRow ) ), UNO_QUERY ); if( xRange.is() ) xRows = xRange->getRows(); } return xRows; } -Reference< XDrawPage > WorksheetData::getDrawPage() const +Reference< XDrawPage > WorksheetGlobals::getDrawPage() const { Reference< XDrawPage > xDrawPage; try @@ -747,15 +587,13 @@ Reference< XDrawPage > WorksheetData::getDrawPage() const return xDrawPage; } -Size WorksheetData::getDrawPageSize() const +const Size& WorksheetGlobals::getDrawPageSize() const { - Size aSize; - PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) ); - aRangeProp.getProperty( aSize, PROP_Size ); - return aSize; + OSL_ENSURE( (maDrawPageSize.Width > 0) && (maDrawPageSize.Height > 0), "WorksheetGlobals::getDrawPageSize - called too early, size invalid" ); + return maDrawPageSize; } -Point WorksheetData::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const +Point WorksheetGlobals::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const { Point aPoint; PropertySet aCellProp( getCell( CellAddress( getSheetIndex(), nCol, nRow ) ) ); @@ -763,7 +601,7 @@ Point WorksheetData::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const return aPoint; } -Size WorksheetData::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const +Size WorksheetGlobals::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const { Size aSize; PropertySet aCellProp( getCell( CellAddress( getSheetIndex(), nCol, nRow ) ) ); @@ -840,7 +678,7 @@ bool lclUpdateInterval( sal_Int32& rnBegAddr, sal_Int32& rnMidAddr, sal_Int32& r } // namespace -CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, const Size& rDrawPageSize ) const +CellAddress WorksheetGlobals::getCellAddressFromPosition( const Point& rPosition ) const { // starting cell address and its position in drawing layer (top-left edge) sal_Int32 nBegCol = 0; @@ -850,7 +688,7 @@ CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, c // end cell address and its position in drawing layer (bottom-right edge) sal_Int32 nEndCol = mrMaxApiPos.Column + 1; sal_Int32 nEndRow = mrMaxApiPos.Row + 1; - Point aEndPos( rDrawPageSize.Width, rDrawPageSize.Height ); + Point aEndPos( maDrawPageSize.Width, maDrawPageSize.Height ); // starting point for interval search sal_Int32 nMidCol, nMidRow; @@ -876,12 +714,11 @@ CellAddress WorksheetData::getCellAddressFromPosition( const Point& rPosition, c return CellAddress( getSheetIndex(), nMidCol, nMidRow ); } -CellRangeAddress WorksheetData::getCellRangeFromRectangle( const Rectangle& rRect ) const +CellRangeAddress WorksheetGlobals::getCellRangeFromRectangle( const Rectangle& rRect ) const { - Size aPageSize = getDrawPageSize(); - CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ), aPageSize ); + CellAddress aStartAddr = getCellAddressFromPosition( Point( rRect.X, rRect.Y ) ); Point aBotRight( rRect.X + rRect.Width, rRect.Y + rRect.Height ); - CellAddress aEndAddr = getCellAddressFromPosition( aBotRight, aPageSize ); + CellAddress aEndAddr = getCellAddressFromPosition( aBotRight ); bool bMultiCols = aStartAddr.Column < aEndAddr.Column; bool bMultiRows = aStartAddr.Row < aEndAddr.Row; if( bMultiCols || bMultiRows ) @@ -897,62 +734,7 @@ CellRangeAddress WorksheetData::getCellRangeFromRectangle( const Rectangle& rRec return CellRangeAddress( getSheetIndex(), aStartAddr.Column, aStartAddr.Row, aEndAddr.Column, aEndAddr.Row ); } -void WorksheetData::setCellFormat( const CellModel& rModel ) -{ - if( rModel.mxCell.is() && ((rModel.mnXfId >= 0) || (rModel.mnNumFmtId >= 0)) ) - { - // try to merge existing ranges and to write some formatting properties - if( !maXfIdRanges.empty() ) - { - // get row index of last inserted cell - sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow; - // row changed - try to merge ranges of last row with existing ranges - if( rModel.maAddress.Row != nLastRow ) - { - mergeXfIdRanges(); - // write format properties of all ranges above last row and remove them - XfIdRangeMap::iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); - while( aIt != aEnd ) - { - // check that range cannot be merged with current row, and that range is not in cached row range - if( (aIt->second.maRange.EndRow < nLastRow) && !maXfIdRowRange.intersects( aIt->second.maRange ) ) - { - writeXfIdRangeProperties( aIt->second ); - maXfIdRanges.erase( aIt++ ); - } - else - ++aIt; - } - } - } - - // try to expand last existing range, or create new range entry - if( maXfIdRanges.empty() || !maXfIdRanges.rbegin()->second.tryExpand( rModel ) ) - maXfIdRanges[ RowColKey( rModel.maAddress.Row, rModel.maAddress.Column ) ].set( rModel ); - - // update merged ranges for 'center across selection' and 'fill' - if( const Xf* pXf = getStyles().getCellXf( rModel.mnXfId ).get() ) - { - sal_Int32 nHorAlign = pXf->getAlignment().getModel().mnHorAlign; - if( (nHorAlign == XML_centerContinuous) || (nHorAlign == XML_fill) ) - { - /* start new merged range, if cell is not empty (#108781#), - or try to expand last range with empty cell */ - if( rModel.mnCellType != XML_TOKEN_INVALID ) - maCenterFillRanges.push_back( MergedRange( rModel.maAddress, nHorAlign ) ); - else if( !maCenterFillRanges.empty() ) - maCenterFillRanges.rbegin()->tryExpand( rModel.maAddress, nHorAlign ); - } - } - } -} - -void WorksheetData::setMergedRange( const CellRangeAddress& rRange ) -{ - maMergedRanges.push_back( MergedRange( rRange ) ); -} - -void WorksheetData::setPageBreak( const PageBreakModel& rModel, bool bRowBreak ) +void WorksheetGlobals::setPageBreak( const PageBreakModel& rModel, bool bRowBreak ) { if( rModel.mbManual && (rModel.mnColRow > 0) ) { @@ -961,27 +743,27 @@ void WorksheetData::setPageBreak( const PageBreakModel& rModel, bool bRowBreak ) } } -void WorksheetData::setHyperlink( const HyperlinkModel& rModel ) +void WorksheetGlobals::setHyperlink( const HyperlinkModel& rModel ) { maHyperlinks.push_back( rModel ); } -void WorksheetData::setValidation( const ValidationModel& rModel ) +void WorksheetGlobals::setValidation( const ValidationModel& rModel ) { maValidations.push_back( rModel ); } -void WorksheetData::setDrawingPath( const OUString& rDrawingPath ) +void WorksheetGlobals::setDrawingPath( const OUString& rDrawingPath ) { maDrawingPath = rDrawingPath; } -void WorksheetData::setVmlDrawingPath( const OUString& rVmlDrawingPath ) +void WorksheetGlobals::setVmlDrawingPath( const OUString& rVmlDrawingPath ) { maVmlDrawingPath = rVmlDrawingPath; } -void WorksheetData::extendUsedArea( const CellAddress& rAddress ) +void WorksheetGlobals::extendUsedArea( const CellAddress& rAddress ) { maUsedArea.StartColumn = ::std::min( maUsedArea.StartColumn, rAddress.Column ); maUsedArea.StartRow = ::std::min( maUsedArea.StartRow, rAddress.Row ); @@ -989,13 +771,13 @@ void WorksheetData::extendUsedArea( const CellAddress& rAddress ) maUsedArea.EndRow = ::std::max( maUsedArea.EndRow, rAddress.Row ); } -void WorksheetData::extendUsedArea( const CellRangeAddress& rRange ) +void WorksheetGlobals::extendUsedArea( const CellRangeAddress& rRange ) { extendUsedArea( CellAddress( rRange.Sheet, rRange.StartColumn, rRange.StartRow ) ); extendUsedArea( CellAddress( rRange.Sheet, rRange.EndColumn, rRange.EndRow ) ); } -void WorksheetData::extendShapeBoundingBox( const Rectangle& rShapeRect ) +void WorksheetGlobals::extendShapeBoundingBox( const Rectangle& rShapeRect ) { if( (maShapeBoundingBox.Width == 0) && (maShapeBoundingBox.Height == 0) ) { @@ -1013,7 +795,7 @@ void WorksheetData::extendShapeBoundingBox( const Rectangle& rShapeRect ) } } -void WorksheetData::setBaseColumnWidth( sal_Int32 nWidth ) +void WorksheetGlobals::setBaseColumnWidth( sal_Int32 nWidth ) { // do not modify width, if setDefaultColumnWidth() has been used if( !mbHasDefWidth && (nWidth > 0) ) @@ -1025,7 +807,7 @@ void WorksheetData::setBaseColumnWidth( sal_Int32 nWidth ) } } -void WorksheetData::setDefaultColumnWidth( double fWidth ) +void WorksheetGlobals::setDefaultColumnWidth( double fWidth ) { // overrides a width set with setBaseColumnWidth() if( fWidth > 0.0 ) @@ -1035,22 +817,65 @@ void WorksheetData::setDefaultColumnWidth( double fWidth ) } } -void WorksheetData::setColumnModel( const ColumnModel& rModel ) +void WorksheetGlobals::setColumnModel( const ColumnModel& rModel ) { // convert 1-based OOXML column indexes to 0-based API column indexes - sal_Int32 nFirstCol = rModel.mnFirstCol - 1; - sal_Int32 nLastCol = rModel.mnLastCol - 1; - if( (0 <= nFirstCol) && (nFirstCol <= mrMaxApiPos.Column) ) + sal_Int32 nFirstCol = rModel.maRange.mnFirst - 1; + sal_Int32 nLastCol = rModel.maRange.mnLast - 1; + if( getAddressConverter().checkCol( nFirstCol, true ) && (nFirstCol <= nLastCol) ) + { + // validate last column index + if( !getAddressConverter().checkCol( nLastCol, true ) ) + nLastCol = mrMaxApiPos.Column; + // try to find entry in column model map that is able to merge with the passed model + bool bInsertModel = true; + if( !maColModels.empty() ) + { + // find first column model range following nFirstCol (nFirstCol < aIt->first), or end of map + ColumnModelRangeMap::iterator aIt = maColModels.upper_bound( nFirstCol ); + OSL_ENSURE( aIt == maColModels.end(), "WorksheetGlobals::setColModel - columns are unsorted" ); + // if inserting before another column model, get last free column + OSL_ENSURE( (aIt == maColModels.end()) || (nLastCol < aIt->first), "WorksheetGlobals::setColModel - multiple models of the same column" ); + if( aIt != maColModels.end() ) + nLastCol = ::std::min( nLastCol, aIt->first - 1 ); + if( aIt != maColModels.begin() ) + { + // go to previous map element (which may be able to merge with the passed model) + --aIt; + // the usage of upper_bound() above ensures that aIt->first is less than or equal to nFirstCol now + sal_Int32& rnLastMapCol = aIt->second.second; + OSL_ENSURE( rnLastMapCol < nFirstCol, "WorksheetGlobals::setColModel - multiple models of the same column" ); + nFirstCol = ::std::max( rnLastMapCol + 1, nFirstCol ); + if( (rnLastMapCol + 1 == nFirstCol) && (nFirstCol <= nLastCol) && aIt->second.first.isMergeable( rModel ) ) + { + // can merge with existing model, update last column index + rnLastMapCol = nLastCol; + bInsertModel = false; + } + } + } + if( nFirstCol <= nLastCol ) + { + // insert the column model, if it has not been merged with another + if( bInsertModel ) + maColModels[ nFirstCol ] = ColumnModelRange( rModel, nLastCol ); + // set column formatting directly + convertColumnFormat( nFirstCol, nLastCol, rModel.mnXfId ); + } + } +} + +void WorksheetGlobals::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const +{ + CellRangeAddress aRange( getSheetIndex(), nFirstCol, 0, nLastCol, mrMaxApiPos.Row ); + if( getAddressConverter().validateCellRange( aRange, true, false ) ) { - // set column formatting directly, nLastCol is checked inside the function - convertColumnFormat( nFirstCol, nLastCol, rModel.mnXfId ); - // expand last entry or add new entry - if( maColModels.empty() || !maColModels.rbegin()->second.tryExpand( rModel ) ) - maColModels[ nFirstCol ] = rModel; + PropertySet aPropSet( getCellRange( aRange ) ); + getStyles().writeCellXfToPropertySet( aPropSet, nXfId ); } } -void WorksheetData::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ) +void WorksheetGlobals::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ) { maDefRowModel.mfHeight = fHeight; maDefRowModel.mbCustomHeight = bCustomHeight; @@ -1059,83 +884,79 @@ void WorksheetData::setDefaultRowSettings( double fHeight, bool bCustomHeight, b maDefRowModel.mbThickBottom = bThickBottom; } -void WorksheetData::setRowModel( const RowModel& rModel ) +void WorksheetGlobals::setRowModel( const RowModel& rModel ) { - // convert 1-based OOXML row indexes to 0-based API row indexes - sal_Int32 nFirstRow = rModel.mnFirstRow - 1; - sal_Int32 nLastRow = rModel.mnLastRow - 1; - if( (0 <= nFirstRow) && (nFirstRow <= mrMaxApiPos.Row) ) + // convert 1-based OOXML row index to 0-based API row index + sal_Int32 nRow = rModel.mnRow - 1; + if( getAddressConverter().checkRow( nRow, true ) ) { - // set row formatting - if( rModel.mbCustomFormat ) + // try to find entry in row model map that is able to merge with the passed model + bool bInsertModel = true; + bool bUnusedRow = true; + if( !maRowModels.empty() ) { - // try to expand cached row range, if formatting is equal - if( (maXfIdRowRange.mnLastRow < 0) || !maXfIdRowRange.tryExpand( nFirstRow, nLastRow, rModel.mnXfId ) ) + // find first row model range following nRow (nRow < aIt->first), or end of map + RowModelRangeMap::iterator aIt = maRowModels.upper_bound( nRow ); + OSL_ENSURE( aIt == maRowModels.end(), "WorksheetGlobals::setRowModel - rows are unsorted" ); + if( aIt != maRowModels.begin() ) { - writeXfIdRowRangeProperties( maXfIdRowRange ); - maXfIdRowRange.set( nFirstRow, nLastRow, rModel.mnXfId ); + // go to previous map element (which may be able to merge with the passed model) + --aIt; + // the usage of upper_bound() above ensures that aIt->first is less than or equal to nRow now + sal_Int32& rnLastMapRow = aIt->second.second; + bUnusedRow = rnLastMapRow < nRow; + OSL_ENSURE( bUnusedRow, "WorksheetGlobals::setRowModel - multiple models of the same row" ); + if( (rnLastMapRow + 1 == nRow) && aIt->second.first.isMergeable( rModel ) ) + { + // can merge with existing model, update last row index + ++rnLastMapRow; + bInsertModel = false; + } } } - else if( maXfIdRowRange.mnLastRow >= 0 ) + if( bUnusedRow ) { - // finish last cached row range - writeXfIdRowRangeProperties( maXfIdRowRange ); - maXfIdRowRange.set( -1, -1, -1 ); + // insert the row model, if it has not been merged with another + if( bInsertModel ) + maRowModels[ nRow ] = RowModelRange( rModel, nRow ); + // set row formatting + maSheetData.setRowFormat( nRow, rModel.mnXfId, rModel.mbCustomFormat ); + // set column spans + maSheetData.setColSpans( nRow, rModel.maColSpans ); } - - // expand last entry or add new entry - if( maRowModels.empty() || !maRowModels.rbegin()->second.tryExpand( rModel ) ) - maRowModels[ nFirstRow ] = rModel; - } - lclUpdateProgressBar( mxRowProgress, maUsedArea, nLastRow ); -} - -void WorksheetData::convertColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) const -{ - CellRangeAddress aRange( getSheetIndex(), nFirstCol, 0, nLastCol, mrMaxApiPos.Row ); - if( getAddressConverter().validateCellRange( aRange, true, false ) ) - { - PropertySet aPropSet( getCellRange( aRange ) ); - getStyles().writeCellXfToPropertySet( aPropSet, nXfId ); } + lclUpdateProgressBar( mxRowProgress, maUsedArea, nRow ); } -void WorksheetData::convertRowFormat( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) const +void WorksheetGlobals::setManualRowHeight( sal_Int32 nRow ) { - CellRangeAddress aRange( getSheetIndex(), 0, nFirstRow, mrMaxApiPos.Column, nLastRow ); - if( getAddressConverter().validateCellRange( aRange, true, false ) ) - { - PropertySet aPropSet( getCellRange( aRange ) ); - getStyles().writeCellXfToPropertySet( aPropSet, nXfId ); - } + maManualRowHeights.insert( nRow ); } -void WorksheetData::initializeWorksheetImport() +void WorksheetGlobals::initializeWorksheetImport() { // set default cell style for unused cells PropertySet aPropSet( mxSheet ); aPropSet.setProperty( PROP_CellStyle, getStyles().getDefaultStyleName() ); - /* Remember current sheet index in global data, needed by some global + /* Remember the current sheet index in global data, needed by global objects, e.g. the chart converter. */ setCurrentSheetIndex( getSheetIndex() ); } -void WorksheetData::finalizeWorksheetImport() +void WorksheetGlobals::finalizeWorksheetImport() { lclUpdateProgressBar( mxRowProgress, 1.0 ); - finalizeXfIdRanges(); + maSheetData.finalizeImport(); lclUpdateProgressBar( mxFinalProgress, 0.25 ); finalizeHyperlinkRanges(); finalizeValidationRanges(); - finalizeMergedRanges(); maAutoFilters.finalizeImport( getSheetIndex() ); - maSheetSett.finalizeImport(); maCondFormats.finalizeImport(); maQueryTables.finalizeImport(); + maSheetSett.finalizeImport(); maPageSett.finalizeImport(); maSheetViewSett.finalizeImport(); - maSheetSett.finalizeImport(); lclUpdateProgressBar( mxFinalProgress, 0.5 ); convertColumns(); @@ -1144,159 +965,13 @@ void WorksheetData::finalizeWorksheetImport() finalizeDrawings(); lclUpdateProgressBar( mxFinalProgress, 1.0 ); - // reset current sheet index in global data + // forget current sheet index in global data setCurrentSheetIndex( -1 ); } // private -------------------------------------------------------------------- -WorksheetData::XfIdRowRange::XfIdRowRange() : - mnFirstRow( -1 ), - mnLastRow( -1 ), - mnXfId( -1 ) -{ -} - -bool WorksheetData::XfIdRowRange::intersects( const CellRangeAddress& rRange ) const -{ - return (rRange.StartRow <= mnLastRow) && (mnFirstRow <= rRange.EndRow); -} - -void WorksheetData::XfIdRowRange::set( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) -{ - mnFirstRow = nFirstRow; - mnLastRow = nLastRow; - mnXfId = nXfId; -} - -bool WorksheetData::XfIdRowRange::tryExpand( sal_Int32 nFirstRow, sal_Int32 nLastRow, sal_Int32 nXfId ) -{ - if( mnXfId == nXfId ) - { - if( mnLastRow + 1 == nFirstRow ) - { - mnLastRow = nLastRow; - return true; - } - if( mnFirstRow == nLastRow + 1 ) - { - mnFirstRow = nFirstRow; - return true; - } - } - return false; -} - -void WorksheetData::XfIdRange::set( const CellModel& rModel ) -{ - maRange.Sheet = rModel.maAddress.Sheet; - maRange.StartColumn = maRange.EndColumn = rModel.maAddress.Column; - maRange.StartRow = maRange.EndRow = rModel.maAddress.Row; - mnXfId = rModel.mnXfId; - mnNumFmtId = rModel.mnNumFmtId; -} - -bool WorksheetData::XfIdRange::tryExpand( const CellModel& rModel ) -{ - if( (mnXfId == rModel.mnXfId) && (mnNumFmtId == rModel.mnNumFmtId) && - (maRange.StartRow == rModel.maAddress.Row) && - (maRange.EndRow == rModel.maAddress.Row) && - (maRange.EndColumn + 1 == rModel.maAddress.Column) ) - { - ++maRange.EndColumn; - return true; - } - return false; -} - -bool WorksheetData::XfIdRange::tryMerge( const XfIdRange& rXfIdRange ) -{ - if( (mnXfId == rXfIdRange.mnXfId) && - (mnNumFmtId == rXfIdRange.mnNumFmtId) && - (maRange.EndRow + 1 == rXfIdRange.maRange.StartRow) && - (maRange.StartColumn == rXfIdRange.maRange.StartColumn) && - (maRange.EndColumn == rXfIdRange.maRange.EndColumn) ) - { - maRange.EndRow = rXfIdRange.maRange.EndRow; - return true; - } - return false; -} - - -WorksheetData::MergedRange::MergedRange( const CellRangeAddress& rRange ) : - maRange( rRange ), - mnHorAlign( XML_TOKEN_INVALID ) -{ -} - -WorksheetData::MergedRange::MergedRange( const CellAddress& rAddress, sal_Int32 nHorAlign ) : - maRange( rAddress.Sheet, rAddress.Column, rAddress.Row, rAddress.Column, rAddress.Row ), - mnHorAlign( nHorAlign ) -{ -} - -bool WorksheetData::MergedRange::tryExpand( const CellAddress& rAddress, sal_Int32 nHorAlign ) -{ - if( (mnHorAlign == nHorAlign) && (maRange.StartRow == rAddress.Row) && - (maRange.EndRow == rAddress.Row) && (maRange.EndColumn + 1 == rAddress.Column) ) - { - ++maRange.EndColumn; - return true; - } - return false; -} - -void WorksheetData::writeXfIdRowRangeProperties( const XfIdRowRange& rXfIdRowRange ) const -{ - if( (rXfIdRowRange.mnLastRow >= 0) && (rXfIdRowRange.mnXfId >= 0) ) - convertRowFormat( rXfIdRowRange.mnFirstRow, rXfIdRowRange.mnLastRow, rXfIdRowRange.mnXfId ); -} - -void WorksheetData::writeXfIdRangeProperties( const XfIdRange& rXfIdRange ) const -{ - StylesBuffer& rStyles = getStyles(); - PropertyMap aPropMap; - if( rXfIdRange.mnXfId >= 0 ) - rStyles.writeCellXfToPropertyMap( aPropMap, rXfIdRange.mnXfId ); - if( rXfIdRange.mnNumFmtId >= 0 ) - rStyles.writeNumFmtToPropertyMap( aPropMap, rXfIdRange.mnNumFmtId ); - PropertySet aPropSet( getCellRange( rXfIdRange.maRange ) ); - aPropSet.setProperties( aPropMap ); -} - -void WorksheetData::mergeXfIdRanges() -{ - if( !maXfIdRanges.empty() ) - { - // get row index of last range - sal_Int32 nLastRow = maXfIdRanges.rbegin()->second.maRange.StartRow; - // process all ranges located in the same row of the last range - XfIdRangeMap::iterator aMergeIt = maXfIdRanges.end(); - while( (aMergeIt != maXfIdRanges.begin()) && ((--aMergeIt)->second.maRange.StartRow == nLastRow) ) - { - const XfIdRange& rMergeXfIdRange = aMergeIt->second; - // try to find a range that can be merged with rMergeRange - bool bFound = false; - for( XfIdRangeMap::iterator aIt = maXfIdRanges.begin(); !bFound && (aIt != aMergeIt); ++aIt ) - if( (bFound = aIt->second.tryMerge( rMergeXfIdRange )) == true ) - maXfIdRanges.erase( aMergeIt++ ); - } - } -} - -void WorksheetData::finalizeXfIdRanges() -{ - // write default formatting of remaining row range - writeXfIdRowRangeProperties( maXfIdRowRange ); - // try to merge remaining inserted ranges - mergeXfIdRanges(); - // write all formatting - for( XfIdRangeMap::const_iterator aIt = maXfIdRanges.begin(), aEnd = maXfIdRanges.end(); aIt != aEnd; ++aIt ) - writeXfIdRangeProperties( aIt->second ); -} - -void WorksheetData::finalizeHyperlinkRanges() const +void WorksheetGlobals::finalizeHyperlinkRanges() const { for( HyperlinkModelList::const_iterator aIt = maHyperlinks.begin(), aEnd = maHyperlinks.end(); aIt != aEnd; ++aIt ) { @@ -1309,7 +984,7 @@ void WorksheetData::finalizeHyperlinkRanges() const } } -OUString WorksheetData::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const +OUString WorksheetGlobals::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) const { OUStringBuffer aUrlBuffer; if( rHyperlink.maTarget.getLength() > 0 ) @@ -1337,20 +1012,20 @@ OUString WorksheetData::getHyperlinkUrl( const HyperlinkModel& rHyperlink ) cons return aUrl; } -void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const +void WorksheetGlobals::insertHyperlink( const CellAddress& rAddress, const OUString& rUrl ) const { Reference< XCell > xCell = getCell( rAddress ); if( xCell.is() ) switch( xCell->getType() ) { // #i54261# restrict creation of URL field to text cells - case ::com::sun::star::table::CellContentType_TEXT: + case CellContentType_TEXT: { Reference< XText > xText( xCell, UNO_QUERY ); if( xText.is() ) { // create a URL field object and set its properties - Reference< XTextContent > xUrlField( getDocumentFactory()->createInstance( maUrlTextField ), UNO_QUERY ); - OSL_ENSURE( xUrlField.is(), "WorksheetData::insertHyperlink - cannot create text field" ); + Reference< XTextContent > xUrlField( getBaseFilter().getModelFactory()->createInstance( maUrlTextField ), UNO_QUERY ); + OSL_ENSURE( xUrlField.is(), "WorksheetGlobals::insertHyperlink - cannot create text field" ); if( xUrlField.is() ) { // properties of the URL field @@ -1366,7 +1041,7 @@ void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString } catch( const Exception& ) { - OSL_ENSURE( false, "WorksheetData::insertHyperlink - cannot insert text field" ); + OSL_ENSURE( false, "WorksheetGlobals::insertHyperlink - cannot insert text field" ); } } } @@ -1376,15 +1051,13 @@ void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString // fix for #i31050# disabled, HYPERLINK is not able to return numeric value (#i91351#) #if 0 // #i31050# replace number with HYPERLINK function - case ::com::sun::star::table::CellContentType_VALUE: + case CellContentType_VALUE: { Reference< XFormulaTokens > xTokens( xCell, UNO_QUERY ); - OSL_ENSURE( xTokens.is(), "WorksheetHelper::insertHyperlink - missing formula interface" ); - if( xTokens.is() ) - { - SimpleFormulaContext aContext( xTokens, false, false ); - getFormulaParser().convertNumberToHyperlink( aContext, rUrl, xCell->getValue() ); - } + ApiTokenSequence aTokens = getFormulaParser().convertNumberToHyperlink( rUrl, xCell->getValue() ); + OSL_ENSURE( xTokens.is(), "WorksheetHelper::insertHyperlink - missing formula token interface" ); + if( xTokens.is() && aTokens.hasElements() ) + xTokens->setTokens( aTokens ); } break; #endif @@ -1393,7 +1066,7 @@ void WorksheetData::insertHyperlink( const CellAddress& rAddress, const OUString } } -void WorksheetData::finalizeValidationRanges() const +void WorksheetGlobals::finalizeValidationRanges() const { for( ValidationModelList::const_iterator aIt = maValidations.begin(), aEnd = maValidations.end(); aIt != aEnd; ++aIt ) { @@ -1403,37 +1076,36 @@ void WorksheetData::finalizeValidationRanges() const if( xValidation.is() ) { PropertySet aValProps( xValidation ); - namespace csss = ::com::sun::star::sheet; // convert validation type to API enum - ValidationType eType = csss::ValidationType_ANY; + ValidationType eType = ValidationType_ANY; switch( aIt->mnType ) { - case XML_custom: eType = csss::ValidationType_CUSTOM; break; - case XML_date: eType = csss::ValidationType_DATE; break; - case XML_decimal: eType = csss::ValidationType_DECIMAL; break; - case XML_list: eType = csss::ValidationType_LIST; break; - case XML_none: eType = csss::ValidationType_ANY; break; - case XML_textLength: eType = csss::ValidationType_TEXT_LEN; break; - case XML_time: eType = csss::ValidationType_TIME; break; - case XML_whole: eType = csss::ValidationType_WHOLE; break; - default: OSL_ENSURE( false, "WorksheetData::finalizeValidationRanges - unknown validation type" ); + case XML_custom: eType = ValidationType_CUSTOM; break; + case XML_date: eType = ValidationType_DATE; break; + case XML_decimal: eType = ValidationType_DECIMAL; break; + case XML_list: eType = ValidationType_LIST; break; + case XML_none: eType = ValidationType_ANY; break; + case XML_textLength: eType = ValidationType_TEXT_LEN; break; + case XML_time: eType = ValidationType_TIME; break; + case XML_whole: eType = ValidationType_WHOLE; break; + default: OSL_ENSURE( false, "WorksheetGlobals::finalizeValidationRanges - unknown validation type" ); } aValProps.setProperty( PROP_Type, eType ); // convert error alert style to API enum - ValidationAlertStyle eAlertStyle = csss::ValidationAlertStyle_STOP; + ValidationAlertStyle eAlertStyle = ValidationAlertStyle_STOP; switch( aIt->mnErrorStyle ) { - case XML_information: eAlertStyle = csss::ValidationAlertStyle_INFO; break; - case XML_stop: eAlertStyle = csss::ValidationAlertStyle_STOP; break; - case XML_warning: eAlertStyle = csss::ValidationAlertStyle_WARNING; break; - default: OSL_ENSURE( false, "WorksheetData::finalizeValidationRanges - unknown error style" ); + case XML_information: eAlertStyle = ValidationAlertStyle_INFO; break; + case XML_stop: eAlertStyle = ValidationAlertStyle_STOP; break; + case XML_warning: eAlertStyle = ValidationAlertStyle_WARNING; break; + default: OSL_ENSURE( false, "WorksheetGlobals::finalizeValidationRanges - unknown error style" ); } aValProps.setProperty( PROP_ErrorAlertStyle, eAlertStyle ); // convert dropdown style to API visibility constants - sal_Int16 nVisibility = aIt->mbNoDropDown ? csss::TableValidationVisibility::INVISIBLE : csss::TableValidationVisibility::UNSORTED; + sal_Int16 nVisibility = aIt->mbNoDropDown ? TableValidationVisibility::INVISIBLE : TableValidationVisibility::UNSORTED; aValProps.setProperty( PROP_ShowList, nVisibility ); // messages @@ -1468,99 +1140,36 @@ void WorksheetData::finalizeValidationRanges() const } } -void WorksheetData::finalizeMergedRanges() -{ - MergedRangeList::const_iterator aIt, aEnd; - for( aIt = maMergedRanges.begin(), aEnd = maMergedRanges.end(); aIt != aEnd; ++aIt ) - finalizeMergedRange( aIt->maRange ); - for( aIt = maCenterFillRanges.begin(), aEnd = maCenterFillRanges.end(); aIt != aEnd; ++aIt ) - finalizeMergedRange( aIt->maRange ); -} - -void WorksheetData::finalizeMergedRange( const CellRangeAddress& rRange ) -{ - bool bMultiCol = rRange.StartColumn < rRange.EndColumn; - bool bMultiRow = rRange.StartRow < rRange.EndRow; - - if( bMultiCol || bMultiRow ) try - { - // merge the cell range - Reference< XMergeable > xMerge( getCellRange( rRange ), UNO_QUERY_THROW ); - xMerge->merge( sal_True ); - - // if merging this range worked (no overlapping merged ranges), update cell borders - Reference< XCell > xTopLeft( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.StartRow ) ), UNO_SET_THROW ); - PropertySet aTopLeftProp( xTopLeft ); - - // copy right border of top-right cell to right border of top-left cell - if( bMultiCol ) - { - PropertySet aTopRightProp( getCell( CellAddress( getSheetIndex(), rRange.EndColumn, rRange.StartRow ) ) ); - BorderLine aLine; - if( aTopRightProp.getProperty( aLine, PROP_RightBorder ) ) - aTopLeftProp.setProperty( PROP_RightBorder, aLine ); - } - - // copy bottom border of bottom-left cell to bottom border of top-left cell - if( bMultiRow ) - { - PropertySet aBottomLeftProp( getCell( CellAddress( getSheetIndex(), rRange.StartColumn, rRange.EndRow ) ) ); - BorderLine aLine; - if( aBottomLeftProp.getProperty( aLine, PROP_BottomBorder ) ) - aTopLeftProp.setProperty( PROP_BottomBorder, aLine ); - } - - // #i93609# merged range in a single row: test if manual row height is needed - if( !bMultiRow ) - { - bool bTextWrap = aTopLeftProp.getBoolProperty( PROP_IsTextWrapped ); - if( !bTextWrap && (xTopLeft->getType() == ::com::sun::star::table::CellContentType_TEXT) ) - { - Reference< XText > xText( xTopLeft, UNO_QUERY ); - bTextWrap = xText.is() && (xText->getString().indexOf( '\x0A' ) >= 0); - } - if( bTextWrap ) - maManualRowHeights.insert( rRange.StartRow ); - } - } - catch( Exception& ) - { - } -} - -void WorksheetData::convertColumns() +void WorksheetGlobals::convertColumns() { sal_Int32 nNextCol = 0; sal_Int32 nMaxCol = mrMaxApiPos.Column; // stores first grouped column index for each level OutlineLevelVec aColLevels; - for( ColumnModelMap::const_iterator aIt = maColModels.begin(), aEnd = maColModels.end(); aIt != aEnd; ++aIt ) + for( ColumnModelRangeMap::iterator aIt = maColModels.begin(), aEnd = maColModels.end(); aIt != aEnd; ++aIt ) { - // convert 1-based OOXML column indexes to 0-based API column indexes - sal_Int32 nFirstCol = ::std::max( aIt->second.mnFirstCol - 1, nNextCol ); - sal_Int32 nLastCol = ::std::min( aIt->second.mnLastCol - 1, nMaxCol ); - + // column indexes are stored 0-based in maColModels + ValueRange aColRange( ::std::max( aIt->first, nNextCol ), ::std::min( aIt->second.second, nMaxCol ) ); // process gap between two column models, use default column model - if( nNextCol < nFirstCol ) - convertColumns( aColLevels, nNextCol, nFirstCol - 1, maDefColModel ); + if( nNextCol < aColRange.mnFirst ) + convertColumns( aColLevels, ValueRange( nNextCol, aColRange.mnFirst - 1 ), maDefColModel ); // process the column model - convertColumns( aColLevels, nFirstCol, nLastCol, aIt->second ); - + convertColumns( aColLevels, aColRange, aIt->second.first ); // cache next column to be processed - nNextCol = nLastCol + 1; + nNextCol = aColRange.mnLast + 1; } // remaining default columns to end of sheet - convertColumns( aColLevels, nNextCol, nMaxCol, maDefColModel ); + convertColumns( aColLevels, ValueRange( nNextCol, nMaxCol ), maDefColModel ); // close remaining column outlines spanning to end of sheet convertOutlines( aColLevels, nMaxCol + 1, 0, false, false ); } -void WorksheetData::convertColumns( OutlineLevelVec& orColLevels, - sal_Int32 nFirstCol, sal_Int32 nLastCol, const ColumnModel& rModel ) +void WorksheetGlobals::convertColumns( OutlineLevelVec& orColLevels, + const ValueRange& rColRange, const ColumnModel& rModel ) { - PropertySet aPropSet( getColumns( nFirstCol, nLastCol ) ); + PropertySet aPropSet( getColumns( rColRange ) ); // column width: convert 'number of characters' to column width in 1/100 mm sal_Int32 nWidth = getUnitConverter().scaleToMm100( rModel.mfWidth, UNIT_DIGIT ); @@ -1575,54 +1184,55 @@ void WorksheetData::convertColumns( OutlineLevelVec& orColLevels, aPropSet.setProperty( PROP_IsVisible, false ); // outline settings for this column range - convertOutlines( orColLevels, nFirstCol, rModel.mnLevel, rModel.mbCollapsed, false ); + convertOutlines( orColLevels, rColRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, false ); } -void WorksheetData::convertRows() +void WorksheetGlobals::convertRows() { sal_Int32 nNextRow = 0; sal_Int32 nMaxRow = mrMaxApiPos.Row; // stores first grouped row index for each level OutlineLevelVec aRowLevels; - for( RowModelMap::const_iterator aIt = maRowModels.begin(), aEnd = maRowModels.end(); aIt != aEnd; ++aIt ) + for( RowModelRangeMap::iterator aIt = maRowModels.begin(), aEnd = maRowModels.end(); aIt != aEnd; ++aIt ) { - // convert 1-based OOXML row indexes to 0-based API row indexes - sal_Int32 nFirstRow = ::std::max( aIt->second.mnFirstRow - 1, nNextRow ); - sal_Int32 nLastRow = ::std::min( aIt->second.mnLastRow - 1, nMaxRow ); - + // row indexes are stored 0-based in maRowModels + ValueRange aRowRange( ::std::max( aIt->first, nNextRow ), ::std::min( aIt->second.second, nMaxRow ) ); // process gap between two row models, use default row model - if( nNextRow < nFirstRow ) - convertRows( aRowLevels, nNextRow, nFirstRow - 1, maDefRowModel ); + if( nNextRow < aRowRange.mnFirst ) + convertRows( aRowLevels, ValueRange( nNextRow, aRowRange.mnFirst - 1 ), maDefRowModel ); // process the row model - convertRows( aRowLevels, nFirstRow, nLastRow, aIt->second, maDefRowModel.mfHeight ); - + convertRows( aRowLevels, aRowRange, aIt->second.first, maDefRowModel.mfHeight ); // cache next row to be processed - nNextRow = nLastRow + 1; + nNextRow = aRowRange.mnLast + 1; } // remaining default rows to end of sheet - convertRows( aRowLevels, nNextRow, nMaxRow, maDefRowModel ); + convertRows( aRowLevels, ValueRange( nNextRow, nMaxRow ), maDefRowModel ); // close remaining row outlines spanning to end of sheet convertOutlines( aRowLevels, nMaxRow + 1, 0, false, true ); } -void WorksheetData::convertRows( OutlineLevelVec& orRowLevels, - sal_Int32 nFirstRow, sal_Int32 nLastRow, const RowModel& rModel, double fDefHeight ) +void WorksheetGlobals::convertRows( OutlineLevelVec& orRowLevels, + const ValueRange& rRowRange, const RowModel& rModel, double fDefHeight ) { // row height: convert points to row height in 1/100 mm double fHeight = (rModel.mfHeight >= 0.0) ? rModel.mfHeight : fDefHeight; sal_Int32 nHeight = getUnitConverter().scaleToMm100( fHeight, UNIT_POINT ); if( nHeight > 0 ) { + /* Get all rows that have custom height inside the passed row model. + If the model has the custom height flag set, all its rows have + custom height, otherwise get all rows specified in the class member + maManualRowHeights that are inside the passed row model. */ ValueRangeVector aManualRows; if( rModel.mbCustomHeight ) - aManualRows.push_back( ValueRange( nFirstRow, nLastRow ) ); + aManualRows.push_back( rRowRange ); else - maManualRowHeights.intersect( aManualRows, nFirstRow, nLastRow ); + aManualRows = maManualRowHeights.getIntersection( rRowRange ); for( ValueRangeVector::const_iterator aIt = aManualRows.begin(), aEnd = aManualRows.end(); aIt != aEnd; ++aIt ) { - PropertySet aPropSet( getRows( aIt->mnFirst, aIt->mnLast ) ); + PropertySet aPropSet( getRows( *aIt ) ); aPropSet.setProperty( PROP_Height, nHeight ); } } @@ -1630,21 +1240,21 @@ void WorksheetData::convertRows( OutlineLevelVec& orRowLevels, // hidden rows: TODO: #108683# hide rows later? if( rModel.mbHidden ) { - PropertySet aPropSet( getRows( nFirstRow, nLastRow ) ); + PropertySet aPropSet( getRows( rRowRange ) ); aPropSet.setProperty( PROP_IsVisible, false ); } // outline settings for this row range - convertOutlines( orRowLevels, nFirstRow, rModel.mnLevel, rModel.mbCollapsed, true ); + convertOutlines( orRowLevels, rRowRange.mnFirst, rModel.mnLevel, rModel.mbCollapsed, true ); } -void WorksheetData::convertOutlines( OutlineLevelVec& orLevels, +void WorksheetGlobals::convertOutlines( OutlineLevelVec& orLevels, sal_Int32 nColRow, sal_Int32 nLevel, bool bCollapsed, bool bRows ) { /* It is ensured from caller functions, that this function is called without any gaps between the processed column or row ranges. */ - OSL_ENSURE( nLevel >= 0, "WorksheetData::convertOutlines - negative outline level" ); + OSL_ENSURE( nLevel >= 0, "WorksheetGlobals::convertOutlines - negative outline level" ); nLevel = ::std::max< sal_Int32 >( nLevel, 0 ); sal_Int32 nSize = orLevels.size(); @@ -1667,7 +1277,7 @@ void WorksheetData::convertOutlines( OutlineLevelVec& orLevels, } } -void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows ) +void WorksheetGlobals::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastColRow, bool bCollapse, bool bRows ) { try { @@ -1675,14 +1285,14 @@ void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastC if( bRows ) { CellRangeAddress aRange( getSheetIndex(), 0, nFirstColRow, 0, nLastColRow ); - xOutline->group( aRange, ::com::sun::star::table::TableOrientation_ROWS ); + xOutline->group( aRange, TableOrientation_ROWS ); if( bCollapse ) xOutline->hideDetail( aRange ); } else { CellRangeAddress aRange( getSheetIndex(), nFirstColRow, 0, nLastColRow, 0 ); - xOutline->group( aRange, ::com::sun::star::table::TableOrientation_COLUMNS ); + xOutline->group( aRange, TableOrientation_COLUMNS ); if( bCollapse ) xOutline->hideDetail( aRange ); } @@ -1692,8 +1302,12 @@ void WorksheetData::groupColumnsOrRows( sal_Int32 nFirstColRow, sal_Int32 nLastC } } -void WorksheetData::finalizeDrawings() +void WorksheetGlobals::finalizeDrawings() { + // calculate the current drawing page size (after rows/columns are imported) + PropertySet aRangeProp( getCellRange( CellRangeAddress( getSheetIndex(), 0, 0, mrMaxApiPos.Column, mrMaxApiPos.Row ) ) ); + aRangeProp.getProperty( maDrawPageSize, PROP_Size ); + switch( getFilterType() ) { case FILTER_OOXML: @@ -1703,11 +1317,12 @@ void WorksheetData::finalizeDrawings() if( maVmlDrawingPath.getLength() > 0 ) importOoxFragment( new VmlDrawingFragment( *this, maVmlDrawingPath ) ); break; - + case FILTER_BIFF: - // TODO: import DFF shapes + // convert BIFF3-BIFF5 drawing objects, or import and convert DFF stream + getBiffDrawing().finalizeImport(); break; - + case FILTER_UNKNOWN: break; } @@ -1737,109 +1352,56 @@ void WorksheetData::finalizeDrawings() if( maSheetViewSett.isSheetRightToLeft() ) { PropertySet aPropSet( mxSheet ); - aPropSet.setProperty( PROP_TableLayout, ::com::sun::star::text::WritingMode2::RL_TB ); + aPropSet.setProperty( PROP_TableLayout, WritingMode2::RL_TB ); } } // ============================================================================ // ============================================================================ -WorksheetHelper::WorksheetHelper( WorksheetData& rSheetData ) : - WorkbookHelper( rSheetData ), - mrSheetData( rSheetData ) +WorksheetHelper::WorksheetHelper( WorksheetGlobals& rSheetGlob ) : + WorkbookHelper( rSheetGlob ), + mrSheetGlob( rSheetGlob ) { } +/*static*/ WorksheetGlobalsRef WorksheetHelper::constructGlobals( const WorkbookHelper& rHelper, + const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) +{ + WorksheetGlobalsRef xSheetGlob( new WorksheetGlobals( rHelper, rxProgressBar, eSheetType, nSheet ) ); + if( !xSheetGlob->isValidSheet() ) + xSheetGlob.reset(); + return xSheetGlob; +} + WorksheetType WorksheetHelper::getSheetType() const { - return mrSheetData.getSheetType(); + return mrSheetGlob.getSheetType(); } sal_Int16 WorksheetHelper::getSheetIndex() const { - return mrSheetData.getSheetIndex(); + return mrSheetGlob.getSheetIndex(); } const Reference< XSpreadsheet >& WorksheetHelper::getSheet() const { - return mrSheetData.getSheet(); + return mrSheetGlob.getSheet(); } Reference< XCell > WorksheetHelper::getCell( const CellAddress& rAddress ) const { - return mrSheetData.getCell( rAddress ); -} - -Reference< XCell > WorksheetHelper::getCell( const OUString& rAddressStr, CellAddress* opAddress ) const -{ - CellAddress aAddress; - if( getAddressConverter().convertToCellAddress( aAddress, rAddressStr, mrSheetData.getSheetIndex(), true ) ) - { - if( opAddress ) *opAddress = aAddress; - return mrSheetData.getCell( aAddress ); - } - return Reference< XCell >(); -} - -Reference< XCell > WorksheetHelper::getCell( const BinAddress& rBinAddress, CellAddress* opAddress ) const -{ - CellAddress aAddress; - if( getAddressConverter().convertToCellAddress( aAddress, rBinAddress, mrSheetData.getSheetIndex(), true ) ) - { - if( opAddress ) *opAddress = aAddress; - return mrSheetData.getCell( aAddress ); - } - return Reference< XCell >(); + return mrSheetGlob.getCell( rAddress ); } Reference< XCellRange > WorksheetHelper::getCellRange( const CellRangeAddress& rRange ) const { - return mrSheetData.getCellRange( rRange ); -} - -Reference< XCellRange > WorksheetHelper::getCellRange( const OUString& rRangeStr, CellRangeAddress* opRange ) const -{ - CellRangeAddress aRange; - if( getAddressConverter().convertToCellRange( aRange, rRangeStr, mrSheetData.getSheetIndex(), true, true ) ) - { - if( opRange ) *opRange = aRange; - return mrSheetData.getCellRange( aRange ); - } - return Reference< XCellRange >(); -} - -Reference< XCellRange > WorksheetHelper::getCellRange( const BinRange& rBinRange, CellRangeAddress* opRange ) const -{ - CellRangeAddress aRange; - if( getAddressConverter().convertToCellRange( aRange, rBinRange, mrSheetData.getSheetIndex(), true, true ) ) - { - if( opRange ) *opRange = aRange; - return mrSheetData.getCellRange( aRange ); - } - return Reference< XCellRange >(); + return mrSheetGlob.getCellRange( rRange ); } Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( const ApiCellRangeList& rRanges ) const { - return mrSheetData.getCellRangeList( rRanges ); -} - -Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( - const OUString& rRangesStr, ApiCellRangeList* opRanges ) const -{ - ApiCellRangeList aRanges; - getAddressConverter().convertToCellRangeList( aRanges, rRangesStr, mrSheetData.getSheetIndex(), true ); - if( opRanges ) *opRanges = aRanges; - return mrSheetData.getCellRangeList( aRanges ); -} - -Reference< XSheetCellRanges > WorksheetHelper::getCellRangeList( - const BinRangeList& rBinRanges, ApiCellRangeList* opRanges ) const -{ - ApiCellRangeList aRanges; - getAddressConverter().convertToCellRangeList( aRanges, rBinRanges, mrSheetData.getSheetIndex(), true ); - if( opRanges ) *opRanges = aRanges; - return mrSheetData.getCellRangeList( aRanges ); + return mrSheetGlob.getCellRangeList( rRanges ); } CellAddress WorksheetHelper::getCellAddress( const Reference< XCell >& rxCell ) @@ -1864,267 +1426,112 @@ CellRangeAddress WorksheetHelper::getRangeAddress( const Reference< XCellRange > Reference< XCellRange > WorksheetHelper::getColumn( sal_Int32 nCol ) const { - return mrSheetData.getColumn( nCol ); + return mrSheetGlob.getColumn( nCol ); } Reference< XCellRange > WorksheetHelper::getRow( sal_Int32 nRow ) const { - return mrSheetData.getRow( nRow ); + return mrSheetGlob.getRow( nRow ); } -Reference< XTableColumns > WorksheetHelper::getColumns( sal_Int32 nFirstCol, sal_Int32 nLastCol ) const +Reference< XTableColumns > WorksheetHelper::getColumns( const ValueRange& rColRange ) const { - return mrSheetData.getColumns( nFirstCol, nLastCol ); + return mrSheetGlob.getColumns( rColRange ); } -Reference< XTableRows > WorksheetHelper::getRows( sal_Int32 nFirstRow, sal_Int32 nLastRow ) const +Reference< XTableRows > WorksheetHelper::getRows( const ValueRange& rRowRange ) const { - return mrSheetData.getRows( nFirstRow, nLastRow ); + return mrSheetGlob.getRows( rRowRange ); } Reference< XDrawPage > WorksheetHelper::getDrawPage() const { - return mrSheetData.getDrawPage(); + return mrSheetGlob.getDrawPage(); } Point WorksheetHelper::getCellPosition( sal_Int32 nCol, sal_Int32 nRow ) const { - return mrSheetData.getCellPosition( nCol, nRow ); + return mrSheetGlob.getCellPosition( nCol, nRow ); } Size WorksheetHelper::getCellSize( sal_Int32 nCol, sal_Int32 nRow ) const { - return mrSheetData.getCellSize( nCol, nRow ); + return mrSheetGlob.getCellSize( nCol, nRow ); } Size WorksheetHelper::getDrawPageSize() const { - return mrSheetData.getDrawPageSize(); + return mrSheetGlob.getDrawPageSize(); } -WorksheetSettings& WorksheetHelper::getWorksheetSettings() const -{ - return mrSheetData.getWorksheetSettings(); -} - -SharedFormulaBuffer& WorksheetHelper::getSharedFormulas() const +SheetDataBuffer& WorksheetHelper::getSheetData() const { - return mrSheetData.getSharedFormulas(); + return mrSheetGlob.getSheetData(); } CondFormatBuffer& WorksheetHelper::getCondFormats() const { - return mrSheetData.getCondFormats(); + return mrSheetGlob.getCondFormats(); } CommentsBuffer& WorksheetHelper::getComments() const { - return mrSheetData.getComments(); + return mrSheetGlob.getComments(); } AutoFilterBuffer& WorksheetHelper::getAutoFilters() const { - return mrSheetData.getAutoFilters(); + return mrSheetGlob.getAutoFilters(); } QueryTableBuffer& WorksheetHelper::getQueryTables() const { - return mrSheetData.getQueryTables(); + return mrSheetGlob.getQueryTables(); } -PageSettings& WorksheetHelper::getPageSettings() const -{ - return mrSheetData.getPageSettings(); -} - -SheetViewSettings& WorksheetHelper::getSheetViewSettings() const -{ - return mrSheetData.getSheetViewSettings(); -} - -VmlDrawing& WorksheetHelper::getVmlDrawing() const -{ - return mrSheetData.getVmlDrawing(); -} - -void WorksheetHelper::setStringCell( const Reference< XCell >& rxCell, const OUString& rText ) const -{ - OSL_ENSURE( rxCell.is(), "WorksheetHelper::setStringCell - missing cell interface" ); - Reference< XText > xText( rxCell, UNO_QUERY ); - if( xText.is() ) - xText->setString( rText ); -} - -void WorksheetHelper::setSharedStringCell( const Reference< XCell >& rxCell, sal_Int32 nStringId, sal_Int32 nXfId ) const -{ - OSL_ENSURE( rxCell.is(), "WorksheetHelper::setSharedStringCell - missing cell interface" ); - getSharedStrings().convertString( Reference< XText >( rxCell, UNO_QUERY ), nStringId, nXfId ); -} - -void WorksheetHelper::setDateTimeCell( const Reference< XCell >& rxCell, const DateTime& rDateTime ) const -{ - OSL_ENSURE( rxCell.is(), "WorksheetHelper::setDateTimeCell - missing cell interface" ); - // write serial date/time value into the cell - double fSerial = getUnitConverter().calcSerialFromDateTime( rDateTime ); - rxCell->setValue( fSerial ); - // set appropriate number format - using namespace ::com::sun::star::util::NumberFormat; - sal_Int16 nStdFmt = (fSerial < 1.0) ? TIME : (((rDateTime.Hours > 0) || (rDateTime.Minutes > 0) || (rDateTime.Seconds > 0)) ? DATETIME : DATE); - setStandardNumFmt( rxCell, nStdFmt ); -} - -void WorksheetHelper::setBooleanCell( const Reference< XCell >& rxCell, bool bValue ) const +WorksheetSettings& WorksheetHelper::getWorksheetSettings() const { - OSL_ENSURE( rxCell.is(), "WorksheetHelper::setBooleanCell - missing cell interface" ); - rxCell->setFormula( mrSheetData.getBooleanFormula( bValue ) ); + return mrSheetGlob.getWorksheetSettings(); } -void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, const OUString& rErrorCode ) const +PageSettings& WorksheetHelper::getPageSettings() const { - setErrorCell( rxCell, getUnitConverter().calcBiffErrorCode( rErrorCode ) ); + return mrSheetGlob.getPageSettings(); } -void WorksheetHelper::setErrorCell( const Reference< XCell >& rxCell, sal_uInt8 nErrorCode ) const +SheetViewSettings& WorksheetHelper::getSheetViewSettings() const { - Reference< XFormulaTokens > xTokens( rxCell, UNO_QUERY ); - OSL_ENSURE( xTokens.is(), "WorksheetHelper::setErrorCell - missing formula interface" ); - if( xTokens.is() ) - { - SimpleFormulaContext aContext( xTokens, false, false ); - getFormulaParser().convertErrorToFormula( aContext, nErrorCode ); - } + return mrSheetGlob.getSheetViewSettings(); } -void WorksheetHelper::setCell( CellModel& orModel ) const +VmlDrawing& WorksheetHelper::getVmlDrawing() const { - OSL_ENSURE( orModel.mxCell.is(), "WorksheetHelper::setCell - missing cell interface" ); - if( orModel.mbHasValueStr ) switch( orModel.mnCellType ) - { - case XML_b: - setBooleanCell( orModel.mxCell, orModel.maValueStr.toDouble() != 0.0 ); - // #108770# set 'Standard' number format for all Boolean cells - orModel.mnNumFmtId = 0; - break; - case XML_n: - orModel.mxCell->setValue( orModel.maValueStr.toDouble() ); - break; - case XML_e: - setErrorCell( orModel.mxCell, orModel.maValueStr ); - break; - case XML_str: - setStringCell( orModel.mxCell, orModel.maValueStr ); - break; - case XML_s: - setSharedStringCell( orModel.mxCell, orModel.maValueStr.toInt32(), orModel.mnXfId ); - break; - } + return mrSheetGlob.getVmlDrawing(); } -void WorksheetHelper::setStandardNumFmt( const Reference< XCell >& rxCell, sal_Int16 nStdNumFmt ) const +BiffSheetDrawing& WorksheetHelper::getBiffDrawing() const { - try - { - Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY_THROW ); - Reference< XNumberFormatTypes > xNumFmtTypes( xNumFmtsSupp->getNumberFormats(), UNO_QUERY_THROW ); - sal_Int32 nIndex = xNumFmtTypes->getStandardFormat( nStdNumFmt, Locale() ); - PropertySet aPropSet( rxCell ); - aPropSet.setProperty( PROP_NumberFormat, nIndex ); - } - catch( Exception& ) - { - } + return mrSheetGlob.getBiffDrawing(); } void WorksheetHelper::setSheetType( WorksheetType eSheetType ) { - mrSheetData.setSheetType( eSheetType ); -} - -void WorksheetHelper::setCellFormat( const CellModel& rModel ) -{ - mrSheetData.setCellFormat( rModel ); -} - -void WorksheetHelper::setMergedRange( const CellRangeAddress& rRange ) -{ - mrSheetData.setMergedRange( rRange ); + mrSheetGlob.setSheetType( eSheetType ); } void WorksheetHelper::setPageBreak( const PageBreakModel& rModel, bool bRowBreak ) { - mrSheetData.setPageBreak( rModel, bRowBreak ); + mrSheetGlob.setPageBreak( rModel, bRowBreak ); } void WorksheetHelper::setHyperlink( const HyperlinkModel& rModel ) { - mrSheetData.setHyperlink( rModel ); + mrSheetGlob.setHyperlink( rModel ); } void WorksheetHelper::setValidation( const ValidationModel& rModel ) { - mrSheetData.setValidation( rModel ); -} - -void WorksheetHelper::setTableOperation( const CellRangeAddress& rRange, const DataTableModel& rModel ) const -{ - OSL_ENSURE( getAddressConverter().checkCellRange( rRange, true, false ), "WorksheetHelper::setTableOperation - invalid range" ); - bool bOk = false; - if( !rModel.mbRef1Deleted && (rModel.maRef1.getLength() > 0) && (rRange.StartColumn > 0) && (rRange.StartRow > 0) ) - { - CellRangeAddress aOpRange = rRange; - CellAddress aRef1, aRef2; - if( getAddressConverter().convertToCellAddress( aRef1, rModel.maRef1, mrSheetData.getSheetIndex(), true ) ) try - { - if( rModel.mb2dTable ) - { - if( !rModel.mbRef2Deleted && getAddressConverter().convertToCellAddress( aRef2, rModel.maRef2, mrSheetData.getSheetIndex(), true ) ) - { - // API call expects input values inside operation range - --aOpRange.StartColumn; - --aOpRange.StartRow; - // formula range is top-left cell of operation range - CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow, aOpRange.StartColumn, aOpRange.StartRow ); - // set multiple operation - Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW ); - xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_BOTH, aRef2, aRef1 ); - bOk = true; - } - } - else if( rModel.mbRowTable ) - { - // formula range is column to the left of operation range - CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn - 1, aOpRange.StartRow, aOpRange.StartColumn - 1, aOpRange.EndRow ); - // API call expects input values (top row) inside operation range - --aOpRange.StartRow; - // set multiple operation - Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW ); - xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_ROW, aRef1, aRef1 ); - bOk = true; - } - else - { - // formula range is row above operation range - CellRangeAddress aFormulaRange( mrSheetData.getSheetIndex(), aOpRange.StartColumn, aOpRange.StartRow - 1, aOpRange.EndColumn, aOpRange.StartRow - 1 ); - // API call expects input values (left column) inside operation range - --aOpRange.StartColumn; - // set multiple operation - Reference< XMultipleOperation > xMultOp( mrSheetData.getCellRange( aOpRange ), UNO_QUERY_THROW ); - xMultOp->setTableOperation( aFormulaRange, ::com::sun::star::sheet::TableOperationMode_COLUMN, aRef1, aRef1 ); - bOk = true; - } - } - catch( Exception& ) - { - } - } - - // on error: fill cell range with error codes - if( !bOk ) - { - for( CellAddress aPos( mrSheetData.getSheetIndex(), rRange.StartColumn, rRange.StartRow ); aPos.Row <= rRange.EndRow; ++aPos.Row ) - for( aPos.Column = rRange.StartColumn; aPos.Column <= rRange.EndColumn; ++aPos.Column ) - setErrorCell( mrSheetData.getCell( aPos ), BIFF_ERR_REF ); - } + mrSheetGlob.setValidation( rModel ); } void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const ApiCellRangeList& rRowRanges ) @@ -2181,107 +1588,100 @@ void WorksheetHelper::setLabelRanges( const ApiCellRangeList& rColRanges, const void WorksheetHelper::setDrawingPath( const OUString& rDrawingPath ) { - mrSheetData.setDrawingPath( rDrawingPath ); + mrSheetGlob.setDrawingPath( rDrawingPath ); } void WorksheetHelper::setVmlDrawingPath( const OUString& rVmlDrawingPath ) { - mrSheetData.setVmlDrawingPath( rVmlDrawingPath ); + mrSheetGlob.setVmlDrawingPath( rVmlDrawingPath ); } void WorksheetHelper::extendUsedArea( const CellAddress& rAddress ) { - mrSheetData.extendUsedArea( rAddress ); + mrSheetGlob.extendUsedArea( rAddress ); } void WorksheetHelper::extendUsedArea( const CellRangeAddress& rRange ) { - mrSheetData.extendUsedArea( rRange ); + mrSheetGlob.extendUsedArea( rRange ); } void WorksheetHelper::extendShapeBoundingBox( const Rectangle& rShapeRect ) { - mrSheetData.extendShapeBoundingBox( rShapeRect ); + mrSheetGlob.extendShapeBoundingBox( rShapeRect ); } void WorksheetHelper::setBaseColumnWidth( sal_Int32 nWidth ) { - mrSheetData.setBaseColumnWidth( nWidth ); + mrSheetGlob.setBaseColumnWidth( nWidth ); } void WorksheetHelper::setDefaultColumnWidth( double fWidth ) { - mrSheetData.setDefaultColumnWidth( fWidth ); + mrSheetGlob.setDefaultColumnWidth( fWidth ); } void WorksheetHelper::setDefaultColumnFormat( sal_Int32 nFirstCol, sal_Int32 nLastCol, sal_Int32 nXfId ) { - mrSheetData.convertColumnFormat( nFirstCol, nLastCol, nXfId ); + mrSheetGlob.convertColumnFormat( nFirstCol, nLastCol, nXfId ); } void WorksheetHelper::setColumnModel( const ColumnModel& rModel ) { - mrSheetData.setColumnModel( rModel ); + mrSheetGlob.setColumnModel( rModel ); } void WorksheetHelper::setDefaultRowSettings( double fHeight, bool bCustomHeight, bool bHidden, bool bThickTop, bool bThickBottom ) { - mrSheetData.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom ); + mrSheetGlob.setDefaultRowSettings( fHeight, bCustomHeight, bHidden, bThickTop, bThickBottom ); } void WorksheetHelper::setRowModel( const RowModel& rModel ) { - mrSheetData.setRowModel( rModel ); -} - -void WorksheetHelper::initializeWorksheetImport() -{ - mrSheetData.initializeWorksheetImport(); + mrSheetGlob.setRowModel( rModel ); } -void WorksheetHelper::finalizeWorksheetImport() +void WorksheetHelper::setManualRowHeight( sal_Int32 nRow ) { - mrSheetData.finalizeWorksheetImport(); + mrSheetGlob.setManualRowHeight( nRow ); } -// ============================================================================ - -namespace prv { - -WorksheetDataOwner::WorksheetDataOwner( WorksheetDataRef xSheetData ) : - mxSheetData( xSheetData ) +void WorksheetHelper::putValue( const CellAddress& rAddress, double fValue ) const { + Reference< XCell > xCell = getCell( rAddress ); + OSL_ENSURE( xCell.is(), "WorksheetHelper::putValue - missing cell interface" ); + if( xCell.is() ) xCell->setValue( fValue ); } -WorksheetDataOwner::~WorksheetDataOwner() +void WorksheetHelper::putString( const CellAddress& rAddress, const OUString& rText ) const { + Reference< XText > xText( getCell( rAddress ), UNO_QUERY ); + OSL_ENSURE( xText.is(), "WorksheetHelper::putString - missing text interface" ); + if( xText.is() ) xText->setString( rText ); } -} // namespace prv - -// ---------------------------------------------------------------------------- - -WorksheetHelperRoot::WorksheetHelperRoot( const WorkbookHelper& rHelper, const ISegmentProgressBarRef& rxProgressBar, WorksheetType eSheetType, sal_Int16 nSheet ) : - prv::WorksheetDataOwner( prv::WorksheetDataRef( new WorksheetData( rHelper, rxProgressBar, eSheetType, nSheet ) ) ), - WorksheetHelper( *mxSheetData ) +void WorksheetHelper::putRichString( const CellAddress& rAddress, const RichString& rString, const Font* pFirstPortionFont ) const { + Reference< XText > xText( getCell( rAddress ), UNO_QUERY ); + OSL_ENSURE( xText.is(), "WorksheetHelper::putRichString - missing text interface" ); + rString.convert( xText, pFirstPortionFont ); } -WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelper& rHelper ) : - prv::WorksheetDataOwner( prv::WorksheetDataRef() ), - WorksheetHelper( rHelper ) +void WorksheetHelper::putFormulaTokens( const CellAddress& rAddress, const ApiTokenSequence& rTokens ) const { + Reference< XFormulaTokens > xTokens( getCell( rAddress ), UNO_QUERY ); + OSL_ENSURE( xTokens.is(), "WorksheetHelper::putFormulaTokens - missing token interface" ); + if( xTokens.is() ) xTokens->setTokens( rTokens ); } -WorksheetHelperRoot::WorksheetHelperRoot( const WorksheetHelperRoot& rHelper ) : - prv::WorksheetDataOwner( rHelper.mxSheetData ), - WorksheetHelper( rHelper ) +void WorksheetHelper::initializeWorksheetImport() { + mrSheetGlob.initializeWorksheetImport(); } -bool WorksheetHelperRoot::isValidSheet() const +void WorksheetHelper::finalizeWorksheetImport() { - return mxSheetData->isValidSheet(); + mrSheetGlob.finalizeWorksheetImport(); } // ============================================================================ diff --git a/oox/util/makefile.mk b/oox/util/makefile.mk index 329ced792..329ced792 100644..100755 --- a/oox/util/makefile.mk +++ b/oox/util/makefile.mk diff --git a/oox/util/makefile.pmk b/oox/util/makefile.pmk index adb0222c2..adb0222c2 100644..100755 --- a/oox/util/makefile.pmk +++ b/oox/util/makefile.pmk diff --git a/unoxml/JunitTest_unordf_complex.mk b/unoxml/JunitTest_unordf_complex.mk new file mode 100644 index 000000000..7637eef13 --- /dev/null +++ b/unoxml/JunitTest_unordf_complex.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_JunitTest_JunitTest,unordf_complex)) + +$(eval $(call gb_JunitTest_set_defs,unordf_complex,\ + $$(DEFS) \ + -Dorg.openoffice.test.arg.tdoc=$(SRCDIR)/unoxml/qa/complex/unoxml/testdocuments \ +)) + +$(eval $(call gb_JunitTest_add_jars,unordf_complex,\ + $(OUTDIR)/bin/OOoRunner.jar \ + $(OUTDIR)/bin/ridl.jar \ + $(OUTDIR)/bin/test.jar \ + $(OUTDIR)/bin/unoil.jar \ + $(OUTDIR)/bin/jurt.jar \ +)) + +$(eval $(call gb_JunitTest_add_sourcefiles,unordf_complex,\ + unoxml/qa/complex/unoxml/RDFRepositoryTest \ + unoxml/qa/complex/unoxml/TestDocument \ +)) + +$(eval $(call gb_JunitTest_add_classes,unordf_complex,\ + complex.unoxml.RDFRepositoryTest \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/JunitTest_unoxml_complex.mk b/unoxml/JunitTest_unoxml_complex.mk new file mode 100644 index 000000000..09eaa32e7 --- /dev/null +++ b/unoxml/JunitTest_unoxml_complex.mk @@ -0,0 +1,52 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_JunitTest_JunitTest,unoxml_complex)) + +$(eval $(call gb_JunitTest_set_defs,unoxml_complex,\ + $$(DEFS) \ + -Dorg.openoffice.test.arg.tdoc=$(SRCDIR)/unoxml/qa/complex/unoxml/testdocuments \ +)) + +$(eval $(call gb_JunitTest_add_jars,unoxml_complex,\ + $(OUTDIR)/bin/OOoRunner.jar \ + $(OUTDIR)/bin/ridl.jar \ + $(OUTDIR)/bin/test.jar \ + $(OUTDIR)/bin/unoil.jar \ + $(OUTDIR)/bin/jurt.jar \ +)) + +$(eval $(call gb_JunitTest_add_sourcefiles,unoxml_complex,\ + unoxml/qa/complex/unoxml/DOMTest \ + unoxml/qa/complex/unoxml/TestDocument \ +)) + +$(eval $(call gb_JunitTest_add_classes,unoxml_complex,\ + complex.unoxml.DOMTest \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/unoxml/Library_unordf.mk b/unoxml/Library_unordf.mk new file mode 100644 index 000000000..79123c6a3 --- /dev/null +++ b/unoxml/Library_unordf.mk @@ -0,0 +1,74 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,unordf)) + +$(eval $(call gb_Library_set_componentfile,unordf,unoxml/source/rdf/unordf)) + +$(eval $(call gb_Library_set_include,unordf,\ + $$(INCLUDE) \ + -I$(OUTDIR)/inc/offuh \ +)) + +$(eval $(call gb_Library_set_defs,unordf,\ + $$(DEFS) \ +)) + +$(eval $(call gb_Library_add_linked_libs,unordf,\ + cppuhelper \ + cppu \ + sal \ + stl \ + rdf \ + xslt \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_add_exception_objects,unordf,\ + unoxml/source/rdf/CBlankNode \ + unoxml/source/rdf/CURI \ + unoxml/source/rdf/CLiteral \ + unoxml/source/rdf/librdf_repository \ + unoxml/source/rdf/librdf_services \ +)) + +ifeq ($(SYSTEM_REDLAND),YES) +$(eval $(call gb_Library_set_cxxflags,unordf,\ + $$(CXXFLAGS) \ + -DSYSTEM_REDLAND $$(REDLAND_CFLAGS) \ +)) +endif + +ifeq ($(SYSTEM_LIBXSLT),YES) +$(eval $(call gb_Library_set_cxxflags,unordf,\ + $$(CXXFLAGS) \ + $$(LIBXSLT_CFLAGS) \ +)) +endif + +# vim: set noet sw=4 ts=4: + diff --git a/unoxml/Library_unoxml.mk b/unoxml/Library_unoxml.mk new file mode 100644 index 000000000..517c8a846 --- /dev/null +++ b/unoxml/Library_unoxml.mk @@ -0,0 +1,96 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2009 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,unoxml)) + +$(eval $(call gb_Library_set_componentfile,unoxml,unoxml/source/service/unoxml)) + +$(eval $(call gb_Library_set_include,unoxml,\ + $$(INCLUDE) \ + -I$(OUTDIR)/inc/offuh \ +)) + +$(eval $(call gb_Library_set_defs,unoxml,\ + $$(DEFS) \ +)) + +$(eval $(call gb_Library_add_linked_libs,unoxml,\ + ucbhelper \ + sax \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + stl \ + xml2 \ + $(gb_STDLIBS) \ +)) + +$(eval $(call gb_Library_add_exception_objects,unoxml,\ + unoxml/source/dom/node \ + unoxml/source/dom/document \ + unoxml/source/dom/element \ + unoxml/source/dom/attr \ + unoxml/source/dom/cdatasection \ + unoxml/source/dom/characterdata \ + unoxml/source/dom/comment \ + unoxml/source/dom/documentbuilder \ + unoxml/source/dom/documentfragment \ + unoxml/source/dom/documenttype \ + unoxml/source/dom/entity \ + unoxml/source/dom/entityreference \ + unoxml/source/dom/notation \ + unoxml/source/dom/processinginstruction \ + unoxml/source/dom/text \ + unoxml/source/dom/domimplementation \ + unoxml/source/dom/elementlist \ + unoxml/source/dom/childlist \ + unoxml/source/dom/notationsmap \ + unoxml/source/dom/entitiesmap \ + unoxml/source/dom/attributesmap \ + unoxml/source/dom/saxbuilder \ + unoxml/source/xpath/xpathobject \ + unoxml/source/xpath/nodelist \ + unoxml/source/xpath/xpathapi \ + unoxml/source/events/event \ + unoxml/source/events/eventdispatcher \ + unoxml/source/events/mutationevent \ + unoxml/source/events/uievent \ + unoxml/source/events/mouseevent \ + unoxml/source/events/testlistener \ + unoxml/source/service/services \ +)) + +ifeq ($(SYSTEM_LIBXML),YES) +$(eval $(call gb_Library_set_cxxflags,unoxml,\ + $$(CXXFLAGS) \ + -DSYSTEM_LIBXML $$(LIBXML_CFLAGS) \ +)) +endif + +# vim: set noet sw=4 ts=4: + diff --git a/unoxml/qa/complex/unoxml/makefile.mk b/unoxml/Makefile index 136d23a9a..c898975e5 100644 --- a/unoxml/qa/complex/unoxml/makefile.mk +++ b/unoxml/Makefile @@ -1,7 +1,7 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # Copyright 2000, 2010 Oracle and/or its affiliates. # # OpenOffice.org - a multi-platform office productivity suite @@ -23,37 +23,16 @@ # <http://www.openoffice.org/license.html> # for a copy of the LGPLv3 License. # -#***********************************************************************/ - -.IF "$(OOO_SUBSEQUENT_TESTS)" == "" -nothing .PHONY: -.ELSE - -PRJ = ../../.. -PRJNAME = unoxml -TARGET = qa_complex_unoxml - -.IF "$(OOO_JUNIT_JAR)" != "" -PACKAGE = complex/unoxml -JAVATESTFILES = \ - RDFRepositoryTest.java - -JAVAFILES = $(JAVATESTFILES) \ - TestDocument.java - -JARFILES = OOoRunner.jar ridl.jar test.jar unoil.jar jurt.jar -EXTRAJARFILES = $(OOO_JUNIT_JAR) - -# Sample how to debug -# JAVAIFLAGS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=9003,suspend=y -.END - -.INCLUDE: settings.mk -.INCLUDE: target.mk -.INCLUDE: installationtest.mk +#************************************************************************* -ALLTAR : javatest +ifeq ($(strip $(SOLARENV)),) +$(error No environment set!) +endif -.END +gb_PARTIALBUILD := T +GBUILDDIR := $(SOLARENV)/gbuild +include $(GBUILDDIR)/gbuild.mk +$(eval $(call gb_Module_make_global_targets,$(shell ls $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/Module*.mk))) +# vim: set noet sw=4 ts=4: diff --git a/unoxml/source/events/makefile.mk b/unoxml/Module_unoxml.mk index 2ec7489e1..5050d0701 100644 --- a/unoxml/source/events/makefile.mk +++ b/unoxml/Module_unoxml.mk @@ -1,8 +1,8 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# Copyright 2009 by Sun Microsystems, Inc. # # OpenOffice.org - a multi-platform office productivity suite # @@ -14,43 +14,27 @@ # # 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 +# 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 +# version 3 along with OpenOffice.org. If not, see # <http://www.openoffice.org/license.html> # for a copy of the LGPLv3 License. # #************************************************************************* -PRJ=../.. - -PRJNAME=unoxml -TARGET=eventsimpl -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) -.ENDIF - -# --- Files -------------------------------------------------------- - -SLOFILES =\ - $(SLO)$/event.obj \ - $(SLO)$/eventdispatcher.obj \ - $(SLO)$/mutationevent.obj \ - $(SLO)$/uievent.obj \ - $(SLO)$/mouseevent.obj \ - $(SLO)$/testlistener.obj - -# --- Targets ------------------------------------------------------ +$(eval $(call gb_Module_Module,unoxml)) -.INCLUDE : target.mk +$(eval $(call gb_Module_add_targets,unoxml,\ + Library_unoxml \ + Library_unordf \ +)) +$(eval $(call gb_Module_add_subsequentcheck_targets,unoxml,\ + JunitTest_unoxml_complex \ + JunitTest_unordf_complex \ +)) +# vim: set noet sw=4 ts=4: diff --git a/unoxml/prj/build.lst b/unoxml/prj/build.lst index 4da29cb9d..02f0482d7 100644 --- a/unoxml/prj/build.lst +++ b/unoxml/prj/build.lst @@ -1,8 +1,2 @@ -ux unoxml : offuh cppuhelper LIBXML2:libxml2 LIBXSLT:libxslt REDLAND:redland tools NULL -ux unoxml\source\dom nmake - all ux_dom NULL -ux unoxml\source\xpath nmake - all ux_xpath ux_dom NULL -ux unoxml\source\events nmake - all ux_events ux_dom NULL -ux unoxml\source\service nmake - all ux_service ux_dom ux_xpath ux_events NULL -ux unoxml\source\rdf nmake - all ux_librdf NULL - -ux unoxml\qa\complex\unoxml nmake - all ux_complex ux_librdf NULL +ux unoxml : offuh cppuhelper LIBXML2:libxml2 LIBXSLT:libxslt REDLAND:redland sax comphelper ucbhelper NULL +ux unoxml\prj nmake - all ux_prj NULL diff --git a/unoxml/prj/d.lst b/unoxml/prj/d.lst index 4fcedbdba..e69de29bb 100644 --- a/unoxml/prj/d.lst +++ b/unoxml/prj/d.lst @@ -1,5 +0,0 @@ -..\%__SRC%\lib\lib*.so %_DEST%\lib%_EXT%\lib*.so -..\%__SRC%\lib\lib*.dylib %_DEST%\lib%_EXT%\lib*.dylib -..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll -..\%__SRC%\misc\unordf.component %_DEST%\xml%_EXT%\unordf.component -..\%__SRC%\misc\unoxml.component %_DEST%\xml%_EXT%\unoxml.component diff --git a/unoxml/source/xpath/makefile.mk b/unoxml/prj/makefile.mk index 7b1ccdae7..5ebed8a45 100644 --- a/unoxml/source/xpath/makefile.mk +++ b/unoxml/prj/makefile.mk @@ -1,7 +1,7 @@ #************************************************************************* # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # Copyright 2000, 2010 Oracle and/or its affiliates. # # OpenOffice.org - a multi-platform office productivity suite @@ -25,28 +25,16 @@ # #************************************************************************* -PRJ=../.. - -PRJNAME=unoxml -TARGET=xpathimpl -ENABLE_EXCEPTIONS=TRUE +PRJ=.. +TARGET=prj -# --- Settings ----------------------------------------------------- +.INCLUDE : settings.mk -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) +.IF "$(VERBOSE)"!="" +VERBOSEFLAG := +.ELSE +VERBOSEFLAG := -s .ENDIF -# --- Files -------------------------------------------------------- - -SLOFILES = \ - $(SLO)$/xpathobject.obj \ - $(SLO)$/nodelist.obj \ - $(SLO)$/xpathapi.obj - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - +all: + cd $(PRJ) && $(GNUMAKE) $(VERBOSEFLAG) -r -j$(MAXPROCESS) $(gb_MAKETARGET) diff --git a/unoxml/qa/complex/unoxml/DOMTest.java b/unoxml/qa/complex/unoxml/DOMTest.java new file mode 100644 index 000000000..e7efad8ab --- /dev/null +++ b/unoxml/qa/complex/unoxml/DOMTest.java @@ -0,0 +1,2986 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package complex.unoxml; + +import lib.TestParameters; +import helper.StreamSimulator; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.beans.XPropertySet; +import com.sun.star.io.XInputStream; +import com.sun.star.xml.dom.*; +import static com.sun.star.xml.dom.DOMExceptionType.*; +import static com.sun.star.xml.dom.NodeType.*; +import com.sun.star.xml.dom.events.*; +import com.sun.star.xml.xpath.*; +import static com.sun.star.xml.xpath.XPathObjectType.*; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openoffice.test.OfficeConnection; +import static org.junit.Assert.*; + +/** + * Test for com.sun.star.xml.dom.*, com.sun.star.xml.xpath.* + */ +public class DOMTest +{ + private static final OfficeConnection connection = new OfficeConnection(); + + // setup and close connections + @BeforeClass public static void setUpConnection() throws Exception { + System.out.println("setUpConnection()"); + connection.setUp(); + } + + @AfterClass public static void tearDownConnection() + throws InterruptedException, com.sun.star.uno.Exception + { + System.out.println("tearDownConnection()"); + connection.tearDown(); + } + + XComponentContext m_xContext; + XMultiServiceFactory m_xMSF; + TestParameters m_params; + + @Before public void before() throws Exception + { + final XMultiServiceFactory xMSF = UnoRuntime.queryInterface( + XMultiServiceFactory.class, + connection.getComponentContext().getServiceManager()); + assertNotNull("could not create MultiServiceFactory.", xMSF); + m_params = new TestParameters(); + m_params.put("ServiceFactory", xMSF); + XPropertySet xPropertySet = + UnoRuntime.queryInterface(XPropertySet.class, xMSF); + m_xContext = UnoRuntime.queryInterface(XComponentContext.class, + xPropertySet.getPropertyValue("DefaultContext")); + assertNotNull("could not get component context.", m_xContext); + m_xMSF = xMSF; + } + + @Test public void testXSAXDocumentBuilder() throws Exception + { + XSAXDocumentBuilder xSAXBuilder = + UnoRuntime.queryInterface(XSAXDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.SAXDocumentBuilder")); + //FIXME TODO + } + + @Test public void testXDocumentBuilder() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + XDOMImplementation xDomImpl = xBuilder.getDOMImplementation(); +//FIXME fails assertNotNull("getDOMImplementation", xDomImpl); + + xBuilder.isNamespaceAware(); + xBuilder.isValidating(); + + { + XDocument xDoc = xBuilder.newDocument(); + assertNotNull("newDocument", xDoc); + } + + try { + xBuilder.parse(null); + fail("XDocumentBuilder.parse(null)"); + } catch (Exception e) { /* expected */ } + { + XInputStream xIn = new StreamSimulator( + TestDocument.getUrl("example.rdf"), true, m_params); + XDocument xDoc = xBuilder.parse(xIn); + assertNotNull("XDocumentBuilder.parse", xDoc); + } + try { + xBuilder.parseURI(""); + fail("XDocumentBuilder.parseURI(\"\")"); + } catch (Exception e) { /* expected */ } + { + XDocument xDoc = + xBuilder.parseURI(TestDocument.getUrl("example.rdf")); + assertNotNull("XDocumentBuilder.parseURI", xDoc); + } + + xBuilder.setEntityResolver(null); + /* FIXME TODO + XEntityResolver xER; + xBuilder.setEntityResolver(xER); + */ + + xBuilder.setErrorHandler(null); + /* FIXME TODO + XErrorHandler xEH; + xBuilder.setErrorHandler(xEH); + */ + } + + @Test public void testXDocument() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + /* FIXME + try { + xDoc.createAttribute("&"); + fail("XDocument.createAttribute"); + } catch (DOMException e) { + assertTrue("XDocument.createAttribute", + INVALID_CHARACTER_ERR == e.Code); + }*/ + { + XAttr xAttr = xDoc.createAttribute("foo"); + assertNotNull("XDocument.createAttribute", xAttr); + assertEquals("XDocument.createAttribute", + "foo", xAttr.getNodeName()); + } + + String ns = "http://example.com/"; + /* FIXME + try { + xDoc.createAttributeNS(ns, "&"); + fail("XDocument.createAttributeNS"); + } catch (DOMException e) { + assertTrue("XDocument.createAttributeNS", + INVALID_CHARACTER_ERR == e.Code); + } + */ + { + XAttr xAttr = xDoc.createAttributeNS(ns, "e:foo"); + assertNotNull("XDocument.createAttributeNS", xAttr); + assertEquals("XDocument.createAttributeNS", "foo", + xAttr.getNodeName()); + } + + XCDATASection xCDS = xDoc.createCDATASection("foo"); + assertNotNull("XDocument.createCDATASection", xCDS); + + XComment xComment = xDoc.createComment("foo"); + assertNotNull("XDocument.createComment", xComment); + + XDocumentFragment xDF = xDoc.createDocumentFragment(); + assertNotNull("XDocument.createDocumentFragment", xDF); + + /* FIXME + try { + xDoc.createElement("&"); + fail("XDocument.createElement(\"&\")"); + } catch (DOMException e) { + assertTrue("XDocument.createElement(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement(\"foo\")", xElemFoo); + assertEquals("XDocument.createElement(\"foo\")", + "foo", xElemFoo.getNodeName()); + + /* FIXME + try { + xDoc.createElementNS(ns, "&"); + fail("XDocument.createElementNS(\"&\")"); + } catch (DOMException e) { + assertTrue("XDocument.createElementNS(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + XElement xElemFooNs = xDoc.createElementNS(ns, "foo"); + assertNotNull("XDocument.createElementNS(\"foo\")", xElemFooNs); + assertEquals("XDocument.createElementNS(\"foo\")", + "foo", xElemFooNs.getNodeName()); + + XEntityReference xER = xDoc.createEntityReference("foo"); + assertNotNull("XDocument.createEntityReference", xER); + + XProcessingInstruction xPI = + xDoc.createProcessingInstruction("foo", "bar"); + assertNotNull("XDocument.createProcessingInstruction", xPI); + + XText xText = xDoc.createTextNode("foo"); + assertNotNull("XDocument.createTextNode", xText); + + XDocumentType xDT = xDoc.getDoctype(); + assertNull("XDocument.getDoctype", xDT); + + { + XElement xDE = xDoc.getDocumentElement(); + assertNull("XDocument.getDocumentElement", xDE); + } + { + XElement xById = xDoc.getElementById("foo"); + assertNull("XDocument.getDocumentElement", xById); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagName("foo"); + assertNotNull("XDocument.getElementsByTagName", xNodeList); + assertTrue("XDocument.getElementsByTagName", + 0 == xNodeList.getLength()); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XDocument.getElementsByTagNameNS", xNodeList); + assertTrue("XDocument.getElementsByTagNameNS", + 0 == xNodeList.getLength()); + } + + XDOMImplementation xDOMImpl = xDoc.getImplementation(); + assertNotNull("XDocument.getImplementation", xDOMImpl); + + { + XNode xRet = xElemFooNs.appendChild(xElemFoo); + assertEquals("XElement.appendChild(xElemFoo)", xElemFoo, xRet); + } + { + XNode xRet = xDoc.appendChild(xElemFooNs); + assertTrue("XDocument.appendChild(xElemFooNs)", + xElemFooNs.equals(xRet)); + } + + XElement xDE = xDoc.getDocumentElement(); + assertNotNull("XDocument.getDocumentElement", xDE); + assertEquals("XDocument.getDocumentElement", xElemFooNs, xDE); + + { + XNodeList xNodeList = xDoc.getElementsByTagName("foo"); + assertNotNull("XDocument.getElementsByTagName", xNodeList); + assertTrue("XDocument.getElementsByTagName", + 2 == xNodeList.getLength()); + assertEquals("XDocument.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + assertEquals("XDocument.getElementsByTagName", + xElemFoo, xNodeList.item(1)); + } + + { + XNodeList xNodeList = xDoc.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XDocument.getElementsByTagNameNS", xNodeList); + assertTrue("XDocument.getElementsByTagNameNS", + 1 == xNodeList.getLength()); + assertEquals("XDocument.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + } + + xElemFoo.setAttributeNS("http://www.w3.org/XML/1998/namespace", + "xml:id", "bar"); + + XElement xById = xDoc.getElementById("bar"); + assertNotNull("XDocument.getDocumentElement", xById); + assertEquals("XDocument.getDocumentElement", xElemFoo, xById); + + try { + xDoc.importNode(null, false); + fail("XDocument.importNode(null)"); + } catch (Exception e) { /* expected */ } + { + XNode xImported = xDoc.importNode(xElemFoo, false); + assertNotNull("XDocument.importNode()", xImported); + assertEquals("XDocument.importNode()", xElemFoo, xImported); + } + { + MockAttr xMockAttrBar = new MockAttr("bar", "blah"); + MockAttr xMockAttrBaz = new MockAttr("baz", "quux"); + MockElement xMockElemFoo = new MockElement("foo", + new MockAttr[] { xMockAttrBar, xMockAttrBaz }); + MockElement xMockElemBar = new MockElement("bar", + new MockAttr[] { }); + MockElement xMockElemRoot = + new MockElement("root", new MockAttr[] { }); + MockDoc xMockDoc = new MockDoc(); + xMockDoc.init(new MockNode[] { xMockElemRoot }); + xMockElemRoot.init(xMockDoc, xMockDoc, null, null, + new MockNode[] { xMockElemFoo, xMockElemBar }); + xMockElemFoo.init(xMockDoc, xMockElemRoot, null, xMockElemBar, + new MockNode[] { }); + xMockElemBar.init(xMockDoc, xMockElemRoot, xMockElemFoo, null, + new MockNode[] { }); + + { + XNode xImported = xDoc.importNode(xMockElemRoot, false); + assertNotNull("XDocument.importNode(false)", xImported); + XElement xE = + UnoRuntime.queryInterface(XElement.class, xImported); + assertNotNull("XDocument.importNode(false)", xE); + assertEquals("XDocument.importNode(false)", + "root", xE.getLocalName()); + assertFalse("XDocument.importNode(false)", xE.hasAttributes()); + assertFalse("XDocument.importNode(false)", xE.hasChildNodes()); + } + + { + XNode xImported = xDoc.importNode(xMockElemRoot, true); + assertNotNull("XDocument.importNode(true)", xImported); + XElement xImpRoot = + UnoRuntime.queryInterface(XElement.class, xImported); + assertNotNull("XDocument.importNode(true)", xImpRoot); + assertEquals("XDocument.importNode(true)", + "root", xImpRoot.getLocalName()); + assertFalse("XDocument.importNode(true)", + xImpRoot.hasAttributes()); + assertTrue("XDocument.importNode(true)", + xImpRoot.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "root", xImpRoot.getNodeName()); + + XNode xImpFooN = xImpRoot.getFirstChild(); + assertNotNull("XDocument.importNode(true)", xImpFooN); + XElement xImpFoo = + UnoRuntime.queryInterface(XElement.class, xImpFooN); + assertNotNull("XDocument.importNode(true)", xImpFoo); + assertTrue("XDocument.importNode(true)", + xImpFoo.hasAttributes()); + assertFalse("XDocument.importNode(true)", + xImpFoo.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "foo", xImpFoo.getNodeName()); + assertEquals("XDocument.importNode(true)", + "blah", xImpFoo.getAttribute("bar")); + assertEquals("XDocument.importNode(true)", + "quux", xImpFoo.getAttribute("baz")); + XNode xImpBarN = xImpFooN.getNextSibling(); + assertNotNull("XDocument.importNode(true)", xImpBarN); + XElement xImpBar = + UnoRuntime.queryInterface(XElement.class, xImpBarN); + assertNotNull("XDocument.importNode(true)", xImpBar); + assertFalse("XDocument.importNode(true)", + xImpBar.hasAttributes()); + assertFalse("XDocument.importNode(true)", + xImpBar.hasChildNodes()); + assertEquals("XDocument.importNode(true)", + "bar", xImpBar.getNodeName()); + assertNull("XDocument.importNode(true)", + xImpBar.getNextSibling()); + } + } + + // XNode //////////////////////////////////////////////////// + + { + XNode xDocCloneN = xDoc.cloneNode(false); + assertNotNull("XDocument.cloneNode(false)", xDocCloneN); + XDocument xDocClone = + UnoRuntime.queryInterface(XDocument.class, xDocCloneN); + assertNotNull("XDocument.cloneNode(false)", xDocClone); + assertFalse("XDocument.cloneNode(false)", + xDocClone.hasChildNodes()); + assertNull("XDocument.cloneNode(false)", xDocClone.getFirstChild()); + assertNull("XDocument.cloneNode(false)", + xDocClone.getDocumentElement()); + } + { + XNode xDocCloneN = xDoc.cloneNode(true); + assertNotNull("XDocument.cloneNode(true)", xDocCloneN); + XDocument xDocClone = + UnoRuntime.queryInterface(XDocument.class, xDocCloneN); + assertNotNull("XDocument.cloneNode(true)", xDocClone); + assertTrue("XDocument.cloneNode(true)", xDocClone.hasChildNodes()); + assertNotNull("XDocument.cloneNode(true)", + xDocClone.getFirstChild()); + XElement xE = xDocClone.getDocumentElement(); + assertNotNull("XDocument.cloneNode(true)", xE); + assertFalse("XDocument.cloneNode(true)", xElemFooNs.equals(xE)); + assertEquals("XDocument.cloneNode(true)", "foo", xE.getLocalName()); + assertEquals("XDocument.cloneNode(true)", ns, xE.getNamespaceURI()); + } + + assertNull("XDocument.getAttributes()", xDoc.getAttributes()); + + { + XNodeList xChildren = xDoc.getChildNodes(); + assertTrue("XDocument.getChildNodes()", 1 == xChildren.getLength()); + assertEquals("XDocument.getChildNodes()", + xElemFooNs, xChildren.item(0)); + + XNode xFirst = xDoc.getFirstChild(); + assertEquals("XDocument.getFirstChild()", xElemFooNs, xFirst); + XNode xLast = xDoc.getLastChild(); + assertEquals("XDocument.getLastChild()", xElemFooNs, xLast); + } + + assertEquals("XDocument.getLocalName()", "", xDoc.getLocalName()); + + assertEquals("XDocument.getNamespaceURI()", "", xDoc.getNamespaceURI()); + + assertNull("XDocument.getNextSibling()", xDoc.getNextSibling()); + + assertEquals("XDocument.getNodeName()", + "#document", xDoc.getNodeName()); + + assertTrue("XDocument.getNodeType()", + DOCUMENT_NODE == xDoc.getNodeType()); + + assertEquals("XDocument.getNodeValue()", "", xDoc.getNodeValue()); + + assertEquals("XDocument.getOwnerDocument()", + xDoc, xDoc.getOwnerDocument()); + + assertNull("XDocument.getParentNode()", xDoc.getParentNode()); + + assertEquals("XDocument.getPrefix()", "", xDoc.getPrefix()); + + assertNull("XDocument.getPreviousSibling()", xDoc.getPreviousSibling()); + + assertFalse("XDocument.hasAttributes()", xDoc.hasAttributes()); + + assertTrue("XDocument.hasChildNodes()", xDoc.hasChildNodes()); + + assertFalse("XDocument.isSupported()", + xDoc.isSupported("frobnication", "v99.33.0.0.0.1")); + + xDoc.normalize(); + + try { + xDoc.setNodeValue("42"); + fail("XDocument.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XDocument.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDoc.setPrefix("foo"); + fail("XDocument.setPrefix()"); + } catch (DOMException e) { + assertTrue("XDocument.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDoc.appendChild(null); + fail("XDocument.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + + try { + xDoc.insertBefore(null, xText); + fail("XDocument.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.insertBefore(xText, null); + fail("XDocument.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.insertBefore(xText, xText); + fail("XDocument.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocument.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xDoc.insertBefore(xComment, xElemFooNs); + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xRet, xElemFooNs); // why does this return the old node? + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xComment, xDoc.getFirstChild()); + assertEquals("XDocument.insertBefore(xComment, xElemFooNs)", + xDoc, xComment.getParentNode()); + assertEquals("XDocument.insertBefore(xCommnet, xElemFooNs)", + xElemFooNs, xDoc.getLastChild()); + } + + try { + xDoc.replaceChild(null, xText); + fail("XDocument.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xDoc.replaceChild(xText, null); + fail("XDocument.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.replaceChild(xElemFoo, xElemFoo); // not child + fail("XDocument.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XDocument.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xDoc.replaceChild(xElemFooNs, xElemFooNs); // child + assertFalse("XDocument.replaceChild(xElemFooNs, xElemFooNs)", + false); + } catch (DOMException e) { + assertTrue("XDocument.replaceChild(xElemFooNs, xElemFooNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xDoc.replaceChild(xPI, xComment); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xReplaced, xComment); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xPI, xDoc.getFirstChild()); + assertEquals("XDocument.replaceChild(xPI, xComment)", + xElemFooNs, xDoc.getLastChild()); + + try { + xDoc.removeChild(null); + fail("XDocument.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xDoc.removeChild(xElemFoo); + fail("XDocument.removeChild()"); + } catch (DOMException e) { + assertTrue("XDocument.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xDoc.removeChild(xPI); + assertEquals("XDocument.removeChild(xPI)", xRemoved, xPI); + assertTrue("XDocument.removeChild(xPI)", xDoc.hasChildNodes()); + assertEquals("XDocument.removeChild(xPI)", + xElemFooNs, xDoc.getFirstChild()); + assertEquals("XDocument.removeChild(xPI)", + xElemFooNs, xDoc.getLastChild()); + } + + @Test public void testXDocumentFragment() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XDocumentFragment xDF = xDoc.createDocumentFragment(); + assertNotNull("XDocument.createDocumentFragment", xDF); + + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement", xElemFoo); + + xDF.appendChild(xElemFoo); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNode xDFCloneN = xDF.cloneNode(false); + assertNotNull("XDocumentFragment.cloneNode(false)", xDFCloneN); + XDocumentFragment xDFClone = + UnoRuntime.queryInterface(XDocumentFragment.class, xDFCloneN); + assertNotNull("XDocumentFragment.cloneNode(false)", xDFClone); + assertFalse("XDocumentFragment.cloneNode(false)", + xDFClone.hasChildNodes()); + assertNull("XDocumentFragment.cloneNode(false)", + xDFClone.getFirstChild()); + } + { + XNode xDFCloneN = xDF.cloneNode(true); + assertNotNull("XDocumentFragment.cloneNode(true)", xDFCloneN); + XDocumentFragment xDFClone = + UnoRuntime.queryInterface(XDocumentFragment.class, xDFCloneN); + assertNotNull("XDocumentFragment.cloneNode(true)", xDFClone); + assertTrue("XDocumentFragment.cloneNode(true)", + xDFClone.hasChildNodes()); + XNode xChild = xDFClone.getFirstChild(); + assertNotNull("XDocumentFragment.cloneNode(true)", xChild); + XElement xE = UnoRuntime.queryInterface(XElement.class, xChild); + assertFalse("XDocumentFragment.cloneNode(true)", + xElemFoo.equals(xE)); + assertEquals("XDocumentFragment.cloneNode(true)", + "foo", xE.getLocalName()); + } + + assertNull("XDocumentFragment.getAttributes()", xDF.getAttributes()); + + { + XNodeList xChildren = xDF.getChildNodes(); + assertTrue("XDocumentFragment.getChildNodes()", + 1 == xChildren.getLength()); + assertEquals("XDocumentFragment.getChildNodes()", + xElemFoo, xChildren.item(0)); + + XNode xFirst = xDF.getFirstChild(); + assertEquals("XDocumentFragment.getFirstChild()", + xElemFoo, xFirst); + XNode xLast = xDF.getLastChild(); + assertEquals("XDocumentFragment.getLastChild()", xElemFoo, xLast); + } + + assertEquals("XDocumentFragment.getLocalName()", + "", xDF.getLocalName()); + + assertEquals("XDocumentFragment.getNamespaceURI()", + "", xDF.getNamespaceURI()); + + assertNull("XDocumentFragment.getNextSibling()", xDF.getNextSibling()); + + assertEquals("XDocumentFragment.getNodeName()", + "#document-fragment", xDF.getNodeName()); + + assertTrue("XDocumentFragment.getNodeType()", + DOCUMENT_FRAGMENT_NODE == xDF.getNodeType()); + + assertEquals("XDocumentFragment.getNodeValue()", + "", xDF.getNodeValue()); + + assertEquals("XDocumentFragment.getOwnerDocument()", + xDoc, xDF.getOwnerDocument()); + + assertNull("XDocumentFragment.getParentNode()", xDF.getParentNode()); + + assertEquals("XDocumentFragment.getPrefix()", "", xDF.getPrefix()); + + assertNull("XDocumentFragment.getPreviousSibling()", + xDF.getPreviousSibling()); + + assertFalse("XDocumentFragment.hasAttributes()", xDF.hasAttributes()); + + assertTrue("XDocumentFragment.hasChildNodes()", xDF.hasChildNodes()); + + assertFalse("XDocumentFragment.isSupported()", + xDF.isSupported("frobnication", "v99.33.0.0.0.1")); + + xDF.normalize(); + + try { + xDF.setNodeValue("42"); + fail("XDocumentFragment.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDF.setPrefix("foo"); + fail("XDocumentFragment.setPrefix()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xDF.appendChild(null); + fail("XDocumentFragment.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + + try { + xDF.insertBefore(null, xText); + fail("XDocumentFragment.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xDF.insertBefore(xText, null); + fail("XDocumentFragment.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.insertBefore(xText, xText); + fail("XDocumentFragment.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xDF.insertBefore(xComment, xElemFoo); + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xRet, xElemFoo); // why does this return the old node? + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xComment, xDF.getFirstChild()); + assertEquals("XDocumentFragment.insertBefore(xComment, xElemFoo)", + xDF, xComment.getParentNode()); + assertEquals("XDocumentFragment.insertBefore(xCommnet, xElemFoo)", + xElemFoo, xDF.getLastChild()); + } + + try { + xDF.replaceChild(null, xText); + fail("XDocumentFragment.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xDF.replaceChild(xText, null); + fail("XDocumentFragment.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.replaceChild(xElemFoo, xElemFoo); // not child + fail("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xDF.replaceChild(xElemFoo, xElemFoo); // child + assertFalse("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + false); + } catch (DOMException e) { + assertTrue("XDocumentFragment.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xDF.replaceChild(xText, xComment); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xReplaced, xComment); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xText, xDF.getFirstChild()); + assertEquals("XDocumentFragment.replaceChild(xText, xComment)", + xElemFoo, xDF.getLastChild()); + + try { + xDF.removeChild(null); + fail("XDocumentFragment.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xDF.removeChild(xComment); + fail("XDocumentFragment.removeChild()"); + } catch (DOMException e) { + assertTrue("XDocumentFragment.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xDF.removeChild(xText); + assertEquals("XDocumentFragment.removeChild(xText)", xRemoved, xText); + assertTrue("XDocumentFragment.removeChild(xText)", xDF.hasChildNodes()); + assertEquals("XDocumentFragment.removeChild(xText)", + xElemFoo, xDF.getFirstChild()); + assertEquals("XDocumentFragment.removeChild(xText)", + xElemFoo, xDF.getLastChild()); + } + + @Test public void testXElement() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XElement xElemFoo = xDoc.createElement("foo"); + assertNotNull("XDocument.createElement(\"foo\")", xElemFoo); + + XElement xElemFooNs = xDoc.createElementNS(ns, "e:foo"); + assertNotNull("XDocument.createElementNs(\"foo\")", xElemFooNs); + + assertEquals("XElement.getTagName", "foo", xElemFoo.getTagName()); + + { + XNodeList xNodeList = xElemFoo.getElementsByTagName("bar"); + assertNotNull("XElement.getElementsByTagName", xNodeList); + assertTrue("XElement.getElementsByTagName", + 0 == xNodeList.getLength()); + } + + { + XNodeList xNodeList = xElemFoo.getElementsByTagNameNS(ns, "bar"); + assertNotNull("XElement.getElementsByTagNameNS", xNodeList); + assertTrue("XElement.getElementsByTagNameNS", + 0 == xNodeList.getLength()); + } + + xElemFoo.appendChild(xElemFooNs); + + { + XNodeList xNodeList = xElemFoo.getElementsByTagName("foo"); + assertNotNull("XElement.getElementsByTagName", xNodeList); + assertTrue("XElement.getElementsByTagName", + 2 == xNodeList.getLength()); + assertEquals("XElement.getElementsByTagName", + xElemFoo, xNodeList.item(0)); + assertEquals("XElement.getElementsByTagName", + xElemFooNs, xNodeList.item(1)); + } + { + XNodeList xNodeList = xElemFoo.getElementsByTagNameNS(ns, "foo"); + assertNotNull("XElement.getElementsByTagNameNS", xNodeList); + assertTrue("XElement.getElementsByTagNameNS", + 1 == xNodeList.getLength()); + assertEquals("XElement.getElementsByTagNameNS", + xElemFooNs, xNodeList.item(0)); + } + + { + String ret = xElemFoo.getAttribute("foo"); + assertEquals("XElement.getAttribute", "", ret); + } + { + String ret = xElemFoo.getAttributeNS(ns, "foo"); + assertEquals("XElement.getAttributeNS", "", ret); + } + { + XNode xAttr = xElemFoo.getAttributeNode("foo"); + assertNull("XElement.getAttributeNode", xAttr); + } + { + XNode xAttr = xElemFoo.getAttributeNodeNS(ns, "foo"); + assertNull("XElement.getAttributeNodeNS", xAttr); + } + assertFalse("XElement.hasAttribute", xElemFoo.hasAttribute("foo")); + assertFalse("XElement.hasAttributeNS", + xElemFoo.hasAttributeNS(ns, "foo")); + + // surprisingly this does not throw? + xElemFoo.removeAttribute("foo"); + xElemFoo.removeAttributeNS(ns, "foo"); + + XAttr xAttr = xDoc.createAttribute("foo"); + XAttr xAttrNs = xDoc.createAttributeNS(ns, "foo"); + + try { + xElemFoo.removeAttributeNode(null); + fail("XElement.removeAttributeNode(null)"); + } catch (Exception e) { /* expected */ } + + try { + xElemFoo.removeAttributeNode(xAttr); + fail("XElement.removeAttributeNode(xAttr)"); + } catch (DOMException e) { + assertTrue("XElement.removeAttributeNode(xAttr)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + /* FIXME + try { + xElemFoo.setAttribute("&", "foo"); + fail("XElement.setAttribute(\"&\")"); + } catch (DOMException e) { + assertTrue("XElement.setAttribute(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + try { + xElemFoo.setAttributeNS(ns, "&", "foo"); + fail("XElement.setAttributeNS(\"&\")"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNS(\"&\")", + INVALID_CHARACTER_ERR == e.Code); + } + */ + + XAttr xAttrSet = xElemFoo.setAttributeNode(xAttr); + assertEquals("XElement.setAttributeNode(xAttr)", + xAttrSet, xElemFoo.getAttributeNode("foo")); + assertEquals("XElement.setAttributeNode(xAttr)", + xElemFoo, xAttrSet.getOwnerElement()); + try { + xElemFooNs.setAttributeNode(xAttrSet); + fail("XElement.setAttributeNode(xAttrSet)"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNode(xAttrSet)", + INUSE_ATTRIBUTE_ERR == e.Code); + } + + XAttr xAttrNsSet = xElemFooNs.setAttributeNodeNS(xAttrNs); + assertEquals("XElement.setAttributeNodeNS(xAttr)", + xAttrNsSet, xElemFooNs.getAttributeNodeNS(ns, "foo")); + assertEquals("XElement.setAttributeNodeNS(xAttrNs)", + xElemFooNs, xAttrNsSet.getOwnerElement()); + try { + xElemFooNs.setAttributeNodeNS(xAttrNsSet); + fail("XElement.setAttributeNodeNS(xAttrNsSet)"); + } catch (DOMException e) { + assertTrue("XElement.setAttributeNodeNS(xAttrNsSet)", + INUSE_ATTRIBUTE_ERR == e.Code); + } + + XAttr xAttrRemoved = xElemFoo.removeAttributeNode(xAttrSet); + assertNotNull("XElement.removeAttributeNode(xAttrSet)", xAttrRemoved); + assertEquals("XElement.removeAttributeNode(xAttrSet)", + "foo", xAttrRemoved.getName()); + assertNull("XElement.removeAttributeNode(xAttrSet)", + xAttrRemoved.getOwnerElement()); + + XAttr xAttrNsRemoved = xElemFooNs.removeAttributeNode(xAttrNsSet); + assertNotNull("XElement.removeAttributeNode(xAttrNsSet)", + xAttrNsRemoved); + assertEquals("XElement.removeAttributeNode(xAttrNsSet)", + "foo", xAttrNsRemoved.getName()); + assertNull("XElement.removeAttributeNode(xAttrNsSet)", + xAttrNsRemoved.getOwnerElement()); + + + xElemFoo.setAttribute("foo", "bar"); + assertEquals("XElement.setAttribute()", + "bar", xElemFoo.getAttribute("foo")); + + xElemFooNs.setAttributeNS(ns, "foo", "bar"); + assertEquals("XElement.setAttributeNS()", + "bar", xElemFooNs.getAttributeNS(ns, "foo")); + + xElemFoo.removeAttribute("foo"); + assertNull("XElement.removeAttribute", + xElemFoo.getAttributeNode("foo")); + + xElemFooNs.removeAttributeNS(ns, "foo"); + assertNull("XElement.removeAttributeNS", + xElemFooNs.getAttributeNodeNS(ns, "foo")); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNamedNodeMap xAttrMap = xElemFoo.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 0 == xAttrMap.getLength()); + assertFalse("XElement.hasAttributes()", xElemFoo.hasAttributes()); + } + + xElemFooNs.setAttribute("foo", "bar"); + xElemFoo.setAttributeNS(ns, "foo", "bar"); + + { + XNamedNodeMap xAttrMap = xElemFoo.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 1 == xAttrMap.getLength()); + XNode xAttr_ = xAttrMap.getNamedItemNS(ns, "foo"); + assertNotNull("XElement.getAttributes", xAttr_); + } + { + XNamedNodeMap xAttrMap = xElemFooNs.getAttributes(); + assertNotNull("XElement.getAttributes", xAttrMap); + assertTrue("XElement.getAttributes", 1 == xAttrMap.getLength()); + XNode xAttr_ = xAttrMap.getNamedItem("foo"); + assertNotNull("XElement.getAttributes", xAttr_); + } + + { + XNode xElemFooCloneN = xElemFoo.cloneNode(false); + assertNotNull("XElement.cloneNode(false)", xElemFooCloneN); + XElement xElemFooClone = + UnoRuntime.queryInterface(XElement.class, xElemFooCloneN); + assertNotNull("XElement.cloneNode(false)", xElemFooClone); + assertFalse("XElement.cloneNode(false)", + xElemFooClone.hasChildNodes()); + assertNull("XElement.cloneNode(false)", + xElemFooClone.getFirstChild()); + } + { + XNode xElemFooCloneN = xElemFoo.cloneNode(true); + assertNotNull("XElement.cloneNode(true)", xElemFooCloneN); + XElement xElemFooClone = + UnoRuntime.queryInterface(XElement.class, xElemFooCloneN); + assertNotNull("XElement.cloneNode(true)", xElemFooClone); + assertTrue("XElement.cloneNode(true)", + xElemFooClone.hasChildNodes()); + assertTrue("XElement.cloneNode(true)", + xElemFooClone.hasAttributeNS(ns, "foo")); + XNode xChild = xElemFooClone.getFirstChild(); + assertNotNull("XElement.cloneNode(true)", xChild); + XElement xElemFooNsClone = + UnoRuntime.queryInterface(XElement.class, xChild); + assertNotNull("XElement.cloneNode(true)", xElemFooNsClone); + assertEquals("XElement.cloneNode(true)", "foo", + xElemFooNsClone.getLocalName()); + assertEquals("XElement.cloneNode(true)", ns, + xElemFooNsClone.getNamespaceURI()); + assertTrue("XElement.cloneNode(true)", + xElemFooNsClone.hasAttribute("foo")); + } + + { + XNodeList xChildren = xElemFoo.getChildNodes(); + assertTrue("XElement.getChildNodes()", 1 == xChildren.getLength()); + assertEquals("XElement.getChildNodes()", + xElemFooNs, xChildren.item(0)); + + XNode xFirst = xElemFoo.getFirstChild(); + assertEquals("XDocument.getFirstChild()", xElemFooNs, xFirst); + XNode xLast = xElemFoo.getLastChild(); + assertEquals("XDocument.getLastChild()", xElemFooNs, xLast); + } + + assertEquals("XElement.getLocalName()", "foo", xElemFoo.getLocalName()); + assertEquals("XElement.getLocalName()", "foo", + xElemFooNs.getLocalName()); + + assertEquals("XElement.getNamespaceURI()", "", + xElemFoo.getNamespaceURI()); + assertEquals("XElement.getNamespaceURI()", ns, + xElemFooNs.getNamespaceURI()); + + assertNull("XElement.getNextSibling()", xElemFoo.getNextSibling()); + + assertEquals("XElement.getNodeName()", "foo", xElemFoo.getNodeName()); + assertEquals("XElement.getNodeName()", "foo", + xElemFooNs.getNodeName()); + + assertTrue("XElement.getNodeType()", + ELEMENT_NODE == xElemFoo.getNodeType()); + + assertEquals("XElement.getNodeValue()", "", xElemFoo.getNodeValue()); + + assertEquals("XElement.getOwnerDocument()", + xDoc, xElemFoo.getOwnerDocument()); + + assertNull("XElement.getParentNode()", xElemFoo.getParentNode()); + assertEquals("XElement.getParentNode()", + xElemFoo, xElemFooNs.getParentNode()); + + assertEquals("XElement.getPrefix()", "", xElemFoo.getPrefix()); + assertEquals("XElement.getPrefix()", "e", xElemFooNs.getPrefix()); + + assertNull("XElement.getPreviousSibling()", + xElemFoo.getPreviousSibling()); + + assertTrue("XElement.hasAttributes()", xElemFoo.hasAttributes()); + + assertTrue("XElement.hasChildNodes()", xElemFoo.hasChildNodes()); + assertFalse("XElement.hasChildNodes()", xElemFooNs.hasChildNodes()); + + assertFalse("XElement.isSupported()", + xElemFoo.isSupported("frobnication", "v99.33.0.0.0.1")); + + xElemFoo.normalize(); + + try { + xElemFoo.setNodeValue("42"); + fail("XElement.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XElement.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + xElemFooNs.setPrefix("f"); + assertEquals("XElement.getPrefix()", "f", xElemFooNs.getPrefix()); + + try { + xElemFoo.appendChild(null); + fail("XElement.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xElemFoo.insertBefore(null, xText); + fail("XElemFoo.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.insertBefore(xText, null); + fail("XElemFoo.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.insertBefore(xText, xText); + fail("XElement.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XDocument.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xElemFoo.insertBefore(xText, xElemFooNs); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xRet, xElemFooNs); // why does this return the old node? + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xText, xElemFoo.getFirstChild()); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xElemFoo, xText.getParentNode()); + assertEquals("XElement.insertBefore(xText, xElemFooNs)", + xElemFooNs, xElemFoo.getLastChild()); + } + + try { + xElemFoo.replaceChild(null, xText); + fail("XElement.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.replaceChild(xText, null); + fail("XElement.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.replaceChild(xElemFoo, xElemFoo); // not child + fail("XElement.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XElement.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xElemFoo.replaceChild(xElemFooNs, xElemFooNs); // child + assertFalse("XElement.replaceChild(xElemFooNs, xElemFooNs)", + false); + } catch (DOMException e) { + assertTrue("XElement.replaceChild(xElemFooNs, xElemFooNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xElemFoo.replaceChild(xComment, xText); + assertEquals("XElement.replaceChild(xComment, xText)", + xReplaced, xText); + assertEquals("XElement.replaceChild(xComment, xText)", + xComment, xElemFoo.getFirstChild()); + assertEquals("XElement.replaceChild(xComment, xText)", + xElemFooNs, xElemFoo.getLastChild()); + + try { + xElemFoo.removeChild(null); + fail("XElement.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xElemFoo.removeChild(xElemFoo); + fail("XElement.removeChild()"); + } catch (DOMException e) { + assertTrue("XElement.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xElemFoo.removeChild(xComment); + assertEquals("XElement.removeChild(xComment)", xRemoved, xComment); + assertTrue("XElement.removeChild(xComment)", xElemFoo.hasChildNodes()); + assertEquals("XElement.removeChild(xComment)", + xElemFooNs, xElemFoo.getFirstChild()); + assertEquals("XElement.removeChild(xComment)", + xElemFooNs, xElemFoo.getLastChild()); + } + + @Test public void testXAttr() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XAttr xAttr = xDoc.createAttribute("foo"); + assertNotNull("XDocument.createAttribute", xAttr); + + XAttr xAttrNs = xDoc.createAttributeNS(ns, "e:foo"); + assertNotNull("XDocument.createAttribute", xAttr); + + assertTrue("XAttr.getSpecified", xAttr.getSpecified()); + + assertEquals("XAttr.getName()", "foo", xAttr.getName()); + + assertNull("XAttr.getOwnerElement()", xAttr.getOwnerElement()); + + XElement xElemFoo = xDoc.createElement("foo"); + XNode xInserted = xElemFoo.appendChild(xAttr); + XAttr xAttrIns = + UnoRuntime.queryInterface(XAttr.class, xInserted); + assertNotNull(xAttrIns); + assertEquals("XAttr.getOwnerElement()", + xElemFoo, xAttrIns.getOwnerElement()); + + assertEquals("XAttr.getValue()", "", xAttr.getValue()); + + xAttr.setValue("bar"); + assertEquals("XAttr.setValue()", "bar", xAttr.getValue()); + + // XNode //////////////////////////////////////////////////// + + { + XNode xAttrCloneN = xAttr.cloneNode(false); + assertNotNull("XAttr.cloneNode(false)", xAttrCloneN); + XAttr xAttrClone = + UnoRuntime.queryInterface(XAttr.class, xAttrCloneN); + assertNotNull("XAttr.cloneNode(false)", xAttrClone); + // actually the children are copied even if bDeep=false + // does that make sense for attributes? + /* + assertFalse("XAttr.cloneNode(false)", xAttrClone.hasChildNodes()); + assertNull("XAttr.cloneNode(false)", xAttrClone.getFirstChild()); + */ + assertTrue("XAttr.cloneNode(true)", xAttrClone.hasChildNodes()); + XNode xChild = xAttrClone.getFirstChild(); + assertNotNull("XAttr.cloneNode(true)", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.cloneNode(true)", xText); + assertEquals("XAttr.cloneNode(true)", "bar", xText.getNodeValue()); + } + { + XNode xAttrCloneN = xAttr.cloneNode(true); + assertNotNull("XAttr.cloneNode(true)", xAttrCloneN); + XAttr xAttrClone = + UnoRuntime.queryInterface(XAttr.class, xAttrCloneN); + assertNotNull("XAttr.cloneNode(true)", xAttrClone); + assertTrue("XAttr.cloneNode(true)", xAttrClone.hasChildNodes()); + XNode xChild = xAttrClone.getFirstChild(); + assertNotNull("XAttr.cloneNode(true)", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.cloneNode(true)", xText); + assertEquals("XAttr.cloneNode(true)", "bar", xText.getNodeValue()); + } + + assertNull("XAttr.getAttributes()", xAttr.getAttributes()); + + { + XNodeList xChildren = xAttr.getChildNodes(); + assertTrue("XAttr.getChildNodes()", 1 == xChildren.getLength()); + XNode xChild = xChildren.item(0); + assertNotNull("XAttr.getChildNodes()", xChild); + XText xText = UnoRuntime.queryInterface(XText.class, xChild); + assertNotNull("XAttr.getChildNodes()", xText); + + XNode xFirst = xAttr.getFirstChild(); + assertEquals("XAttr.getFirstChild()", xText, xFirst); + XNode xLast = xAttr.getLastChild(); + assertEquals("XAttr.getLastChild()", xText, xLast); + } + + assertEquals("XAttr.getLocalName()", "foo", xAttr.getLocalName()); + assertEquals("XAttr.getLocalName()", "foo", xAttrNs.getLocalName()); + + assertEquals("XAttr.getNamespaceURI()", "", xAttr.getNamespaceURI()); + assertEquals("XAttr.getNamespaceURI()", ns, xAttrNs.getNamespaceURI()); + + assertNull("XAttr.getNextSibling()", xAttr.getNextSibling()); + + assertEquals("XAttr.getNodeName()", "foo", xAttr.getNodeName()); + assertEquals("XAttr.getNodeName()", "foo", xAttrNs.getNodeName()); + + assertTrue("XAttr.getNodeType()", + ATTRIBUTE_NODE == xAttr.getNodeType()); + + assertEquals("XAttr.getNodeValue()", "bar", xAttr.getNodeValue()); + assertEquals("XAttr.getNodeValue()", "", xAttrNs.getNodeValue()); + + assertEquals("XAttr.getOwnerDocument()", + xDoc, xDoc.getOwnerDocument()); + + assertNull("XAttr.getParentNode()", xAttr.getParentNode()); + + assertEquals("XAttr.getPrefix()", "", xAttr.getPrefix()); + assertEquals("XAttr.getPrefix()", "e", xAttrNs.getPrefix()); + + assertNull("XAttr.getPreviousSibling()", xAttr.getPreviousSibling()); + + assertFalse("XAttr.hasAttributes()", xAttr.hasAttributes()); + + assertTrue("XAttr.hasChildNodes()", xAttr.hasChildNodes()); + + assertFalse("XAttr.isSupported()", + xAttr.isSupported("frobnication", "v99.33.0.0.0.1")); + + xAttr.normalize(); + + xAttr.setNodeValue("42"); + assertEquals("XAttr.setNodeValue()", "42", xAttr.getNodeValue()); + + xAttrNs.setPrefix("f"); + assertEquals("XAttr.setPrefix()", "f", xAttrNs.getPrefix()); + + XText xText = xDoc.createTextNode("baz"); + XText xTextNew = xDoc.createTextNode("quux"); + + try { + xAttr.appendChild(null); + fail("XAttr.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xAttr.insertBefore(null, xText); + fail("XAttr.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.insertBefore(xText, null); + fail("XAttr.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.insertBefore(xText, xText); + fail("XAttr.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XAttr.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xChild = xAttr.getFirstChild(); + assertNotNull(xChild); + + { + XNode xRet = xAttr.insertBefore(xText, xChild); + assertEquals("XAttr.insertBefore(xText, xChild)", + xRet, xChild); // why does this return the old node? + assertEquals("XAttr.insertBefore(xText, xChild)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.insertBefore(xText, xChild)", + xAttr, xText.getParentNode()); + assertEquals("XAttr.insertBefore(xText, xChild)", + xChild, xAttr.getLastChild()); + } + + try { + xAttr.replaceChild(null, xText); + fail("XAttr.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xAttr.replaceChild(xText, null); + fail("XAttr.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.replaceChild(xAttrNs, xAttrNs); // not child + fail("XAttr.replaceChild(xAttrNs, xAttrNs)"); + } catch (DOMException e) { + assertTrue("XAttr.replaceChild(xAttrNs, xAttrNs)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xAttr.replaceChild(xChild, xChild); // child + assertFalse("XAttr.replaceChild(xChild, xChild)", + false); + } catch (DOMException e) { + assertTrue("XAttr.replaceChild(xChild, xChild)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xAttr.replaceChild(xTextNew, xChild); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", xChild, xReplaced); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.replaceChild(xTextNew, xChild)", + xTextNew, xAttr.getLastChild()); + + try { + xAttr.removeChild(null); + fail("XAttr.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xAttr.removeChild(xAttrNs); + fail("XAttr.removeChild()"); + } catch (DOMException e) { + assertTrue("XAttr.removeChild()", HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xAttr.removeChild(xTextNew); + assertEquals("XAttr.removeChild(xText)", xRemoved, xTextNew); + assertTrue("XAttr.removeChild(xText)", xAttr.hasChildNodes()); + assertEquals("XAttr.removeChild(xText)", + xText, xAttr.getFirstChild()); + assertEquals("XAttr.removeChild(xText)", + xText, xAttr.getLastChild()); + } + + @Test public void testXText() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XText xText = xDoc.createTextNode("foobar"); + assertNotNull(xText); + + assertEquals("XText.getData", "foobar", xText.getData()); + assertEquals("XText.getLength", 6, xText.getLength()); + + /* FIXME + try { + xText.splitText(9999); + fail("XText.splitText(9999)"); + } catch (DOMException e) { + assertTrue("XText.splitText(9999)", INDEX_SIZE_ERR == e.Code); + } + + { + XText xTextBar = xText.splitText(2); + assertNotNull("XText.splitText", xTextBar); + assertEquals("XText.splitText", "foo", xText.getData()); + assertEquals("XText.splitText", "bar", xTextBar.getData()); + } + */ + xText.setData("foo"); + + xText.appendData("baz"); + assertEquals("XText.appendData", "foobaz", xText.getData()); + + try { + xText.deleteData(999,999); + fail("XText.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XText.deleteData(999,999)", INDEX_SIZE_ERR == e.Code); + } + xText.deleteData(0, 3); + assertEquals("XText.deleteData", "baz", xText.getData()); + + try { + xText.insertData(999,"blah"); + fail("XText.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XText.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xText.insertData(1, "arb"); + assertEquals("XText.insertData", "barbaz", xText.getData()); + + try { + xText.replaceData(999,999,"x"); + fail("XText.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XText.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xText.replaceData(3, 3, "foo"); + assertEquals("XText.replaceData", "barfoo", xText.getData()); + + xText.setData("quux"); + assertEquals("XText.setData", "quux", xText.getData()); + + try { + xText.subStringData(999,999); + fail("XText.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XText.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XText.subStringData", "x", xText.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xTextCloneN = xText.cloneNode(false); + assertNotNull("XText.cloneNode(false)", xTextCloneN); + XText xTextClone = + UnoRuntime.queryInterface(XText.class, xTextCloneN); + assertNotNull("XText.cloneNode(false)", xTextClone); + assertFalse("XText.cloneNode(false)", + xTextClone.hasChildNodes()); + } + { + XNode xTextCloneN = xText.cloneNode(true); + assertNotNull("XText.cloneNode(true)", xTextCloneN); + XText xTextClone = + UnoRuntime.queryInterface(XText.class, xTextCloneN); + assertNotNull("XText.cloneNode(true)", xTextClone); + assertFalse("XText.cloneNode(true)", xTextClone.hasChildNodes()); + } + + assertNull("XText.getAttributes()", xText.getAttributes()); + + { + XNodeList xChildren = xText.getChildNodes(); + assertTrue("XText.getChildNodes()", 0 == xChildren.getLength()); + } + + assertEquals("XText.getLocalName()", "", xText.getLocalName()); + + assertEquals("XText.getNamespaceURI()", "", xText.getNamespaceURI()); + + assertNull("XText.getNextSibling()", xText.getNextSibling()); + + assertEquals("XText.getNodeName()", "#text", xText.getNodeName()); + + assertTrue("XText.getNodeType()", + TEXT_NODE == xText.getNodeType()); + + assertEquals("XText.getNodeValue()", "quux", xText.getNodeValue()); + + assertEquals("XText.getOwnerDocument()", + xDoc, xText.getOwnerDocument()); + + assertNull("XText.getParentNode()", xText.getParentNode()); + + assertEquals("XText.getPrefix()", "", xText.getPrefix()); + + assertNull("XText.getPreviousSibling()", xText.getPreviousSibling()); + + assertFalse("XText.hasAttributes()", xText.hasAttributes()); + + assertFalse("XText.hasChildNodes()", xText.hasChildNodes()); + + assertFalse("XText.isSupported()", + xText.isSupported("frobnication", "v99.33.0.0.0.1")); + + xText.normalize(); + + xText.setNodeValue("42"); + assertEquals("XText.setNodeValue()", "42", xText.getNodeValue()); + + try { + xText.setPrefix("foo"); + fail("XText.setPrefix()"); + } catch (DOMException e) { + assertTrue("XText.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XText xText2 = xDoc.createTextNode("foobar"); + XText xText3 = xDoc.createTextNode("foobar"); + + try { + xText.appendChild(null); + fail("XText.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xText.appendChild(xText2); + fail("XText.appendChild(xText2)"); + } catch (DOMException e) { + assertTrue("XText.appendChild(xText2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xText.insertBefore(xText2, xText3); + fail("XText.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xText.replaceChild(xText2, xText3); + fail("XText.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xText.removeChild(null); + fail("XText.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xText.removeChild(xText2); + fail("XText.removeChild"); + } catch (DOMException e) { + assertTrue("XText.removeChild", HIERARCHY_REQUEST_ERR == e.Code); + } + } + + @Test public void testXCDataSection() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XCDATASection xCDS = xDoc.createCDATASection("foobar"); + assertNotNull(xCDS); + + assertEquals("XCDATASection.getData", "foobar", xCDS.getData()); + assertEquals("XCDATASection.getLength", 6, xCDS.getLength()); + + /* FIXME + try { + xCDS.splitText(9999); + fail("XCDATASection.splitText(9999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.splitText(9999)", + INDEX_SIZE_ERR == e.Code); + } + + { + XCDATASection xCDSBar = xCDS.splitText(2); + assertNotNull("XCDATASection.splitText", xCDSBar); + assertEquals("XCDATASection.splitText", "foo", xCDS.getData()); + assertEquals("XCDATASection.splitText", "bar", xCDSBar.getData()); + } + */ + xCDS.setData("foo"); + + xCDS.appendData("baz"); + assertEquals("XCDATASection.appendData", "foobaz", xCDS.getData()); + + try { + xCDS.deleteData(999,999); + fail("XCDATASection.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.deleteData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + xCDS.deleteData(0, 3); + assertEquals("XCDATASection.deleteData", "baz", xCDS.getData()); + + try { + xCDS.insertData(999,"blah"); + fail("XCDATASection.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XCDATASection.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xCDS.insertData(1, "arb"); + assertEquals("XCDATASection.insertData", "barbaz", xCDS.getData()); + + try { + xCDS.replaceData(999,999,"x"); + fail("XCDATASection.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XCDATASection.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xCDS.replaceData(3, 3, "foo"); + assertEquals("XCDATASection.replaceData", "barfoo", xCDS.getData()); + + xCDS.setData("quux"); + assertEquals("XCDATASection.setData", "quux", xCDS.getData()); + + try { + xCDS.subStringData(999,999); + fail("XCDATASection.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XCDATASection.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XCDATASection.subStringData", "x", + xCDS.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xCDSCloneN = xCDS.cloneNode(false); + assertNotNull("XCDATASection.cloneNode(false)", xCDSCloneN); + XCDATASection xCDSClone = + UnoRuntime.queryInterface(XCDATASection.class, xCDSCloneN); + assertNotNull("XCDATASection.cloneNode(false)", xCDSClone); + assertFalse("XCDATASection.cloneNode(false)", + xCDSClone.hasChildNodes()); + } + { + XNode xCDSCloneN = xCDS.cloneNode(true); + assertNotNull("XCDATASection.cloneNode(true)", xCDSCloneN); + XCDATASection xCDSClone = + UnoRuntime.queryInterface(XCDATASection.class, xCDSCloneN); + assertNotNull("XCDATASection.cloneNode(true)", xCDSClone); + assertFalse("XCDATASection.cloneNode(true)", + xCDSClone.hasChildNodes()); + } + + assertNull("XCDATASection.getAttributes()", xCDS.getAttributes()); + + { + XNodeList xChildren = xCDS.getChildNodes(); + assertTrue("XCDATASection.getChildNodes()", + 0 == xChildren.getLength()); + } + + assertEquals("XCDATASection.getLocalName()", "", xCDS.getLocalName()); + + assertEquals("XCDATASection.getNamespaceURI()", "", + xCDS.getNamespaceURI()); + + assertNull("XCDATASection.getNextSibling()", xCDS.getNextSibling()); + + assertEquals("XCDATASection.getNodeName()", "#cdata-section", + xCDS.getNodeName()); + + assertTrue("XCDATASection.getNodeType()", + CDATA_SECTION_NODE == xCDS.getNodeType()); + + assertEquals("XCDATASection.getNodeValue()", "quux", + xCDS.getNodeValue()); + + assertEquals("XCDATASection.getOwnerDocument()", + xDoc, xCDS.getOwnerDocument()); + + assertNull("XCDATASection.getParentNode()", xCDS.getParentNode()); + + assertEquals("XCDATASection.getPrefix()", "", xCDS.getPrefix()); + + assertNull("XCDATASection.getPreviousSibling()", + xCDS.getPreviousSibling()); + + assertFalse("XCDATASection.hasAttributes()", xCDS.hasAttributes()); + + assertFalse("XCDATASection.hasChildNodes()", xCDS.hasChildNodes()); + + assertFalse("XCDATASection.isSupported()", + xCDS.isSupported("frobnication", "v99.33.0.0.0.1")); + + xCDS.normalize(); + + xCDS.setNodeValue("42"); + assertEquals("XCDATASection.setNodeValue()", "42", xCDS.getNodeValue()); + + try { + xCDS.setPrefix("foo"); + fail("XCDATASection.setPrefix()"); + } catch (DOMException e) { + assertTrue("XCDATASection.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XCDATASection xCDS2 = xDoc.createCDATASection("foobar"); + XCDATASection xCDS3 = xDoc.createCDATASection("foobar"); + + try { + xCDS.appendChild(null); + fail("XCDATASection.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xCDS.appendChild(xCDS2); + fail("XCDATASection.appendChild(xCDS2)"); + } catch (DOMException e) { + assertTrue("XCDATASection.appendChild(xCDS2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xCDS.insertBefore(xCDS2, xCDS3); + fail("XCDATASection.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.replaceChild(xCDS2, xCDS3); + fail("XCDATASection.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.removeChild(null); + fail("XCDATASection.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xCDS.removeChild(xCDS2); + fail("XCDATASection.removeChild"); + } catch (DOMException e) { + assertTrue("XCDATASection.removeChild", + HIERARCHY_REQUEST_ERR == e.Code); + } + + } + + @Test public void testXComment() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XComment xComment = xDoc.createComment("foo"); + assertNotNull(xComment); + + assertEquals("XComment.getData", "foo", xComment.getData()); + assertEquals("XComment.getLength", 3, xComment.getLength()); + + xComment.appendData("baz"); + assertEquals("XComment.appendData", "foobaz", xComment.getData()); + + try { + xComment.deleteData(999,999); + fail("XComment.deleteData(999,999)"); + } catch (DOMException e) { + assertTrue("XComment.deleteData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + xComment.deleteData(0, 3); + assertEquals("XComment.deleteData", "baz", xComment.getData()); + + try { + xComment.insertData(999,"blah"); + fail("XComment.insertData(999,\"blah\")"); + } catch (DOMException e) { + assertTrue("XComment.insertData(999,\"blah\")", + INDEX_SIZE_ERR == e.Code); + } + xComment.insertData(1, "arb"); + assertEquals("XComment.insertData", "barbaz", xComment.getData()); + + try { + xComment.replaceData(999,999,"x"); + fail("XComment.replaceData(999,999,\"x\")"); + } catch (DOMException e) { + assertTrue("XComment.replaceData(999,999,\"x\")", + INDEX_SIZE_ERR == e.Code); + } + xComment.replaceData(3, 3, "foo"); + assertEquals("XComment.replaceData", "barfoo", xComment.getData()); + + xComment.setData("quux"); + assertEquals("XComment.setData", "quux", xComment.getData()); + + try { + xComment.subStringData(999,999); + fail("XComment.subStringData(999,999)"); + } catch (DOMException e) { + assertTrue("XComment.subStringData(999,999)", + INDEX_SIZE_ERR == e.Code); + } + assertEquals("XComment.subStringData", "x", + xComment.subStringData(3, 1)); + + // XNode //////////////////////////////////////////////////// + + { + XNode xCommentCloneN = xComment.cloneNode(false); + assertNotNull("XComment.cloneNode(false)", xCommentCloneN); + XComment xCommentClone = + UnoRuntime.queryInterface(XComment.class, xCommentCloneN); + assertNotNull("XComment.cloneNode(false)", xCommentClone); + assertFalse("XComment.cloneNode(false)", + xCommentClone.hasChildNodes()); + } + { + XNode xCommentCloneN = xComment.cloneNode(true); + assertNotNull("XComment.cloneNode(true)", xCommentCloneN); + XComment xCommentClone = + UnoRuntime.queryInterface(XComment.class, xCommentCloneN); + assertNotNull("XComment.cloneNode(true)", xCommentClone); + assertFalse("XComment.cloneNode(true)", + xCommentClone.hasChildNodes()); + } + + assertNull("XComment.getAttributes()", xComment.getAttributes()); + + { + XNodeList xChildren = xComment.getChildNodes(); + assertTrue("XComment.getChildNodes()", 0 == xChildren.getLength()); + } + + assertEquals("XComment.getLocalName()", "", xComment.getLocalName()); + + assertEquals("XComment.getNamespaceURI()", "", + xComment.getNamespaceURI()); + + assertNull("XComment.getNextSibling()", xComment.getNextSibling()); + + assertEquals("XComment.getNodeName()", "#comment", + xComment.getNodeName()); + + assertTrue("XComment.getNodeType()", + COMMENT_NODE == xComment.getNodeType()); + + assertEquals("XComment.getNodeValue()", "quux", + xComment.getNodeValue()); + + assertEquals("XComment.getOwnerDocument()", + xDoc, xComment.getOwnerDocument()); + + assertNull("XComment.getParentNode()", xComment.getParentNode()); + + assertEquals("XComment.getPrefix()", "", xComment.getPrefix()); + + assertNull("XComment.getPreviousSibling()", + xComment.getPreviousSibling()); + + assertFalse("XComment.hasAttributes()", xComment.hasAttributes()); + + assertFalse("XComment.hasChildNodes()", xComment.hasChildNodes()); + + assertFalse("XComment.isSupported()", + xComment.isSupported("frobnication", "v99.33.0.0.0.1")); + + xComment.normalize(); + + xComment.setNodeValue("42"); + assertEquals("XComment.setNodeValue()", "42", xComment.getNodeValue()); + + try { + xComment.setPrefix("foo"); + fail("XComment.setPrefix()"); + } catch (DOMException e) { + assertTrue("XComment.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XComment xComment2 = xDoc.createComment("foobar"); + XComment xComment3 = xDoc.createComment("foobar"); + + try { + xComment.appendChild(null); + fail("XComment.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xComment.appendChild(xComment2); + fail("XComment.appendChild(xComment2)"); + } catch (DOMException e) { + assertTrue("XComment.appendChild(xComment2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xComment.insertBefore(xComment2, xComment3); + fail("XComment.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xComment.replaceChild(xComment2, xComment3); + fail("XComment.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xComment.removeChild(null); + fail("XComment.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xComment.removeChild(xComment2); + fail("XComment.removeChild"); + } catch (DOMException e) { + assertTrue("XComment.removeChild", HIERARCHY_REQUEST_ERR == e.Code); + } + } + + @Test public void testXEntityReference() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XEntityReference xER = xDoc.createEntityReference("foobar"); + assertNotNull(xER); + + XEntityReference xERChild = xDoc.createEntityReference("baz"); + assertNotNull(xERChild); + + xER.appendChild(xERChild); + + // XNode //////////////////////////////////////////////////// + + XText xText = xDoc.createTextNode("foo"); + XComment xComment = xDoc.createComment("foo"); + + { + XNode xERCloneN = xER.cloneNode(false); + assertNotNull("XEntityReference.cloneNode(false)", xERCloneN); + XEntityReference xERClone = + UnoRuntime.queryInterface(XEntityReference.class, xERCloneN); + assertNotNull("XEntityReference.cloneNode(false)", xERClone); + assertFalse("XEntityReference.cloneNode(false)", + xERClone.hasChildNodes()); + assertNull("XEntityReference.cloneNode(false)", + xERClone.getFirstChild()); + } + { + XNode xERCloneN = xER.cloneNode(true); + assertNotNull("XEntityReference.cloneNode(true)", xERCloneN); + XEntityReference xERClone = + UnoRuntime.queryInterface(XEntityReference.class, xERCloneN); + assertNotNull("XEntityReference.cloneNode(true)", xERClone); + /* FIXME this is actually in libxml2: children are not copied + assertTrue("XEntityReference.cloneNode(true)", + xERClone.hasChildNodes()); + XNode xChild = xERClone.getFirstChild(); + assertNotNull("XEntityReference.cloneNode(true)", xChild); + XEntityReference xChildER = + UnoRuntime.queryInterface(XEntityReference.class, xChild); + assertNotNull("XEntityReference.cloneNode(true)", xChildER); + assertFalse("XEntityReference.cloneNode(true)", + xChildER.equals(xERChild)); + assertEquals("XEntityReference.cloneNode(true)", + "baz", xChildER.getLocalName()); + */ + } + + assertNull("XEntityReference.getAttributes()", xER.getAttributes()); + + { + XNodeList xChildren = xER.getChildNodes(); + assertTrue("XEntityReference.getChildNodes()", + 1 == xChildren.getLength()); + assertEquals("XEntityReference.getChildNodes()", + xERChild, xChildren.item(0)); + + XNode xFirst = xER.getFirstChild(); + assertEquals("XEntityReference.getFirstChild()", + xERChild, xFirst); + XNode xLast = xER.getLastChild(); + assertEquals("XEntityReference.getLastChild()", xERChild, xLast); + } + + assertEquals("XEntityReference.getLocalName()", "", xER.getLocalName()); + + assertEquals("XEntityReference.getNamespaceURI()", "", + xER.getNamespaceURI()); + + assertNull("XEntityReference.getNextSibling()", xER.getNextSibling()); + + assertEquals("XEntityReference.getNodeName()", + "foobar", xER.getNodeName()); + + assertTrue("XEntityReference.getNodeType()", + ENTITY_REFERENCE_NODE == xER.getNodeType()); + + assertEquals("XEntityReference.getNodeValue()", "", xER.getNodeValue()); + + assertEquals("XEntityReference.getOwnerDocument()", + xDoc, xER.getOwnerDocument()); + + assertNull("XEntityReference.getParentNode()", xER.getParentNode()); + + assertEquals("XEntityReference.getPrefix()", "", xER.getPrefix()); + + assertNull("XEntityReference.getPreviousSibling()", + xER.getPreviousSibling()); + + assertFalse("XEntityReference.hasAttributes()", xER.hasAttributes()); + + assertTrue("XEntityReference.hasChildNodes()", xER.hasChildNodes()); + + assertFalse("XEntityReference.isSupported()", + xER.isSupported("frobnication", "v99.33.0.0.0.1")); + + xER.normalize(); + + try { + xER.setNodeValue("42"); + fail("XEntityReference.setNodeValue()"); + } catch (DOMException e) { + assertTrue("XEntityReference.setNodeValue()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xER.setPrefix("foo"); + fail("XEntityReference.setPrefix()"); + } catch (DOMException e) { + assertTrue("XEntityReference.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + try { + xER.appendChild(null); + fail("XEntityReference.appendChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xER.insertBefore(null, xText); + fail("XEntityReference.insertBefore(null,)"); + } catch (Exception e) { /* expected */ } + try { + xER.insertBefore(xText, null); + fail("XEntityReference.insertBefore(, null)"); + } catch (Exception e) { /* expected */ } + try { + xER.insertBefore(xText, xText); + fail("XEntityReference.insertBefore(x, x)"); + } catch (DOMException e) { + assertTrue("XEntityReference.insertBefore(x, x)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + { + XNode xRet = xER.insertBefore(xComment, xERChild); + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xRet, xERChild); // why does this return the old node? + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xComment, xER.getFirstChild()); + assertEquals("XEntityReference.insertBefore(xComment, xERChild)", + xER, xComment.getParentNode()); + assertEquals("XEntityReference.insertBefore(xCommnet, xERChild)", + xERChild, xER.getLastChild()); + } + + try { + xER.replaceChild(null, xText); + fail("XEntityReference.replaceChild(null, )"); + } catch (Exception e) { /* expected */ } + try { + xER.replaceChild(xText, null); + fail("XEntityReference.replaceChild(, null)"); + } catch (Exception e) { /* expected */ } + try { + xER.replaceChild(xText, xText); // not child + fail("XEntityReference.replaceChild(xElemFoo, xElemFoo)"); + } catch (DOMException e) { + assertTrue("XEntityReference.replaceChild(xElemFoo, xElemFoo)", + HIERARCHY_REQUEST_ERR == e.Code); + } + try { + xER.replaceChild(xERChild, xERChild); // child + assertFalse("XEntityReference.replaceChild(xERChild, xERChild)", + false); + } catch (DOMException e) { + assertTrue("XEntityReference.replaceChild(xERChild, xERChild)", + HIERARCHY_REQUEST_ERR == e.Code); + } + XNode xReplaced = xER.replaceChild(xText, xComment); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xReplaced, xComment); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xText, xER.getFirstChild()); + assertEquals("XEntityReference.replaceChild(xText, xComment)", + xERChild, xER.getLastChild()); + + try { + xER.removeChild(null); + fail("XEntityReference.removeChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xER.removeChild(xER); + fail("XEntityReference.removeChild()"); + } catch (DOMException e) { + assertTrue("XEntityReference.removeChild()", + HIERARCHY_REQUEST_ERR == e.Code); + } + + XNode xRemoved = xER.removeChild(xText); + assertEquals("XEntityReference.removeChild(xText)", xRemoved, xText); + assertTrue("XEntityReference.removeChild(xText)", xER.hasChildNodes()); + assertEquals("XEntityReference.removeChild(xText)", + xERChild, xER.getFirstChild()); + assertEquals("XEntityReference.removeChild(xText)", + xERChild, xER.getLastChild()); + } + + @Test public void testXProcessingInstruction() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XProcessingInstruction xPI = + xDoc.createProcessingInstruction("foo", "bar"); + assertNotNull(xPI); + + assertEquals("XProcessingInstruction.getTarget", + "foo", xPI.getTarget()); + + assertEquals("XProcessingInstruction.getData", "bar", xPI.getData()); + + xPI.setData("baz"); + assertEquals("XProcessingInstruction.setData", "baz", xPI.getData()); + + // XNode //////////////////////////////////////////////////// + + { + XNode xPICloneN = xPI.cloneNode(false); + assertNotNull("XProcessingInstruction.cloneNode(false)", xPICloneN); + XProcessingInstruction xPIClone = UnoRuntime.queryInterface( + XProcessingInstruction.class, xPICloneN); + assertNotNull("XProcessingInstruction.cloneNode(false)", xPIClone); + assertFalse("XProcessingInstruction.cloneNode(false)", + xPIClone.hasChildNodes()); + } + { + XNode xPICloneN = xPI.cloneNode(true); + assertNotNull("XProcessingInstruction.cloneNode(true)", xPICloneN); + XProcessingInstruction xPIClone = UnoRuntime.queryInterface( + XProcessingInstruction.class, xPICloneN); + assertNotNull("XProcessingInstruction.cloneNode(true)", xPIClone); + assertFalse("XProcessingInstruction.cloneNode(true)", + xPIClone.hasChildNodes()); + } + + assertNull("XProcessingInstruction.getAttributes()", + xPI.getAttributes()); + + { + XNodeList xChildren = xPI.getChildNodes(); + assertTrue("XProcessingInstruction.getChildNodes()", + 0 == xChildren.getLength()); + } + + assertEquals("XProcessingInstruction.getLocalName()", + "", xPI.getLocalName()); + + assertEquals("XProcessingInstruction.getNamespaceURI()", + "", xPI.getNamespaceURI()); + + assertNull("XProcessingInstruction.getNextSibling()", + xPI.getNextSibling()); + + assertEquals("XProcessingInstruction.getNodeName()", + "foo", xPI.getNodeName()); + + assertTrue("XProcessingInstruction.getNodeType()", + PROCESSING_INSTRUCTION_NODE == xPI.getNodeType()); + + assertEquals("XProcessingInstruction.getNodeValue()", + "baz", xPI.getNodeValue()); + + assertEquals("XProcessingInstruction.getOwnerDocument()", + xDoc, xPI.getOwnerDocument()); + + assertNull("XProcessingInstruction.getParentNode()", + xPI.getParentNode()); + + assertEquals("XProcessingInstruction.getPrefix()", "", xPI.getPrefix()); + + assertNull("XProcessingInstruction.getPreviousSibling()", + xPI.getPreviousSibling()); + + assertFalse("XProcessingInstruction.hasAttributes()", + xPI.hasAttributes()); + + assertFalse("XProcessingInstruction.hasChildNodes()", + xPI.hasChildNodes()); + + assertFalse("XProcessingInstruction.isSupported()", + xPI.isSupported("frobnication", "v99.33.0.0.0.1")); + + xPI.normalize(); + + xPI.setNodeValue("42"); + assertEquals("XProcessingInstruction.setNodeValue()", + "42", xPI.getNodeValue()); + + try { + xPI.setPrefix("foo"); + fail("XProcessingInstruction.setPrefix()"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.setPrefix()", + NO_MODIFICATION_ALLOWED_ERR == e.Code); + } + + XText xText2 = xDoc.createTextNode("foobar"); + XText xText3 = xDoc.createTextNode("foobar"); + + try { + xPI.appendChild(null); + fail("XProcessingInstruction.appendChild(null)"); + } catch (Exception e) { /* expected */ } + try { + xPI.appendChild(xText2); + fail("XProcessingInstruction.appendChild(xText2)"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.appendChild(xText2)", + HIERARCHY_REQUEST_ERR == e.Code); + } + + try { + xPI.insertBefore(xText2, xText3); + fail("XProcessingInstruction.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xPI.replaceChild(xText2, xText3); + fail("XProcessingInstruction.insertBefore"); + } catch (Exception e) { /* expected */ } + + try { + xPI.removeChild(null); + fail("XProcessingInstruction.removeChild(null)"); + } catch (Exception e) { /* expected */ } + + try { + xPI.removeChild(xText2); + fail("XProcessingInstruction.removeChild"); + } catch (DOMException e) { + assertTrue("XProcessingInstruction.removeChild", + HIERARCHY_REQUEST_ERR == e.Code); + } + } + + /* + @Test public void testXEntity() throws Exception + { + XEntity xEntity = FIXME how to get at this shy creature? + } + */ + + /* + @Test public void testXNotation() throws Exception + { + XNotation xNotation = FIXME how to create? + } + */ + + /* + @Test public void testXDocumentType() throws Exception + { + XDocumentType xDT = FIXME how to create? + } + */ + + @Test public void testXNodeList_ChildList() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + XElement xFoo = xDoc.createElement("foo"); + XElement xBar = xDoc.createElement("bar"); + XElement xBaz = xDoc.createElement("baz"); + + xDoc.appendChild(xRoot); + + XNodeList xChildList = xRoot.getChildNodes(); + assertNotNull(xChildList); + assertSame("ChildList.getLength()", 0, xChildList.getLength()); + + try { + xChildList.item(4); + } catch (Exception e) { /* expected */ } + + xRoot.appendChild(xFoo); + assertSame("ChildList.getLength()", 1, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + + xRoot.appendChild(xBar); + assertSame("ChildList.getLength()", 2, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBar, xChildList.item(1)); + + xRoot.appendChild(xBaz); + assertSame("ChildList.getLength()", 3, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBar, xChildList.item(1)); + assertEquals("ChildList.item", xBaz, xChildList.item(2)); + + xRoot.removeChild(xBar); + assertSame("ChildList.getLength()", 2, xChildList.getLength()); + assertEquals("ChildList.item", xFoo, xChildList.item(0)); + assertEquals("ChildList.item", xBaz, xChildList.item(1)); + } + + @Test public void testXNodeList_ElementList() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + XElement xBar = xDoc.createElement("bar"); + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFoo3 = xDoc.createElement("foo"); + + xDoc.appendChild(xRoot); + + XNodeList xElementList = xRoot.getElementsByTagName("foo"); + assertNotNull(xElementList); + assertSame("ElementList.getLength()", 0, xElementList.getLength()); + + try { + xElementList.item(4); + } catch (Exception e) { /* expected */ } + + xRoot.appendChild(xFoo1); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + + xFoo1.appendChild(xBar); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + + xRoot.appendChild(xFoo3); + assertSame("ElementList.getLength()", 2, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + assertEquals("ElementList.item", xFoo3, xElementList.item(1)); + + xBar.appendChild(xFoo2); + assertSame("ElementList.getLength()", 3, xElementList.getLength()); + assertEquals("ElementList.item", xFoo1, xElementList.item(0)); + assertEquals("ElementList.item", xFoo2, xElementList.item(1)); + assertEquals("ElementList.item", xFoo3, xElementList.item(2)); + + xRoot.removeChild(xFoo1); + assertSame("ElementList.getLength()", 1, xElementList.getLength()); + assertEquals("ElementList.item", xFoo3, xElementList.item(0)); + } + + @Test public void testXNamedNodeMap_AttributesMap() throws Exception + { + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + XDocument xDoc = xBuilder.newDocument(); + + String ns = "http://example.com/"; + + XElement xElem = xDoc.createElement("foo"); + + XNamedNodeMap xAttributes = xElem.getAttributes(); + assertNotNull(xAttributes); + assertSame("AttributesMap.getLength()", 0, xAttributes.getLength()); + + try { + xAttributes.item(4); + } catch (Exception e) { /* expected */ } + + xElem.setAttribute("bar", "42"); + XAttr xAttrBar = xElem.getAttributeNode("bar"); + assertSame("AttributesMap.getLength()", 1, xAttributes.getLength()); + assertEquals("AttributesMap.item", xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.getNamedItem", + xAttrBar, xAttributes.getNamedItem("bar")); + + xElem.setAttributeNS(ns, "n:bar", "43"); + XAttr xAttrBarNs = xElem.getAttributeNodeNS(ns, "bar"); + assertSame("AttributesMap.getLength()", 2, xAttributes.getLength()); + assertEquals("AttributesMap.item", xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.item", xAttrBarNs, xAttributes.item(1)); + assertEquals("AttributesMap.getNamedItem", + xAttrBar, xAttributes.getNamedItem("bar")); + assertEquals("AttributesMap.getNamedItemNS", + xAttrBarNs, xAttributes.getNamedItemNS(ns, "bar")); + + XNode xAttrBarNsRem = xAttributes.removeNamedItemNS(ns, "bar"); + assertSame("AttributesMap.getLength()", 1, xAttributes.getLength()); + assertEquals("AttributesMap.removeNamedItemNS", + xAttrBar, xAttributes.item(0)); + assertEquals("AttributesMap.removeNamedItemNS", + xAttrBar, xAttributes.getNamedItem("bar")); + assertNull("AttributesMap.removeNamedItemNS", + xAttrBarNsRem.getParentNode()); + + XNode xAttrBarRem = xAttributes.removeNamedItem("bar"); + assertSame("AttributesMap.getLength()", 0, xAttributes.getLength()); + assertNull("AttributesMap.removeNamedItem", + xAttrBarRem.getParentNode()); + + XNode xAttrBarSetN = xAttributes.setNamedItem(xAttrBarRem); + assertNotNull("AttributesMap.setNamedItem", xAttrBarSetN); + XAttr xAttrBarSet = + UnoRuntime.queryInterface(XAttr.class, xAttrBarSetN); + assertNotNull("AttributesMap.setNamedItem", xAttrBarSet); + assertEquals("AttributesMap.setNamedItem", + xAttrBarSet, xAttributes.getNamedItem("bar")); + + XNode xAttrBarNsSetN = xAttributes.setNamedItemNS(xAttrBarNsRem); + assertNotNull("AttributesMap.setNamedItemNS", xAttrBarNsSetN); + XAttr xAttrBarNsSet = + UnoRuntime.queryInterface(XAttr.class, xAttrBarNsSetN); + assertNotNull("AttributesMap.setNamedItemNS", xAttrBarNsSet); + assertEquals("AttributesMap.setNamedItemNS", + xAttrBarNsSet, xAttributes.getNamedItemNS(ns, "bar")); + assertSame("AttributesMap.getLength()", 2, xAttributes.getLength()); + } + + /* + @Test public void testXNamedNodeMap_EntitiesMap() throws Exception + { + XNamedNodeMap xEntities = FIXME + } + */ + + /* + @Test public void testXNamedNodeMap_NotationsMap() throws Exception + { + XNamedNodeMap xNotations = FIXME + } + */ + + @Test public void testXXPathAPI() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + try { + xXPathAPI.eval(xRoot, "~/-$+&#_"); + fail("XXPathAPI.eval"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.evalNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.evalNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectNodeList(xRoot, "~/-$+&#_"); + fail("XXPathAPI.selectNodeList"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectNodeListNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.selectNodeListNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectSingleNode(xRoot, "~/-$+&#_"); + fail("XXPathAPI.selectSingleNode"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.selectSingleNodeNS(xRoot, "~/-$+&#_", xRoot); + fail("XXPathAPI.selectSingleNodeNS"); + } catch (XPathException e) { /* expected */ } + try { + xXPathAPI.eval(null, "child::foo"); + fail("XXPathAPI.eval(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.evalNS(null, "child::foo", xRoot); + fail("XXPathAPI.evalNS(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectNodeList(null, "child::foo"); + fail("XXPathAPI.selectNodeList(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectNodeListNS(null, "child::foo", xRoot); + fail("XXPathAPI.selectNodeListNS(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectSingleNode(null, "child::foo"); + fail("XXPathAPI.selectSingleNode(null)"); + } catch (Exception e) { /* expected */ } + try { + xXPathAPI.selectSingleNodeNS(null, "child::foo", xRoot); + fail("XXPathAPI.selectSingleNodeNS(null)"); + } catch (Exception e) { /* expected */ } + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(child::foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathAPI.eval", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathAPI.eval", 1, xResult.getLong()); + } + { + XXPathObject xResult = + xXPathAPI.evalNS(xRoot, "count(//ns:foo)", xFooNs); + assertNotNull("XXPathAPI.evalNS", xResult); + assertEquals("XXPathAPI.evalNS", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathAPI.evalNS", 1, xResult.getLong()); + } + { + XNodeList xResult = xXPathAPI.selectNodeList(xRoot, "child::foo"); + assertNotNull("XXPathAPI.selectNodeList", xResult); + assertEquals("XXPathAPI.selectNodeList", 1, xResult.getLength()); + assertEquals("XXPathAPI.selectNodeList", xFoo1, xResult.item(0)); + } + { + XNodeList xResult = + xXPathAPI.selectNodeListNS(xRoot, ".//ns:foo", xFooNs); + assertNotNull("XXPathAPI.selectNodeListNS", xResult); + assertEquals("XXPathAPI.selectNodeListNS", 1, xResult.getLength()); + assertEquals("XXPathAPI.selectNodeListNS", xFooNs, xResult.item(0)); + } + { + XNode xResult = xXPathAPI.selectSingleNode(xBar, "child::foo"); + assertNotNull("XXPathAPI.selectSingleNode", xResult); + assertEquals("XXPathAPI.selectSingleNode", xFoo2, xResult); + } + { + XNode xResult = + xXPathAPI.selectSingleNodeNS(xFoo2, "//ns:foo", xFooNs); + assertNotNull("XXPathAPI.selectSingleNodeNS", xResult); + assertEquals("XXPathAPI.selectSingleNodeNS", xFooNs, xResult); + } + + try { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + fail("XXPathAPI.selectSingleNode"); + } catch (XPathException e) { /* expected */ } + xXPathAPI.registerNS("pre", ns); + { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + assertNotNull("XXPathAPI.registerNS", xResult); + assertEquals("XXPathAPI.registerNS", xFooNs, xResult); + } + + xXPathAPI.unregisterNS("pre", ns); + try { + XNode xResult = xXPathAPI.selectSingleNode(xDoc, "//pre:foo"); + fail("XXPathAPI.unregisterNS"); + } catch (XPathException e) { /* expected */ } + + /* FIXME + registerExtension(""); + registerExtensionInstance(xExtension); + */ + } + + @Test public void testXXPathObject() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NUMBER, xResult.getObjectType()); + assertEquals("XXPathObject.getByte", 2, xResult.getByte()); + assertEquals("XXPathObject.getShort", 2, xResult.getShort()); + assertEquals("XXPathObject.getLong", 2, xResult.getLong()); + assertEquals("XXPathObject.getHyper", 2, xResult.getHyper()); + assertEquals("XXPathObject.getFloat", 2.0, xResult.getFloat(), 0.0); + assertEquals("XXPathObject.getDouble", + 2.0, xResult.getDouble(), 0.0); + assertEquals("XXPathObject.getString", "2", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo) = 2"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_BOOLEAN, xResult.getObjectType()); + assertEquals("XXPathObject.getBoolean", true, xResult.getBoolean()); + assertEquals("XXPathObject.getString", "true", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "count(//foo) = 2"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_BOOLEAN, xResult.getObjectType()); + assertEquals("XXPathObject.getBoolean", true, xResult.getBoolean()); + assertEquals("XXPathObject.getString", "true", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "local-name(foo)"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_STRING, xResult.getObjectType()); + assertEquals("XXPathObject.getString", "foo", xResult.getString()); + } + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "//foo"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NODESET, xResult.getObjectType()); + assertNotNull("XXPathObject.getNodeList", xResult.getNodeList()); + } + } + + @Test public void testXNodeList_NodeList() throws Exception + { + XXPathAPI xXPathAPI = + UnoRuntime.queryInterface(XXPathAPI.class, + m_xMSF.createInstance("com.sun.star.xml.xpath.XPathAPI")); + XDocumentBuilder xBuilder = + UnoRuntime.queryInterface(XDocumentBuilder.class, + m_xMSF.createInstance("com.sun.star.xml.dom.DocumentBuilder")); + + String ns = "http://example.com/"; + + XDocument xDoc = xBuilder.newDocument(); + + XElement xRoot = xDoc.createElement("root"); + + XElement xFoo1 = xDoc.createElement("foo"); + XElement xFoo2 = xDoc.createElement("foo"); + XElement xFooNs = xDoc.createElementNS(ns, "ns:foo"); + XElement xBar = xDoc.createElement("bar"); + + xDoc.appendChild(xRoot); + xRoot.appendChild(xFoo1); + xFoo1.appendChild(xBar); + xBar.appendChild(xFoo2); + xRoot.appendChild(xFooNs); + + { + XXPathObject xResult = xXPathAPI.eval(xRoot, "//foo"); + assertNotNull("XXPathAPI.eval", xResult); + assertEquals("XXPathObject.getObjectType", + XPATH_NODESET, xResult.getObjectType()); + XNodeList xNodeList = xResult.getNodeList(); + assertNotNull("XXPathObject.getNodeList", xNodeList); + assertEquals("NodeList.getLength", 2, xNodeList.getLength()); + assertEquals("NodeList.item", xFoo1, xNodeList.item(0)); + assertEquals("NodeList.item", xFoo2, xNodeList.item(1)); + } + } + + + // just for importNode... + abstract class MockNode implements XNode + { + MockDoc m_document; + MockNode m_parent; + MockNode m_prev; + MockNode m_next; + MockNode[] m_children; + String m_localname; + +// MockNode() { ; } + void init(MockDoc doc, MockNode parent, MockNode prev, MockNode next, + MockNode[] children) + { + m_document = doc; + m_parent = parent; m_prev = prev; m_next = next; + m_children = children; + } + + public XNode appendChild(XNode c) throws DOMException { + fail("MockNode.appendChild called?"); + return null; + } + public XNode cloneNode(boolean b) { + fail("MockNode.cloneNode called?"); + return null; + } + public XNamedNodeMap getAttributes() { + fail("MockNode.getAttributes not implemented"); + return null; + } + public XNodeList getChildNodes() { + fail("MockNode.getChildList not implemented"); + return null; + } + public XNode getFirstChild() { + return (m_children.length != 0) ? m_children[0] : null; + } + public XNode getLastChild() { + return (m_children.length != 0) + ? m_children[m_children.length-1] : null; + } + public String getLocalName() { return m_localname; } + public String getNamespaceURI() { return ""; } + public XNode getNextSibling() { return m_next; } + public String getNodeName() { return m_localname; } +// NodeType getNodeType() { return m_type; } + public String getNodeValue() throws DOMException { return ""; } + public XDocument getOwnerDocument() { return m_document; } + public XNode getParentNode() { return m_parent; } + public String getPrefix() { return ""; } + public XNode getPreviousSibling() { return m_prev; } + public boolean hasAttributes() { return false; } + public boolean hasChildNodes() { return m_children.length != 0; } + public XNode insertBefore(XNode c, XNode r) throws DOMException { + fail("MockNode.insertBefore called?"); + return null; + } + public boolean isSupported(String a, String b) { return false; } + public void normalize() { + fail("MockNode.normalize called?"); + } + public XNode removeChild(XNode c) throws DOMException { + fail("MockNode.removeChild called?"); + return null; + } + public XNode replaceChild(XNode c, XNode o) throws DOMException { + fail("MockNode.replaceChild called?"); + return null; + } + public void setNodeValue(String v) throws DOMException { + fail("MockNode.setNodeValue called?"); + } + public void setPrefix(String p) throws DOMException { + fail("MockNode.setPrefix called?"); + } + } + class MockDoc extends MockNode implements XDocument + { +// MockDoc() { } + void init(MockNode[] children) { + super.init(this, null, null, null, children); + } + + public NodeType getNodeType() { return DOCUMENT_NODE; } + + public XAttr createAttribute(String n) throws DOMException { + fail("MockNode.createAttribute called?"); + return null; + } + public XAttr createAttributeNS(String n, String q) throws DOMException { + fail("MockNode.createAttributeNS called?"); + return null; + } + public XCDATASection createCDATASection(String s) throws DOMException { + fail("MockNode.createCDATASection called?"); + return null; + } + public XComment createComment(String s) { + fail("MockNode.createCDATASection called?"); + return null; + } + public XDocumentFragment createDocumentFragment() { + fail("MockNode.createDocumentFragment called?"); + return null; + } + public XElement createElement(String n) { + fail("MockNode.createElement called?"); + return null; + } + public XElement createElementNS(String n, String q) { + fail("MockNode.createElementNS called?"); + return null; + } + public XEntityReference createEntityReference(String n) + throws DOMException { + fail("MockNode.createEntityReference called?"); + return null; + } + public XProcessingInstruction createProcessingInstruction(String t, + String d) throws DOMException { + fail("MockNode.createEntityReference called?"); + return null; + } + public XText createTextNode(String d) { + fail("MockNode.createTextNode called?"); + return null; + } + public XDocumentType getDoctype() { + fail("MockNode.getDoctype called?"); + return null; + } + public XElement getDocumentElement() { + fail("MockNode.getDocumentElement called?"); + return null; + } + public XElement getElementById(String id) { + fail("MockNode.getElementById called?"); + return null; + } + public XNodeList getElementsByTagName(String n) { + fail("MockNode.getElementsByTagName called?"); + return null; + } + public XNodeList getElementsByTagNameNS(String n, String q) { + fail("MockNode.getElementsByTagNameNS called?"); + return null; + } + public XDOMImplementation getImplementation() { + fail("MockNode.getImplementation called?"); + return null; + } + public XNode importNode(XNode i, boolean b) throws DOMException { + fail("MockNode.importNode called?"); + return null; + } + } + class MockNodeMap implements XNamedNodeMap + { + MockAttr[] m_attributes; + + MockNodeMap(MockAttr[] attrs) { m_attributes = attrs; } + + public int getLength() { return m_attributes.length; } + public XNode getNamedItem(String name) { + fail("MockNodeMap.getNamedItem not implemented"); + return null; + } + public XNode getNamedItemNS(String n, String l) { + fail("MockNodeMap.getNamedItemNS not implemented"); + return null; + } + public XNode item(int index) { + return m_attributes[index]; + } + public XNode removeNamedItem(String n) throws DOMException { + fail("MockNodeMap.removeNamedItem called?"); + return null; + } + public XNode removeNamedItemNS(String n, String l) throws DOMException { + fail("MockNodeMap.removeNamedItemNS called?"); + return null; + } + public XNode setNamedItem(XNode n) throws DOMException { + fail("MockNodeMap.setNamedItem called?"); + return null; + } + public XNode setNamedItemNS(XNode n) throws DOMException { + fail("MockNodeMap.setNamedItemNS called?"); + return null; + } + } + class MockElement extends MockNode implements XElement + { + MockAttr[] m_attributes; + + MockElement(String name, MockAttr[] attrs) { + m_localname = name; m_attributes = attrs; + } + + public NodeType getNodeType() { return ELEMENT_NODE; } + public XNamedNodeMap getAttributes() { + return new MockNodeMap(m_attributes); + } + public boolean hasAttributes() { return m_attributes.length != 0; } + + public String getAttribute(String n) { + fail("MockNode.getAttribute not implemented"); + return null; + } + public XAttr getAttributeNode(String n) { + fail("MockNode.getAttributeNode not implemented"); + return null; + } + public XAttr getAttributeNodeNS(String n, String l) { + fail("MockNode.getAttributeNodeNS not implemented"); + return null; + } + public String getAttributeNS(String n, String q) { + fail("MockNode.getAttributeNS not implemented"); + return null; + } + public XNodeList getElementsByTagName(String n) { + fail("MockNode.getElementsByTagName called?"); + return null; + } + public XNodeList getElementsByTagNameNS(String n, String l) { + fail("MockNode.getElementsByTagNameNS called?"); + return null; + } + public String getTagName() { + return getLocalName(); + } + public boolean hasAttribute(String n) { + fail("MockNode.hasAttribute not implemented"); + return false; + } + public boolean hasAttributeNS(String n, String l) { + fail("MockNode.hasAttributeNS not implemented"); + return false; + } + public void removeAttribute(String n) throws DOMException { + fail("MockNode.removeAttribute called?"); + } + public XAttr removeAttributeNode(XAttr o) throws DOMException { + fail("MockNode.removeAttributeNode called?"); + return null; + } + public void removeAttributeNS(String n, String l) throws DOMException { + fail("MockNode.removeAttributeNS called?"); + } + public void setAttribute(String n, String v) throws DOMException { + fail("MockNode.setAttribute called?"); + } + public XAttr setAttributeNode(XAttr n) throws DOMException { + fail("MockNode.setAttributeNode called?"); + return null; + } + public XAttr setAttributeNodeNS(XAttr n) throws DOMException { + fail("MockNode.setAttributeNodeNS called?"); + return null; + } + public void setAttributeNS(String n, String q, String v) + throws DOMException { + fail("MockNode.setAttributeNS called?"); + } + } + class MockAttr extends MockNode implements XAttr + { + String m_value; + + MockAttr(String name, String value) { + m_localname = name; m_value = value; + } + + public NodeType getNodeType() { return ATTRIBUTE_NODE; } + + public String getName() { return m_localname; } + public XElement getOwnerElement() { return (XElement) m_parent; } + public boolean getSpecified() { return true; } + public String getValue() { return m_value; } + public void setValue(String v) { + fail("MockNode.setValue called?"); + } + } +} + diff --git a/unoxml/qa/complex/unoxml/RDFRepositoryTest.java b/unoxml/qa/complex/unoxml/RDFRepositoryTest.java index 7840724a4..1fb0a7974 100644 --- a/unoxml/qa/complex/unoxml/RDFRepositoryTest.java +++ b/unoxml/qa/complex/unoxml/RDFRepositoryTest.java @@ -172,14 +172,14 @@ public class RDFRepositoryTest try { xRep.createGraph(foo); - assertFalse("creating duplicate graph was allowed", false); + fail("creating duplicate graph was allowed"); } catch (ElementExistException e) { // ignore } try { xRep.createGraph(null); - assertFalse("invalid graph name was allowed", false); + fail("invalid graph name was allowed"); } catch (IllegalArgumentException e) { // ignore } @@ -296,7 +296,7 @@ public class RDFRepositoryTest xFooIn = new StreamSimulator(tempDir + "foo.rdf", true, param); try { xRep.importGraph(FileFormat.RDF_XML, xFooIn, bar, base); - assertFalse("importing existing graph did not fail", false); + fail("importing existing graph did not fail"); } catch (ElementExistException e) { // ignore } @@ -328,28 +328,28 @@ public class RDFRepositoryTest try { xBazGraph.clear(); - assertFalse("deleted graph not invalid (clear)", false); + fail("deleted graph not invalid (clear)"); } catch (NoSuchElementException e) { // ignore } try { xBazGraph.addStatement(foo, foo, foo); - assertFalse("deleted graph not invalid (add)", false); + fail("deleted graph not invalid (add)"); } catch (NoSuchElementException e) { // ignore } try { xBazGraph.removeStatements(null, null, null); - assertFalse("deleted graph not invalid (remove)", false); + fail("deleted graph not invalid (remove)"); } catch (NoSuchElementException e) { // ignore } try { xBazGraph.getStatements(null, null, null); - assertFalse("deleted graph not invalid (get)", false); + fail("deleted graph not invalid (get)"); } catch (NoSuchElementException e) { // ignore } @@ -473,14 +473,14 @@ public class RDFRepositoryTest try { xRep.setStatementRDFa(foo, new XURI[] {}, xM, "", null); - assertFalse("RDFa: set: no predicate", false); + fail("RDFa: set: no predicate"); } catch (IllegalArgumentException e) { // ignore } try { xRep.setStatementRDFa(foo, new XURI[] {bar}, null, "", null); - assertFalse("RDFa: set: null", false); + fail("RDFa: set: null"); } catch (IllegalArgumentException e) { // ignore } diff --git a/unoxml/qa/complex/unoxml/TestDocument.java b/unoxml/qa/complex/unoxml/TestDocument.java index bce9510e4..d64431f21 100644 --- a/unoxml/qa/complex/unoxml/TestDocument.java +++ b/unoxml/qa/complex/unoxml/TestDocument.java @@ -29,10 +29,11 @@ package complex.unoxml; import java.io.File; import org.openoffice.test.OfficeFileUrl; +import org.openoffice.test.Argument; final class TestDocument { public static String getUrl(String name) { - return OfficeFileUrl.getAbsolute(new File("testdocuments", name)); + return OfficeFileUrl.getAbsolute(new File(Argument.get("tdoc"), name)); } private TestDocument() {} diff --git a/unoxml/source/dom/attr.cxx b/unoxml/source/dom/attr.cxx index dc4a0b11b..8851c3ada 100644 --- a/unoxml/source/dom/attr.cxx +++ b/unoxml/source/dom/attr.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,18 +25,60 @@ * ************************************************************************/ -#include "attr.hxx" -#include "element.hxx" -#include <com/sun/star/xml/dom/DOMException.hdl> +#include <attr.hxx> + #include <string.h> +#include <boost/shared_ptr.hpp> + +#include <com/sun/star/xml/dom/DOMException.hdl> +#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> + +#include <document.hxx> + + namespace DOM { - CAttr::CAttr(const xmlAttrPtr pAttr) + CAttr::CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlAttrPtr const pAttr) + : CAttr_Base(rDocument, rMutex, + NodeType_ATTRIBUTE_NODE, reinterpret_cast<xmlNodePtr>(pAttr)) + , m_aAttrPtr(pAttr) { - m_aAttrPtr = pAttr; - m_aNodeType = NodeType_ATTRIBUTE_NODE; - init_node((xmlNodePtr)pAttr); + } + + xmlNsPtr CAttr::GetNamespace(xmlNodePtr const pNode) + { + if (!m_pNamespace.get()) { + return 0; + } + xmlChar const*const pUri(reinterpret_cast<xmlChar const*>( + m_pNamespace->first.getStr())); + xmlChar const*const pPrefix(reinterpret_cast<xmlChar const*>( + m_pNamespace->second.getStr())); + xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, pPrefix); + if (pNs && (0 != xmlStrcmp(pNs->href, pUri))) { + return pNs; + } + pNs = xmlNewNs(pNode, pUri, pPrefix); + if (pNs) { + return pNs; + } + pNs = xmlSearchNsByHref(pNode->doc, pNode, pUri); + // if (!pNs) hmm... now what? throw? + if (!pNs) { OSL_TRACE("CAtttr: cannot create namespace"); } + return pNs; + } + + bool CAttr::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_TEXT_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } } OUString SAL_CALL CAttr::getNodeName() @@ -61,38 +103,48 @@ namespace DOM */ OUString SAL_CALL CAttr::getName() throw (RuntimeException) { - OUString aName; - if (m_aAttrPtr != NULL) - { - aName = OUString((char*)m_aAttrPtr->name, strlen((char*)m_aAttrPtr->name), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return ::rtl::OUString(); } + OUString const aName((char*)m_aAttrPtr->name, + strlen((char*)m_aAttrPtr->name), RTL_TEXTENCODING_UTF8); return aName; } /** - The Element node this attribute is attached to or null if this + The Element node this attribute is attached to or null if this attribute is not in use. */ Reference< XElement > SAL_CALL CAttr::getOwnerElement() throw (RuntimeException) { - Reference< XElement > aElement; - if (m_aAttrPtr != NULL && m_aAttrPtr->parent != NULL) - { - aElement = Reference< XElement >(static_cast< CElement* >(CNode::get(m_aAttrPtr->parent))); + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return 0; + } + if (0 == m_aAttrPtr->parent) { + return 0; } - return aElement; + Reference< XElement > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + m_aAttrPtr->parent).get()), + UNO_QUERY_THROW); + return xRet; } /** - If this attribute was explicitly given a value in the original + If this attribute was explicitly given a value in the original document, this is true; otherwise, it is false. */ sal_Bool SAL_CALL CAttr::getSpecified() throw (RuntimeException) { - // XXX what is this supposed do exactly? - return sal_False; + // FIXME if this DOM implemenatation supported DTDs it would need + // to check that this attribute is not default or something + return sal_True; } /** @@ -101,13 +153,19 @@ namespace DOM OUString SAL_CALL CAttr::getValue() throw (RuntimeException) { - OUString aName; - if (m_aAttrPtr != NULL && m_aAttrPtr->children != NULL) - { - aName = OUString((char*)m_aAttrPtr->children->content, strlen((char*)m_aAttrPtr->children->content), - RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return ::rtl::OUString(); } - return aName; + if (0 == m_aAttrPtr->children) { + return ::rtl::OUString(); + } + char const*const pContent((m_aAttrPtr->children) + ? reinterpret_cast<char const*>(m_aAttrPtr->children->content) + : ""); + OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8); + return ret; } /** @@ -116,6 +174,12 @@ namespace DOM void SAL_CALL CAttr::setValue(const OUString& value) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + + if ((0 == m_aNodePtr) || (0 == m_aAttrPtr)) { + return; + } + // remember old value (for mutation event) OUString sOldValue = getValue(); @@ -125,8 +189,11 @@ namespace DOM // this does not work if the attribute was created anew // xmlNodePtr pNode = m_aAttrPtr->parent; // xmlSetProp(pNode, m_aAttrPtr->name, xValue); - xmlChar *buffer = xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, xValue); - m_aAttrPtr->children = xmlStringGetNodeList(m_aAttrPtr->doc, buffer); + ::boost::shared_ptr<xmlChar const> const buffer( + xmlEncodeEntitiesReentrant(m_aAttrPtr->doc, xValue), xmlFree); + xmlFreeNodeList(m_aAttrPtr->children); + m_aAttrPtr->children = + xmlStringGetNodeList(m_aAttrPtr->doc, buffer.get()); xmlNodePtr tmp = m_aAttrPtr->children; while (tmp != NULL) { tmp->parent = (xmlNodePtr) m_aNodePtr; @@ -145,9 +212,60 @@ namespace DOM sEventName, sal_True, sal_False, Reference<XNode>( static_cast<XAttr*>( this ) ), sOldValue, value, getName(), AttrChangeType_MODIFICATION ); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); dispatchSubtreeModified(); - xmlFree(buffer); } + void SAL_CALL CAttr::setPrefix(const OUString& prefix) + throw (RuntimeException, DOMException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return; } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + m_pNamespace->second = + OUStringToOString(prefix, RTL_TEXTENCODING_UTF8); + } else { + CNode::setPrefix(prefix); + } + } + + OUString SAL_CALL CAttr::getPrefix() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return ::rtl::OUString(); } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + OUString const ret(::rtl::OStringToOUString( + m_pNamespace->second, RTL_TEXTENCODING_UTF8)); + return ret; + } else { + return CNode::getPrefix(); + } + } + + OUString SAL_CALL CAttr::getNamespaceURI() + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_aNodePtr) { return ::rtl::OUString(); } + + if (m_pNamespace.get()) { + OSL_ASSERT(!m_aNodePtr->parent); + OUString const ret(::rtl::OStringToOUString( + m_pNamespace->first, RTL_TEXTENCODING_UTF8)); + return ret; + } else { + return CNode::getNamespaceURI(); + } + } } diff --git a/unoxml/source/dom/attr.hxx b/unoxml/source/dom/attr.hxx index 73118020f..824f042a2 100644 --- a/unoxml/source/dom/attr.hxx +++ b/unoxml/source/dom/attr.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,16 +25,20 @@ * ************************************************************************/ -#ifndef _ATTR_HXX -#define _ATTR_HXX +#ifndef DOM_ATTR_HXX +#define DOM_ATTR_HXX + +#include <memory> + +#include <libxml/tree.h> #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XAttr.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> using ::rtl::OUString; using namespace com::sun::star::uno; @@ -42,30 +46,43 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CAttr : public cppu::ImplInheritanceHelper1< CNode, XAttr > + typedef ::std::pair< ::rtl::OString, ::rtl::OString > stringpair_t; + + typedef ::cppu::ImplInheritanceHelper1< CNode, XAttr > CAttr_Base; + + class CAttr + : public CAttr_Base { - friend class CNode; - friend class CElement; + private: + friend class CDocument; + private: xmlAttrPtr m_aAttrPtr; + ::std::auto_ptr< stringpair_t > m_pNamespace; protected: - CAttr(const xmlAttrPtr aAttrPtr); + CAttr(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlAttrPtr const pAttr); public: + /// return the libxml namespace corresponding to m_pNamespace on pNode + xmlNsPtr GetNamespace(xmlNodePtr const pNode); + + virtual bool IsChildTypeAllowed(NodeType const nodeType); + /** Returns the name of this attribute. */ virtual OUString SAL_CALL getName() throw (RuntimeException); /** - The Element node this attribute is attached to or null if this + The Element node this attribute is attached to or null if this attribute is not in use. */ virtual Reference< XElement > SAL_CALL getOwnerElement() throw (RuntimeException); /** - If this attribute was explicitly given a value in the original + If this attribute was explicitly given a value in the original document, this is true; otherwise, it is false. */ virtual sal_Bool SAL_CALL getSpecified()throw (RuntimeException); @@ -122,10 +139,7 @@ namespace DOM return CNode::getLastChild(); } virtual OUString SAL_CALL getNamespaceURI() - throw (RuntimeException) - { - return CNode::getNamespaceURI(); - } + throw (RuntimeException); virtual Reference< XNode > SAL_CALL getNextSibling() throw (RuntimeException) { @@ -147,10 +161,7 @@ namespace DOM return CNode::getParentNode(); } virtual OUString SAL_CALL getPrefix() - throw (RuntimeException) - { - return CNode::getPrefix(); - } + throw (RuntimeException); virtual Reference< XNode > SAL_CALL getPreviousSibling() throw (RuntimeException) { @@ -199,10 +210,7 @@ namespace DOM return setValue(nodeValue); } virtual void SAL_CALL setPrefix(const OUString& prefix) - throw (RuntimeException, DOMException) - { - return CNode::setPrefix(prefix); - } + throw (RuntimeException, DOMException); }; } diff --git a/unoxml/source/dom/attributesmap.cxx b/unoxml/source/dom/attributesmap.cxx index cb6f13a41..3cec81767 100644 --- a/unoxml/source/dom/attributesmap.cxx +++ b/unoxml/source/dom/attributesmap.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,13 +25,20 @@ * ************************************************************************/ -#include "attributesmap.hxx" +#include <attributesmap.hxx> + #include <string.h> +#include <element.hxx> +#include <document.hxx> + + namespace DOM { - CAttributesMap::CAttributesMap(const CElement* aElement) - : m_pElement(aElement) + CAttributesMap::CAttributesMap(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex) + : m_pElement(pElement) + , m_rMutex(rMutex) { } @@ -40,8 +47,10 @@ namespace DOM */ sal_Int32 SAL_CALL CAttributesMap::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 count = 0; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { xmlAttrPtr cur = pNode->properties; @@ -52,16 +61,18 @@ namespace DOM } } return count; - } /** - Retrieves a node specified by local name + Retrieves a node specified by local name */ - Reference< XNode > SAL_CALL CAttributesMap::getNamedItem(const OUString& name) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::getNamedItem(OUString const& name) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); @@ -71,7 +82,9 @@ namespace DOM { if( strcmp((char*)xName, (char*)cur->name) == 0) { - aNode = Reference< XNode >(static_cast<CNode*>(CNode::get((xmlNodePtr)cur))); + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); break; } cur = cur->next; @@ -83,24 +96,32 @@ namespace DOM /** Retrieves a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CAttributesMap::getNamedItemNS(const OUString& namespaceURI,const OUString& localName) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); xmlChar* xName = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar* xNs = (xmlChar*)o1.getStr(); - xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, xNs); + xmlChar const*const xNs = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlNsPtr const pNs = xmlSearchNsByHref(pNode->doc, pNode, xNs); xmlAttrPtr cur = pNode->properties; while (cur != NULL && pNs != NULL) { if( strcmp((char*)xName, (char*)cur->name) == 0 && cur->ns == pNs) { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); break; } cur = cur->next; @@ -112,10 +133,13 @@ namespace DOM /** Returns the indexth item in the map. */ - Reference< XNode > SAL_CALL CAttributesMap::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::item(sal_Int32 index) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; + xmlNodePtr pNode = m_pElement->GetNodePtr(); if (pNode != NULL) { xmlAttrPtr cur = pNode->properties; @@ -124,7 +148,9 @@ namespace DOM { if (count == index) { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); + aNode = Reference< XNode >( + m_pElement->GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(cur)).get() ); break; } count++; @@ -132,80 +158,87 @@ namespace DOM } } return aNode; - } /** Removes a node specified by name. */ - Reference< XNode > SAL_CALL CAttributesMap::removeNamedItem(const OUString& name) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::removeNamedItem(OUString const& name) + throw (RuntimeException) { - Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; - if (pNode != NULL) - { - OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); - xmlChar* xName = (xmlChar*)o1.getStr(); - xmlAttrPtr cur = pNode->properties; - while (cur != NULL) - { - if( strcmp((char*)xName, (char*)cur->name) == 0) - { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); - xmlUnlinkNode((xmlNodePtr)cur); - break; - } - cur = cur->next; - } + // no MutexGuard needed: m_pElement is const + Reference< XAttr > const xAttr(m_pElement->getAttributeNode(name)); + if (!xAttr.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::removeNamedItem: no such attribute")), + static_cast<OWeakObject*>(this), + DOMExceptionType_NOT_FOUND_ERR); } - return aNode; + Reference< XNode > const xRet( + m_pElement->removeAttributeNode(xAttr), UNO_QUERY); + return xRet; } /** // Removes a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CAttributesMap::removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException) { - Reference< XNode > aNode; - xmlNodePtr pNode = m_pElement->m_aNodePtr; - if (pNode != NULL) - { - OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar* xName = (xmlChar*)o1.getStr(); - OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar* xNs = (xmlChar*)o1.getStr(); - xmlNsPtr pNs = xmlSearchNs(pNode->doc, pNode, xNs); - xmlAttrPtr cur = pNode->properties; - while (cur != NULL && pNs != NULL) - { - if( strcmp((char*)xName, (char*)cur->name) == 0 && - cur->ns == pNs) - { - aNode = Reference< XNode >(static_cast< CNode* >(CNode::get((xmlNodePtr)cur))); - xmlUnlinkNode((xmlNodePtr)cur); - break; - } - cur = cur->next; - } + // no MutexGuard needed: m_pElement is const + Reference< XAttr > const xAttr( + m_pElement->getAttributeNodeNS(namespaceURI, localName)); + if (!xAttr.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::removeNamedItemNS: no such attribute")), + static_cast<OWeakObject*>(this), + DOMExceptionType_NOT_FOUND_ERR); } - return aNode; + Reference< XNode > const xRet( + m_pElement->removeAttributeNode(xAttr), UNO_QUERY); + return xRet; } /** // Adds a node using its nodeName attribute. */ - Reference< XNode > SAL_CALL CAttributesMap::setNamedItem(const Reference< XNode >& arg) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::setNamedItem(Reference< XNode > const& xNode) + throw (RuntimeException) { - return arg; - // return Reference< XNode >(); + Reference< XAttr > const xAttr(xNode, UNO_QUERY); + if (!xNode.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::setNamedItem: XAttr argument expected")), + static_cast<OWeakObject*>(this), + DOMExceptionType_HIERARCHY_REQUEST_ERR); + } + // no MutexGuard needed: m_pElement is const + Reference< XNode > const xRet( + m_pElement->setAttributeNode(xAttr), UNO_QUERY); + return xRet; } /** Adds a node using its namespaceURI and localName. */ - Reference< XNode > SAL_CALL CAttributesMap::setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException) + Reference< XNode > SAL_CALL + CAttributesMap::setNamedItemNS(Reference< XNode > const& xNode) + throw (RuntimeException) { - return arg; - // return Reference< XNode >(); + Reference< XAttr > const xAttr(xNode, UNO_QUERY); + if (!xNode.is()) { + throw DOMException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "CAttributesMap::setNamedItemNS: XAttr argument expected")), + static_cast<OWeakObject*>(this), + DOMExceptionType_HIERARCHY_REQUEST_ERR); + } + // no MutexGuard needed: m_pElement is const + Reference< XNode > const xRet( + m_pElement->setAttributeNodeNS(xAttr), UNO_QUERY); + return xRet; } } diff --git a/unoxml/source/dom/attributesmap.hxx b/unoxml/source/dom/attributesmap.hxx index 0bee51eb9..b987349c9 100644 --- a/unoxml/source/dom/attributesmap.hxx +++ b/unoxml/source/dom/attributesmap.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,19 +25,18 @@ * ************************************************************************/ -#ifndef _ATTRIBUTESMAP_HXX -#define _ATTRIBUTESMAP_HXX +#ifndef DOM_ATTRIBUTESMAP_HXX +#define DOM_ATTRIBUTESMAP_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "node.hxx" -#include "element.hxx" -#include "attr.hxx" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -45,12 +44,18 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CAttributesMap : public cppu::WeakImplHelper1< XNamedNodeMap > + class CElement; + + class CAttributesMap + : public cppu::WeakImplHelper1< XNamedNodeMap > { private: - const CElement* m_pElement; + ::rtl::Reference<CElement> const m_pElement; + ::osl::Mutex & m_rMutex; + public: - CAttributesMap(const CElement* aDocType); + CAttributesMap(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex); /** The number of nodes in this map. @@ -58,39 +63,51 @@ namespace DOM virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); /** - Retrieves a node specified by local name + Retrieves a node specified by local name */ - virtual Reference< XNode > SAL_CALL getNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItem(OUString const& name) + throw (RuntimeException); /** Retrieves a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL getNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** Returns the indexth item in the map. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); /** Removes a node specified by name. */ - virtual Reference< XNode > SAL_CALL removeNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) + throw (RuntimeException); /** // Removes a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** // Adds a node using its nodeName attribute. */ - virtual Reference< XNode > SAL_CALL setNamedItem(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); /** Adds a node using its namespaceURI and localName. */ - virtual Reference< XNode > SAL_CALL setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/cdatasection.cxx b/unoxml/source/dom/cdatasection.cxx index dbae7584c..6f8035a79 100644 --- a/unoxml/source/dom/cdatasection.cxx +++ b/unoxml/source/dom/cdatasection.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,20 +25,22 @@ * ************************************************************************/ -#include "cdatasection.hxx" +#include <cdatasection.hxx> #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> namespace DOM { - CCDATASection::CCDATASection(const xmlNodePtr aNodePtr) + CCDATASection::CCDATASection( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CCDATASection_Base(rDocument, rMutex, + NodeType_CDATA_SECTION_NODE, pNode) { - m_aNodeType = NodeType_CDATA_SECTION_NODE; - init_text(aNodePtr); } - void SAL_CALL CCDATASection::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + void CCDATASection::saxify(const Reference< XDocumentHandler >& i_xHandler) + { if (!i_xHandler.is()) throw RuntimeException(); Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); if (xExtended.is()) { diff --git a/unoxml/source/dom/cdatasection.hxx b/unoxml/source/dom/cdatasection.hxx index 4bcaa07f3..d809ef7e7 100644 --- a/unoxml/source/dom/cdatasection.hxx +++ b/unoxml/source/dom/cdatasection.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,14 +25,14 @@ * ************************************************************************/ -#ifndef _CDATASECTION_HXX -#define _CDATASECTION_HXX +#ifndef DOM_CDATASECTION_HXX +#define DOM_CDATASECTION_HXX #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XCDATASection.hpp> -#include "text.hxx" +#include <text.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,16 +40,21 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CCDATASection : public cppu::ImplInheritanceHelper1< CText, XCDATASection > + typedef ::cppu::ImplInheritanceHelper1< CText, XCDATASection > + CCDATASection_Base; + + class CCDATASection + : public CCDATASection_Base { - friend class CNode; + friend class CDocument; + protected: - CCDATASection(const xmlNodePtr aNodePtr); + CCDATASection(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); virtual Reference< XText > SAL_CALL splitText(sal_Int32 offset) throw (RuntimeException) @@ -215,7 +220,7 @@ namespace DOM virtual void SAL_CALL setNodeValue(const OUString& nodeValue) throw (RuntimeException, DOMException) { - return CNode::setNodeValue(nodeValue); + return CText::setNodeValue(nodeValue); } virtual void SAL_CALL setPrefix(const OUString& prefix) throw (RuntimeException, DOMException) diff --git a/unoxml/source/dom/characterdata.cxx b/unoxml/source/dom/characterdata.cxx index aeb989dc0..6cd3d9f2c 100644 --- a/unoxml/source/dom/characterdata.cxx +++ b/unoxml/source/dom/characterdata.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,18 +25,29 @@ * ************************************************************************/ +#include <characterdata.hxx> + +#include <string.h> + +#include <boost/shared_ptr.hpp> + #include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> -#include "characterdata.hxx" + #include "../events/mutationevent.hxx" -#include <string.h> + namespace DOM { - CCharacterData::CCharacterData() - {} + CCharacterData::CCharacterData( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : CCharacterData_Base(rDocument, rMutex, reNodeType, rpNode) + { + } - void CCharacterData::_dispatchEvent(const OUString& prevValue, const OUString& newValue) + void CCharacterData::dispatchEvent_Impl( + OUString const& prevValue, OUString const& newValue) { Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); Reference< XMutationEvent > event(docevent->createEvent( @@ -49,23 +60,22 @@ namespace DOM dispatchSubtreeModified(); } - void CCharacterData::init_characterdata(const xmlNodePtr aNodePtr) - { - init_node(aNodePtr); - } - /** Append the string to the end of the character data of the node. */ void SAL_CALL CCharacterData::appendData(const OUString& arg) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeAddContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(arg, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -75,10 +85,14 @@ namespace DOM void SAL_CALL CCharacterData::deleteData(sal_Int32 offset, sal_Int32 count) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0 || count < 0) { DOMException e; @@ -93,8 +107,9 @@ namespace DOM OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -104,6 +119,8 @@ namespace DOM */ OUString SAL_CALL CCharacterData::getData() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aData; if (m_aNodePtr != NULL) { @@ -120,8 +137,10 @@ namespace DOM The number of 16-bit units that are available through data and the substringData method below. */ - sal_Int32 CCharacterData::getLength() throw (RuntimeException) + sal_Int32 SAL_CALL CCharacterData::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 length = 0; if (m_aNodePtr != NULL) { @@ -137,10 +156,14 @@ namespace DOM void SAL_CALL CCharacterData::insertData(sal_Int32 offset, const OUString& arg) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0) { DOMException e; @@ -154,23 +177,28 @@ namespace DOM OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } /** - Replace the characters starting at the specified 16-bit unit offset + Replace the characters starting at the specified 16-bit unit offset with the specified string. */ void SAL_CALL CCharacterData::replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0 || count < 0){ DOMException e; @@ -186,7 +214,9 @@ namespace DOM OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -196,13 +226,16 @@ namespace DOM void SAL_CALL CCharacterData::setData(const OUString& data) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + if (m_aNodePtr != NULL) { OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr())); OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8); - _dispatchEvent(oldValue, newValue); + guard.clear(); // release mutex before calling event handlers + dispatchEvent_Impl(oldValue, newValue); } } @@ -212,11 +245,15 @@ namespace DOM OUString SAL_CALL CCharacterData::subStringData(sal_Int32 offset, sal_Int32 count) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aStr; if (m_aNodePtr != NULL) { // get current data - OString aData((const sal_Char*)xmlNodeGetContent(m_aNodePtr)); + ::boost::shared_ptr<xmlChar const> const pContent( + xmlNodeGetContent(m_aNodePtr), xmlFree); + OString aData(reinterpret_cast<sal_Char const*>(pContent.get())); OUString tmp(aData, aData.getLength(), RTL_TEXTENCODING_UTF8); if (offset > tmp.getLength() || offset < 0 || count < 0) { DOMException e; diff --git a/unoxml/source/dom/characterdata.hxx b/unoxml/source/dom/characterdata.hxx index 200b0652b..9639108f1 100644 --- a/unoxml/source/dom/characterdata.hxx +++ b/unoxml/source/dom/characterdata.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,19 +25,21 @@ * ************************************************************************/ -#ifndef _CHARACTERDATA_HXX -#define _CHARACTERDATA_HXX +#ifndef DOM_CHARACTERDATA_HXX +#define DOM_CHARACTERDATA_HXX + +#include <libxml/tree.h> #include <sal/types.h> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XCharacterData.hpp> -#include <com/sun/star/xml/dom/XElement.hpp> -#include <com/sun/star/xml/dom/XDOMImplementation.hpp> -#include <libxml/tree.h> -#include "node.hxx" + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -45,14 +47,19 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CCharacterData : public cppu::ImplInheritanceHelper1< CNode, XCharacterData > - { + typedef ::cppu::ImplInheritanceHelper1< CNode, XCharacterData > + CCharacterData_Base; + class CCharacterData + : public CCharacterData_Base + { protected: - CCharacterData(); - void init_characterdata(const xmlNodePtr aNodePtr); - void _dispatchEvent(const OUString& prevValue, const OUString& newValue); + CCharacterData(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + + void dispatchEvent_Impl( + OUString const& prevValue, OUString const& newValue); public: /** @@ -85,7 +92,7 @@ namespace DOM throw (RuntimeException, DOMException); /** - Replace the characters starting at the specified 16-bit unit offset + Replace the characters starting at the specified 16-bit unit offset with the specified string. */ virtual void SAL_CALL replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg) diff --git a/unoxml/source/dom/childlist.cxx b/unoxml/source/dom/childlist.cxx index a300e22a9..3c80c6642 100644 --- a/unoxml/source/dom/childlist.cxx +++ b/unoxml/source/dom/childlist.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,11 +25,20 @@ * ************************************************************************/ -#include "childlist.hxx" +#include <childlist.hxx> + +#include <libxml/tree.h> + +#include <node.hxx> +#include <document.hxx> + + namespace DOM { - CChildList::CChildList(const CNode* base) - : m_pNode(base->m_aNodePtr) + CChildList::CChildList(::rtl::Reference<CNode> const& pBase, + ::osl::Mutex & rMutex) + : m_pNode(pBase) + , m_rMutex(rMutex) { } @@ -38,10 +47,15 @@ namespace DOM */ sal_Int32 SAL_CALL CChildList::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 length = 0; if (m_pNode != NULL) { - xmlNodePtr cur = m_pNode->children; + xmlNodePtr cur = m_pNode->GetNodePtr(); + if (0 != cur) { + cur = cur->children; + } while (cur != NULL) { length++; @@ -54,19 +68,26 @@ namespace DOM /** Returns the indexth item in the collection. */ - Reference< XNode > SAL_CALL CChildList::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL CChildList::item(sal_Int32 index) + throw (RuntimeException) { - Reference< XNode >aNode; + ::osl::MutexGuard const g(m_rMutex); + if (m_pNode != NULL) { - xmlNodePtr cur = m_pNode->children; + xmlNodePtr cur = m_pNode->GetNodePtr(); + if (0 != cur) { + cur = cur->children; + } while (cur != NULL) { - if (index-- == 0) - aNode = Reference< XNode >(CNode::get(cur)); + if (index-- == 0) { + return Reference< XNode >( + m_pNode->GetOwnerDocument().GetCNode(cur).get()); + } cur = cur->next; } } - return aNode; + return 0; } } diff --git a/unoxml/source/dom/childlist.hxx b/unoxml/source/dom/childlist.hxx index 10e10aa99..f23617e49 100644 --- a/unoxml/source/dom/childlist.hxx +++ b/unoxml/source/dom/childlist.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,18 +25,18 @@ * ************************************************************************/ -#ifndef _CHILDLIST_HXX -#define _CHILDLIST_HXX +#ifndef DOM_CHILDLIST_HXX +#define DOM_CHILDLIST_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> -#include "node.hxx" -#include "libxml/tree.h" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -44,12 +44,19 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CChildList : public cppu::WeakImplHelper1< XNodeList > + class CNode; + + class CChildList + : public cppu::WeakImplHelper1< XNodeList > { private: - const xmlNodePtr m_pNode; + ::rtl::Reference<CNode> const m_pNode; + ::osl::Mutex & m_rMutex; + public: - CChildList(const CNode* base); + CChildList(::rtl::Reference<CNode> const& pBase, + ::osl::Mutex & rMutex); + /** The number of nodes in the list. */ @@ -57,7 +64,8 @@ namespace DOM /** Returns the indexth item in the collection. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/comment.cxx b/unoxml/source/dom/comment.cxx index f47b0200c..d1ea6d83e 100644 --- a/unoxml/source/dom/comment.cxx +++ b/unoxml/source/dom/comment.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,19 +25,20 @@ * ************************************************************************/ -#include "comment.hxx" +#include <comment.hxx> #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + namespace DOM { - CComment::CComment(const xmlNodePtr aNodePtr) + CComment::CComment(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CComment_Base(rDocument, rMutex, NodeType_COMMENT_NODE, pNode) { - m_aNodeType = NodeType_COMMENT_NODE; - init_node(aNodePtr); } - void SAL_CALL CComment::saxify( + void CComment::saxify( const Reference< XDocumentHandler >& i_xHandler) { if (!i_xHandler.is()) throw RuntimeException(); Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); diff --git a/unoxml/source/dom/comment.hxx b/unoxml/source/dom/comment.hxx index d6997337b..0aed0cf6a 100644 --- a/unoxml/source/dom/comment.hxx +++ b/unoxml/source/dom/comment.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,13 +25,14 @@ * ************************************************************************/ -#ifndef _COMMENT_HXX -#define _COMMENT_HXX +#ifndef DOM_COMMENT_HXX +#define DOM_COMMENT_HXX #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XComment.hpp> -#include "characterdata.hxx" + +#include <characterdata.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -39,16 +40,22 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CComment : public cppu::ImplInheritanceHelper1< CCharacterData, XComment > + typedef ::cppu::ImplInheritanceHelper1< CCharacterData, XComment > + CComment_Base; + + class CComment + : public CComment_Base { - friend class CNode; + private: + friend class CDocument; + protected: - CComment(const xmlNodePtr aNodePtr); + CComment(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); // --- delegations for XCharacterData virtual void SAL_CALL appendData(const OUString& arg) diff --git a/unoxml/source/dom/document.cxx b/unoxml/source/dom/document.cxx index 80258cd1d..14d725551 100644 --- a/unoxml/source/dom/document.cxx +++ b/unoxml/source/dom/document.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -40,11 +40,14 @@ #include "documenttype.hxx" #include "elementlist.hxx" #include "domimplementation.hxx" +#include <entity.hxx> +#include <notation.hxx> #include "../events/event.hxx" #include "../events/mutationevent.hxx" #include "../events/uievent.hxx" #include "../events/mouseevent.hxx" +#include "../events/eventdispatcher.hxx" #include <string.h> @@ -53,52 +56,287 @@ namespace DOM { + static xmlNodePtr lcl_getDocumentType(xmlDocPtr const i_pDocument) + { + // find the doc type + xmlNodePtr cur = i_pDocument->children; + while (cur != NULL) + { + if ((cur->type == XML_DOCUMENT_TYPE_NODE) || + (cur->type == XML_DTD_NODE)) { + return cur; + } + } + return 0; + } + + /// get the pointer to the root element node of the document + static xmlNodePtr lcl_getDocumentRootPtr(xmlDocPtr const i_pDocument) + { + // find the document element + xmlNodePtr cur = i_pDocument->children; + while (cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE) + break; + cur = cur->next; + } + return cur; + } + + CDocument::CDocument(xmlDocPtr const pDoc) + : CDocument_Base(*this, m_Mutex, + NodeType_DOCUMENT_NODE, reinterpret_cast<xmlNodePtr>(pDoc)) + , m_aDocPtr(pDoc) + , m_streamListeners() + , m_pEventDispatcher(new events::CEventDispatcher()) + { + } + + ::rtl::Reference<CDocument> CDocument::CreateCDocument(xmlDocPtr const pDoc) + { + ::rtl::Reference<CDocument> const xDoc(new CDocument(pDoc)); + // add the doc itself to its nodemap! + xDoc->m_NodeMap.insert( + nodemap_t::value_type(reinterpret_cast<xmlNodePtr>(pDoc), + ::std::make_pair( + WeakReference<XNode>(static_cast<XDocument*>(xDoc.get())), + xDoc.get()))); + return xDoc; + } + CDocument::~CDocument() { + ::osl::MutexGuard const g(m_Mutex); +#ifdef DBG_UTIL + // node map must be empty now, otherwise CDocument must not die! + for (nodemap_t::iterator i = m_NodeMap.begin(); + i != m_NodeMap.end(); ++i) + { + Reference<XNode> const xNode(i->second.first); + OSL_ENSURE(!xNode.is(), + "CDocument::~CDocument(): ERROR: live node in document node map!"); + } +#endif xmlFreeDoc(m_aDocPtr); } - CDocument::CDocument(xmlDocPtr aDocPtr): - m_aDocPtr(aDocPtr), - m_streamListeners() - { - // init node base - m_aNodeType = NodeType_DOCUMENT_NODE; - init_node((xmlNodePtr)m_aDocPtr); + + events::CEventDispatcher & CDocument::GetEventDispatcher() + { + return *m_pEventDispatcher; + } + + ::rtl::Reference< CElement > CDocument::GetDocumentElement() + { + xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr); + ::rtl::Reference< CElement > const xRet( + dynamic_cast<CElement*>(GetCNode(pNode).get())); + return xRet; + } + + void + CDocument::RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode) + { + nodemap_t::iterator const i = m_NodeMap.find(pNode); + if (i != m_NodeMap.end()) { + // #i113681# consider this scenario: + // T1 calls ~CNode + // T2 calls getCNode: lookup will find i->second->first invalid + // so a new CNode is created and inserted + // T1 calls removeCNode: i->second->second now points to a + // different CNode instance! + // + // check that the CNode is the right one + CNode *const pCurrent = i->second.second; + if (pCurrent == pCNode) { + m_NodeMap.erase(i); + } + } + } + + /** NB: this is the CNode factory. + it is the only place where CNodes may be instantiated. + all CNodes must be registered at the m_NodeMap. + */ + ::rtl::Reference<CNode> + CDocument::GetCNode(xmlNodePtr const pNode, bool const bCreate) + { + if (0 == pNode) { + return 0; + } + //check whether there is already an instance for this node + nodemap_t::const_iterator const i = m_NodeMap.find(pNode); + if (i != m_NodeMap.end()) { + // #i113681# check that the CNode is still alive + uno::Reference<XNode> const xNode(i->second.first); + if (xNode.is()) + { + ::rtl::Reference<CNode> ret(i->second.second); + OSL_ASSERT(ret.is()); + return ret; + } + } + + if (!bCreate) { return 0; } + + // there is not yet an instance wrapping this node, + // create it and store it in the map + + ::rtl::Reference<CNode> pCNode; + switch (pNode->type) + { + case XML_ELEMENT_NODE: + // m_aNodeType = NodeType::ELEMENT_NODE; + pCNode = static_cast< CNode* >( + new CElement(*this, m_Mutex, pNode)); + break; + case XML_TEXT_NODE: + // m_aNodeType = NodeType::TEXT_NODE; + pCNode = static_cast< CNode* >( + new CText(*this, m_Mutex, pNode)); + break; + case XML_CDATA_SECTION_NODE: + // m_aNodeType = NodeType::CDATA_SECTION_NODE; + pCNode = static_cast< CNode* >( + new CCDATASection(*this, m_Mutex, pNode)); + break; + case XML_ENTITY_REF_NODE: + // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE; + pCNode = static_cast< CNode* >( + new CEntityReference(*this, m_Mutex, pNode)); + break; + case XML_ENTITY_NODE: + // m_aNodeType = NodeType::ENTITY_NODE; + pCNode = static_cast< CNode* >(new CEntity(*this, m_Mutex, + reinterpret_cast<xmlEntityPtr>(pNode))); + break; + case XML_PI_NODE: + // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE; + pCNode = static_cast< CNode* >( + new CProcessingInstruction(*this, m_Mutex, pNode)); + break; + case XML_COMMENT_NODE: + // m_aNodeType = NodeType::COMMENT_NODE; + pCNode = static_cast< CNode* >( + new CComment(*this, m_Mutex, pNode)); + break; + case XML_DOCUMENT_NODE: + // m_aNodeType = NodeType::DOCUMENT_NODE; + OSL_ENSURE(false, "CDocument::GetCNode is not supposed to" + " create a CDocument!!!"); + pCNode = static_cast< CNode* >(new CDocument( + reinterpret_cast<xmlDocPtr>(pNode))); + break; + case XML_DOCUMENT_TYPE_NODE: + case XML_DTD_NODE: + // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE; + pCNode = static_cast< CNode* >(new CDocumentType(*this, m_Mutex, + reinterpret_cast<xmlDtdPtr>(pNode))); + break; + case XML_DOCUMENT_FRAG_NODE: + // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE; + pCNode = static_cast< CNode* >( + new CDocumentFragment(*this, m_Mutex, pNode)); + break; + case XML_NOTATION_NODE: + // m_aNodeType = NodeType::NOTATION_NODE; + pCNode = static_cast< CNode* >(new CNotation(*this, m_Mutex, + reinterpret_cast<xmlNotationPtr>(pNode))); + break; + case XML_ATTRIBUTE_NODE: + // m_aNodeType = NodeType::ATTRIBUTE_NODE; + pCNode = static_cast< CNode* >(new CAttr(*this, m_Mutex, + reinterpret_cast<xmlAttrPtr>(pNode))); + break; + // unsupported node types + case XML_HTML_DOCUMENT_NODE: + case XML_ELEMENT_DECL: + case XML_ATTRIBUTE_DECL: + case XML_ENTITY_DECL: + case XML_NAMESPACE_DECL: + default: + break; + } + + if (pCNode != 0) { + bool const bInserted = m_NodeMap.insert( + nodemap_t::value_type(pNode, + ::std::make_pair(WeakReference<XNode>(pCNode.get()), + pCNode.get())) + ).second; + OSL_ASSERT(bInserted); + if (!bInserted) { + // if insertion failed, delete new instance and return null + return 0; + } + } + + OSL_ENSURE(pCNode.is(), "no node produced during CDocument::GetCNode!"); + return pCNode; + } + + + CDocument & CDocument::GetOwnerDocument() + { + return *this; } - void SAL_CALL CDocument::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + void CDocument::saxify(const Reference< XDocumentHandler >& i_xHandler) + { i_xHandler->startDocument(); for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode = GetCNode(pChild); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->saxify(i_xHandler); } i_xHandler->endDocument(); } - void SAL_CALL CDocument::fastSaxify( Context& rContext ) { + void CDocument::fastSaxify( Context& rContext ) + { rContext.mxDocHandler->startDocument(); for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode = GetCNode(pChild); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->fastSaxify(rContext); } rContext.mxDocHandler->endDocument(); } + bool CDocument::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + return true; + case NodeType_ELEMENT_NODE: + // there may be only one! + return 0 == lcl_getDocumentRootPtr(m_aDocPtr); + case NodeType_DOCUMENT_TYPE_NODE: + // there may be only one! + return 0 == lcl_getDocumentType(m_aDocPtr); + default: + return false; + } + } + + void SAL_CALL CDocument::addListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_streamListeners.insert(aListener); } void SAL_CALL CDocument::removeListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_streamListeners.erase(aListener); } @@ -134,30 +372,42 @@ namespace DOM void SAL_CALL CDocument::start() throw (RuntimeException) { - if (! m_rOutputStream.is()) return; + listenerlist_t streamListeners; + { + ::osl::MutexGuard const g(m_Mutex); - // notify listners about start - listenerlist_t::const_iterator iter1 = m_streamListeners.begin(); - while (iter1 != m_streamListeners.end()) { + if (! m_rOutputStream.is()) { throw RuntimeException(); } + streamListeners = m_streamListeners; + } + + // notify listeners about start + listenerlist_t::const_iterator iter1 = streamListeners.begin(); + while (iter1 != streamListeners.end()) { Reference< XStreamListener > aListener = *iter1; aListener->started(); iter1++; } - // setup libxml IO and write data to output stream - IOContext ioctx = {m_rOutputStream, false}; - xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO( - writeCallback, closeCallback, &ioctx, NULL); - xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL); + { + ::osl::MutexGuard const g(m_Mutex); + + // check again! could have been reset... + if (! m_rOutputStream.is()) { throw RuntimeException(); } + + // setup libxml IO and write data to output stream + IOContext ioctx = {m_rOutputStream, false}; + xmlOutputBufferPtr pOut = xmlOutputBufferCreateIO( + writeCallback, closeCallback, &ioctx, NULL); + xmlSaveFileTo(pOut, m_aNodePtr->doc, NULL); + } // call listeners - listenerlist_t::const_iterator iter2 = m_streamListeners.begin(); - while (iter2 != m_streamListeners.end()) { + listenerlist_t::const_iterator iter2 = streamListeners.begin(); + while (iter2 != streamListeners.end()) { Reference< XStreamListener > aListener = *iter2; aListener->closed(); iter2++; } - } void SAL_CALL CDocument::terminate() @@ -169,11 +419,15 @@ namespace DOM void SAL_CALL CDocument::setOutputStream( const Reference< XOutputStream >& aStream ) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_rOutputStream = aStream; } Reference< XOutputStream > SAL_CALL CDocument::getOutputStream() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + return m_rOutputStream; } @@ -181,10 +435,16 @@ namespace DOM Reference< XAttr > SAL_CALL CDocument::createAttribute(const OUString& name) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); - return Reference< XAttr >(static_cast< CAttr* >( - CNode::get((xmlNodePtr)xmlNewDocProp(m_aDocPtr, xName, NULL)))); + xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, xName, NULL); + ::rtl::Reference< CAttr > const pCAttr( + dynamic_cast< CAttr* >(GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get())); + pCAttr->m_bUnlinked = true; + return pCAttr.get(); }; // Creates an attribute of the given qualified name and namespace URI. @@ -192,73 +452,96 @@ namespace DOM const OUString& ns, const OUString& qname) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); // libxml does not allow a NS definition to be attached to an // attribute node - which is a good thing, since namespaces are // only defined as parts of element nodes - // thus, we create a temporary element node which carries the ns definition - // and is removed/merged as soon as the attribute gets append to it's - // actual parent + // thus the namespace data is stored in CAttr::m_pNamespace sal_Int32 i = qname.indexOf(':'); OString oPrefix, oName, oUri; - xmlChar *xPrefix, *xName, *xUri; if (i != -1) { oPrefix = OUStringToOString(qname.copy(0, i), RTL_TEXTENCODING_UTF8); - xPrefix = (xmlChar*)oPrefix.getStr(); oName = OUStringToOString(qname.copy(i+1, qname.getLength()-i-1), RTL_TEXTENCODING_UTF8); } else { - xPrefix = (xmlChar*)""; oName = OUStringToOString(qname, RTL_TEXTENCODING_UTF8); } - xName = (xmlChar*)oName.getStr(); oUri = OUStringToOString(ns, RTL_TEXTENCODING_UTF8); - xUri = (xmlChar*)oUri.getStr(); + xmlAttrPtr const pAttr = xmlNewDocProp(m_aDocPtr, + reinterpret_cast<xmlChar const*>(oName.getStr()), 0); + ::rtl::Reference< CAttr > const pCAttr( + dynamic_cast< CAttr* >(GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get())); + if (!pCAttr.is()) { throw RuntimeException(); } + // store the namespace data! + pCAttr->m_pNamespace.reset( new stringpair_t(oUri, oPrefix) ); + pCAttr->m_bUnlinked = true; - // create the carrier node - xmlNodePtr pNode = xmlNewDocNode(m_aDocPtr, NULL, (xmlChar*)"__private", NULL); - xmlNsPtr pNs = xmlNewNs(pNode, xUri, xPrefix); - xmlAttrPtr pAttr = xmlNewNsProp(pNode, pNs, xName, NULL); - return Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)pAttr))); + return pCAttr.get(); }; // Creates a CDATASection node whose value is the specified string. Reference< XCDATASection > SAL_CALL CDocument::createCDATASection(const OUString& data) throw (RuntimeException) { - xmlChar *xData = (xmlChar*)OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr(); - xmlNodePtr pText = xmlNewCDataBlock(m_aDocPtr, xData, strlen((char*)xData)); - return Reference< XCDATASection >(static_cast< CCDATASection* >(CNode::get(pText))); + ::osl::MutexGuard const g(m_Mutex); + + OString const oData( + ::rtl::OUStringToOString(data, RTL_TEXTENCODING_UTF8)); + xmlChar const*const pData = + reinterpret_cast<xmlChar const*>(oData.getStr()); + xmlNodePtr const pText = + xmlNewCDataBlock(m_aDocPtr, pData, strlen(oData.getStr())); + Reference< XCDATASection > const xRet( + static_cast< XNode* >(GetCNode(pText).get()), + UNO_QUERY_THROW); + return xRet; } // Creates a Comment node given the specified string. Reference< XComment > SAL_CALL CDocument::createComment(const OUString& data) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); xmlChar *xData = (xmlChar*)o1.getStr(); xmlNodePtr pComment = xmlNewDocComment(m_aDocPtr, xData); - return Reference< XComment >(static_cast< CComment* >(CNode::get(pComment))); + Reference< XComment > const xRet( + static_cast< XNode* >(GetCNode(pComment).get()), + UNO_QUERY_THROW); + return xRet; } //Creates an empty DocumentFragment object. Reference< XDocumentFragment > SAL_CALL CDocument::createDocumentFragment() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + xmlNodePtr pFrag = xmlNewDocFragment(m_aDocPtr); - return Reference< XDocumentFragment >(static_cast< CDocumentFragment* >(CNode::get(pFrag))); + Reference< XDocumentFragment > const xRet( + static_cast< XNode* >(GetCNode(pFrag).get()), + UNO_QUERY_THROW); + return xRet; } // Creates an element of the type specified. Reference< XElement > SAL_CALL CDocument::createElement(const OUString& tagName) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(tagName, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); - xmlNodePtr aNodePtr = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); - return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } // Creates an element of the given qualified name and namespace URI. @@ -266,6 +549,8 @@ namespace DOM const OUString& ns, const OUString& qname) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + sal_Int32 i = qname.indexOf(':'); if (ns.getLength() == 0) throw RuntimeException(); xmlChar *xPrefix; @@ -287,45 +572,63 @@ namespace DOM // xmlNsPtr aNsPtr = xmlNewReconciledNs? // xmlNsPtr aNsPtr = xmlNewGlobalNs? - xmlNodePtr aNodePtr = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); - xmlNsPtr pNs = xmlNewNs(aNodePtr, xUri, xPrefix); - xmlSetNs(aNodePtr, pNs); - return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocNode(m_aDocPtr, NULL, xName, NULL); + xmlNsPtr const pNs = xmlNewNs(pNode, xUri, xPrefix); + xmlSetNs(pNode, pNs); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } //Creates an EntityReference object. Reference< XEntityReference > SAL_CALL CDocument::createEntityReference(const OUString& name) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); - xmlNodePtr aNodePtr = xmlNewReference(m_aDocPtr, xName); - return Reference< XEntityReference >(static_cast< CEntityReference* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewReference(m_aDocPtr, xName); + Reference< XEntityReference > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } - // Creates a ProcessingInstruction node given the specified name and + // Creates a ProcessingInstruction node given the specified name and // data strings. Reference< XProcessingInstruction > SAL_CALL CDocument::createProcessingInstruction( const OUString& target, const OUString& data) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(target, RTL_TEXTENCODING_UTF8); xmlChar *xTarget = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); xmlChar *xData = (xmlChar*)o2.getStr(); - xmlNodePtr aNodePtr = xmlNewPI(xTarget, xData); - aNodePtr->doc = m_aDocPtr; - return Reference< XProcessingInstruction >(static_cast< CProcessingInstruction* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocPI(m_aDocPtr, xTarget, xData); + pNode->doc = m_aDocPtr; + Reference< XProcessingInstruction > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } // Creates a Text node given the specified string. Reference< XText > SAL_CALL CDocument::createTextNode(const OUString& data) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + OString o1 = OUStringToOString(data, RTL_TEXTENCODING_UTF8); xmlChar *xData = (xmlChar*)o1.getStr(); - xmlNodePtr aNodePtr = xmlNewDocText(m_aDocPtr, xData); - return Reference< XText >(static_cast< CText* >(CNode::get(aNodePtr))); + xmlNodePtr const pNode = xmlNewDocText(m_aDocPtr, xData); + Reference< XText > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY_THROW); + return xRet; } // The Document Type Declaration (see DocumentType) associated with this @@ -333,27 +636,13 @@ namespace DOM Reference< XDocumentType > SAL_CALL CDocument::getDoctype() throw (RuntimeException) { - // find the doc type - xmlNodePtr cur = m_aDocPtr->children; - while (cur != NULL) - { - if (cur->type == XML_DOCUMENT_TYPE_NODE || cur->type == XML_DTD_NODE) - break; - } - return Reference< XDocumentType >(static_cast< CDocumentType* >(CNode::get(cur))); - } + ::osl::MutexGuard const g(m_Mutex); - /// get the pointer to the root element node of the document - static xmlNodePtr SAL_CALL _getDocumentRootPtr(xmlDocPtr i_pDocument) { - // find the document element - xmlNodePtr cur = i_pDocument->children; - while (cur != NULL) - { - if (cur->type == XML_ELEMENT_NODE) - break; - cur = cur->next; - } - return cur; + xmlNodePtr const pDocType(lcl_getDocumentType(m_aDocPtr)); + Reference< XDocumentType > const xRet( + static_cast< XNode* >(GetCNode(pDocType).get()), + UNO_QUERY); + return xRet; } // This is a convenience attribute that allows direct access to the child @@ -361,13 +650,19 @@ namespace DOM Reference< XElement > SAL_CALL CDocument::getDocumentElement() throw (RuntimeException) { - xmlNodePtr cur = _getDocumentRootPtr(m_aDocPtr); - return Reference< XElement >(static_cast< CElement* >(CNode::get(cur))); + ::osl::MutexGuard const g(m_Mutex); + + xmlNodePtr const pNode = lcl_getDocumentRootPtr(m_aDocPtr); + if (!pNode) { return 0; } + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY); + return xRet; } - static xmlNodePtr _search_element_by_id(const xmlNodePtr cur, const xmlChar* id) + static xmlNodePtr + lcl_search_element_by_id(const xmlNodePtr cur, const xmlChar* id) { - if (cur == NULL) return NULL; // look in current node @@ -384,175 +679,195 @@ namespace DOM } } // look in children - xmlNodePtr result = _search_element_by_id(cur->children, id); + xmlNodePtr result = lcl_search_element_by_id(cur->children, id); if (result != NULL) return result; - result = _search_element_by_id(cur->next, id); + result = lcl_search_element_by_id(cur->next, id); return result; } // Returns the Element whose ID is given by elementId. - Reference< XElement > SAL_CALL CDocument::getElementById(const OUString& elementId) + Reference< XElement > SAL_CALL + CDocument::getElementById(const OUString& elementId) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // search the tree for an element with the given ID OString o1 = OUStringToOString(elementId, RTL_TEXTENCODING_UTF8); xmlChar *xId = (xmlChar*)o1.getStr(); - xmlNodePtr pStart = CNode::getNodePtr(getDocumentElement().get()); - xmlNodePtr aNodePtr = _search_element_by_id(pStart, xId); - return Reference< XElement >(static_cast< CElement* >(CNode::get(aNodePtr))); + xmlNodePtr const pStart = lcl_getDocumentRootPtr(m_aDocPtr); + if (!pStart) { return 0; } + xmlNodePtr const pNode = lcl_search_element_by_id(pStart, xId); + Reference< XElement > const xRet( + static_cast< XNode* >(GetCNode(pNode).get()), + UNO_QUERY); + return xRet; } - Reference< XNodeList > SAL_CALL CDocument::getElementsByTagName(const OUString& tagname) + Reference< XNodeList > SAL_CALL + CDocument::getElementsByTagName(OUString const& rTagname) throw (RuntimeException) { - // build a list - return Reference< XNodeList >( - new CElementList(static_cast< CElement* >( - this->getDocumentElement().get()), tagname)); + ::osl::MutexGuard const g(m_Mutex); + + Reference< XNodeList > const xRet( + new CElementList(this->GetDocumentElement(), m_Mutex, rTagname)); + return xRet; } Reference< XNodeList > SAL_CALL CDocument::getElementsByTagNameNS( - const OUString& namespaceURI, const OUString& localName) + OUString const& rNamespaceURI, OUString const& rLocalName) throw (RuntimeException) { - return Reference< XNodeList >( - new CElementList(static_cast< CElement* >( - this->getDocumentElement().get()), namespaceURI, localName)); + ::osl::MutexGuard const g(m_Mutex); + + Reference< XNodeList > const xRet( + new CElementList(this->GetDocumentElement(), m_Mutex, + rLocalName, &rNamespaceURI)); + return xRet; } Reference< XDOMImplementation > SAL_CALL CDocument::getImplementation() throw (RuntimeException) { - // XXX + // does not need mutex currently return Reference< XDOMImplementation >(CDOMImplementation::get()); } - // helper function to recall import for siblings - static Reference< XNode > _import_siblings ( - const Reference< XNode > aNode, const Reference< XNode> parent, CDocument* pTarget) + // helper function to recursively import siblings + static void lcl_ImportSiblings( + Reference< XDocument > const& xTargetDocument, + Reference< XNode > const& xTargetParent, + Reference< XNode > const& xChild) { - Reference< XNode > sibling = aNode; - Reference< XNode > tmp; - Reference< XNode > firstImported; - while (sibling.is()) + Reference< XNode > xSibling = xChild; + while (xSibling.is()) { - tmp = pTarget->importNode(sibling, sal_True); - parent->appendChild(tmp); - if (!firstImported.is()) - firstImported = tmp; - sibling = sibling->getNextSibling(); + Reference< XNode > const xTmp( + xTargetDocument->importNode(xSibling, sal_True)); + xTargetParent->appendChild(xTmp); + xSibling = xSibling->getNextSibling(); } - return firstImported; } - Reference< XNode > SAL_CALL CDocument::importNode( - const Reference< XNode >& importedNode, sal_Bool deep) - throw (RuntimeException, DOMException) + static Reference< XNode > + lcl_ImportNode( Reference< XDocument > const& xDocument, + Reference< XNode > const& xImportedNode, sal_Bool deep) { - // this node could be from another memory model - // only use uno interfaces to access is!!! - - // allready in doc? - if ( importedNode->getOwnerDocument() == - Reference< XDocument>(static_cast< CDocument* >(CNode::get((xmlNodePtr)m_aDocPtr)))) - return importedNode; - - Reference< XNode > aNode; - NodeType aNodeType = importedNode->getNodeType(); + Reference< XNode > xNode; + NodeType aNodeType = xImportedNode->getNodeType(); switch (aNodeType) { case NodeType_ATTRIBUTE_NODE: { - Reference< XAttr > attr(importedNode, UNO_QUERY); - Reference< XAttr > newAttr = createAttribute(attr->getName()); - newAttr->setValue(attr->getValue()); - aNode.set(newAttr, UNO_QUERY); + Reference< XAttr > const xAttr(xImportedNode, UNO_QUERY_THROW); + Reference< XAttr > const xNew = + xDocument->createAttribute(xAttr->getName()); + xNew->setValue(xAttr->getValue()); + xNode.set(xNew, UNO_QUERY); break; } case NodeType_CDATA_SECTION_NODE: { - Reference< XCDATASection > cdata(importedNode, UNO_QUERY); - Reference< XCDATASection > newCdata = createCDATASection(cdata->getData()); - aNode.set(newCdata, UNO_QUERY); + Reference< XCDATASection > const xCData(xImportedNode, + UNO_QUERY_THROW); + Reference< XCDATASection > const xNewCData = + xDocument->createCDATASection(xCData->getData()); + xNode.set(xNewCData, UNO_QUERY); break; } case NodeType_COMMENT_NODE: { - Reference< XComment > comment(importedNode, UNO_QUERY); - Reference< XComment > newComment = createComment(comment->getData()); - aNode.set(newComment, UNO_QUERY); + Reference< XComment > const xComment(xImportedNode, + UNO_QUERY_THROW); + Reference< XComment > const xNewComment = + xDocument->createComment(xComment->getData()); + xNode.set(xNewComment, UNO_QUERY); break; } case NodeType_DOCUMENT_FRAGMENT_NODE: { - Reference< XDocumentFragment > frag(importedNode, UNO_QUERY); - Reference< XDocumentFragment > newFrag = createDocumentFragment(); - aNode.set(newFrag, UNO_QUERY); + Reference< XDocumentFragment > const xFrag(xImportedNode, + UNO_QUERY_THROW); + Reference< XDocumentFragment > const xNewFrag = + xDocument->createDocumentFragment(); + xNode.set(xNewFrag, UNO_QUERY); break; } case NodeType_ELEMENT_NODE: { - Reference< XElement > element(importedNode, UNO_QUERY); - OUString aNsUri = importedNode->getNamespaceURI(); - OUString aNsPrefix = importedNode->getPrefix(); - OUString aQName = element->getTagName(); - Reference< XElement > newElement; + Reference< XElement > const xElement(xImportedNode, + UNO_QUERY_THROW); + OUString const aNsUri = xImportedNode->getNamespaceURI(); + OUString const aNsPrefix = xImportedNode->getPrefix(); + OUString aQName = xElement->getTagName(); + Reference< XElement > xNewElement; if (aNsUri.getLength() > 0) { - - if (aNsPrefix.getLength() > 0) - aQName = aNsPrefix + OUString::createFromAscii(":") + aQName; - newElement = createElementNS(aNsUri, aQName); + if (aNsPrefix.getLength() > 0) { + aQName = aNsPrefix + OUString::createFromAscii(":") + + aQName; + } + xNewElement = xDocument->createElementNS(aNsUri, aQName); + } else { + xNewElement = xDocument->createElement(aQName); } - else - newElement = createElement(aQName); // get attributes - if (element->hasAttributes()) + if (xElement->hasAttributes()) { - Reference< XNamedNodeMap > attribs = element->getAttributes(); - Reference< XAttr > curAttr; + Reference< XNamedNodeMap > attribs = xElement->getAttributes(); for (sal_Int32 i = 0; i < attribs->getLength(); i++) { - curAttr = Reference< XAttr >(attribs->item(i), UNO_QUERY); - OUString aAttrUri = curAttr->getNamespaceURI(); - OUString aAttrPrefix = curAttr->getPrefix(); + Reference< XAttr > const curAttr(attribs->item(i), + UNO_QUERY_THROW); + OUString const aAttrUri = curAttr->getNamespaceURI(); + OUString const aAttrPrefix = curAttr->getPrefix(); OUString aAttrName = curAttr->getName(); + OUString const sValue = curAttr->getValue(); if (aAttrUri.getLength() > 0) { - if (aAttrPrefix.getLength() > 0) - aAttrName = aAttrPrefix + OUString::createFromAscii(":") + aAttrName; - newElement->setAttributeNS(aAttrUri, aAttrName, curAttr->getValue()); + if (aAttrPrefix.getLength() > 0) { + aAttrName = aAttrPrefix + + OUString::createFromAscii(":") + aAttrName; + } + xNewElement->setAttributeNS( + aAttrUri, aAttrName, sValue); + } else { + xNewElement->setAttribute(aAttrName, sValue); } - else - newElement->setAttribute(aAttrName, curAttr->getValue()); } } - aNode.set(newElement, UNO_QUERY); + xNode.set(xNewElement, UNO_QUERY); break; } case NodeType_ENTITY_REFERENCE_NODE: { - Reference< XEntityReference > ref(importedNode, UNO_QUERY); - Reference< XEntityReference > newRef(createEntityReference(ref->getNodeName())); - aNode.set(newRef, UNO_QUERY); + Reference< XEntityReference > const xRef(xImportedNode, + UNO_QUERY_THROW); + Reference< XEntityReference > const xNewRef( + xDocument->createEntityReference(xRef->getNodeName())); + xNode.set(xNewRef, UNO_QUERY); break; } case NodeType_PROCESSING_INSTRUCTION_NODE: { - Reference< XProcessingInstruction > pi(importedNode, UNO_QUERY); - Reference< XProcessingInstruction > newPi( - createProcessingInstruction(pi->getTarget(), pi->getData())); - aNode.set(newPi, UNO_QUERY); + Reference< XProcessingInstruction > const xPi(xImportedNode, + UNO_QUERY_THROW); + Reference< XProcessingInstruction > const xNewPi( + xDocument->createProcessingInstruction( + xPi->getTarget(), xPi->getData())); + xNode.set(xNewPi, UNO_QUERY); break; } case NodeType_TEXT_NODE: { - Reference< XText > text(importedNode, UNO_QUERY); - Reference< XText > newText(createTextNode(text->getData())); - aNode.set(newText, UNO_QUERY); + Reference< XText > const xText(xImportedNode, UNO_QUERY_THROW); + Reference< XText > const xNewText( + xDocument->createTextNode(xText->getData())); + xNode.set(xNewText, UNO_QUERY); break; } case NodeType_ENTITY_NODE: @@ -567,48 +882,104 @@ namespace DOM if (deep) { // get children and import them - Reference< XNode > child = importedNode->getFirstChild(); - if (child.is()) + Reference< XNode > const xChild = xImportedNode->getFirstChild(); + if (xChild.is()) { - _import_siblings(child, aNode, this); + lcl_ImportSiblings(xDocument, xNode, xChild); } } /* DOMNodeInsertedIntoDocument - * Fired when a node is being inserted into a document, - * either through direct insertion of the Node or insertion of a - * subtree in which it is contained. This event is dispatched after - * the insertion has taken place. The target of this event is the node - * being inserted. If the Node is being directly inserted the DOMNodeInserted + * Fired when a node is being inserted into a document, + * either through direct insertion of the Node or insertion of a + * subtree in which it is contained. This event is dispatched after + * the insertion has taken place. The target of this event is the node + * being inserted. If the Node is being directly inserted the DOMNodeInserted * event will fire before the DOMNodeInsertedIntoDocument event. * Bubbles: No * Cancelable: No * Context Info: None */ - if (aNode.is()) + if (xNode.is()) { - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMNodeInsertedIntoDocument")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMNodeInsertedIntoDocument") + Reference< XDocumentEvent > const xDocevent(xDocument, UNO_QUERY); + Reference< XMutationEvent > const event(xDocevent->createEvent( + OUString::createFromAscii("DOMNodeInsertedIntoDocument")), + UNO_QUERY_THROW); + event->initMutationEvent( + OUString::createFromAscii("DOMNodeInsertedIntoDocument") , sal_True, sal_False, Reference< XNode >(), OUString(), OUString(), OUString(), (AttrChangeType)0 ); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + Reference< XEventTarget > const xDocET(xDocument, UNO_QUERY); + xDocET->dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); } - return aNode; + return xNode; } + + Reference< XNode > SAL_CALL CDocument::importNode( + Reference< XNode > const& xImportedNode, sal_Bool deep) + throw (RuntimeException, DOMException) + { + if (!xImportedNode.is()) { throw RuntimeException(); } + + // NB: this whole operation inherently accesses 2 distinct documents. + // The imported node could even be from a different DOM implementation, + // so this implementation cannot make any assumptions about the + // locking strategy of the imported node. + // So the import takes no lock on this document; + // it only calls UNO methods on this document that temporarily + // lock the document, and UNO methods on the imported node that + // may temporarily lock the other document. + // As a consequence, the import is not atomic with regard to + // concurrent modifications of either document, but it should not + // deadlock. + // To ensure that no members are accessed, the implementation is in + // static non-member functions. + + Reference< XDocument > const xDocument(this); + // already in doc? + if (xImportedNode->getOwnerDocument() == xDocument) { + return xImportedNode; + } + + Reference< XNode > const xNode( + lcl_ImportNode(xDocument, xImportedNode, deep) ); + return xNode; + } + + OUString SAL_CALL CDocument::getNodeName()throw (RuntimeException) { + // does not need mutex currently return OUString::createFromAscii("#document"); } + OUString SAL_CALL CDocument::getNodeValue() throw (RuntimeException) { + // does not need mutex currently return OUString(); } + Reference< XNode > SAL_CALL CDocument::cloneNode(sal_Bool bDeep) + throw (RuntimeException) + { + ::osl::MutexGuard const g(m_rMutex); + + OSL_ASSERT(0 != m_aNodePtr); + if (0 == m_aNodePtr) { + return 0; + } + xmlDocPtr const pClone(xmlCopyDoc(m_aDocPtr, (bDeep) ? 1 : 0)); + if (0 == pClone) { return 0; } + Reference< XNode > const xRet( + static_cast<CNode*>(CDocument::CreateCDocument(pClone).get())); + return xRet; + } + Reference< XEvent > SAL_CALL CDocument::createEvent(const OUString& aType) throw (RuntimeException) { + // does not need mutex currently events::CEvent *pEvent = 0; if ( aType.compareToAscii("DOMSubtreeModified") == 0|| @@ -650,8 +1021,10 @@ namespace DOM const Sequence< beans::StringPair >& i_rNamespaces) throw (RuntimeException, SAXException) { + ::osl::MutexGuard const g(m_Mutex); + // add new namespaces to root node - xmlNodePtr pRoot = _getDocumentRootPtr(m_aDocPtr); + xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr); if (0 != pRoot) { const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); for (const beans::StringPair *pNsDef = pSeq; @@ -665,20 +1038,22 @@ namespace DOM reinterpret_cast<const xmlChar*>(prefix.getStr())); } // eliminate duplicate namespace declarations - _nscleanup(pRoot->children, pRoot); + nscleanup(pRoot->children, pRoot); } saxify(i_xHandler); } // ::com::sun::star::xml::sax::XFastSAXSerializable - void SAL_CALL CDocument::fastSerialize( const Reference< XFastDocumentHandler >& i_xHandler, - const Reference< XFastTokenHandler >& i_xTokenHandler, + void SAL_CALL CDocument::fastSerialize( const Reference< XFastDocumentHandler >& i_xHandler, + const Reference< XFastTokenHandler >& i_xTokenHandler, const Sequence< beans::StringPair >& i_rNamespaces, - const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& i_rRegisterNamespaces ) + const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& i_rRegisterNamespaces ) throw (SAXException, RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // add new namespaces to root node - xmlNodePtr pRoot = _getDocumentRootPtr(m_aDocPtr); + xmlNodePtr const pRoot = lcl_getDocumentRootPtr(m_aDocPtr); if (0 != pRoot) { const beans::StringPair * pSeq = i_rNamespaces.getConstArray(); for (const beans::StringPair *pNsDef = pSeq; @@ -692,7 +1067,7 @@ namespace DOM reinterpret_cast<const xmlChar*>(prefix.getStr())); } // eliminate duplicate namespace declarations - _nscleanup(pRoot->children, pRoot); + nscleanup(pRoot->children, pRoot); } Context aContext(i_xHandler, @@ -701,7 +1076,7 @@ namespace DOM // register namespace ids const beans::Pair<OUString,sal_Int32>* pSeq = i_rRegisterNamespaces.getConstArray(); for (const beans::Pair<OUString,sal_Int32>* pNs = pSeq; - pNs < pSeq + i_rRegisterNamespaces.getLength(); ++pNs) + pNs < pSeq + i_rRegisterNamespaces.getLength(); ++pNs) { OSL_ENSURE(pNs->Second >= FastToken::NAMESPACE, "CDocument::fastSerialize(): invalid NS token id"); diff --git a/unoxml/source/dom/document.hxx b/unoxml/source/dom/document.hxx index 687381b3c..df8f27278 100644 --- a/unoxml/source/dom/document.hxx +++ b/unoxml/source/dom/document.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,15 +25,19 @@ * ************************************************************************/ -#ifndef _DOCUMENT_HXX -#define _DOCUMENT_HXX +#ifndef DOM_DOCUMENT_HXX +#define DOM_DOCUMENT_HXX -#include <list> #include <set> +#include <memory> + +#include <libxml/tree.h> + #include <sal/types.h> + #include <cppuhelper/implbase6.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/beans/StringPair.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XAttr.hpp> @@ -52,13 +56,11 @@ #include "node.hxx" -#include <libxml/tree.h> using namespace std; using ::rtl::OUString; using namespace com::sun::star; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::sax; using namespace com::sun::star::io; using namespace com::sun::star::xml::dom; @@ -66,32 +68,70 @@ using namespace com::sun::star::xml::dom::events; namespace DOM { + namespace events { + class CEventDispatcher; + } + + class CElement; - class CDocument : public cppu::ImplInheritanceHelper6< - CNode, XDocument, XDocumentEvent, - XActiveDataControl, XActiveDataSource, XSAXSerializable, XFastSAXSerializable> + typedef ::cppu::ImplInheritanceHelper6< + CNode, XDocument, XDocumentEvent, + XActiveDataControl, XActiveDataSource, + XSAXSerializable, XFastSAXSerializable> + CDocument_Base; + + class CDocument + : public CDocument_Base { - friend class CNode; - typedef set< Reference< XStreamListener > > listenerlist_t; - private: - xmlDocPtr m_aDocPtr; + private: + /// this Mutex is used for synchronization of all UNO wrapper + /// objects that belong to this document + ::osl::Mutex m_Mutex; + /// the libxml document: freed in destructor + /// => all UNO wrapper objects must keep the CDocument alive + xmlDocPtr const m_aDocPtr; // datacontrol/source state + typedef set< Reference< XStreamListener > > listenerlist_t; listenerlist_t m_streamListeners; Reference< XOutputStream > m_rOutputStream; - protected: - CDocument(xmlDocPtr aDocPtr); + typedef std::map< const xmlNodePtr, + ::std::pair< WeakReference<XNode>, CNode* > > nodemap_t; + nodemap_t m_NodeMap; + + ::std::auto_ptr<events::CEventDispatcher> const m_pEventDispatcher; + + CDocument(xmlDocPtr const pDocPtr); + public: + /// factory: only way to create instance! + static ::rtl::Reference<CDocument> + CreateCDocument(xmlDocPtr const pDoc); virtual ~CDocument(); - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + // needed by CXPathAPI + ::osl::Mutex & GetMutex() { return m_Mutex; } + + events::CEventDispatcher & GetEventDispatcher(); + ::rtl::Reference< CElement > GetDocumentElement(); + + /// get UNO wrapper instance for a libxml node + ::rtl::Reference<CNode> GetCNode( + xmlNodePtr const pNode, bool const bCreate = true); + /// remove a UNO wrapper instance + void RemoveCNode(xmlNodePtr const pNode, CNode const*const pCNode); + + virtual CDocument & GetOwnerDocument(); - virtual void SAL_CALL fastSaxify( Context& rContext ); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual void fastSaxify( Context& rContext ); + + virtual bool IsChildTypeAllowed(NodeType const nodeType); /** Creates an Attr of the given name. @@ -142,7 +182,7 @@ namespace DOM throw (RuntimeException, DOMException); /** - Creates a ProcessingInstruction node given the specified name and + Creates a ProcessingInstruction node given the specified name and data strings. */ virtual Reference< XProcessingInstruction > SAL_CALL createProcessingInstruction( @@ -176,7 +216,7 @@ namespace DOM throw (RuntimeException); /** - Returns a NodeList of all the Elements with a given tag name in the + Returns a NodeList of all the Elements with a given tag name in the order in which they are encountered in a preorder traversal of the Document tree. */ @@ -184,8 +224,8 @@ namespace DOM throw (RuntimeException); /** - Returns a NodeList of all the Elements with a given local name and - namespace URI in the order in which they are encountered in a preorder + Returns a NodeList of all the Elements with a given local name and + namespace URI in the order in which they are encountered in a preorder traversal of the Document tree. */ virtual Reference< XNodeList > SAL_CALL getElementsByTagNameNS(const OUString& namespaceURI, const OUString& localName) @@ -206,7 +246,7 @@ namespace DOM // XDocumentEvent virtual Reference< XEvent > SAL_CALL createEvent(const OUString& eventType) throw (RuntimeException); - // XActiveDataControl, + // XActiveDataControl, // see http://api.openoffice.org/docs/common/ref/com/sun/star/io/XActiveDataControl.html virtual void SAL_CALL addListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException); virtual void SAL_CALL removeListener(const Reference< XStreamListener >& aListener ) throw (RuntimeException); @@ -224,17 +264,14 @@ namespace DOM throw (RuntimeException); virtual OUString SAL_CALL getNodeValue() throw (RuntimeException); + virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) + throw (RuntimeException); // --- delegation for XNde base. virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) throw (RuntimeException, DOMException) { return CNode::appendChild(newChild); } - virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) - throw (RuntimeException) - { - return CNode::cloneNode(deep); - } virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() throw (RuntimeException) { @@ -307,7 +344,7 @@ namespace DOM } virtual Reference< XNode > SAL_CALL insertBefore( const Reference< XNode >& newChild, const Reference< XNode >& refChild) - throw (DOMException) + throw (RuntimeException, DOMException) { return CNode::insertBefore(newChild, refChild); } @@ -348,12 +385,12 @@ namespace DOM const Reference< XDocumentHandler >& i_xHandler, const Sequence< beans::StringPair >& i_rNamespaces) throw (RuntimeException, SAXException); - - // ::com::sun::star::xml::sax::XFastSAXSerializable - virtual void SAL_CALL fastSerialize( const Reference< XFastDocumentHandler >& handler, - const Reference< XFastTokenHandler >& tokenHandler, + + // ::com::sun::star::xml::sax::XFastSAXSerializable + virtual void SAL_CALL fastSerialize( const Reference< XFastDocumentHandler >& handler, + const Reference< XFastTokenHandler >& tokenHandler, const Sequence< beans::StringPair >& i_rNamespaces, - const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& namespaces ) + const Sequence< beans::Pair< rtl::OUString, sal_Int32 > >& namespaces ) throw (SAXException, RuntimeException); }; } diff --git a/unoxml/source/dom/documentbuilder.cxx b/unoxml/source/dom/documentbuilder.cxx index 07e37a747..695ccb670 100644 --- a/unoxml/source/dom/documentbuilder.cxx +++ b/unoxml/source/dom/documentbuilder.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,9 +25,16 @@ * ************************************************************************/ -#include "documentbuilder.hxx" -#include "node.hxx" -#include "document.hxx" +#include <documentbuilder.hxx> + +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +#include <libxml/xmlerror.h> +#include <libxml/tree.h> + +#include <boost/shared_ptr.hpp> #include <rtl/alloc.h> #include <rtl/memory.h> @@ -35,17 +42,15 @@ #include <cppuhelper/implbase1.hxx> -#include <libxml/xmlerror.h> - #include <com/sun/star/xml/sax/SAXParseException.hpp> #include <com/sun/star/ucb/XCommandEnvironment.hpp> #include <com/sun/star/task/XInteractionHandler.hpp> + #include <ucbhelper/content.hxx> #include <ucbhelper/commandenvironment.hxx> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> +#include <node.hxx> +#include <document.hxx> using ::rtl::OUStringBuffer; @@ -58,26 +63,11 @@ using ::com::sun::star::task::XInteractionHandler; namespace DOM { - extern "C" { - //char *strdup(const char *s); - /* - static char* strdupfunc(const char* s) - { - sal_Int32 len = 0; - while (s[len] != '\0') len++; - char *newStr = (char*)rtl_allocateMemory(len+1); - if (newStr != NULL) - rtl_copyMemory(newStr, s, len+1); - return newStr; - } - */ - } - class CDefaultEntityResolver : public cppu::WeakImplHelper1< XEntityResolver > { public: - virtual InputSource SAL_CALL resolveEntity( const OUString& sPublicId, const OUString& sSystemId ) + virtual InputSource SAL_CALL resolveEntity( const OUString& sPublicId, const OUString& sSystemId ) throw (::com::sun::star::uno::RuntimeException) { InputSource is; @@ -87,7 +77,7 @@ namespace DOM try { Reference< XCommandEnvironment > aEnvironment( - new CommandEnvironment(Reference< XInteractionHandler >(), + new CommandEnvironment(Reference< XInteractionHandler >(), Reference< XProgressHandler >() )); Content aContent(sSystemId, aEnvironment); @@ -101,9 +91,10 @@ namespace DOM }; - CDocumentBuilder::CDocumentBuilder(const Reference< XMultiServiceFactory >& xFactory) - : m_aFactory(xFactory) - , m_aEntityResolver(Reference< XEntityResolver > (new CDefaultEntityResolver())) + CDocumentBuilder::CDocumentBuilder( + Reference< XMultiServiceFactory > const& xFactory) + : m_xFactory(xFactory) + , m_xEntityResolver(new CDefaultEntityResolver()) { // init libxml. libxml will protect itself against multiple // initializations so there is no problem here if this gets @@ -113,7 +104,6 @@ namespace DOM Reference< XInterface > CDocumentBuilder::_getInstance(const Reference< XMultiServiceFactory >& rSMgr) { - // XXX return static_cast< XDocumentBuilder* >(new CDocumentBuilder(rSMgr)); } @@ -182,14 +172,18 @@ namespace DOM Reference< XDocument > SAL_CALL CDocumentBuilder::newDocument() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // create a new document xmlDocPtr pDocument = xmlNewDoc((const xmlChar*)"1.0"); - return Reference< XDocument >(static_cast< CDocument* >(CNode::get((xmlNodePtr)pDocument))); + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDocument).get()); + return xRet; } static OUString make_error_message(xmlParserCtxtPtr ctxt) { - OUStringBuffer buf; + OUStringBuffer buf; buf.appendAscii(ctxt->lastError.message); buf.appendAscii("Line: "); buf.append(static_cast<sal_Int32>(ctxt->lastError.line)); @@ -214,25 +208,25 @@ namespace DOM static int xmlIO_read_func( void *context, char *buffer, int len) { // get the context... - context_t *pctx = static_cast<context_t*>(context); + context_t *pctx = static_cast<context_t*>(context); if (!pctx->rInputStream.is()) return -1; try { // try to read the requested number of bytes Sequence< sal_Int8 > chunk(len); - int nread = pctx->rInputStream->readBytes(chunk, len); + int nread = pctx->rInputStream->readBytes(chunk, len); // copy bytes to the provided buffer - rtl_copyMemory(buffer, chunk.getConstArray(), nread); + rtl_copyMemory(buffer, chunk.getConstArray(), nread); return nread; } catch (com::sun::star::uno::Exception& ex) { (void) ex; OSL_ENSURE(sal_False, OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr()); return -1; - } + } } - static int xmlIO_close_func(void* context) + static int xmlIO_close_func(void* context) { // get the context... context_t *pctx = static_cast<context_t*>(context); @@ -250,7 +244,7 @@ namespace DOM OSL_ENSURE(sal_False, OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr()); return -1; } - } + } static xmlParserInputPtr resolve_func(void *ctx, const xmlChar *publicId, @@ -287,11 +281,13 @@ namespace DOM return pInput; } +#if 0 static xmlParserInputPtr external_entity_loader(const char *URL, const char * /*ID*/, xmlParserCtxtPtr ctxt) { // just call our resolver function using the URL as systemId return resolve_func(ctxt, 0, (const xmlChar*)URL); } +#endif // default warning handler triggers assertion static void warning_func(void * ctx, const char * /*msg*/, ...) @@ -304,7 +300,7 @@ namespace DOM // default error handler triggers assertion static void error_func(void * ctx, const char * /*msg*/, ...) - { + { OUStringBuffer buf(OUString::createFromAscii("libxml2 error\n")); buf.append(make_error_message(static_cast< xmlParserCtxtPtr >(ctx))); OString msg = OUStringToOString(buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US); @@ -315,7 +311,6 @@ namespace DOM void throwEx(xmlParserCtxtPtr ctxt) { OUString msg = make_error_message(ctxt); - xmlFreeParserCtxt(ctxt); com::sun::star::xml::sax::SAXParseException saxex; saxex.Message = msg; saxex.LineNumber = static_cast<sal_Int32>(ctxt->lastError.line); @@ -326,6 +321,11 @@ namespace DOM Reference< XDocument > SAL_CALL CDocumentBuilder::parse(const Reference< XInputStream >& is) throw (RuntimeException, SAXParseException, IOException) { + if (!is.is()) { + throw RuntimeException(); + } + + ::osl::MutexGuard const g(m_Mutex); // encoding... /* @@ -333,14 +333,15 @@ namespace DOM xmlCharEncoding enc = xmlParseCharEncoding(encstr); */ - xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); + ::boost::shared_ptr<xmlParserCtxt> const pContext( + xmlNewParserCtxt(), xmlFreeParserCtxt); // register error functions to prevent errors being printed // on the console - ctxt->_private = this; - ctxt->sax->error = error_func; - ctxt->sax->warning = warning_func; - ctxt->sax->resolveEntity = resolve_func; + pContext->_private = this; + pContext->sax->error = error_func; + pContext->sax->warning = warning_func; + pContext->sax->resolveEntity = resolve_func; // IO context struct context_t c; @@ -349,81 +350,63 @@ namespace DOM // we did not open the stream, thus we do not close it. c.close = false; c.freeOnClose = false; - xmlDocPtr pDoc = xmlCtxtReadIO(ctxt, xmlIO_read_func, xmlIO_close_func, &c, - 0, 0, 0); + xmlDocPtr const pDoc = xmlCtxtReadIO(pContext.get(), + xmlIO_read_func, xmlIO_close_func, &c, 0, 0, 0); if (pDoc == 0) { - throwEx(ctxt); - } - xmlFreeParserCtxt(ctxt); - return Reference< XDocument >(static_cast< CDocument* >(CNode::get((xmlNodePtr)pDoc))); - } - - Reference< XDocument > SAL_CALL CDocumentBuilder::parseSource(const InputSource& is) - throw (RuntimeException, SAXParseException, IOException) - { - // if there is an encoding specified in the input source, use it - xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; - if (is.sEncoding.getLength() > 0) { - OString oEncstr = OUStringToOString(is.sEncoding, RTL_TEXTENCODING_UTF8); - char *encstr = (char*) oEncstr.getStr(); - enc = xmlParseCharEncoding(encstr); + throwEx(pContext.get()); } - - // set up parser context - xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); - // register error functions to prevent errors being printed - // on the console - ctxt->_private = this; - ctxt->sax->error = error_func; - ctxt->sax->warning = warning_func; - - // setup entity resolver binding(s) - ctxt->sax->resolveEntity = resolve_func; - xmlSetExternalEntityLoader(external_entity_loader); - - // if an input stream is provided, use it - - // use the systemID - - return Reference< XDocument >(); + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDoc).get()); + return xRet; } Reference< XDocument > SAL_CALL CDocumentBuilder::parseURI(const OUString& sUri) throw (RuntimeException, SAXParseException, IOException) { - xmlParserCtxtPtr ctxt = xmlNewParserCtxt(); - ctxt->_private = this; - ctxt->sax->error = error_func; - ctxt->sax->warning = warning_func; - ctxt->sax->resolveEntity = resolve_func; + ::osl::MutexGuard const g(m_Mutex); + + ::boost::shared_ptr<xmlParserCtxt> const pContext( + xmlNewParserCtxt(), xmlFreeParserCtxt); + pContext->_private = this; + pContext->sax->error = error_func; + pContext->sax->warning = warning_func; + pContext->sax->resolveEntity = resolve_func; // xmlSetExternalEntityLoader(external_entity_loader); OString oUri = OUStringToOString(sUri, RTL_TEXTENCODING_UTF8); char *uri = (char*) oUri.getStr(); - xmlDocPtr pDoc = xmlCtxtReadFile(ctxt, uri, 0, 0); + xmlDocPtr pDoc = xmlCtxtReadFile(pContext.get(), uri, 0, 0); if (pDoc == 0) { - throwEx(ctxt); + throwEx(pContext.get()); } - xmlFreeParserCtxt(ctxt); - return Reference< XDocument >(static_cast< CDocument* >(CNode::get((xmlNodePtr)pDoc))); + Reference< XDocument > const xRet( + CDocument::CreateCDocument(pDoc).get()); + return xRet; } - void SAL_CALL CDocumentBuilder::setEntityResolver(const Reference< XEntityResolver >& er) + void SAL_CALL + CDocumentBuilder::setEntityResolver(Reference< XEntityResolver > const& xER) throw (RuntimeException) { - m_aEntityResolver = er; + ::osl::MutexGuard const g(m_Mutex); + + m_xEntityResolver = xER; } Reference< XEntityResolver > SAL_CALL CDocumentBuilder::getEntityResolver() throw (RuntimeException) { - return m_aEntityResolver; - } + ::osl::MutexGuard const g(m_Mutex); + return m_xEntityResolver; + } - void SAL_CALL CDocumentBuilder::setErrorHandler(const Reference< XErrorHandler >& eh) + void SAL_CALL + CDocumentBuilder::setErrorHandler(Reference< XErrorHandler > const& xEH) throw (RuntimeException) { - m_aErrorHandler = eh; + ::osl::MutexGuard const g(m_Mutex); + + m_xErrorHandler = xEH; } } diff --git a/unoxml/source/dom/documentbuilder.hxx b/unoxml/source/dom/documentbuilder.hxx index 2cfe4b0f5..ea1bfcc60 100644 --- a/unoxml/source/dom/documentbuilder.hxx +++ b/unoxml/source/dom/documentbuilder.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,16 +25,17 @@ * ************************************************************************/ -#ifndef _DOCUMENTBUILDER_HXX -#define _DOCUMENTBUILDER_HXX +#ifndef DOM_DOCUMENTBUILDER_HXX +#define DOM_DOCUMENTBUILDER_HXX #include <sal/types.h> + #include <cppuhelper/implbase2.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> #include <com/sun/star/uno/XInterface.hpp> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocumentBuilder.hpp> #include <com/sun/star/xml/dom/XDocument.hpp> #include <com/sun/star/xml/dom/XDOMImplementation.hpp> @@ -44,10 +45,8 @@ #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> -#include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include "libxml/tree.h" using ::rtl::OUString; using namespace com::sun::star::uno; @@ -58,28 +57,41 @@ using namespace com::sun::star::io; namespace DOM { - class CDocumentBuilder - : public ::cppu::WeakImplHelper2< XDocumentBuilder, XServiceInfo > + typedef ::cppu::WeakImplHelper2 + < XDocumentBuilder + , ::com::sun::star::lang::XServiceInfo + > CDocumentBuilder_Base; + + class CDocumentBuilder + : public CDocumentBuilder_Base { private: - Reference< XMultiServiceFactory > m_aFactory; - Reference< XEntityResolver > m_aEntityResolver; - Reference< XErrorHandler > m_aErrorHandler; + ::osl::Mutex m_Mutex; + Reference< ::com::sun::star::lang::XMultiServiceFactory > const + m_xFactory; + Reference< XEntityResolver > m_xEntityResolver; + Reference< XErrorHandler > m_xErrorHandler; public: // ctor - CDocumentBuilder(const Reference< XMultiServiceFactory >& xFactory); + CDocumentBuilder( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + xFactory); // call for factory - static Reference< XInterface > getInstance(const Reference < XMultiServiceFactory >& xFactory); + static Reference< XInterface > getInstance( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + xFactory); // static helpers for service info and component management static const char* aImplementationName; static const char* aSupportedServiceNames[]; static OUString _getImplementationName(); static Sequence< OUString > _getSupportedServiceNames(); - static Reference< XInterface > _getInstance(const Reference< XMultiServiceFactory >& rSMgr); + static Reference< XInterface > _getInstance( + Reference< ::com::sun::star::lang::XMultiServiceFactory > const& + rSMgr); // XServiceInfo virtual OUString SAL_CALL getImplementationName() @@ -96,44 +108,40 @@ namespace DOM throw (RuntimeException); /** - Indicates whether or not this parser is configured to understand - namespaces. + Indicates whether or not this parser is configured to understand + namespaces. */ virtual sal_Bool SAL_CALL isNamespaceAware() throw (RuntimeException); - /** - Indicates whether or not this parser is configured to validate XML + /** + Indicates whether or not this parser is configured to validate XML documents. */ virtual sal_Bool SAL_CALL isValidating() throw (RuntimeException); /** - Obtain a new instance of a DOM Document object to build a DOM tree - with. + Obtain a new instance of a DOM Document object to build a DOM tree + with. */ virtual Reference< XDocument > SAL_CALL newDocument() throw (RuntimeException); /** - Parse the content of the given InputStream as an XML document and - return a new DOM Document object. + Parse the content of the given InputStream as an XML document and + return a new DOM Document object. */ virtual Reference< XDocument > SAL_CALL parse(const Reference< XInputStream >& is) throw (RuntimeException, SAXParseException, IOException); /** - Parse the content of the given URI as an XML document and return + Parse the content of the given URI as an XML document and return a new DOM Document object. */ virtual Reference< XDocument > SAL_CALL parseURI(const OUString& uri) throw (RuntimeException, SAXParseException, IOException); - virtual Reference< XDocument > SAL_CALL parseSource(const InputSource& is) - throw (RuntimeException, SAXParseException, IOException); - - /** Specify the EntityResolver to be used to resolve entities present in the XML document to be parsed. diff --git a/unoxml/source/dom/documentfragment.cxx b/unoxml/source/dom/documentfragment.cxx index 2d4418dac..683938e7f 100644 --- a/unoxml/source/dom/documentfragment.cxx +++ b/unoxml/source/dom/documentfragment.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,15 +25,33 @@ * ************************************************************************/ -#include "documentfragment.hxx" +#include <documentfragment.hxx> namespace DOM { - CDocumentFragment::CDocumentFragment(const xmlNodePtr aNodePtr) + CDocumentFragment::CDocumentFragment( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CDocumentFragment_Base(rDocument, rMutex, + NodeType_DOCUMENT_FRAGMENT_NODE, pNode) { - m_aNodeType = NodeType_DOCUMENT_FRAGMENT_NODE; - init_node(aNodePtr); } + + bool CDocumentFragment::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } + } + OUString SAL_CALL CDocumentFragment::getNodeName()throw (RuntimeException) { return OUString::createFromAscii("#document-fragment"); diff --git a/unoxml/source/dom/documentfragment.hxx b/unoxml/source/dom/documentfragment.hxx index 4df341b25..6236d5ca4 100644 --- a/unoxml/source/dom/documentfragment.hxx +++ b/unoxml/source/dom/documentfragment.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,14 +25,14 @@ * ************************************************************************/ -#ifndef _DOCUMENTFRAGMENT_HXX -#define _DOCUMENTFRAGMENT_HXX +#ifndef DOM_DOCUMENTFRAGMENT_HXX +#define DOM_DOCUMENTFRAGMENT_HXX #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocumentFragment.hpp> -#include "node.hxx" +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,13 +40,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CDocumentFragment : public cppu::ImplInheritanceHelper1< CNode, XDocumentFragment > + typedef ::cppu::ImplInheritanceHelper1< CNode, XDocumentFragment > + CDocumentFragment_Base; + + class CDocumentFragment + : public CDocumentFragment_Base { - friend class CNode; + private: + friend class CDocument; + protected: - CDocumentFragment(const xmlNodePtr aNodePtr); + CDocumentFragment( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); + // ---- resolve uno inheritance problems... // overrides for XNode base virtual OUString SAL_CALL getNodeName() diff --git a/unoxml/source/dom/documenttype.cxx b/unoxml/source/dom/documenttype.cxx index 52c515796..f105e804e 100644 --- a/unoxml/source/dom/documenttype.cxx +++ b/unoxml/source/dom/documenttype.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,32 +25,38 @@ * ************************************************************************/ -#include "documenttype.hxx" -#include "entitiesmap.hxx" -#include "notationsmap.hxx" +#include <documenttype.hxx> #include <string.h> +#include <entitiesmap.hxx> +#include <notationsmap.hxx> + + namespace DOM { - CDocumentType::CDocumentType(const xmlDtdPtr aDtdPtr) + CDocumentType::CDocumentType( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlDtdPtr const pDtd) + : CDocumentType_Base(rDocument, rMutex, + NodeType_DOCUMENT_TYPE_NODE, reinterpret_cast<xmlNodePtr>(pDtd)) + , m_aDtdPtr(pDtd) { - m_aNodeType = NodeType_DOCUMENT_TYPE_NODE; - m_aDtdPtr = aDtdPtr; - init_node((xmlNodePtr)aDtdPtr); } /** - A NamedNodeMap containing the general entities, both external and + A NamedNodeMap containing the general entities, both external and internal, declared in the DTD. */ Reference< XNamedNodeMap > SAL_CALL CDocumentType::getEntities() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNamedNodeMap > aMap; if (m_aDtdPtr != NULL) { - aMap = Reference< XNamedNodeMap >(new CEntitiesMap(this)); + aMap.set(new CEntitiesMap(this, m_rMutex)); } return aMap; } @@ -60,16 +66,19 @@ namespace DOM */ OUString SAL_CALL CDocumentType::getInternalSubset() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CDocumentType::getInternalSubset: not implemented (#i113683#)"); return OUString(); } /** - The name of DTD; i.e., the name immediately following the DOCTYPE + The name of DTD; i.e., the name immediately following the DOCTYPE keyword. */ OUString SAL_CALL CDocumentType::getName() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aDtdPtr != NULL) { @@ -83,10 +92,12 @@ namespace DOM */ Reference< XNamedNodeMap > SAL_CALL CDocumentType::getNotations() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + Reference< XNamedNodeMap > aMap; if (m_aDtdPtr != NULL) { - aMap.set(new CNotationsMap(this)); + aMap.set(new CNotationsMap(this, m_rMutex)); } return aMap; } @@ -96,6 +107,8 @@ namespace DOM */ OUString SAL_CALL CDocumentType::getPublicId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aId; if (m_aDtdPtr != NULL) { @@ -109,6 +122,8 @@ namespace DOM */ OUString SAL_CALL CDocumentType::getSystemId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aId; if (m_aDtdPtr != NULL) { @@ -116,10 +131,12 @@ namespace DOM } return aId; } + OUString SAL_CALL CDocumentType::getNodeName()throw (RuntimeException) { return getName(); } + OUString SAL_CALL CDocumentType::getNodeValue() throw (RuntimeException) { return OUString(); diff --git a/unoxml/source/dom/documenttype.hxx b/unoxml/source/dom/documenttype.hxx index 6c79013a2..ca276bb38 100644 --- a/unoxml/source/dom/documenttype.hxx +++ b/unoxml/source/dom/documenttype.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,19 +25,20 @@ * ************************************************************************/ -#ifndef _DOCUMENTTYPE_HXX -#define _DOCUMENTTYPE_HXX +#ifndef DOM_DOCUMENTTYPE_HXX +#define DOM_DOCUMENTTYPE_HXX + +#include <libxml/tree.h> #include <sal/types.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocumentType.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "node.hxx" +#include <node.hxx> -#include <libxml/tree.h> using ::rtl::OUString; using namespace com::sun::star::uno; @@ -45,18 +46,25 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CDocumentType : public cppu::ImplInheritanceHelper1< CNode, XDocumentType > + typedef ::cppu::ImplInheritanceHelper1< CNode, XDocumentType > + CDocumentType_Base; + + class CDocumentType + : public CDocumentType_Base { - friend class CNode; + private: + friend class CDocument; + private: xmlDtdPtr m_aDtdPtr; protected: - CDocumentType(const xmlDtdPtr aDtdPtr); + CDocumentType(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlDtdPtr const pDtd); public: /** - A NamedNodeMap containing the general entities, both external and + A NamedNodeMap containing the general entities, both external and internal, declared in the DTD. */ virtual Reference< XNamedNodeMap > SAL_CALL getEntities() throw (RuntimeException); @@ -67,7 +75,7 @@ namespace DOM virtual OUString SAL_CALL getInternalSubset() throw (RuntimeException); /** - The name of DTD; i.e., the name immediately following the DOCTYPE + The name of DTD; i.e., the name immediately following the DOCTYPE keyword. */ virtual OUString SAL_CALL getName() throw (RuntimeException); diff --git a/unoxml/source/dom/domimplementation.cxx b/unoxml/source/dom/domimplementation.cxx index e9986af24..6f4cc692c 100644 --- a/unoxml/source/dom/domimplementation.cxx +++ b/unoxml/source/dom/domimplementation.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,28 +25,41 @@ * ************************************************************************/ -#include "domimplementation.hxx" +#include <domimplementation.hxx> + +#include <rtl/instance.hxx> + namespace DOM { - CDOMImplementation* CDOMImplementation::aDOMImplementation = new CDOMImplementation(); + // why the heck is this thing static? + // perhaps it would be helpful to know what the implementation should + // do to answer this question... + namespace { + struct DOMImplementation + : public ::rtl::Static<CDOMImplementation, DOMImplementation> {}; + } + CDOMImplementation* CDOMImplementation::get() { - return CDOMImplementation::aDOMImplementation; + return & DOMImplementation::get(); } + // there is just 1 static instance, so these must not delete it! + void SAL_CALL CDOMImplementation::acquire() throw () { } + void SAL_CALL CDOMImplementation::release() throw () { } + /** Creates a DOM Document object of the specified type with its document element. */ Reference <XDocument > SAL_CALL CDOMImplementation::createDocument( - const OUString& namespaceURI, - const OUString& qualifiedName, - const Reference< XDocumentType >& doctype) + OUString const& /*rNamespaceURI*/, + OUString const& /*rQualifiedName*/, + Reference< XDocumentType > const& /*xDoctype*/) throw (RuntimeException) { - OUString aNamespaceURI = namespaceURI; - OUString aQName = qualifiedName; - Reference< XDocumentType > aType = doctype; + OSL_ENSURE(false, + "CDOMImplementation::createDocument: not implemented (#i113683#)"); return Reference<XDocument>(); } @@ -54,22 +67,24 @@ namespace DOM Creates an empty DocumentType node. */ Reference< XDocumentType > SAL_CALL CDOMImplementation::createDocumentType( - const OUString& qualifiedName, const OUString& publicId, const OUString& systemId) + OUString const& /*rQualifiedName*/, + OUString const& /*rPublicId*/, OUString const& /*rSystemId*/) throw (RuntimeException) { - OUString qName = qualifiedName; - OUString aPublicId = publicId; - OUString aSystemId = systemId; + OSL_ENSURE(false, "CDOMImplementation::createDocumentType: " + "not implemented (#i113683#)"); return Reference<XDocumentType>(); } + /** Test if the DOM implementation implements a specific feature. */ - sal_Bool SAL_CALL CDOMImplementation::hasFeature(const OUString& feature, const OUString& ver) + sal_Bool SAL_CALL + CDOMImplementation::hasFeature(OUString const& /*feature*/, OUString const& /*ver*/) throw (RuntimeException) { - OUString aFeature = feature; - OUString aVersion = ver; + OSL_ENSURE(false, + "CDOMImplementation::hasFeature: not implemented (#i113683#)"); return sal_False; } } diff --git a/unoxml/source/dom/domimplementation.hxx b/unoxml/source/dom/domimplementation.hxx index 4609aff26..53895287e 100644 --- a/unoxml/source/dom/domimplementation.hxx +++ b/unoxml/source/dom/domimplementation.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,18 +25,18 @@ * ************************************************************************/ -#ifndef _DOMIMPLEMENTATION_HXX -#define _DOMIMPLEMENTATION_HXX +#ifndef DOM_DOMIMPLEMENTATION_HXX +#define DOM_DOMIMPLEMENTATION_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XDocument.hpp> #include <com/sun/star/xml/dom/XDocumentType.hpp> #include <com/sun/star/xml/dom/XDOMImplementation.hpp> -#include <com/sun/star/xml/dom/XDOMImplementation.hpp> + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -44,13 +44,17 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CDOMImplementation : public cppu::WeakImplHelper1< XDOMImplementation > + class CDOMImplementation + : public cppu::WeakImplHelper1< XDOMImplementation > { public: - static CDOMImplementation* aDOMImplementation; static CDOMImplementation* get(); + // there is just 1 static instance, so these must not delete it! + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + /** Creates a DOM Document object of the specified type with its document element. */ diff --git a/unoxml/source/dom/element.cxx b/unoxml/source/dom/element.cxx index 46218e8eb..c034ca125 100644 --- a/unoxml/source/dom/element.cxx +++ b/unoxml/source/dom/element.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,30 +25,38 @@ * ************************************************************************/ -#include "node.hxx" -#include "element.hxx" -#include "attr.hxx" -#include "elementlist.hxx" -#include "attributesmap.hxx" -#include "../events/mutationevent.hxx" +#include <element.hxx> + +#include <string.h> + +#include <boost/shared_ptr.hpp> + +#include <rtl/ustrbuf.hxx> -#include "comphelper/attributelist.hxx" #include <com/sun/star/xml/sax/FastToken.hdl> -#include <string.h> +#include <comphelper/attributelist.hxx> + +#include <node.hxx> +#include <attr.hxx> +#include <elementlist.hxx> +#include <attributesmap.hxx> +#include <document.hxx> + +#include "../events/mutationevent.hxx" namespace DOM { - CElement::CElement(const xmlNodePtr aNodePtr) + CElement::CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CElement_Base(rDocument, rMutex, NodeType_ELEMENT_NODE, pNode) { - m_aNodeType = NodeType_ELEMENT_NODE; - init_node(aNodePtr); } - void SAL_CALL CElement::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + void CElement::saxify(const Reference< XDocumentHandler >& i_xHandler) + { if (!i_xHandler.is()) throw RuntimeException(); comphelper::AttributeList *pAttrs = new comphelper::AttributeList(); @@ -71,7 +79,8 @@ namespace DOM // add attributes for (xmlAttrPtr pAttr = m_aNodePtr->properties; pAttr != 0; pAttr = pAttr->next) { - CNode * pNode = CNode::get(reinterpret_cast<xmlNodePtr>(pAttr)); + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); OUString prefix = pNode->getPrefix(); OUString name = (prefix.getLength() == 0) @@ -89,14 +98,16 @@ namespace DOM // recurse for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode( + GetOwnerDocument().GetCNode(pChild)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->saxify(i_xHandler); } i_xHandler->endElement(name); } - void SAL_CALL CElement::fastSaxify( Context& i_rContext ) { + void CElement::fastSaxify( Context& i_rContext ) + { if (!i_rContext.mxDocHandler.is()) throw RuntimeException(); pushContext(i_rContext); addNamespaces(i_rContext,m_aNodePtr); @@ -105,21 +116,22 @@ namespace DOM i_rContext.mxAttribList->clear(); for (xmlAttrPtr pAttr = m_aNodePtr->properties; pAttr != 0; pAttr = pAttr->next) { - CNode * pNode = CNode::get(reinterpret_cast<xmlNodePtr>(pAttr)); + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); const xmlChar* xName = pAttr->name; sal_Int32 nAttributeToken=FastToken::DONTKNOW; if( pAttr->ns && strlen((char*)pAttr->ns->prefix) ) - nAttributeToken = getTokenWithPrefix( i_rContext, - (sal_Char*)pAttr->ns->prefix, + nAttributeToken = getTokenWithPrefix( i_rContext, + (sal_Char*)pAttr->ns->prefix, (sal_Char*)xName ); else nAttributeToken = getToken( i_rContext, (sal_Char*)xName ); if( nAttributeToken != FastToken::DONTKNOW ) - i_rContext.mxAttribList->add( nAttributeToken, + i_rContext.mxAttribList->add( nAttributeToken, OUStringToOString(pNode->getNodeValue(), RTL_TEXTENCODING_UTF8)); } @@ -139,8 +151,8 @@ namespace DOM if( nElementToken == FastToken::DONTKNOW ) { const OUString aNamespace; - const OUString aElementName( (sal_Char*)xPrefix, - strlen((char*)xPrefix), + const OUString aElementName( (sal_Char*)xPrefix, + strlen((char*)xPrefix), RTL_TEXTENCODING_UTF8 ); if( xParentHandler.is() ) @@ -168,7 +180,8 @@ namespace DOM // recurse for (xmlNodePtr pChild = m_aNodePtr->children; pChild != 0; pChild = pChild->next) { - CNode * pNode = CNode::get(pChild); + ::rtl::Reference<CNode> const pNode( + GetOwnerDocument().GetCNode(pChild)); OSL_ENSURE(pNode != 0, "CNode::get returned 0"); pNode->fastSaxify(i_rContext); } @@ -180,8 +193,8 @@ namespace DOM else { const OUString aNamespace; - const OUString aElementName( (sal_Char*)xPrefix, - strlen((char*)xPrefix), + const OUString aElementName( (sal_Char*)xPrefix, + strlen((char*)xPrefix), RTL_TEXTENCODING_UTF8 ); i_rContext.mxCurrentHandler->endUnknownElement( aNamespace, aElementName ); @@ -195,124 +208,184 @@ namespace DOM popContext(i_rContext); } + bool CElement::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_COMMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + case NodeType_ATTRIBUTE_NODE: + /* this is not relly allowed by the DOM spec, but this + implementation has evidently supported it (by special case + handling, so the attribute does not actually become a child) + so allow it for backward compatiblity */ + return true; + default: + return false; + } + } + + /** Retrieves an attribute value by name. return empty string if attribute is not set */ - OUString CElement::getAttribute(const OUString& name) + OUString SAL_CALL CElement::getAttribute(OUString const& name) throw (RuntimeException) { - OUString aValue; - // search properties - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); - xmlChar *xValue = xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()); - if (xValue != NULL) { - aValue = OUString((sal_Char*)xValue, strlen((char*)xValue), RTL_TEXTENCODING_UTF8); - } + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); } - return aValue; + // search properties + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + ::boost::shared_ptr<xmlChar const> const pValue( + xmlGetProp(m_aNodePtr, (xmlChar*)o1.getStr()), xmlFree); + OUString const ret( (pValue) + ? OUString(reinterpret_cast<sal_Char const*>(pValue.get()), + strlen(reinterpret_cast<char const*>(pValue.get())), + RTL_TEXTENCODING_UTF8) + : OUString() ); + return ret; } /** Retrieves an attribute node by name. */ - Reference< XAttr > CElement::getAttributeNode(const OUString& name) + Reference< XAttr > SAL_CALL CElement::getAttributeNode(OUString const& name) throw (RuntimeException) { - Reference< XAttr > aAttr; - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); - xmlAttrPtr pAttr = xmlHasProp(m_aNodePtr, xName); - aAttr = Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)pAttr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aAttr; + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); + if (0 == pAttr) { + return 0; + } + Reference< XAttr > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get()), + UNO_QUERY_THROW); + return xRet; } /** Retrieves an Attr node by local name and namespace URI. */ - Reference< XAttr > CElement::getAttributeNodeNS( + Reference< XAttr > SAL_CALL CElement::getAttributeNodeNS( const OUString& namespaceURI, const OUString& localName) throw (RuntimeException) { - Reference< XAttr > aAttr; - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); - OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar *xNS = (xmlChar*)o2.getStr(); - xmlAttrPtr pAttr = xmlHasNsProp(m_aNodePtr, xName, xNS); - aAttr = Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)pAttr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aAttr; + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const pNS = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pNS); + if (0 == pAttr) { + return 0; + } + Reference< XAttr > const xRet( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr)).get()), + UNO_QUERY_THROW); + return xRet; } /** Retrieves an attribute value by local name and namespace URI. return empty string if attribute is not set */ - OUString CElement::getAttributeNS(const OUString& namespaceURI, const OUString& localName) + OUString SAL_CALL + CElement::getAttributeNS( + OUString const& namespaceURI, OUString const& localName) throw (RuntimeException) { - OUString aValue; - // search properties - if (m_aNodePtr != NULL) - { - OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); - OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar *xNS = (xmlChar*)o2.getStr(); - xmlChar *xValue = (xmlChar*)xmlGetNsProp(m_aNodePtr, xName, xNS); - if (xValue != NULL) { - aValue = OUString((sal_Char*)xValue, strlen((char*)xValue), RTL_TEXTENCODING_UTF8); - xmlFree(xValue); - } + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); + xmlChar const*const pNS = + reinterpret_cast<xmlChar const*>(o2.getStr()); + ::boost::shared_ptr<xmlChar const> const pValue( + xmlGetNsProp(m_aNodePtr, pName, pNS), xmlFree); + if (0 == pValue) { + return ::rtl::OUString(); } - return aValue; + OUString const ret(reinterpret_cast<sal_Char const*>(pValue.get()), + strlen(reinterpret_cast<char const*>(pValue.get())), + RTL_TEXTENCODING_UTF8); + return ret; } /** - Returns a NodeList of all descendant Elements with a given tag name, - in the order in which they are + Returns a NodeList of all descendant Elements with a given tag name, + in the order in which they are encountered in a preorder traversal of this Element tree. */ - Reference< XNodeList > CElement::getElementsByTagName(const OUString& name) + Reference< XNodeList > SAL_CALL + CElement::getElementsByTagName(OUString const& rLocalName) throw (RuntimeException) { - Reference< XNodeList > aList = Reference< XNodeList >(new CElementList(this, name)); - return aList; + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xList( + new CElementList(this, m_rMutex, rLocalName)); + return xList; } /** - Returns a NodeList of all the descendant Elements with a given local + Returns a NodeList of all the descendant Elements with a given local name and namespace URI in the order in which they are encountered in a preorder traversal of this Element tree. */ - Reference< XNodeList > CElement::getElementsByTagNameNS(const OUString& namespaceURI, - const OUString& localName) + Reference< XNodeList > SAL_CALL + CElement::getElementsByTagNameNS( + OUString const& rNamespaceURI, OUString const& rLocalName) throw (RuntimeException) { - Reference< XNodeList > aList = Reference< XNodeList >(new CElementList(this, localName, namespaceURI)); - return aList; + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xList( + new CElementList(this, m_rMutex, rLocalName, &rNamespaceURI)); + return xList; } /** The name of the element. */ - OUString CElement::getTagName() + OUString SAL_CALL CElement::getTagName() throw (RuntimeException) { - OUString aName; - if (m_aNodePtr != NULL) - { - aName = OUString((sal_Char*)m_aNodePtr->name, strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); } - return aName; + OUString const ret((sal_Char*)m_aNodePtr->name, + strlen((char*)m_aNodePtr->name), RTL_TEXTENCODING_UTF8); + return ret; } @@ -320,9 +393,11 @@ namespace DOM Returns true when an attribute with a given name is specified on this element or has a default value, false otherwise. */ - sal_Bool CElement::hasAttribute(const OUString& name) + sal_Bool SAL_CALL CElement::hasAttribute(OUString const& name) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); return (m_aNodePtr != NULL && xmlHasProp(m_aNodePtr, xName) != NULL); @@ -332,9 +407,12 @@ namespace DOM Returns true when an attribute with a given local name and namespace URI is specified on this element or has a default value, false otherwise. */ - sal_Bool CElement::hasAttributeNS(const OUString& namespaceURI, const OUString& localName) + sal_Bool SAL_CALL CElement::hasAttributeNS( + OUString const& namespaceURI, OUString const& localName) throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); @@ -345,196 +423,253 @@ namespace DOM /** Removes an attribute by name. */ - void CElement::removeAttribute(const OUString& name) + void SAL_CALL CElement::removeAttribute(OUString const& name) throw (RuntimeException, DOMException) { - xmlChar *xName = (xmlChar*)OUStringToOString(name, RTL_TEXTENCODING_UTF8).getStr(); - if (m_aNodePtr != NULL) { - xmlUnsetProp(m_aNodePtr, xName); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return; + } + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); + xmlAttrPtr const pAttr = xmlHasProp(m_aNodePtr, pName); + if (0 == xmlUnsetProp(m_aNodePtr, pName)) { + ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr), false)); + if (pCNode.is()) { + pCNode->invalidate(); // freed by xmlUnsetProp + } } } /** Removes an attribute by local name and namespace URI. */ - void CElement::removeAttributeNS(const OUString& namespaceURI, const OUString& localName) + void SAL_CALL CElement::removeAttributeNS( + OUString const& namespaceURI, OUString const& localName) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return; + } OString o1 = OUStringToOString(localName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)o1.getStr(); + xmlChar const*const pName = + reinterpret_cast<xmlChar const*>(o1.getStr()); OString o2 = OUStringToOString(namespaceURI, RTL_TEXTENCODING_UTF8); - xmlChar *xURI = (xmlChar*)o2.getStr(); - if (m_aNodePtr != NULL) { - // XXX - xmlNsPtr pNs = xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, xURI); - xmlUnsetNsProp(m_aNodePtr, pNs, xName); + xmlChar const*const pURI = + reinterpret_cast<xmlChar const*>(o2.getStr()); + xmlNsPtr const pNs = + xmlSearchNsByHref(m_aNodePtr->doc, m_aNodePtr, pURI); + xmlAttrPtr const pAttr = xmlHasNsProp(m_aNodePtr, pName, pURI); + if (0 == xmlUnsetNsProp(m_aNodePtr, pNs, pName)) { + ::rtl::Reference<CNode> const pCNode(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(pAttr), false)); + if (pCNode.is()) { + pCNode->invalidate(); // freed by xmlUnsetNsProp + } } } /** Removes the specified attribute node. */ - Reference< XAttr > CElement::removeAttributeNode(const Reference< XAttr >& oldAttr) + Reference< XAttr > SAL_CALL + CElement::removeAttributeNode(Reference< XAttr > const& oldAttr) throw (RuntimeException, DOMException) { - Reference< XAttr > aAttr; - if(m_aNodePtr != NULL) - { - xmlAttrPtr pAttr = (xmlAttrPtr) CNode::getNodePtr(oldAttr.get()); + ::osl::MutexGuard const g(m_rMutex); - if (pAttr->parent != m_aNodePtr) - { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } - if (pAttr->doc != m_aNodePtr->doc) - { - DOMException e; - e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; - throw e; - } + if (0 == m_aNodePtr) { + return 0; + } - if (oldAttr->getNamespaceURI().getLength() > 0) - aAttr = oldAttr->getOwnerDocument()->createAttributeNS( - oldAttr->getNamespaceURI(), oldAttr->getName()); - else - aAttr = oldAttr->getOwnerDocument()->createAttribute(oldAttr->getName()); - aAttr->setValue(oldAttr->getValue()); - xmlRemoveProp(pAttr); + ::rtl::Reference<CNode> const pCNode( + CNode::GetImplementation(Reference<XNode>(oldAttr.get()))); + if (!pCNode.is()) { throw RuntimeException(); } + xmlNodePtr const pNode = pCNode->GetNodePtr(); + xmlAttrPtr const pAttr = (xmlAttrPtr) pNode; + if (!pAttr) { throw RuntimeException(); } + + if (pAttr->parent != m_aNodePtr) + { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (pAttr->doc != m_aNodePtr->doc) + { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + + Reference< XAttr > aAttr; + if (oldAttr->getNamespaceURI().getLength() > 0) { + ::rtl::OUStringBuffer qname(oldAttr->getPrefix()); + if (0 != qname.getLength()) { + qname.append(sal_Unicode(':')); + } + qname.append(oldAttr->getName()); + aAttr = GetOwnerDocument().createAttributeNS( + oldAttr->getNamespaceURI(), qname.makeStringAndClear()); + } else { + aAttr = GetOwnerDocument().createAttribute(oldAttr->getName()); } + aAttr->setValue(oldAttr->getValue()); + xmlRemoveProp(pAttr); + pCNode->invalidate(); // freed by xmlRemoveProp + return aAttr; } /** Adds a new attribute node. */ - Reference< XAttr > CElement::_setAttributeNode(const Reference< XAttr >& newAttr, sal_Bool bNS) - throw (RuntimeException) + Reference< XAttr > + CElement::setAttributeNode_Impl_Lock( + Reference< XAttr > const& xNewAttr, bool const bNS) { - Reference< XAttr > aAttr; - if (m_aNodePtr != NULL) - { - // check whether the attrib belongs to this document - Reference< XDocument > newDoc(newAttr->getOwnerDocument(), UNO_QUERY); - Reference< XDocument > oldDoc(CNode::getOwnerDocument(), UNO_QUERY); - if (newDoc != oldDoc) { - throw RuntimeException(); - } - - // get the implementation - xmlAttrPtr pAttr = (xmlAttrPtr) CNode::getNodePtr(newAttr.get()); - - // check whether the attribute is not in use by another element - xmlNsPtr pNs = NULL; - if (pAttr->parent != NULL) - if(strcmp((char*)pAttr->parent->name, "__private") == 0 - && pNs && pAttr->ns != NULL) - { - pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, pAttr->ns->prefix); - if (pNs == NULL || strcmp((char*)pNs->href, (char*)pAttr->ns->href) !=0 ) - pNs = xmlNewNs(m_aNodePtr, pAttr->ns->href, pAttr->ns->href); - else - throw RuntimeException(); - } + if (xNewAttr->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } - xmlAttrPtr res = NULL; + ::osl::ClearableMutexGuard guard(m_rMutex); - if (bNS) - res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pAttr->children->content); - else - res = xmlNewProp(m_aNodePtr, pAttr->name, pAttr->children->content); + if (0 == m_aNodePtr) { + throw RuntimeException(); + } - // free carrier node ... - if(pAttr->parent != NULL && strcmp((char*)pAttr->parent->name, "__private")== 0) - xmlFreeNode(pAttr->parent); - // ... remove the old attr from the node cache - CNode::remove((xmlNodePtr)pAttr); + // get the implementation + CAttr *const pCAttr = dynamic_cast<CAttr*>( + CNode::GetImplementation(xNewAttr)); + if (!pCAttr) { throw RuntimeException(); } + xmlAttrPtr const pAttr = + reinterpret_cast<xmlAttrPtr>(pCAttr->GetNodePtr()); + if (!pAttr) { throw RuntimeException(); } - // get the new attr node - aAttr = Reference< XAttr >(static_cast< CAttr* >(CNode::get((xmlNodePtr)res))); + // check whether the attribute is not in use by another element + if (pAttr->parent) { + DOMException e; + e.Code = DOMExceptionType_INUSE_ATTRIBUTE_ERR; + throw e; } - if (aAttr.is()) - { - // attribute adition event - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), - sal_True, sal_False, Reference< XNode >(aAttr, UNO_QUERY), - OUString(), aAttr->getValue(), aAttr->getName(), AttrChangeType_ADDITION); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); - dispatchSubtreeModified(); + xmlAttrPtr res = NULL; + xmlChar const*const pContent( + (pAttr->children) ? pAttr->children->content : 0); + + if (bNS) { + xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); + res = xmlNewNsProp(m_aNodePtr, pNs, pAttr->name, pContent); + } else { + res = xmlNewProp(m_aNodePtr, pAttr->name, pContent); } - return aAttr; + + // get the new attr node + Reference< XAttr > const xAttr( + static_cast< XNode* >(GetOwnerDocument().GetCNode( + reinterpret_cast<xmlNodePtr>(res)).get()), + UNO_QUERY_THROW); + + // attribute adition event + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), + sal_True, sal_False, Reference< XNode >(xAttr, UNO_QUERY), + OUString(), xAttr->getValue(), xAttr->getName(), + AttrChangeType_ADDITION); + + guard.clear(); // release mutex before calling event handlers + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); + + return xAttr; } - Reference< XAttr > CElement::setAttributeNode(const Reference< XAttr >& newAttr) + Reference< XAttr > + CElement::setAttributeNode(const Reference< XAttr >& newAttr) throw (RuntimeException, DOMException) { - return _setAttributeNode(newAttr, sal_False); + return setAttributeNode_Impl_Lock(newAttr, false); } /** Adds a new attribute. */ - Reference< XAttr > CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr) + Reference< XAttr > + CElement::setAttributeNodeNS(const Reference< XAttr >& newAttr) throw (RuntimeException, DOMException) { - return _setAttributeNode(newAttr, sal_True); + return setAttributeNode_Impl_Lock(newAttr, true); } /** Adds a new attribute. */ - void CElement::setAttribute(const OUString& name, const OUString& value) + void SAL_CALL + CElement::setAttribute(OUString const& name, OUString const& value) throw (RuntimeException, DOMException) { + ::osl::ClearableMutexGuard guard(m_rMutex); + OString o1 = OUStringToOString(name, RTL_TEXTENCODING_UTF8); xmlChar *xName = (xmlChar*)o1.getStr(); OString o2 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); xmlChar *xValue = (xmlChar*)o2.getStr(); - if (m_aNodePtr != NULL) - { - OUString oldValue; - AttrChangeType aChangeType = AttrChangeType_MODIFICATION; - xmlChar *xOld = xmlGetProp(m_aNodePtr, xName); - if (xOld == NULL) - { - aChangeType = AttrChangeType_ADDITION; - xmlNewProp(m_aNodePtr, xName, xValue); - } - else - { - oldValue = OUString((char*)xOld, strlen((char*)xOld), RTL_TEXTENCODING_UTF8); - xmlSetProp(m_aNodePtr, xName, xValue); - } - - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), - sal_True, sal_False, Reference< XNode >(getAttributeNode(name), UNO_QUERY), - oldValue, value, name, aChangeType); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); - dispatchSubtreeModified(); + if (0 == m_aNodePtr) { + throw RuntimeException(); } + OUString oldValue; + AttrChangeType aChangeType = AttrChangeType_MODIFICATION; + ::boost::shared_ptr<xmlChar const> const pOld( + xmlGetProp(m_aNodePtr, xName), xmlFree); + if (pOld == NULL) { + aChangeType = AttrChangeType_ADDITION; + xmlNewProp(m_aNodePtr, xName, xValue); + } else { + oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), + strlen(reinterpret_cast<char const*>(pOld.get())), + RTL_TEXTENCODING_UTF8); + xmlSetProp(m_aNodePtr, xName, xValue); + } + + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), + sal_True, sal_False, + Reference< XNode >(getAttributeNode(name), UNO_QUERY), + oldValue, value, name, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); } /** - Adds a new attribute. + Adds a new attribute. */ - void CElement::setAttributeNS( - const OUString& namespaceURI, const OUString& qualifiedName, const OUString& value) + void SAL_CALL + CElement::setAttributeNS(OUString const& namespaceURI, + OUString const& qualifiedName, OUString const& value) throw (RuntimeException, DOMException) { if (namespaceURI.getLength() == 0) throw RuntimeException(); + ::osl::ClearableMutexGuard guard(m_rMutex); + OString o1, o2, o3, o4, o5; xmlChar *xPrefix = NULL; xmlChar *xLName = NULL; @@ -559,63 +694,72 @@ namespace DOM o5 = OUStringToOString(value, RTL_TEXTENCODING_UTF8); xmlChar *xURI= (xmlChar*)o4.getStr(); xmlChar *xValue = (xmlChar*)o5.getStr(); - if (m_aNodePtr != NULL) - { - //find the right namespace - xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix); - // if no namespace found, create a new one - if (pNs == NULL) - pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix); - if (strcmp((char*)pNs->href, (char*)xURI) == 0) - { - // found namespace matches - - OUString oldValue; - AttrChangeType aChangeType = AttrChangeType_MODIFICATION; - xmlChar *xOld = xmlGetNsProp(m_aNodePtr, xLName, pNs->href); - if (xOld == NULL) - { - aChangeType = AttrChangeType_ADDITION; - xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue); - } - else - { - oldValue = OUString((char *)xOld, strlen((char *)xOld), RTL_TEXTENCODING_UTF8); - xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue); - } - // dispatch DOMAttrModified event - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMAttrModified"), sal_True, sal_False, - Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY), - oldValue, value, qualifiedName, aChangeType); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); - dispatchSubtreeModified(); - - } else { - // ambigious ns prefix - throw RuntimeException(); - } + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + + //find the right namespace + xmlNsPtr pNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, xPrefix); + // if no namespace found, create a new one + if (pNs == NULL) { + pNs = xmlNewNs(m_aNodePtr, xURI, xPrefix); + } + + if (strcmp((char*)pNs->href, (char*)xURI) != 0) { + // ambiguous ns prefix + throw RuntimeException(); + } + // found namespace matches + + OUString oldValue; + AttrChangeType aChangeType = AttrChangeType_MODIFICATION; + ::boost::shared_ptr<xmlChar const> const pOld( + xmlGetNsProp(m_aNodePtr, xLName, pNs->href), xmlFree); + if (pOld == NULL) { + aChangeType = AttrChangeType_ADDITION; + xmlNewNsProp(m_aNodePtr, pNs, xLName, xValue); + } else { + oldValue = OUString(reinterpret_cast<sal_Char const*>(pOld.get()), + strlen(reinterpret_cast<char const*>(pOld.get())), + RTL_TEXTENCODING_UTF8); + xmlSetNsProp(m_aNodePtr, pNs, xLName, xValue); } + // dispatch DOMAttrModified event + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMAttrModified")), UNO_QUERY); + event->initMutationEvent( + OUString::createFromAscii("DOMAttrModified"), + sal_True, sal_False, + Reference< XNode >(getAttributeNodeNS(namespaceURI, OUString((char*)xLName, strlen((char*)xLName), RTL_TEXTENCODING_UTF8)), UNO_QUERY), + oldValue, value, qualifiedName, aChangeType); + + guard.clear(); // release mutex before calling event handlers + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + dispatchSubtreeModified(); } - Reference< XNamedNodeMap > SAL_CALL CElement::getAttributes()throw (RuntimeException) + Reference< XNamedNodeMap > SAL_CALL + CElement::getAttributes() throw (RuntimeException) { - Reference< XNamedNodeMap > aMap; - if (hasAttributes()) { - aMap = Reference< XNamedNodeMap >(new CAttributesMap(this)); - } - return aMap; + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNamedNodeMap > const xMap( + new CAttributesMap(this, m_rMutex)); + return xMap; } + OUString SAL_CALL CElement::getNodeName()throw (RuntimeException) { return getLocalName(); } + OUString SAL_CALL CElement::getLocalName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { @@ -624,26 +768,31 @@ namespace DOM } return aName; } + OUString SAL_CALL CElement::getNodeValue() throw (RuntimeException) { return OUString(); } - void SAL_CALL CElement::setElementName(const OUString& aName) throw (RuntimeException, DOMException) + void SAL_CALL CElement::setElementName(const OUString& aName) + throw (RuntimeException, DOMException) { - if (aName.getLength() > 0 && aName.indexOf(OUString::createFromAscii(":")) < 0) - { - OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); - xmlChar *xName = (xmlChar*)oName.getStr(); - // xmlFree((void*)m_aNodePtr->name); - m_aNodePtr->name = xmlStrdup(xName); - } - else + if ((aName.getLength() <= 0) || + (0 <= aName.indexOf(OUString::createFromAscii(":")))) { DOMException e; e.Code = DOMExceptionType_INVALID_CHARACTER_ERR; throw e; } + + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + OString oName = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); + xmlChar *xName = (xmlChar*)oName.getStr(); + xmlNodeSetName(m_aNodePtr, xName); } } diff --git a/unoxml/source/dom/element.hxx b/unoxml/source/dom/element.hxx index bd5d3440a..58891ed0d 100644 --- a/unoxml/source/dom/element.hxx +++ b/unoxml/source/dom/element.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,16 +25,19 @@ * ************************************************************************/ -#ifndef _ELEMENT_HXX -#define _ELEMENT_HXX +#ifndef DOM_ELEMENT_HXX +#define DOM_ELEMENT_HXX + +#include <libxml/tree.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> #include <com/sun/star/xml/dom/NodeType.hpp> -#include <libxml/tree.h> -#include "node.hxx" + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -42,22 +45,28 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CElement : public cppu::ImplInheritanceHelper1<CNode, XElement > + typedef ::cppu::ImplInheritanceHelper1<CNode, XElement > CElement_Base; + + class CElement + : public CElement_Base { - friend class CNode; private: - Reference< XAttr > _setAttributeNode(const Reference< XAttr >& newAttr, sal_Bool bNS) - throw (RuntimeException); + friend class CDocument; + + Reference< XAttr > setAttributeNode_Impl_Lock( + Reference< XAttr > const& xNewAttr, bool const bNS); protected: - CElement(const xmlNodePtr aNodePtr); + CElement(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); + + virtual void fastSaxify( Context& i_rContext ); - virtual void SAL_CALL fastSaxify( Context& i_rContext ); + virtual bool IsChildTypeAllowed(NodeType const nodeType); /** Retrieves an attribute value by name. @@ -84,15 +93,15 @@ namespace DOM throw (RuntimeException); /** - Returns a NodeList of all descendant Elements with a given tag name, - in the order in which they are + Returns a NodeList of all descendant Elements with a given tag name, + in the order in which they are encountered in a preorder traversal of this Element tree. */ virtual Reference< XNodeList > SAL_CALL getElementsByTagName(const OUString& name) throw (RuntimeException); /** - Returns a NodeList of all the descendant Elements with a given local + Returns a NodeList of all the descendant Elements with a given local name and namespace URI in the order in which they are encountered in a preorder traversal of this Element tree. */ @@ -157,7 +166,7 @@ namespace DOM throw (RuntimeException, DOMException); /** - Adds a new attribute. + Adds a new attribute. */ virtual void SAL_CALL setAttributeNS( const OUString& namespaceURI, const OUString& qualifiedName, const OUString& value) diff --git a/unoxml/source/dom/elementlist.cxx b/unoxml/source/dom/elementlist.cxx index b5056392f..92285cca8 100644 --- a/unoxml/source/dom/elementlist.cxx +++ b/unoxml/source/dom/elementlist.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -29,45 +29,45 @@ #include <string.h> +#include <element.hxx> +#include <document.hxx> + + namespace DOM { - CElementList::CElementList(const CElement* aElement, const OUString& aName) - : m_pElement(aElement) - , m_aName(aName) - , xURI(0) - , m_bRebuild(sal_True) + static xmlChar* lcl_initXmlString(::rtl::OUString const& rString) { - OString o1 = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); - xName = new xmlChar[o1.getLength()]; - strcpy((char*)xName, o1.getStr()); - registerListener(aElement); + ::rtl::OString const os = + ::rtl::OUStringToOString(rString, RTL_TEXTENCODING_UTF8); + xmlChar *const pRet = new xmlChar[os.getLength() + 1]; + strcpy(reinterpret_cast<char*>(pRet), os.getStr()); + return pRet; } - CElementList::CElementList(const CElement* aElement, const OUString& aName, const OUString& aURI) - : m_pElement(aElement) - , m_aName(aName) - , m_aURI(aURI) - , m_bRebuild(sal_True) + CElementList::CElementList(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex, + OUString const& rName, OUString const*const pURI) + : m_pElement(pElement) + , m_rMutex(rMutex) + , m_pName(lcl_initXmlString(rName)) + , m_pURI((pURI) ? lcl_initXmlString(*pURI) : 0) + , m_bRebuild(true) { - OString o1 = OUStringToOString(aName, RTL_TEXTENCODING_UTF8); - xName = new xmlChar[o1.getLength()]; - strcpy((char*)xName, o1.getStr()); - OString o2 = OUStringToOString(aURI, RTL_TEXTENCODING_UTF8); - xURI = new xmlChar[o2.getLength()]; - strcpy((char*)xURI, o2.getStr()); - registerListener(aElement); + if (m_pElement.is()) { + registerListener(*m_pElement); + } } - void CElementList::registerListener(const CElement* pElement) + void CElementList::registerListener(CElement & rElement) { try { - // get the XNode - Reference< XNode > xNode(CNode::get(static_cast<const CNode*>(pElement)->m_aNodePtr)); - Reference< XEventTarget > xTarget(xNode, UNO_QUERY_THROW); + Reference< XEventTarget > const xTarget( + static_cast<XElement*>(& rElement), UNO_QUERY_THROW); OUString aType = OUString::createFromAscii("DOMSubtreeModified"); sal_Bool capture = sal_False; - xTarget->addEventListener(aType, Reference< XEventListener >(this), capture); + xTarget->addEventListener(aType, + Reference< XEventListener >(this), capture); } catch (Exception &e){ OString aMsg("Exception caught while registering NodeList as listener:\n"); aMsg += OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); @@ -78,25 +78,30 @@ namespace DOM void CElementList::buildlist(xmlNodePtr pNode, sal_Bool start) { // bail out if no rebuild is needed - if (start) { + if (start) { if (!m_bRebuild) { return; } else { m_nodevector.erase(m_nodevector.begin(), m_nodevector.end()); - m_bRebuild = sal_False; // don't rebuild until tree is mutated + m_bRebuild = false; // don't rebuild until tree is mutated } } - + while (pNode != NULL ) { - if (pNode->type == XML_ELEMENT_NODE && strcmp((char*)pNode->name, (char*)xName)==0) + if (pNode->type == XML_ELEMENT_NODE && + (strcmp((char*)pNode->name, (char*)m_pName.get()) == 0)) { - if (xURI == NULL) + if (!m_pURI) { m_nodevector.push_back(pNode); - else - if (pNode->ns != NULL && strcmp((char*)pNode->ns->href, (char*)xURI) == 0) + } else { + if (pNode->ns != NULL && (0 == + strcmp((char*)pNode->ns->href, (char*)m_pURI.get()))) + { m_nodevector.push_back(pNode); + } + } } if (pNode->children != NULL) buildlist(pNode->children, sal_False); @@ -104,30 +109,47 @@ namespace DOM else break; // fold back } } - + /** The number of nodes in the list. */ sal_Int32 SAL_CALL CElementList::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + + if (!m_pElement.is()) { return 0; } + // this has to be 'live' - buildlist(static_cast<const CNode*>(m_pElement)->m_aNodePtr); + buildlist(m_pElement->GetNodePtr()); return m_nodevector.size(); } /** Returns the indexth item in the collection. */ - Reference< XNode > SAL_CALL CElementList::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL CElementList::item(sal_Int32 index) + throw (RuntimeException) { - if (index < 0) throw RuntimeException(); - buildlist(static_cast<const CNode*>(m_pElement)->m_aNodePtr); - return Reference< XNode >(CNode::get(m_nodevector[index])); + if (index < 0) throw RuntimeException(); + + ::osl::MutexGuard const g(m_rMutex); + + if (!m_pElement.is()) { return 0; } + + buildlist(m_pElement->GetNodePtr()); + if (m_nodevector.size() <= static_cast<size_t>(index)) { + throw RuntimeException(); + } + Reference< XNode > const xRet( + m_pElement->GetOwnerDocument().GetCNode(m_nodevector[index]).get()); + return xRet; } // tree mutations can change the list - void SAL_CALL CElementList::handleEvent(const Reference< XEvent >& evt) throw (RuntimeException) + void SAL_CALL CElementList::handleEvent(Reference< XEvent > const&) + throw (RuntimeException) { - Reference< XEvent > aEvent = evt; - m_bRebuild = sal_True; + ::osl::MutexGuard const g(m_rMutex); + + m_bRebuild = true; } } diff --git a/unoxml/source/dom/elementlist.hxx b/unoxml/source/dom/elementlist.hxx index 1ffc015ff..95b9960e7 100644 --- a/unoxml/source/dom/elementlist.hxx +++ b/unoxml/source/dom/elementlist.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,22 +25,27 @@ * ************************************************************************/ -#ifndef _ELEMENTLIST_HXX -#define _ELEMENTLIST_HXX +#ifndef DOM_ELEMENTLIST_HXX +#define DOM_ELEMENTLIST_HXX #include <vector> + +#include <boost/scoped_array.hpp> + +#include <libxml/tree.h> + #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XEventListener.hpp> -#include "element.hxx" -#include "document.hxx" -#include "libxml/tree.h" + +#include <cppuhelper/implbase2.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -49,26 +54,30 @@ using namespace com::sun::star::xml::dom::events; namespace DOM { - typedef std::vector< xmlNodePtr > nodevector; + class CElement; - class CElementList : public cppu::WeakImplHelper2< XNodeList, com::sun::star::xml::dom::events::XEventListener > + typedef std::vector< xmlNodePtr > nodevector_t; + + class CElementList + : public cppu::WeakImplHelper2< XNodeList, + com::sun::star::xml::dom::events::XEventListener > { private: - const CElement* m_pElement; - const OUString m_aName; - const OUString m_aURI; - xmlChar *xName; - xmlChar *xURI; - sal_Bool m_bRebuild; - nodevector m_nodevector; - - + ::rtl::Reference<CElement> const m_pElement; + ::osl::Mutex & m_rMutex; + ::boost::scoped_array<xmlChar> const m_pName; + ::boost::scoped_array<xmlChar> const m_pURI; + bool m_bRebuild; + nodevector_t m_nodevector; + void buildlist(xmlNodePtr pNode, sal_Bool start=sal_True); - void registerListener(const CElement* pElement); + void registerListener(CElement & rElement); public: - CElementList(const CElement* aDoc, const OUString& aName); - CElementList(const CElement* aDoc, const OUString& aName, const OUString& aURI); + CElementList(::rtl::Reference<CElement> const& pElement, + ::osl::Mutex & rMutex, + OUString const& rName, OUString const*const pURI = 0); + /** The number of nodes in the list. */ @@ -76,10 +85,12 @@ namespace DOM /** Returns the indexth item in the collection. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); // XEventListener - virtual void SAL_CALL handleEvent(const Reference< XEvent >& evt) throw (RuntimeException); + virtual void SAL_CALL handleEvent(const Reference< XEvent >& evt) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/entitiesmap.cxx b/unoxml/source/dom/entitiesmap.cxx index 4fecd2930..aab2f5551 100644 --- a/unoxml/source/dom/entitiesmap.cxx +++ b/unoxml/source/dom/entitiesmap.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,12 +25,17 @@ * ************************************************************************/ -#include "entitiesmap.hxx" +#include <entitiesmap.hxx> + +#include <documenttype.hxx> + namespace DOM { - CEntitiesMap::CEntitiesMap(const CDocumentType* aDocType) - : m_pDocType(aDocType) + CEntitiesMap::CEntitiesMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex) + : m_pDocType(pDocType) + , m_rMutex(rMutex) { } @@ -39,62 +44,91 @@ namespace DOM */ sal_Int32 SAL_CALL CEntitiesMap::getLength() throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::getLength: not implemented (#i113683#)"); return 0; } /** - Retrieves a node specified by local name + Retrieves a node specified by local name */ - Reference< XNode > SAL_CALL CEntitiesMap::getNamedItem(const OUString& /*name*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::getNamedItem(OUString const& /*name*/) throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::getNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Retrieves a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CEntitiesMap::getNamedItemNS(const OUString& /*namespaceURI*/,const OUString& /*localName*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::getNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::getNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** Returns the indexth item in the map. */ - Reference< XNode > SAL_CALL CEntitiesMap::item(sal_Int32 /*index*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::item(sal_Int32 /*index*/) throw (RuntimeException) { + OSL_ENSURE(false, "CEntitiesMap::item: not implemented (#i113683#)"); return Reference< XNode >(); } /** Removes a node specified by name. */ - Reference< XNode > SAL_CALL CEntitiesMap::removeNamedItem(const OUString& /*name*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::removeNamedItem(OUString const& /*name*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::removeNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Removes a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CEntitiesMap::removeNamedItemNS(const OUString& /*namespaceURI*/, const OUString& /*localName*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::removeNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::removeNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Adds a node using its nodeName attribute. */ - Reference< XNode > SAL_CALL CEntitiesMap::setNamedItem(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::setNamedItem(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::setNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Adds a node using its namespaceURI and localName. */ - Reference< XNode > SAL_CALL CEntitiesMap::setNamedItemNS(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CEntitiesMap::setNamedItemNS(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CEntitiesMap::setNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } } diff --git a/unoxml/source/dom/entitiesmap.hxx b/unoxml/source/dom/entitiesmap.hxx index 51c8ca5f2..468e89763 100644 --- a/unoxml/source/dom/entitiesmap.hxx +++ b/unoxml/source/dom/entitiesmap.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,32 +25,37 @@ * ************************************************************************/ -#ifndef _ENTITIESMAP_HXX -#define _ENTITIESMAP_HXX +#ifndef DOM_ENTITIESMAP_HXX +#define DOM_ENTITIESMAP_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "document.hxx" -#include "documenttype.hxx" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; namespace DOM { - class CEntitiesMap : public cppu::WeakImplHelper1< XNamedNodeMap > + class CDocumentType; + + class CEntitiesMap + : public cppu::WeakImplHelper1< XNamedNodeMap > { private: - const CDocumentType* m_pDocType; + ::rtl::Reference<CDocumentType> const m_pDocType; + ::osl::Mutex & m_rMutex; + public: - CEntitiesMap(const CDocumentType* aDocType); + CEntitiesMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex); /** The number of nodes in this map. @@ -58,39 +63,50 @@ namespace DOM virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); /** - Retrieves a node specified by local name + Retrieves a node specified by local name */ - virtual Reference< XNode > SAL_CALL getNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + getNamedItem(const OUString& name) throw (RuntimeException); /** Retrieves a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL getNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** Returns the indexth item in the map. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + item(sal_Int32 index) throw (RuntimeException); /** Removes a node specified by name. */ - virtual Reference< XNode > SAL_CALL removeNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) throw (RuntimeException); /** // Removes a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** // Adds a node using its nodeName attribute. */ - virtual Reference< XNode > SAL_CALL setNamedItem(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); /** Adds a node using its namespaceURI and localName. */ - virtual Reference< XNode > SAL_CALL setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/entity.cxx b/unoxml/source/dom/entity.cxx index 7906a2840..3fb1790ab 100644 --- a/unoxml/source/dom/entity.cxx +++ b/unoxml/source/dom/entity.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,18 +25,35 @@ * ************************************************************************/ -#include "entity.hxx" +#include <entity.hxx> #include <string.h> + namespace DOM { - CEntity::CEntity(const xmlEntityPtr aEntityPtr) + CEntity::CEntity(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlEntityPtr const pEntity) + : CEntity_Base(rDocument, rMutex, + NodeType_ENTITY_NODE, reinterpret_cast<xmlNodePtr>(pEntity)) + , m_aEntityPtr(pEntity) { - m_aNodeType = NodeType_ENTITY_NODE; - m_aEntityPtr = aEntityPtr; - init_node((xmlNodePtr)aEntityPtr); + } + + bool CEntity::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } } /** @@ -44,7 +61,8 @@ namespace DOM */ OUString SAL_CALL CEntity::getNotationName() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CEntity::getNotationName: not implemented (#i113683#)"); return OUString(); } @@ -53,6 +71,8 @@ namespace DOM */ OUString SAL_CALL CEntity::getPublicId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aID; if(m_aEntityPtr != NULL) { @@ -66,6 +86,8 @@ namespace DOM */ OUString SAL_CALL CEntity::getSystemId() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aID; if(m_aEntityPtr != NULL) { @@ -75,6 +97,8 @@ namespace DOM } OUString SAL_CALL CEntity::getNodeName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { diff --git a/unoxml/source/dom/entity.hxx b/unoxml/source/dom/entity.hxx index 3d7761273..671ad8af9 100644 --- a/unoxml/source/dom/entity.hxx +++ b/unoxml/source/dom/entity.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,16 +25,19 @@ * ************************************************************************/ -#ifndef _ENTITY_HXX -#define _ENTITY_HXX +#ifndef DOM_ENTITY_HXX +#define DOM_ENTITY_HXX + +#include <libxml/tree.h> +#include <libxml/entities.h> #include <sal/types.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XEntity.hpp> -#include "node.hxx" -#include <libxml/tree.h> -#include <libxml/entities.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -42,16 +45,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CEntity : public cppu::ImplInheritanceHelper1< CNode, XEntity > + typedef ::cppu::ImplInheritanceHelper1< CNode, XEntity > CEntity_Base; + + class CEntity + : public CEntity_Base { - friend class CNode; + private: + friend class CDocument; + private: xmlEntityPtr m_aEntityPtr; protected: - CEntity(const xmlEntityPtr aEntityPtr); + CEntity(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlEntityPtr const pEntity); public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); /** For unparsed entities, the name of the notation for the entity. diff --git a/unoxml/source/dom/entityreference.cxx b/unoxml/source/dom/entityreference.cxx index f9a9260d6..0dda6bc3f 100644 --- a/unoxml/source/dom/entityreference.cxx +++ b/unoxml/source/dom/entityreference.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,18 +25,39 @@ * ************************************************************************/ -#include "entityreference.hxx" +#include <entityreference.hxx> + #include <string.h> namespace DOM { - CEntityReference::CEntityReference(const xmlNodePtr aNodePtr) + CEntityReference::CEntityReference( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CEntityReference_Base(rDocument, rMutex, + NodeType_ENTITY_REFERENCE_NODE, pNode) { - m_aNodeType = NodeType_ENTITY_REFERENCE_NODE; - init_node(aNodePtr); } + + bool CEntityReference::IsChildTypeAllowed(NodeType const nodeType) + { + switch (nodeType) { + case NodeType_ELEMENT_NODE: + case NodeType_PROCESSING_INSTRUCTION_NODE: + case NodeType_COMMENT_NODE: + case NodeType_TEXT_NODE: + case NodeType_CDATA_SECTION_NODE: + case NodeType_ENTITY_REFERENCE_NODE: + return true; + default: + return false; + } + } + OUString SAL_CALL CEntityReference::getNodeName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { @@ -45,6 +66,7 @@ namespace DOM } return aName; } + OUString SAL_CALL CEntityReference::getNodeValue() throw (RuntimeException) { return OUString(); diff --git a/unoxml/source/dom/entityreference.hxx b/unoxml/source/dom/entityreference.hxx index f64859187..d4e349076 100644 --- a/unoxml/source/dom/entityreference.hxx +++ b/unoxml/source/dom/entityreference.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,13 +25,16 @@ * ************************************************************************/ -#ifndef _ENTITYREFERENCE_HXX -#define _ENTITYREFERENCE_HXX +#ifndef DOM_ENTITYREFERENCE_HXX +#define DOM_ENTITYREFERENCE_HXX + +#include <libxml/tree.h> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XEntityReference.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -39,13 +42,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CEntityReference : public cppu::ImplInheritanceHelper1< CNode, XEntityReference > + typedef ::cppu::ImplInheritanceHelper1< CNode, XEntityReference > + CEntityReference_Base; + + class CEntityReference + : public CEntityReference_Base { - friend class CNode; + private: + friend class CDocument; + protected: - CEntityReference(const xmlNodePtr aNodePtr); + CEntityReference( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: + virtual bool IsChildTypeAllowed(NodeType const nodeType); + // ---- resolve uno inheritance problems... // overrides for XNode base virtual OUString SAL_CALL getNodeName() diff --git a/unoxml/source/dom/makefile.mk b/unoxml/source/dom/makefile.mk deleted file mode 100644 index 32a35ebfd..000000000 --- a/unoxml/source/dom/makefile.mk +++ /dev/null @@ -1,74 +0,0 @@ -#************************************************************************* -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. -# -# OpenOffice.org - a multi-platform office productivity suite -# -# This file is part of OpenOffice.org. -# -# OpenOffice.org is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# only, as published by the Free Software Foundation. -# -# OpenOffice.org is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License version 3 for more details -# (a copy is included in the LICENSE file that accompanied this code). -# -# You should have received a copy of the GNU Lesser General Public License -# version 3 along with OpenOffice.org. If not, see -# <http://www.openoffice.org/license.html> -# for a copy of the LGPLv3 License. -# -#************************************************************************* - -PRJ=..$/.. - -PRJNAME=unoxml -TARGET=domimpl - -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) -.ENDIF - -# --- Files -------------------------------------------------------- - -SLOFILES = \ - $(SLO)$/attr.obj \ - $(SLO)$/cdatasection.obj \ - $(SLO)$/characterdata.obj \ - $(SLO)$/comment.obj \ - $(SLO)$/document.obj \ - $(SLO)$/documentbuilder.obj \ - $(SLO)$/documentfragment.obj \ - $(SLO)$/documenttype.obj \ - $(SLO)$/element.obj \ - $(SLO)$/entity.obj \ - $(SLO)$/entityreference.obj \ - $(SLO)$/node.obj \ - $(SLO)$/notation.obj \ - $(SLO)$/processinginstruction.obj \ - $(SLO)$/text.obj \ - $(SLO)$/domimplementation.obj \ - $(SLO)$/elementlist.obj \ - $(SLO)$/childlist.obj \ - $(SLO)$/notationsmap.obj \ - $(SLO)$/entitiesmap.obj \ - $(SLO)$/attributesmap.obj \ - $(SLO)$/saxbuilder.obj - - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - - diff --git a/unoxml/source/dom/node.cxx b/unoxml/source/dom/node.cxx index dc53f8258..3540b17b7 100644 --- a/unoxml/source/dom/node.cxx +++ b/unoxml/source/dom/node.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,35 +25,47 @@ * ************************************************************************/ +#include <node.hxx> + #include <stdio.h> #include <string.h> -#include "node.hxx" -#include "element.hxx" -#include "text.hxx" -#include "cdatasection.hxx" -#include "entityreference.hxx" -#include "entity.hxx" -#include "processinginstruction.hxx" -#include "comment.hxx" -#include "document.hxx" -#include "documenttype.hxx" -#include "documentfragment.hxx" -#include "notation.hxx" -#include "childlist.hxx" -#include "attr.hxx" + +#include <libxml/xmlstring.h> + +#include <algorithm> + +#include <boost/bind.hpp> + +#include <rtl/uuid.h> +#include <rtl/instance.hxx> +#include <osl/mutex.hxx> #include <com/sun/star/xml/sax/FastToken.hpp> -#include "rtl/instance.hxx" -#include "osl/mutex.hxx" + +#include <document.hxx> +#include <attr.hxx> +#include <childlist.hxx> + #include "../events/eventdispatcher.hxx" #include "../events/mutationevent.hxx" -#include <boost/bind.hpp> -#include <algorithm> + + +using namespace ::com::sun::star; + namespace { -//see CNode::remove - struct NodeMutex: public ::rtl::Static<osl::Mutex, NodeMutex> {}; + struct UnoTunnelId + : public ::rtl::StaticWithInit< Sequence<sal_Int8>, UnoTunnelId > + { + Sequence<sal_Int8> operator() () + { + Sequence<sal_Int8> ret(16); + rtl_createUuid( + reinterpret_cast<sal_uInt8*>(ret.getArray()), 0, sal_True); + return ret; + } + }; } namespace DOM @@ -117,7 +129,7 @@ namespace DOM Context::NamespaceVectorType::value_type::const_iterator aIter; if( (aIter=std::find_if(rContext.maNamespaces.back().begin(), - rContext.maNamespaces.back().end(), + rContext.maNamespaces.back().end(), boost::bind(std::equal_to<OString>(), boost::bind(&Context::Namespace::getPrefix, _1), @@ -133,160 +145,64 @@ namespace DOM } - nodemap_t CNode::theNodeMap; - - void CNode::remove(const xmlNodePtr aNode) + CNode::CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : m_bUnlinked(false) + , m_aNodeType(reNodeType) + , m_aNodePtr(rpNode) + // keep containing document alive + // (but not if this is a document; that would create a leak!) + , m_xDocument( (m_aNodePtr->type != XML_DOCUMENT_NODE) + ? &const_cast<CDocument&>(rDocument) : 0 ) + , m_rMutex(const_cast< ::osl::Mutex & >(rMutex)) { - //Using the guard here protects against races when at the same time - //CNode::get() is called. This fix helps in many cases but is still - //incorrect. remove is called from ~CNode. That is, while the object - //is being destructed it can still be obtained by calling CNode::get(). - //Another bug currently prevents the correct destruction of CNodes. So - //the destructor is rarely called. - // - //Doing this right would probably mean to store WeakReferences in the - //map and also guard oder functions. To keep the risk at a minimum - //we keep this imperfect fix for the upcoming release and fix it later - //properly (http://qa.openoffice.org/issues/show_bug.cgi?id=113682) - ::osl::MutexGuard guard(NodeMutex::get()); - nodemap_t::iterator i = CNode::theNodeMap.find(aNode); - if (i != CNode::theNodeMap.end()) - { - // CNode *pNode = i->second; - CNode::theNodeMap.erase(i); - } + OSL_ASSERT(m_aNodePtr); } - - CNode* CNode::get(const xmlNodePtr aNode, sal_Bool bCreate) + void CNode::invalidate() { - CNode* pNode = 0; - if (aNode == NULL) - return 0; - //see CNode::remove - ::osl::MutexGuard guard(NodeMutex::get()); - //check whether there is already an instance for this node - nodemap_t::const_iterator i = CNode::theNodeMap.find(aNode); - if (i != CNode::theNodeMap.end()) - { - pNode = i->second; - } else - { - - // there is not yet an instance wrapping this node, - // create it and store it in the map - if (!bCreate) return NULL; - - switch (aNode->type) - { - case XML_ELEMENT_NODE: - // m_aNodeType = NodeType::ELEMENT_NODE; - pNode = static_cast< CNode* >(new CElement(aNode)); - break; - case XML_TEXT_NODE: - // m_aNodeType = NodeType::TEXT_NODE; - pNode = static_cast< CNode* >(new CText(aNode)); - break; - case XML_CDATA_SECTION_NODE: - // m_aNodeType = NodeType::CDATA_SECTION_NODE; - pNode = static_cast< CNode* >(new CCDATASection(aNode)); - break; - case XML_ENTITY_REF_NODE: - // m_aNodeType = NodeType::ENTITY_REFERENCE_NODE; - pNode = static_cast< CNode* >(new CEntityReference(aNode)); - break; - case XML_ENTITY_NODE: - // m_aNodeType = NodeType::ENTITY_NODE; - pNode = static_cast< CNode* >(new CEntity((xmlEntityPtr)aNode)); - break; - case XML_PI_NODE: - // m_aNodeType = NodeType::PROCESSING_INSTRUCTION_NODE; - pNode = static_cast< CNode* >(new CProcessingInstruction(aNode)); - break; - case XML_COMMENT_NODE: - // m_aNodeType = NodeType::COMMENT_NODE; - pNode = static_cast< CNode* >(new CComment(aNode)); - break; - case XML_DOCUMENT_NODE: - // m_aNodeType = NodeType::DOCUMENT_NODE; - pNode = static_cast< CNode* >(new CDocument((xmlDocPtr)aNode)); - break; - case XML_DOCUMENT_TYPE_NODE: - case XML_DTD_NODE: - // m_aNodeType = NodeType::DOCUMENT_TYPE_NODE; - pNode = static_cast< CNode* >(new CDocumentType((xmlDtdPtr)aNode)); - break; - case XML_DOCUMENT_FRAG_NODE: - // m_aNodeType = NodeType::DOCUMENT_FRAGMENT_NODE; - pNode = static_cast< CNode* >(new CDocumentFragment(aNode)); - break; - case XML_NOTATION_NODE: - // m_aNodeType = NodeType::NOTATION_NODE; - pNode = static_cast< CNode* >(new CNotation((xmlNotationPtr)aNode)); - break; - case XML_ATTRIBUTE_NODE: - // m_aNodeType = NodeType::NOTATION_NODE; - pNode = static_cast< CNode* >(new CAttr((xmlAttrPtr)aNode)); - break; - // unsupported node types - case XML_HTML_DOCUMENT_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_NAMESPACE_DECL: - default: - pNode = 0; - break; - } - - if ( pNode != 0 ) - { - if(!CNode::theNodeMap.insert(nodemap_t::value_type(aNode, pNode)).second) - { - // if insertion failed, delete the new instance and return null - delete pNode; - pNode = 0; - } - } + //remove from list if this wrapper goes away + if (m_aNodePtr != 0 && m_xDocument.is()) { + m_xDocument->RemoveCNode(m_aNodePtr, this); + } + // #i113663#: unlinked nodes will not be freed by xmlFreeDoc + if (m_bUnlinked) { + xmlFreeNode(m_aNodePtr); } - OSL_ENSURE(pNode, "no node produced during CNode::get!"); - return pNode; + m_aNodePtr = 0; } - xmlNodePtr CNode::getNodePtr(const Reference< XNode >& aNode) + CNode::~CNode() { - try { - CNode* pNode=dynamic_cast<CNode*>(aNode.get()); - if( pNode ) - return pNode->m_aNodePtr; - } - catch(...) {} - return 0; + // if this is the document itself, the mutex is already freed! + if (NodeType_DOCUMENT_NODE == m_aNodeType) { + invalidate(); + } else { + ::osl::MutexGuard const g(m_rMutex); + invalidate(); // other nodes are still alive so must lock mutex + } } - CNode::CNode() - : m_aNodePtr(0) + CNode * + CNode::GetImplementation(uno::Reference<uno::XInterface> const& xNode) { + uno::Reference<lang::XUnoTunnel> const xUnoTunnel(xNode, UNO_QUERY); + if (!xUnoTunnel.is()) { return 0; } + CNode *const pCNode( reinterpret_cast< CNode* >( + ::sal::static_int_cast< sal_IntPtr >( + xUnoTunnel->getSomething(UnoTunnelId::get())))); + return pCNode; } - void CNode::init_node(const xmlNodePtr aNode) + CDocument & CNode::GetOwnerDocument() { - m_aNodePtr = aNode; - - // keep containing document alive - // (if we are not that document ourselves) - if (m_aNodePtr->type != XML_DOCUMENT_NODE) - m_rDocument = getOwnerDocument(); + OSL_ASSERT(m_xDocument.is()); + return *m_xDocument; // needs overriding in CDocument! } - CNode::~CNode() - { - //remove from list if this wrapper goes away - if (m_aNodePtr != 0) - CNode::remove(m_aNodePtr); - } - static void _nsexchange(const xmlNodePtr aNode, xmlNsPtr oldNs, xmlNsPtr newNs) + static void lcl_nsexchange( + xmlNodePtr const aNode, xmlNsPtr const oldNs, xmlNsPtr const newNs) { // recursively exchange any references to oldNs with references to newNs xmlNodePtr cur = aNode; @@ -303,13 +219,13 @@ namespace DOM curAttr->ns = newNs; curAttr = curAttr->next; } - _nsexchange(cur->children, oldNs, newNs); + lcl_nsexchange(cur->children, oldNs, newNs); } cur = cur->next; } } - /*static*/ void _nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent) + /*static*/ void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent) { xmlNodePtr cur = aNode; @@ -331,7 +247,7 @@ namespace DOM while (cur != NULL) { - _nscleanup(cur->children, cur); + nscleanup(cur->children, cur); if (cur->ns != NULL) { xmlNsPtr ns = xmlSearchNs(cur->doc, aParent, cur->ns->prefix); @@ -346,7 +262,7 @@ namespace DOM { // reconnect ns pointers in sub-tree to newly found ns before // removing redundant nsdecl to prevent dangling pointers. - _nsexchange(cur, curDef, ns); + lcl_nsexchange(cur, curDef, ns); *refp = curDef->next; xmlFreeNs(curDef); curDef = *refp; @@ -361,184 +277,187 @@ namespace DOM } } - void SAL_CALL CNode::saxify( - const Reference< XDocumentHandler >& i_xHandler) { + void CNode::saxify(const Reference< XDocumentHandler >& i_xHandler) + { if (!i_xHandler.is()) throw RuntimeException(); // default: do nothing } - void SAL_CALL CNode::fastSaxify(Context& io_rContext) { + void CNode::fastSaxify(Context& io_rContext) + { if (!io_rContext.mxDocHandler.is()) throw RuntimeException(); // default: do nothing } - /** + bool CNode::IsChildTypeAllowed(NodeType const /*nodeType*/) + { + // default: no children allowed + return false; + } + + /** Adds the node newChild to the end of the list of children of this node. */ - Reference< XNode > CNode::appendChild(const Reference< XNode >& newChild) + Reference< XNode > SAL_CALL CNode::appendChild( + Reference< XNode > const& xNewChild) throw (RuntimeException, DOMException) { - Reference< XNode> aNode; - if (m_aNodePtr != NULL) { - xmlNodePtr cur = CNode::getNodePtr(newChild.get()); + ::osl::ClearableMutexGuard guard(m_rMutex); - // error checks: - // from other document - if (cur->doc != m_aNodePtr->doc) { - DOMException e; - e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; - throw e; - } - // same node - if (cur == m_aNodePtr) { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } - // already has parant and is not attribute - if (cur->parent != NULL && cur->type != XML_ATTRIBUTE_NODE) { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } - - // check whether this is an attribute node so we remove it's - // carrier node if it has one - xmlNodePtr res = NULL; - if (cur->type == XML_ATTRIBUTE_NODE) - { - if (cur->parent != NULL) - { - if (m_aNodePtr->type != XML_ELEMENT_NODE || - strcmp((char*)cur->parent->name, "__private") != 0) - { - DOMException e; - e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; - throw e; - } + if (0 == m_aNodePtr) { return 0; } - xmlNsPtr pAttrNs = cur->ns; - xmlNsPtr pParentNs = xmlSearchNs(m_aNodePtr->doc, m_aNodePtr, pAttrNs->prefix); - if (pParentNs == NULL || strcmp((char*)pParentNs->href, (char*)pAttrNs->href) != 0) - pParentNs = xmlNewNs(m_aNodePtr, pAttrNs->href, pAttrNs->prefix); + CNode *const pNewChild(CNode::GetImplementation(xNewChild)); + if (!pNewChild) { throw RuntimeException(); } + xmlNodePtr const cur = pNewChild->GetNodePtr(); + if (!cur) { throw RuntimeException(); } - if (cur->children != NULL) - res = (xmlNodePtr)xmlNewNsProp(m_aNodePtr, pParentNs, cur->name, cur->children->content); - else - res = (xmlNodePtr)xmlNewProp(m_aNodePtr, cur->name, (xmlChar*) ""); + // error checks: + // from other document + if (cur->doc != m_aNodePtr->doc) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + // same node + if (cur == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (cur->parent != NULL) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewChild->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } - xmlFreeNode(cur->parent); - cur->parent = NULL; - } - else - { - if (cur->children != NULL) - res = (xmlNodePtr)xmlNewProp(m_aNodePtr, cur->name, cur->children->content); - else - res = (xmlNodePtr)xmlNewProp(m_aNodePtr, cur->name, (xmlChar*) ""); - } - } - else - { - res = xmlAddChild(m_aNodePtr, cur); + // check whether this is an attribute node; it needs special handling + xmlNodePtr res = NULL; + if (cur->type == XML_ATTRIBUTE_NODE) + { + xmlChar const*const pChildren((cur->children) + ? cur->children->content + : reinterpret_cast<xmlChar const*>("")); + CAttr *const pCAttr(dynamic_cast<CAttr *>(pNewChild)); + if (!pCAttr) { throw RuntimeException(); } + xmlNsPtr const pNs( pCAttr->GetNamespace(m_aNodePtr) ); + if (pNs) { + res = reinterpret_cast<xmlNodePtr>( + xmlNewNsProp(m_aNodePtr, pNs, cur->name, pChildren)); + } else { + res = reinterpret_cast<xmlNodePtr>( + xmlNewProp(m_aNodePtr, cur->name, pChildren)); } + } + else + { + res = xmlAddChild(m_aNodePtr, cur); - // libxml can do optimizations, when appending nodes. - // if res != cur, something was optimized and the newchild-wrapper + // libxml can do optimization when appending nodes. + // if res != cur, something was optimized and the newchild-wrapper // should be updated - if (cur != res) - CNode::remove(cur); + if (res && (cur != res)) { + pNewChild->invalidate(); // cur has been freed + } + } + + if (!res) { return 0; } - // use custom ns cleanup instaead of - // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr); + // use custom ns cleanup instead of + // xmlReconciliateNs(m_aNodePtr->doc, m_aNodePtr); // because that will not remove unneeded ns decls - _nscleanup(res, m_aNodePtr); + nscleanup(res, m_aNodePtr); - aNode = Reference< XNode>(CNode::get(res)); - } - //XXX check for errors + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode(res); + + if (!pNode.is()) { return 0; } // dispatch DOMNodeInserted event, target is the new node // this node is the related node // does bubble - if (aNode.is()) - { - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMNodeInserted") - , sal_True, sal_False, Reference< XNode >(CNode::get(m_aNodePtr)), - OUString(), OUString(), OUString(), (AttrChangeType)0 ); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + pNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMNodeInserted")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMNodeInserted") + , sal_True, sal_False, + this, + OUString(), OUString(), OUString(), (AttrChangeType)0 ); - // dispatch subtree modified for this node - dispatchSubtreeModified(); - } - return aNode; + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + // dispatch subtree modified for this node + dispatchSubtreeModified(); + + return pNode.get(); } /** - Returns a duplicate of this node, i.e., serves as a generic copy + Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. */ - Reference< XNode > CNode::cloneNode(sal_Bool bDeep) + Reference< XNode > SAL_CALL CNode::cloneNode(sal_Bool bDeep) throw (RuntimeException) { - Reference< XNode> aNode; - if (m_aNodePtr != NULL) - { - aNode = Reference< XNode>(CNode::get( - xmlCopyNode (m_aNodePtr, static_cast< int >(bDeep)) - )); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - //XXX check for errors - return aNode; + ::rtl::Reference<CNode> const pNode = GetOwnerDocument().GetCNode( + xmlCopyNode(m_aNodePtr, (bDeep) ? 1 : 0)); + if (!pNode.is()) { return 0; } + pNode->m_bUnlinked = true; // not linked yet + return pNode.get(); } /** - A NamedNodeMap containing the attributes of this node (if it is an Element) + A NamedNodeMap containing the attributes of this node (if it is an Element) or null otherwise. */ - Reference< XNamedNodeMap > CNode::getAttributes() + Reference< XNamedNodeMap > SAL_CALL CNode::getAttributes() throw (RuntimeException) { - // return empty reference - // only element node may override this impl + // return empty reference; only element node may override this impl return Reference< XNamedNodeMap>(); - - // get all children that are attributes - /* --> CElement - Reference< NamedNodeMap > aNodeMap(new AttributeNamedNodeMap(m_aNodePtr), UNO_QUERY); - return aNodeMap; - */ } /** A NodeList that contains all children of this node. */ - Reference< XNodeList > CNode::getChildNodes() + Reference< XNodeList > SAL_CALL CNode::getChildNodes() throw (RuntimeException) { - Reference< XNodeList > aNodeList; - if (m_aNodePtr != NULL) - { - aNodeList = Reference< XNodeList >(new CChildList(CNode::get(m_aNodePtr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - // XXX check for errors? - return aNodeList; + Reference< XNodeList > const xNodeList(new CChildList(this, m_rMutex)); + return xNodeList; } /** The first child of this node. */ - Reference< XNode > CNode::getFirstChild() + Reference< XNode > SAL_CALL CNode::getFirstChild() throw (RuntimeException) { - Reference< XNode > aNode; - if (m_aNodePtr != NULL) { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->children)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->children).get()); + return xNode; } /** @@ -547,30 +466,24 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getLastChild() throw (RuntimeException) { - Reference< XNode > aNode; - if (m_aNodePtr != NULL) { - aNode = Reference< XNode >(CNode::get(xmlGetLastChild(m_aNodePtr))); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(xmlGetLastChild(m_aNodePtr)).get()); + return xNode; } /** - Returns the local part of the qualified name of this node. + Returns the local part of the qualified name of this node. */ OUString SAL_CALL CNode::getLocalName() throw (RuntimeException) { - OUString aName; - /* - --> Element / Attribute - if(m_aNodePtr != NULL && (m_aNodeType == NodeType::ATTRIBUTE_NODE - || m_aNodeType == NodeType::ELEMENT_NODE)) - { - aName = OUString(m_aNodePtr->name, RTL_TEXTENCODING_UTF8); - } - //XXX error checking - */ - return aName; + // see CElement/CAttr + return ::rtl::OUString(); } @@ -580,6 +493,8 @@ namespace DOM OUString SAL_CALL CNode::getNamespaceURI() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aURI; if (m_aNodePtr != NULL && (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) && @@ -597,12 +512,14 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getNextSibling() throw (RuntimeException) { - Reference< XNode > aNode; - if(m_aNodePtr != NULL) - { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->next)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->next).get()); + return xNode; } /** @@ -623,10 +540,10 @@ namespace DOM Element tag name null NamedNodeMap Entity entity name null null EntityReference name of entity null null - referenced + referenced Notation notation name null null - Processing\ target entire content excluding null - Instruction the target + Processing\ target entire content excluding null + Instruction the target Text "#text" content of the text node null */ OUString aName; @@ -639,6 +556,8 @@ namespace DOM NodeType SAL_CALL CNode::getNodeType() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return m_aNodeType; } @@ -658,14 +577,13 @@ namespace DOM Reference< XDocument > SAL_CALL CNode::getOwnerDocument() throw (RuntimeException) { - Reference<XDocument> aDoc; - if (m_aNodePtr != NULL) - { - aDoc = Reference< XDocument >(static_cast< CDocument* >( - CNode::get((xmlNodePtr)m_aNodePtr->doc))); - } - return aDoc; + ::osl::MutexGuard const g(m_rMutex); + if (0 == m_aNodePtr) { + return 0; + } + Reference< XDocument > const xDoc(& GetOwnerDocument()); + return xDoc; } /** @@ -674,12 +592,14 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getParentNode() throw (RuntimeException) { - Reference<XNode> aNode; - if (m_aNodePtr != NULL) - { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->parent)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->parent).get()); + return xNode; } /** @@ -688,6 +608,8 @@ namespace DOM OUString SAL_CALL CNode::getPrefix() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aPrefix; if (m_aNodePtr != NULL && (m_aNodePtr->type == XML_ELEMENT_NODE || m_aNodePtr->type == XML_ATTRIBUTE_NODE) && @@ -707,12 +629,14 @@ namespace DOM Reference< XNode > SAL_CALL CNode::getPreviousSibling() throw (RuntimeException) { - Reference< XNode > aNode; - if (m_aNodePtr != NULL) - { - aNode = Reference< XNode >(CNode::get(m_aNodePtr->prev)); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return 0; } - return aNode; + Reference< XNode > const xNode( + GetOwnerDocument().GetCNode(m_aNodePtr->prev).get()); + return xNode; } /** @@ -721,6 +645,8 @@ namespace DOM sal_Bool SAL_CALL CNode::hasAttributes() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (m_aNodePtr != NULL && m_aNodePtr->properties != NULL); } @@ -730,6 +656,8 @@ namespace DOM sal_Bool SAL_CALL CNode::hasChildNodes() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (m_aNodePtr != NULL && m_aNodePtr->children != NULL); } @@ -740,7 +668,8 @@ namespace DOM const Reference< XNode >& newChild, const Reference< XNode >& refChild) throw (RuntimeException, DOMException) { - + if (!newChild.is() || !refChild.is()) { throw RuntimeException(); } + if (newChild->getOwnerDocument() != getOwnerDocument()) { DOMException e; e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; @@ -752,11 +681,42 @@ namespace DOM throw e; } - xmlNodePtr pRefChild = CNode::getNodePtr(refChild.get()); - xmlNodePtr pNewChild = CNode::getNodePtr(newChild.get()); + ::osl::ClearableMutexGuard guard(m_rMutex); + + CNode *const pNewNode(CNode::GetImplementation(newChild)); + CNode *const pRefNode(CNode::GetImplementation(refChild)); + if (!pNewNode || !pRefNode) { throw RuntimeException(); } + xmlNodePtr const pNewChild(pNewNode->GetNodePtr()); + xmlNodePtr const pRefChild(pRefNode->GetNodePtr()); + if (!pNewChild || !pRefChild) { throw RuntimeException(); } + + if (pNewChild == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + // already has parent + if (pNewChild->parent != NULL) + { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + + // attributes are unordered anyway, so just do appendChild + if (XML_ATTRIBUTE_NODE == pNewChild->type) { + guard.clear(); + return appendChild(newChild); + } + xmlNodePtr cur = m_aNodePtr->children; - //search cild before which to insert + //search child before which to insert while (cur != NULL) { if (cur == pRefChild) { @@ -764,8 +724,16 @@ namespace DOM pNewChild->next = cur; pNewChild->prev = cur->prev; cur->prev = pNewChild; - if( pNewChild->prev != NULL) + if (pNewChild->prev != NULL) { pNewChild->prev->next = pNewChild; + } + pNewChild->parent = cur->parent; + if (pNewChild->parent->children == cur) { + pNewChild->parent->children = pNewChild; + } + // do not update parent->last here! + pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc + break; } cur = cur->next; } @@ -779,14 +747,14 @@ namespace DOM sal_Bool SAL_CALL CNode::isSupported(const OUString& /*feature*/, const OUString& /*ver*/) throw (RuntimeException) { - // XXX + OSL_ENSURE(false, "CNode::isSupported: not implemented (#i113683#)"); return sal_False; } /** - Puts all Text nodes in the full depth of the sub-tree underneath this + Puts all Text nodes in the full depth of the sub-tree underneath this Node, including attribute nodes, into a "normal" form where only structure - (e.g., elements, comments, processing instructions, CDATA sections, and + (e.g., elements, comments, processing instructions, CDATA sections, and entity references) separates Text nodes, i.e., there are neither adjacent Text nodes nor empty Text nodes. */ @@ -794,81 +762,81 @@ namespace DOM throw (RuntimeException) { //XXX combine adjacent text nodes and remove empty ones + OSL_ENSURE(false, "CNode::normalize: not implemented (#i113683#)"); } /** Removes the child node indicated by oldChild from the list of children, and returns it. */ - Reference< XNode > SAL_CALL CNode::removeChild(const Reference< XNode >& oldChild) + Reference< XNode > SAL_CALL + CNode::removeChild(const Reference< XNode >& xOldChild) throw (RuntimeException, DOMException) { + if (!xOldChild.is()) { + throw RuntimeException(); + } - if (oldChild->getParentNode() != Reference< XNode >(this)) { + if (xOldChild->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + if (xOldChild->getParentNode() != Reference< XNode >(this)) { DOMException e; e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; throw e; } - Reference<XNode> xReturn( oldChild ); + ::osl::ClearableMutexGuard guard(m_rMutex); + + if (!m_aNodePtr) { throw RuntimeException(); } - xmlNodePtr old = CNode::getNodePtr(oldChild); + Reference<XNode> xReturn( xOldChild ); + + ::rtl::Reference<CNode> const pOld(CNode::GetImplementation(xOldChild)); + if (!pOld.is()) { throw RuntimeException(); } + xmlNodePtr const old = pOld->GetNodePtr(); + if (!old) { throw RuntimeException(); } if( old->type == XML_ATTRIBUTE_NODE ) { - xmlAttrPtr pAttr = (xmlAttrPtr) old; + xmlAttrPtr pAttr = reinterpret_cast<xmlAttrPtr>(old); xmlRemoveProp( pAttr ); + pOld->invalidate(); // freed by xmlRemoveProp xReturn.clear(); } else { - - // update .last - if (m_aNodePtr->last == old) - m_aNodePtr->last = old->prev; - - xmlNodePtr cur = m_aNodePtr->children; - //find old node in child list - while (cur != NULL) - { - if(cur == old) - { - // unlink node from list - if (cur->prev != NULL) - cur->prev->next = cur->next; - if (cur->next != NULL) - cur->next->prev = cur->prev; - if (cur->parent != NULL && cur->parent->children == cur) - cur->parent->children = cur->next; - cur->prev = NULL; - cur->next = NULL; - cur->parent = NULL; - } - cur = cur->next; - } + xmlUnlinkNode(old); + pOld->m_bUnlinked = true; } /*DOMNodeRemoved - * Fired when a node is being removed from its parent node. - * This event is dispatched before the node is removed from the tree. + * Fired when a node is being removed from its parent node. + * This event is dispatched before the node is removed from the tree. * The target of this event is the node being removed. * Bubbles: Yes * Cancelable: No * Context Info: relatedNode holds the parent node */ - if (oldChild.is()) - { - Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); - Reference< XMutationEvent > event(docevent->createEvent( - OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"), sal_True, - sal_False, Reference< XNode >(CNode::get(m_aNodePtr)), - OUString(), OUString(), OUString(), (AttrChangeType)0 ); - dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); + Reference< XMutationEvent > event(docevent->createEvent( + OUString::createFromAscii("DOMNodeRemoved")), UNO_QUERY); + event->initMutationEvent(OUString::createFromAscii("DOMNodeRemoved"), + sal_True, + sal_False, + this, + OUString(), OUString(), OUString(), (AttrChangeType)0 ); + + // the following dispatch functions use only UNO interfaces + // and call event listeners, so release mutex to prevent deadlocks. + guard.clear(); + + dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); + // subtree modified for this node + dispatchSubtreeModified(); - // subtree modofied for this node - dispatchSubtreeModified(); - } return xReturn; } @@ -877,23 +845,56 @@ namespace DOM and returns the oldChild node. */ Reference< XNode > SAL_CALL CNode::replaceChild( - const Reference< XNode >& newChild, const Reference< XNode >& oldChild) + Reference< XNode > const& xNewChild, + Reference< XNode > const& xOldChild) throw (RuntimeException, DOMException) { - // XXX check node types + if (!xOldChild.is() || !xNewChild.is()) { + throw RuntimeException(); + } - if (oldChild->getParentNode() != Reference< XNode >(this)) { + if (xNewChild->getOwnerDocument() != getOwnerDocument()) { + DOMException e; + e.Code = DOMExceptionType_WRONG_DOCUMENT_ERR; + throw e; + } + if (xOldChild->getParentNode() != Reference< XNode >(this)) { DOMException e; e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; throw e; } + ::osl::ClearableMutexGuard guard(m_rMutex); + /* Reference< XNode > aNode = removeChild(oldChild); appendChild(newChild); */ - xmlNodePtr pOld = CNode::getNodePtr(oldChild); - xmlNodePtr pNew = CNode::getNodePtr(newChild); + ::rtl::Reference<CNode> const pOldNode( + CNode::GetImplementation(xOldChild)); + ::rtl::Reference<CNode> const pNewNode( + CNode::GetImplementation(xNewChild)); + if (!pOldNode.is() || !pNewNode.is()) { throw RuntimeException(); } + xmlNodePtr const pOld = pOldNode->GetNodePtr(); + xmlNodePtr const pNew = pNewNode->GetNodePtr(); + if (!pOld || !pNew) { throw RuntimeException(); } + + if (pNew == m_aNodePtr) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + // already has parent + if (pNew->parent != NULL) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } + if (!IsChildTypeAllowed(pNewNode->m_aNodeType)) { + DOMException e; + e.Code = DOMExceptionType_HIERARCHY_REQUEST_ERR; + throw e; + } if( pOld->type == XML_ATTRIBUTE_NODE ) { @@ -907,7 +908,8 @@ namespace DOM xmlAttrPtr pAttr = (xmlAttrPtr)pOld; xmlRemoveProp( pAttr ); - appendChild( newChild ); + pOldNode->invalidate(); // freed by xmlRemoveProp + appendChild(xNewChild); } else { @@ -933,24 +935,30 @@ namespace DOM pOld->next = NULL; pOld->prev = NULL; pOld->parent = NULL; + pOldNode->m_bUnlinked = true; + pNewNode->m_bUnlinked = false; // will be deleted by xmlFreeDoc } cur = cur->next; } } + guard.clear(); // release for calling event handlers dispatchSubtreeModified(); - return oldChild; + return xOldChild; } void CNode::dispatchSubtreeModified() { + // only uses UNO interfaces => needs no mutex + // dispatch DOMSubtreeModified // target is _this_ node Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY); Reference< XMutationEvent > event(docevent->createEvent( OUString::createFromAscii("DOMSubtreeModified")), UNO_QUERY); - event->initMutationEvent(OUString::createFromAscii("DOMSubtreeModified"), sal_True, + event->initMutationEvent( + OUString::createFromAscii("DOMSubtreeModified"), sal_True, sal_False, Reference< XNode >(), OUString(), OUString(), OUString(), (AttrChangeType)0 ); dispatchEvent(Reference< XEvent >(event, UNO_QUERY)); @@ -959,7 +967,7 @@ namespace DOM /** The value of this node, depending on its type; see the table above. */ - void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/) + void SAL_CALL CNode::setNodeValue(const OUString& /*nodeValue*/) throw (RuntimeException, DOMException) { // use specific node implememntation @@ -975,45 +983,81 @@ namespace DOM void SAL_CALL CNode::setPrefix(const OUString& prefix) throw (RuntimeException, DOMException) { + ::osl::MutexGuard const g(m_rMutex); + + if ((0 == m_aNodePtr) || + ((m_aNodePtr->type != XML_ELEMENT_NODE) && + (m_aNodePtr->type != XML_ATTRIBUTE_NODE))) + { + DOMException e; + e.Code = DOMExceptionType_NO_MODIFICATION_ALLOWED_ERR; + throw e; + } OString o1 = OUStringToOString(prefix, RTL_TEXTENCODING_UTF8); xmlChar *pBuf = (xmlChar*)o1.getStr(); - // XXX copy buf? - // XXX free old string? (leak?) if (m_aNodePtr != NULL && m_aNodePtr->ns != NULL) { - m_aNodePtr->ns->prefix = pBuf; + xmlFree(const_cast<xmlChar *>(m_aNodePtr->ns->prefix)); + m_aNodePtr->ns->prefix = xmlStrdup(pBuf); } } // --- XEventTarget - void SAL_CALL CNode::addEventListener(const OUString& eventType, - const Reference< com::sun::star::xml::dom::events::XEventListener >& listener, + void SAL_CALL CNode::addEventListener(const OUString& eventType, + const Reference< com::sun::star::xml::dom::events::XEventListener >& listener, sal_Bool useCapture) throw (RuntimeException) { - events::CEventDispatcher::addListener(m_aNodePtr, eventType, listener, useCapture); + ::osl::MutexGuard const g(m_rMutex); + + CDocument & rDocument(GetOwnerDocument()); + events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher()); + rDispatcher.addListener(m_aNodePtr, eventType, listener, useCapture); } - void SAL_CALL CNode::removeEventListener(const OUString& eventType, - const Reference< com::sun::star::xml::dom::events::XEventListener >& listener, + void SAL_CALL CNode::removeEventListener(const OUString& eventType, + const Reference< com::sun::star::xml::dom::events::XEventListener >& listener, sal_Bool useCapture) throw (RuntimeException) { - events::CEventDispatcher::removeListener(m_aNodePtr, eventType, listener, useCapture); + ::osl::MutexGuard const g(m_rMutex); + + CDocument & rDocument(GetOwnerDocument()); + events::CEventDispatcher & rDispatcher(rDocument.GetEventDispatcher()); + rDispatcher.removeListener(m_aNodePtr, eventType, listener, useCapture); } sal_Bool SAL_CALL CNode::dispatchEvent(const Reference< XEvent >& evt) throw(RuntimeException, EventException) { - events::CEventDispatcher::dispatchEvent(m_aNodePtr, evt); + CDocument * pDocument; + events::CEventDispatcher * pDispatcher; + xmlNodePtr pNode; + { + ::osl::MutexGuard const g(m_rMutex); + + pDocument = & GetOwnerDocument(); + pDispatcher = & pDocument->GetEventDispatcher(); + pNode = m_aNodePtr; + } + // this calls event listeners, do not call with locked mutex + pDispatcher->dispatchEvent(*pDocument, m_rMutex, pNode, this, evt); return sal_True; } - ::sal_Int64 SAL_CALL CNode::getSomething(const Sequence< ::sal_Int8 >& /*aIdentifier*/) + ::sal_Int64 SAL_CALL + CNode::getSomething(Sequence< ::sal_Int8 > const& rId) throw (RuntimeException) { - return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(m_aNodePtr)); + if ((rId.getLength() == 16) && + (0 == rtl_compareMemory(UnoTunnelId::get().getConstArray(), + rId.getConstArray(), 16))) + { + return ::sal::static_int_cast< sal_Int64 >( + reinterpret_cast< sal_IntPtr >(this) ); + } + return 0; } } diff --git a/unoxml/source/dom/node.hxx b/unoxml/source/dom/node.hxx index fc852a37e..d4c94ab87 100644 --- a/unoxml/source/dom/node.hxx +++ b/unoxml/source/dom/node.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,37 +25,35 @@ * ************************************************************************/ -#ifndef _NODE_HXX -#define _NODE_HXX +#ifndef DOM_NODE_HXX +#define DOM_NODE_HXX + +#include <hash_map> + +#include <libxml/tree.h> +#include <sal/types.h> #include <rtl/ref.hxx> #include <rtl/string.hxx> #include <rtl/ustring.hxx> -#include <sal/types.h> -#include <sax/fastattribs.hxx> -#include <cppuhelper/implbase1.hxx> + #include <cppuhelper/implbase3.hxx> + +#include <sax/fastattribs.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Sequence.h> #include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> #include <com/sun/star/xml/dom/NodeType.hpp> -#include <com/sun/star/uno/Sequence.h> #include <com/sun/star/xml/dom/events/XEventTarget.hpp> -#include <com/sun/star/xml/dom/events/XDocumentEvent.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> -#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> -#include <com/sun/star/xml/dom/events/XUIEvent.hpp> -#include <com/sun/star/xml/dom/events/XMouseEvent.hpp> #include <com/sun/star/xml/dom/DOMException.hpp> #include <com/sun/star/xml/sax/XDocumentHandler.hpp> #include <com/sun/star/xml/sax/XFastDocumentHandler.hpp> -#include <libxml/tree.h> -#include <map> -#include <hash_map> using ::rtl::OUString; using ::rtl::OString; @@ -64,9 +62,9 @@ using namespace com::sun::star::uno; using namespace com::sun::star::xml::sax; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::dom::events; - using com::sun::star::lang::XUnoTunnel; + namespace DOM { struct Context @@ -91,8 +89,8 @@ namespace DOM }; typedef std::vector< std::vector<Namespace> > NamespaceVectorType; - typedef std::hash_map< OUString, - sal_Int32, + typedef std::hash_map< OUString, + sal_Int32, rtl::OUStringHash > NamespaceMapType; /// outer vector: xml context; inner vector: current NS @@ -113,31 +111,29 @@ namespace DOM /// add namespaces on this node to context void addNamespaces(Context& io_rContext, xmlNodePtr pNode); - class CNode; - typedef std::map< const xmlNodePtr, CNode* > nodemap_t; - + class CDocument; class CNode : public cppu::WeakImplHelper3< XNode, XUnoTunnel, XEventTarget > { friend class CDocument; friend class CElement; friend class CAttributesMap; - friend class CChildList; - friend class CElementList; - friend class CEntitiesMap; - friend class CNotationsMap; + private: - static nodemap_t theNodeMap; + bool m_bUnlinked; /// node has been removed from document protected: - NodeType m_aNodeType; + NodeType const m_aNodeType; + /// libxml node; NB: not const, because invalidate may reset it to 0! xmlNodePtr m_aNodePtr; - Reference< XDocument > m_rDocument; + ::rtl::Reference< CDocument > const m_xDocument; + ::osl::Mutex & m_rMutex; // for initialization by classes derived through ImplInheritanceHelper - CNode(); - void init_node(const xmlNodePtr aNode); + CNode(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + void invalidate(); void dispatchSubtreeModified(); @@ -145,41 +141,41 @@ namespace DOM virtual ~CNode(); - // get a representaion for a libxml node - static CNode* get(const xmlNodePtr aNode, sal_Bool bCreate = sal_True); - // remove a wrapper instance - static void remove(const xmlNodePtr aNode); + static CNode * GetImplementation(::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface> const& xNode); - // get the libxml node implementation - static xmlNodePtr getNodePtr(const Reference< XNode >& aNode); + xmlNodePtr GetNodePtr() { return m_aNodePtr; } - //static Sequence< sal_Int8 > + virtual CDocument & GetOwnerDocument(); // recursively create SAX events - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); // recursively create SAX events - virtual void SAL_CALL fastSaxify( Context& io_rContext ); + virtual void fastSaxify( Context& io_rContext ); + + // constrains child relationship between nodes based on type + virtual bool IsChildTypeAllowed(NodeType const nodeType); // ---- DOM interfaces /** Adds the node newChild to the end of the list of children of this node. */ - virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) + virtual Reference< XNode > SAL_CALL + appendChild(Reference< XNode > const& xNewChild) throw (RuntimeException, DOMException); /** - Returns a duplicate of this node, i.e., serves as a generic copy + Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. */ virtual Reference< XNode > SAL_CALL cloneNode(sal_Bool deep) throw (RuntimeException); /** - A NamedNodeMap containing the attributes of this node (if it is an Element) - or null otherwise. + A NamedNodeMap containing the attributes of this node + (if it is an Element) or null otherwise. */ virtual Reference< XNamedNodeMap > SAL_CALL getAttributes() throw (RuntimeException); @@ -203,7 +199,7 @@ namespace DOM throw (RuntimeException); /** - Returns the local part of the qualified name of this node. + Returns the local part of the qualified name of this node. */ virtual OUString SAL_CALL getLocalName() throw (RuntimeException); @@ -291,9 +287,9 @@ namespace DOM throw (RuntimeException); /** - Puts all Text nodes in the full depth of the sub-tree underneath this + Puts all Text nodes in the full depth of the sub-tree underneath this Node, including attribute nodes, into a "normal" form where only structure - (e.g., elements, comments, processing instructions, CDATA sections, and + (e.g., elements, comments, processing instructions, CDATA sections, and entity references) separates Text nodes, i.e., there are neither adjacent Text nodes nor empty Text nodes. */ @@ -343,12 +339,13 @@ namespace DOM throw(RuntimeException, EventException); // --- XUnoTunnel - virtual ::sal_Int64 SAL_CALL getSomething(const Sequence< ::sal_Int8 >& aIdentifier) + virtual ::sal_Int64 SAL_CALL + getSomething(Sequence< ::sal_Int8 > const& rId) throw (RuntimeException); }; /// eliminate redundant namespace declarations - void _nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent); + void nscleanup(const xmlNodePtr aNode, const xmlNodePtr aParent); } #endif diff --git a/unoxml/source/dom/notation.cxx b/unoxml/source/dom/notation.cxx index 22be136cd..5988d1a97 100644 --- a/unoxml/source/dom/notation.cxx +++ b/unoxml/source/dom/notation.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,21 +25,24 @@ * ************************************************************************/ -#include "notation.hxx" +#include <notation.hxx> + #include <string.h> namespace DOM { - CNotation::CNotation(const xmlNotationPtr aNotationPtr) + CNotation::CNotation(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNotationPtr const pNotation) + : CNotation_Base(rDocument, rMutex, + NodeType_NOTATION_NODE, reinterpret_cast<xmlNodePtr>(pNotation)) + , m_aNotationPtr(pNotation) { - m_aNodeType = NodeType_NOTATION_NODE; - m_aNotationPtr = aNotationPtr; - init_node((xmlNodePtr)aNotationPtr); } OUString SAL_CALL CNotation::getPublicId() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CNotation::getPublicId: not implemented (#i113683#)"); return OUString(); } @@ -48,13 +51,16 @@ namespace DOM */ OUString SAL_CALL CNotation::getSystemId() throw (RuntimeException) { - // XXX + OSL_ENSURE(false, + "CNotation::getSystemId: not implemented (#i113683#)"); return OUString(); } OUString SAL_CALL CNotation::getNodeName()throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + OUString aName; if (m_aNodePtr != NULL) { @@ -63,6 +69,7 @@ namespace DOM } return aName; } + OUString SAL_CALL CNotation::getNodeValue() throw (RuntimeException) { return OUString(); diff --git a/unoxml/source/dom/notation.hxx b/unoxml/source/dom/notation.hxx index 1335c0e8b..c98e81b35 100644 --- a/unoxml/source/dom/notation.hxx +++ b/unoxml/source/dom/notation.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,14 +25,16 @@ * ************************************************************************/ -#ifndef _NOTATION_HXX -#define _NOTATION_HXX +#ifndef DOM_NOTATION_HXX +#define DOM_NOTATION_HXX + +#include <libxml/tree.h> #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNotation.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,14 +42,20 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CNotation : public cppu::ImplInheritanceHelper1< CNode, XNotation > + typedef cppu::ImplInheritanceHelper1< CNode, XNotation > CNotation_Base; + + class CNotation + : public CNotation_Base { - friend class CNode; + private: + friend class CDocument; + private: xmlNotationPtr m_aNotationPtr; protected: - CNotation(const xmlNotationPtr); + CNotation(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNotationPtr const pNotation); /** The public identifier of this notation. diff --git a/unoxml/source/dom/notationsmap.cxx b/unoxml/source/dom/notationsmap.cxx index cf33d1b4a..a37fed98c 100644 --- a/unoxml/source/dom/notationsmap.cxx +++ b/unoxml/source/dom/notationsmap.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,12 +25,18 @@ * ************************************************************************/ -#include "notationsmap.hxx" +#include <notationsmap.hxx> + +#include <documenttype.hxx> + namespace DOM { - CNotationsMap::CNotationsMap(const CDocumentType* aDocType) - : m_pDocType(aDocType) + CNotationsMap::CNotationsMap( + ::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex) + : m_pDocType(pDocType) + , m_rMutex(rMutex) { } @@ -39,63 +45,92 @@ namespace DOM */ sal_Int32 SAL_CALL CNotationsMap::getLength() throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::getLength: not implemented (#i113683#)"); return 0; } /** - Retrieves a node specified by local name + Retrieves a node specified by local name */ - Reference< XNode > SAL_CALL CNotationsMap::getNamedItem(const OUString& /* name */) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::getNamedItem(OUString const& /*name*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::getNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Retrieves a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CNotationsMap::getNamedItemNS(const OUString& /*namespaceURI*/, const OUString& /*localName*/) -throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::getNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::getNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** Returns the indexth item in the map. */ - Reference< XNode > SAL_CALL CNotationsMap::item(sal_Int32 /*index*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::item(sal_Int32 /*index*/) throw (RuntimeException) { + OSL_ENSURE(false, "CNotationsMap::item: not implemented (#i113683#)"); return Reference< XNode >(); } /** Removes a node specified by name. */ - Reference< XNode > SAL_CALL CNotationsMap::removeNamedItem(const OUString& /*name*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::removeNamedItem(OUString const& /*name*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::removeNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Removes a node specified by local name and namespace URI. */ - Reference< XNode > SAL_CALL CNotationsMap::removeNamedItemNS(const OUString& /*namespaceURI*/, const OUString& /*localName*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::removeNamedItemNS( + OUString const& /*namespaceURI*/, OUString const& /*localName*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::removeNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } /** // Adds a node using its nodeName attribute. */ - Reference< XNode > SAL_CALL CNotationsMap::setNamedItem(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::setNamedItem(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::setNamedItem: not implemented (#i113683#)"); return Reference< XNode >(); } /** Adds a node using its namespaceURI and localName. */ - Reference< XNode > SAL_CALL CNotationsMap::setNamedItemNS(const Reference< XNode >& /*arg*/) throw (RuntimeException) + Reference< XNode > SAL_CALL + CNotationsMap::setNamedItemNS(Reference< XNode > const& /*arg*/) + throw (RuntimeException) { + OSL_ENSURE(false, + "CNotationsMap::setNamedItemNS: not implemented (#i113683#)"); return Reference< XNode >(); } } diff --git a/unoxml/source/dom/notationsmap.hxx b/unoxml/source/dom/notationsmap.hxx index 0564d799c..426483113 100644 --- a/unoxml/source/dom/notationsmap.hxx +++ b/unoxml/source/dom/notationsmap.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,18 +25,18 @@ * ************************************************************************/ -#ifndef _NOTATIONSMAP_HXX -#define _NOTATIONSMAP_HXX +#ifndef DOM_NOTATIONSMAP_HXX +#define DOM_NOTATIONSMAP_HXX -#include <map> #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> +#include <rtl/ref.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNamedNodeMap.hpp> -#include "document.hxx" -#include "documenttype.hxx" + +#include <cppuhelper/implbase1.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -44,13 +44,18 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CNotationsMap : public cppu::WeakImplHelper1< XNamedNodeMap > + class CDocumentType; + + class CNotationsMap + : public cppu::WeakImplHelper1< XNamedNodeMap > { private: - const CDocumentType* m_pDocType; + ::rtl::Reference<CDocumentType> const m_pDocType; + ::osl::Mutex & m_rMutex; public: - CNotationsMap(const CDocumentType* aDocType); + CNotationsMap(::rtl::Reference<CDocumentType> const& pDocType, + ::osl::Mutex & rMutex); /** The number of nodes in this map. @@ -58,39 +63,50 @@ namespace DOM virtual sal_Int32 SAL_CALL getLength() throw (RuntimeException); /** - Retrieves a node specified by local name + Retrieves a node specified by local name */ - virtual Reference< XNode > SAL_CALL getNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + getNamedItem(OUString const& name) throw (RuntimeException); /** Retrieves a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL getNamedItemNS(const OUString& namespaceURI,const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL getNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** Returns the indexth item in the map. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + item(sal_Int32 index) throw (RuntimeException); /** Removes a node specified by name. */ - virtual Reference< XNode > SAL_CALL removeNamedItem(const OUString& name) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + removeNamedItem(OUString const& name) throw (RuntimeException); /** // Removes a node specified by local name and namespace URI. */ - virtual Reference< XNode > SAL_CALL removeNamedItemNS(const OUString& namespaceURI, const OUString& localName) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL removeNamedItemNS( + OUString const& namespaceURI, OUString const& localName) + throw (RuntimeException); /** // Adds a node using its nodeName attribute. */ - virtual Reference< XNode > SAL_CALL setNamedItem(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItem(Reference< XNode > const& arg) + throw (RuntimeException); /** Adds a node using its namespaceURI and localName. */ - virtual Reference< XNode > SAL_CALL setNamedItemNS(const Reference< XNode >& arg) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL + setNamedItemNS(Reference< XNode > const& arg) + throw (RuntimeException); }; } diff --git a/unoxml/source/dom/processinginstruction.cxx b/unoxml/source/dom/processinginstruction.cxx index a24ba05d4..b604a3284 100644 --- a/unoxml/source/dom/processinginstruction.cxx +++ b/unoxml/source/dom/processinginstruction.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,19 +25,24 @@ * ************************************************************************/ -#include "processinginstruction.hxx" -#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <processinginstruction.hxx> + #include <string.h> +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> + + namespace DOM { - CProcessingInstruction::CProcessingInstruction(const xmlNodePtr aNodePtr) + CProcessingInstruction::CProcessingInstruction( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CProcessingInstruction_Base(rDocument, rMutex, + NodeType_PROCESSING_INSTRUCTION_NODE, pNode) { - m_aNodeType = NodeType_PROCESSING_INSTRUCTION_NODE; - init_node(aNodePtr); } - void SAL_CALL CProcessingInstruction::saxify( + void CProcessingInstruction::saxify( const Reference< XDocumentHandler >& i_xHandler) { if (!i_xHandler.is()) throw RuntimeException(); Reference< XExtendedDocumentHandler > xExtended(i_xHandler, UNO_QUERY); @@ -49,44 +54,90 @@ namespace DOM /** The content of this processing instruction. */ - OUString SAL_CALL CProcessingInstruction::getData() throw (RuntimeException) + OUString SAL_CALL + CProcessingInstruction::getData() throw (RuntimeException) { - // XXX - return OUString(); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + + char const*const pContent( + reinterpret_cast<char const*>(m_aNodePtr->content)); + if (0 == pContent) { + return ::rtl::OUString(); + } + OUString const ret(pContent, strlen(pContent), RTL_TEXTENCODING_UTF8); + return ret; } /** The target of this processing instruction. */ - OUString SAL_CALL CProcessingInstruction::getTarget() throw (RuntimeException) + OUString SAL_CALL + CProcessingInstruction::getTarget() throw (RuntimeException) { - // XXX - return OUString(); - } + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); + } + char const*const pName( + reinterpret_cast<char const*>(m_aNodePtr->name)); + if (0 == pName) { + return ::rtl::OUString(); + } + OUString const ret(pName, strlen(pName), RTL_TEXTENCODING_UTF8); + return ret; + } /** The content of this processing instruction. */ - void SAL_CALL CProcessingInstruction::setData(const OUString& /*data*/) throw (RuntimeException, DOMException) + void SAL_CALL CProcessingInstruction::setData(OUString const& rData) + throw (RuntimeException, DOMException) { - // XXX - } + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + throw RuntimeException(); + } + OString const data( + ::rtl::OUStringToOString(rData, RTL_TEXTENCODING_UTF8)); + xmlChar const*const pData( + reinterpret_cast<xmlChar const*>(data.getStr()) ); + xmlFree(m_aNodePtr->content); + m_aNodePtr->content = xmlStrdup(pData); + } - OUString SAL_CALL CProcessingInstruction::getNodeName()throw (RuntimeException) + OUString SAL_CALL + CProcessingInstruction::getNodeName() throw (RuntimeException) { - OUString aName; - if (m_aNodePtr != NULL) - { - const xmlChar* xName = m_aNodePtr->name; - aName = OUString((sal_Char*)xName, strlen((char*)xName), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_aNodePtr) { + return ::rtl::OUString(); } - return aName; + + sal_Char const*const pName = + reinterpret_cast<sal_Char const*>(m_aNodePtr->name); + OUString const ret(pName, strlen(pName), RTL_TEXTENCODING_UTF8); + return ret; } - OUString SAL_CALL CProcessingInstruction::getNodeValue() throw (RuntimeException) + OUString SAL_CALL CProcessingInstruction::getNodeValue() + throw (RuntimeException) { return getData(); } + + void SAL_CALL + CProcessingInstruction::setNodeValue(OUString const& rNodeValue) + throw (RuntimeException, DOMException) + { + return setData(rNodeValue); + } } diff --git a/unoxml/source/dom/processinginstruction.hxx b/unoxml/source/dom/processinginstruction.hxx index ddd204deb..4bf8d52f3 100644 --- a/unoxml/source/dom/processinginstruction.hxx +++ b/unoxml/source/dom/processinginstruction.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,14 +25,16 @@ * ************************************************************************/ -#ifndef _PROCESSINGINSTRUCTION_HXX -#define _PROCESSINGINSTRUCTION_HXX +#ifndef DOM_PROCESSINGINSTRUCTION_HXX +#define DOM_PROCESSINGINSTRUCTION_HXX + +#include <libxml/tree.h> #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XProcessingInstruction.hpp> -#include "node.hxx" -#include <libxml/tree.h> + +#include <node.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; @@ -40,17 +42,23 @@ using namespace com::sun::star::xml::dom; namespace DOM { - class CProcessingInstruction : public cppu::ImplInheritanceHelper1< CNode, XProcessingInstruction > + typedef ::cppu::ImplInheritanceHelper1< CNode, XProcessingInstruction > + CProcessingInstruction_Base; + + class CProcessingInstruction + : public CProcessingInstruction_Base { - friend class CNode; + private: + friend class CDocument; protected: - CProcessingInstruction(const xmlNodePtr aNodePtr); + CProcessingInstruction( + CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); /** The content of this processing instruction. @@ -73,6 +81,9 @@ namespace DOM throw (RuntimeException); virtual OUString SAL_CALL getNodeValue() throw (RuntimeException); + virtual void SAL_CALL setNodeValue(OUString const& rNodeValue) + throw (RuntimeException, DOMException); + // --- delegation for XNde base. virtual Reference< XNode > SAL_CALL appendChild(const Reference< XNode >& newChild) throw (RuntimeException, DOMException) @@ -181,11 +192,6 @@ namespace DOM { return CNode::replaceChild(newChild, oldChild); } - virtual void SAL_CALL setNodeValue(const OUString& nodeValue) - throw (RuntimeException, DOMException) - { - return CNode::setNodeValue(nodeValue); - } virtual void SAL_CALL setPrefix(const OUString& prefix) throw (RuntimeException, DOMException) { diff --git a/unoxml/source/dom/saxbuilder.cxx b/unoxml/source/dom/saxbuilder.cxx index 75d07ddc8..524e4353e 100644 --- a/unoxml/source/dom/saxbuilder.cxx +++ b/unoxml/source/dom/saxbuilder.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -28,11 +28,10 @@ #pragma warning(disable : 4701) #endif -#include "node.hxx" #include "saxbuilder.hxx" + #include <com/sun/star/xml/dom/XDocumentBuilder.hpp> -#include <libxml/tree.h> -#include <com/sun/star/uno/Sequence.h> + namespace DOM { @@ -93,12 +92,16 @@ namespace DOM SAXDocumentBuilderState SAL_CALL CSAXDocumentBuilder::getState() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + return m_aState; } void SAL_CALL CSAXDocumentBuilder::reset() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + m_aDocument = Reference< XDocument >(); m_aFragment = Reference< XDocumentFragment >(); while (!m_aNodeStack.empty()) m_aNodeStack.pop(); @@ -109,6 +112,8 @@ namespace DOM Reference< XDocument > SAL_CALL CSAXDocumentBuilder::getDocument() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + if (m_aState != SAXDocumentBuilderState_DOCUMENT_FINISHED) throw RuntimeException(); @@ -118,6 +123,8 @@ namespace DOM Reference< XDocumentFragment > SAL_CALL CSAXDocumentBuilder::getDocumentFragment() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + if (m_aState != SAXDocumentBuilderState_FRAGMENT_FINISHED) throw RuntimeException(); return m_aFragment; @@ -126,6 +133,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::startDocumentFragment(const Reference< XDocument >& ownerDoc) throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + // start a new document fragment and push it onto the stack // we have to be in a clean state to do this if (!m_aState == SAXDocumentBuilderState_READY) @@ -141,6 +150,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::endDocumentFragment() throw (RuntimeException) { + ::osl::MutexGuard g(m_Mutex); + // there should only be the document left on the node stack if (m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) throw RuntimeException(); @@ -156,6 +167,7 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::startDocument() throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); // start a new document and push it onto the stack // we have to be in a clean state to do this @@ -172,6 +184,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::endDocument() throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // there should only be the document left on the node stack if (!m_aState == SAXDocumentBuilderState_BUILDING_DOCUMENT) throw SAXException(); @@ -186,6 +200,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::startElement(const OUString& aName, const Reference< XAttributeList>& attribs) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) { @@ -241,7 +257,8 @@ namespace DOM if ( result != aNSMap.end()) { // found a URI for prefix - aElement = m_aDocument->createElementNS( result->second, aName); // qualified name + // qualified name + aElement = m_aDocument->createElementNS( result->second, aName); } else { @@ -286,6 +303,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::endElement(const OUString& aName) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // pop the current element from the stack if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -313,6 +332,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::characters(const OUString& aChars) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // append text node to the current top element if (m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -325,6 +346,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::ignorableWhitespace(const OUString& ) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // ignore ignorable whitespace if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -334,6 +357,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::processingInstruction(const OUString& aTarget, const OUString& aData) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // append PI node to the current top if ( m_aState != SAXDocumentBuilderState_BUILDING_DOCUMENT && m_aState != SAXDocumentBuilderState_BUILDING_FRAGMENT) @@ -347,6 +372,8 @@ namespace DOM void SAL_CALL CSAXDocumentBuilder::setDocumentLocator(const Reference< XLocator >& aLocator) throw (RuntimeException, SAXException) { + ::osl::MutexGuard g(m_Mutex); + // set the document locator... m_aLocator = aLocator; } diff --git a/unoxml/source/dom/saxbuilder.hxx b/unoxml/source/dom/saxbuilder.hxx index 83b688a72..cd280c9f7 100644 --- a/unoxml/source/dom/saxbuilder.hxx +++ b/unoxml/source/dom/saxbuilder.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,13 +25,14 @@ * ************************************************************************/ -#ifndef _SAXBUILDER_HXX -#define _SAXBUILDER_HXX +#ifndef DOM_SAXBUILDER_HXX +#define DOM_SAXBUILDER_HXX #include <stack> #include <map> #include <sal/types.h> +#include <osl/mutex.hxx> #include <cppuhelper/implbase3.hxx> #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> @@ -49,8 +50,6 @@ #include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include "libxml/tree.h" - using ::rtl::OUString; using namespace com::sun::star::uno; using namespace com::sun::star::xml::dom; @@ -73,6 +72,7 @@ namespace DOM { private: + ::osl::Mutex m_Mutex; const Reference< XMultiServiceFactory > m_aServiceManager; SAXDocumentBuilderState m_aState; diff --git a/unoxml/source/dom/text.cxx b/unoxml/source/dom/text.cxx index 952a9606d..5d07aa86a 100644 --- a/unoxml/source/dom/text.cxx +++ b/unoxml/source/dom/text.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,40 +25,32 @@ * ************************************************************************/ -#include "text.hxx" +#include <text.hxx> + + namespace DOM { - CText::CText(const xmlNodePtr aNodePtr) + CText::CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode) + : CText_Base(rDocument, rMutex, reNodeType, rpNode) { - m_aNodeType = NodeType_TEXT_NODE; - init_characterdata(aNodePtr); - } - - void SAL_CALL CText::saxify( - const Reference< XDocumentHandler >& i_xHandler) { - if (!i_xHandler.is()) throw RuntimeException(); - i_xHandler->characters(getData()); } - void CText::init_text(const xmlNodePtr aNodePtr) + CText::CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode) + : CText_Base(rDocument, rMutex, NodeType_TEXT_NODE, pNode) { - init_characterdata(aNodePtr); } - Reference< XText > SAL_CALL CText::splitText(sal_Int32 /*offset*/) - throw (RuntimeException) - { - return Reference< XText >(this); + void CText::saxify( + const Reference< XDocumentHandler >& i_xHandler) { + if (!i_xHandler.is()) throw RuntimeException(); + i_xHandler->characters(getData()); } - OUString SAL_CALL CText::getNodeName()throw (RuntimeException) - { - return OUString::createFromAscii("#text"); - } - - void SAL_CALL CText::fastSaxify( Context& io_rContext ) + void CText::fastSaxify( Context& io_rContext ) { - if( io_rContext.mxCurrentHandler.is() ) + if (io_rContext.mxCurrentHandler.is()) { try { @@ -69,4 +61,15 @@ namespace DOM } } + OUString SAL_CALL CText::getNodeName() throw (RuntimeException) + { + return OUString::createFromAscii("#text"); + } + + Reference< XText > SAL_CALL CText::splitText(sal_Int32 /*offset*/) + throw (RuntimeException) + { + OSL_ENSURE(false, "CText::splitText: not implemented (#i113683#)"); + return Reference< XText >(this); + } } diff --git a/unoxml/source/dom/text.hxx b/unoxml/source/dom/text.hxx index 0a3ec5fc4..c58a4e142 100644 --- a/unoxml/source/dom/text.hxx +++ b/unoxml/source/dom/text.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,43 +25,49 @@ * ************************************************************************/ -#ifndef _TEXT_HXX -#define _TEXT_HXX +#ifndef DOM_TEXT_HXX +#define DOM_TEXT_HXX + +#include <libxml/tree.h> #include <sal/types.h> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XText.hpp> -#include <com/sun/star/xml/dom/XCharacterData.hpp> -#include <libxml/tree.h> -#include "characterdata.hxx" + +#include <characterdata.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; namespace DOM { - class CText : public cppu::ImplInheritanceHelper1< CCharacterData, XText > + typedef ::cppu::ImplInheritanceHelper1< CCharacterData, XText > CText_Base; + + class CText + : public CText_Base { - friend class CNode; + private: + friend class CDocument; protected: - CText(){} - CText(const xmlNodePtr aNodePtr); - void init_text(const xmlNodePtr aNodePtr); + CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + NodeType const& reNodeType, xmlNodePtr const& rpNode); + CText(CDocument const& rDocument, ::osl::Mutex const& rMutex, + xmlNodePtr const pNode); public: - virtual void SAL_CALL saxify( - const Reference< XDocumentHandler >& i_xHandler); + virtual void saxify(const Reference< XDocumentHandler >& i_xHandler); - virtual void SAL_CALL fastSaxify( Context& io_rContext ); + virtual void fastSaxify( Context& io_rContext ); - // Breaks this node into two nodes at the specified offset, keeping + // Breaks this node into two nodes at the specified offset, keeping // both in the tree as siblings. virtual Reference< XText > SAL_CALL splitText(sal_Int32 offset) throw (RuntimeException); diff --git a/unoxml/source/events/event.cxx b/unoxml/source/events/event.cxx index 8895e0153..87201d7ee 100644 --- a/unoxml/source/events/event.cxx +++ b/unoxml/source/events/event.cxx @@ -1,59 +1,108 @@ -#include "event.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ -namespace DOM { namespace events +#include <event.hxx> + +namespace DOM { namespace events { + CEvent::CEvent() + : m_canceled(sal_False) + , m_phase(PhaseType_CAPTURING_PHASE) + , m_bubbles(sal_False) + , m_cancelable(sal_True) + { + } + CEvent::~CEvent() { } OUString SAL_CALL CEvent::getType() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_eventType; } - Reference< XEventTarget > SAL_CALL CEvent::getTarget() throw (RuntimeException) + Reference< XEventTarget > SAL_CALL + CEvent::getTarget() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_target; } - Reference< XEventTarget > SAL_CALL CEvent::getCurrentTarget() throw (RuntimeException) + Reference< XEventTarget > SAL_CALL + CEvent::getCurrentTarget() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_currentTarget; } PhaseType SAL_CALL CEvent::getEventPhase() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_phase; } sal_Bool SAL_CALL CEvent::getBubbles() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_bubbles; } sal_Bool SAL_CALL CEvent::getCancelable() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_cancelable; } - com::sun::star::util::Time SAL_CALL CEvent::getTimeStamp() throw (RuntimeException) + com::sun::star::util::Time SAL_CALL + CEvent::getTimeStamp() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_time; } void SAL_CALL CEvent::stopPropagation() throw (RuntimeException) { - if (m_cancelable) m_canceled = sal_True; + ::osl::MutexGuard const g(m_Mutex); + if (m_cancelable) { m_canceled = sal_True; } } void SAL_CALL CEvent::preventDefault() throw (RuntimeException) { } - void SAL_CALL CEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + void SAL_CALL + CEvent::initEvent(OUString const& eventTypeArg, sal_Bool canBubbleArg, sal_Bool cancelableArg) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_eventType = eventTypeArg; m_bubbles = canBubbleArg; m_cancelable = cancelableArg; diff --git a/unoxml/source/events/event.hxx b/unoxml/source/events/event.hxx index b041f1963..0336be164 100644 --- a/unoxml/source/events/event.hxx +++ b/unoxml/source/events/event.hxx @@ -1,19 +1,44 @@ -#ifndef __EVENT_HXX -#define __EVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef EVENT_EVENT_HXX +#define EVENT_EVENT_HXX #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XEventTarget.hpp> #include <com/sun/star/util/Time.hpp> +#include <cppuhelper/implbase1.hxx> + #include "../dom/node.hxx" -#include <libxml/tree.h> using namespace com::sun::star::uno; using namespace com::sun::star::xml::dom; @@ -25,23 +50,13 @@ namespace DOM {namespace events class CEvent : public cppu::WeakImplHelper1< XEvent > { friend class CEventDispatcher; -friend class CNode; -friend class CDocument; -friend class CElement; -friend class CText; -friend class CCharacterData; -friend class CAttr; - - -private: - sal_Bool m_canceled; protected: + ::osl::Mutex m_Mutex; + sal_Bool m_canceled; OUString m_eventType; Reference< XEventTarget > m_target; Reference< XEventTarget > m_currentTarget; - //xmlNodePtr m_target; - //xmlNodePtr m_currentTarget; PhaseType m_phase; sal_Bool m_bubbles; sal_Bool m_cancelable; @@ -49,7 +64,7 @@ protected: public: - CEvent() : m_canceled(sal_False){} + explicit CEvent(); virtual ~CEvent(); virtual OUString SAL_CALL getType() throw (RuntimeException); @@ -62,9 +77,9 @@ public: virtual void SAL_CALL stopPropagation() throw (RuntimeException); virtual void SAL_CALL preventDefault() throw (RuntimeException); virtual void SAL_CALL initEvent( - const OUString& eventTypeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg) throw (RuntimeException); + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) throw (RuntimeException); }; }} #endif diff --git a/unoxml/source/events/eventdispatcher.cxx b/unoxml/source/events/eventdispatcher.cxx index 68c77b04a..4b4cac807 100644 --- a/unoxml/source/events/eventdispatcher.cxx +++ b/unoxml/source/events/eventdispatcher.cxx @@ -1,19 +1,46 @@ -#include "eventdispatcher.hxx" -#include "event.hxx" -#include "mutationevent.hxx" -#include "uievent.hxx" -#include "mouseevent.hxx" -#include "../dom/node.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ -namespace DOM { namespace events { +#include <eventdispatcher.hxx> + +#include <event.hxx> +#include <mutationevent.hxx> +#include <uievent.hxx> +#include <mouseevent.hxx> + +#include "../dom/document.hxx" - TypeListenerMap CEventDispatcher::captureListeners; - TypeListenerMap CEventDispatcher::targetListeners; + +namespace DOM { namespace events { void CEventDispatcher::addListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) { - TypeListenerMap* pTMap = &targetListeners; - if (bCapture) pTMap = &captureListeners; + TypeListenerMap *const pTMap = (bCapture) + ? (& m_CaptureListeners) : (& m_TargetListeners); // get the multimap for the specified type ListenerMap *pMap = 0; @@ -31,15 +58,15 @@ namespace DOM { namespace events { void CEventDispatcher::removeListener(xmlNodePtr pNode, OUString aType, const Reference<XEventListener>& aListener, sal_Bool bCapture) { - TypeListenerMap *pTMap = &targetListeners; - if (bCapture) pTMap = &captureListeners; - + TypeListenerMap *const pTMap = (bCapture) + ? (& m_CaptureListeners) : (& m_TargetListeners); + // get the multimap for the specified type TypeListenerMap::const_iterator tIter = pTMap->find(aType); if (tIter != pTMap->end()) { ListenerMap *pMap = tIter->second; // find listeners of specied type for specified node - ListenerMap::iterator iter = pMap->find(pNode); + ListenerMap::iterator iter = pMap->find(pNode); while (iter != pMap->end() && iter->first == pNode) { // erase all references to specified listener @@ -54,15 +81,15 @@ namespace DOM { namespace events { } } } - - void CEventDispatcher::callListeners(xmlNodePtr pNode, OUString aType, const Reference< XEvent >& xEvent, sal_Bool bCapture) - { - TypeListenerMap *pTMap = &targetListeners; - if (bCapture) pTMap = &captureListeners; - + + void CEventDispatcher::callListeners( + TypeListenerMap const& rTMap, + xmlNodePtr const pNode, + OUString aType, Reference< XEvent > const& xEvent) + { // get the multimap for the specified type - TypeListenerMap::const_iterator tIter = pTMap->find(aType); - if (tIter != pTMap->end()) { + TypeListenerMap::const_iterator tIter = rTMap.find(aType); + if (tIter != rTMap.end()) { ListenerMap *pMap = tIter->second; ListenerMap::const_iterator iter = pMap->lower_bound(pNode); ListenerMap::const_iterator ibound = pMap->upper_bound(pNode); @@ -74,12 +101,14 @@ namespace DOM { namespace events { } } - sal_Bool CEventDispatcher::dispatchEvent(xmlNodePtr aNodePtr, const Reference< XEvent >& aEvent) + bool CEventDispatcher::dispatchEvent( + DOM::CDocument & rDocument, ::osl::Mutex & rMutex, + xmlNodePtr const pNode, Reference<XNode> const& xNode, + Reference< XEvent > const& i_xEvent) const { CEvent *pEvent = 0; // pointer to internal event representation - Reference< XEvent > xEvent; // reference to the event being dispatched; - OUString aType = aEvent->getType(); + OUString const aType = i_xEvent->getType(); if (aType.compareToAscii("DOMSubtreeModified") == 0|| aType.compareToAscii("DOMNodeInserted") == 0|| aType.compareToAscii("DOMNodeRemoved") == 0|| @@ -87,26 +116,27 @@ namespace DOM { namespace events { aType.compareToAscii("DOMNodeInsertedIntoDocument") == 0|| aType.compareToAscii("DOMAttrModified") == 0|| aType.compareToAscii("DOMCharacterDataModified") == 0) - { - Reference< XMutationEvent > aMEvent(aEvent, UNO_QUERY); + { + Reference< XMutationEvent > const aMEvent(i_xEvent, + UNO_QUERY_THROW); // dispatch a mutation event - // we need to clone the event in order to have complete control + // we need to clone the event in order to have complete control // over the implementation CMutationEvent* pMEvent = new CMutationEvent; pMEvent->initMutationEvent( aType, aMEvent->getBubbles(), aMEvent->getCancelable(), aMEvent->getRelatedNode(), aMEvent->getPrevValue(), - aMEvent->getNewValue(), aMEvent->getAttrName(), - aMEvent->getAttrChange()); - pEvent = pMEvent; + aMEvent->getNewValue(), aMEvent->getAttrName(), + aMEvent->getAttrChange()); + pEvent = pMEvent; } else if ( // UIEvent aType.compareToAscii("DOMFocusIn") == 0|| aType.compareToAscii("DOMFocusOut") == 0|| aType.compareToAscii("DOMActivate") == 0) { - Reference< XUIEvent > aUIEvent(aEvent, UNO_QUERY); + Reference< XUIEvent > const aUIEvent(i_xEvent, UNO_QUERY_THROW); CUIEvent* pUIEvent = new CUIEvent; - pUIEvent->initUIEvent(aType, + pUIEvent->initUIEvent(aType, aUIEvent->getBubbles(), aUIEvent->getCancelable(), aUIEvent->getView(), aUIEvent->getDetail()); pEvent = pUIEvent; @@ -118,9 +148,10 @@ namespace DOM { namespace events { aType.compareToAscii("mousemove") == 0|| aType.compareToAscii("mouseout") == 0) { - Reference< XMouseEvent > aMouseEvent(aEvent, UNO_QUERY); + Reference< XMouseEvent > const aMouseEvent(i_xEvent, + UNO_QUERY_THROW); CMouseEvent *pMouseEvent = new CMouseEvent; - pMouseEvent->initMouseEvent(aType, + pMouseEvent->initMouseEvent(aType, aMouseEvent->getBubbles(), aMouseEvent->getCancelable(), aMouseEvent->getView(), aMouseEvent->getDetail(), aMouseEvent->getScreenX(), aMouseEvent->getScreenY(), @@ -134,65 +165,79 @@ namespace DOM { namespace events { { pEvent = new CEvent; pEvent->initEvent( - aType, aEvent->getBubbles(), aEvent->getCancelable()); + aType, i_xEvent->getBubbles(), i_xEvent->getCancelable()); } - pEvent->m_target = Reference< XEventTarget >(DOM::CNode::get(aNodePtr)); - pEvent->m_currentTarget = aEvent->getCurrentTarget(); - pEvent->m_time = aEvent->getTimeStamp(); + pEvent->m_target.set(xNode, UNO_QUERY_THROW); + pEvent->m_currentTarget = i_xEvent->getCurrentTarget(); + pEvent->m_time = i_xEvent->getTimeStamp(); // create the reference to the provate event implementation // that will be dispatched to the listeners - xEvent = Reference< XEvent >(pEvent); + Reference< XEvent > const xEvent(pEvent); // build the path from target node to the root - NodeVector captureVector; - xmlNodePtr cur = DOM::CNode::getNodePtr(Reference< XNode >(xEvent->getTarget(), UNO_QUERY_THROW)); - while (cur != NULL) + typedef std::vector< ::std::pair<Reference<XEventTarget>, xmlNodePtr> > + NodeVector_t; + NodeVector_t captureVector; + TypeListenerMap captureListeners; + TypeListenerMap targetListeners; { - captureVector.push_back(cur); - cur = cur->parent; + ::osl::MutexGuard g(rMutex); + + xmlNodePtr cur = pNode; + while (cur != NULL) + { + Reference< XEventTarget > const xRef( + rDocument.GetCNode(cur).get()); + captureVector.push_back(::std::make_pair(xRef, cur)); + cur = cur->parent; + } + captureListeners = m_CaptureListeners; + targetListeners = m_TargetListeners; } // the caputre vector now holds the node path from target to root - // first we must search for capture listernes in order root to + // first we must search for capture listernes in order root to // to target. after that, any target listeners have to be called // then bubbeling phase listeners are called in target to root // order - NodeVector::const_iterator inode; - // start at the root - inode = captureVector.end(); - inode--; - if (inode != captureVector.end()) + NodeVector_t::const_reverse_iterator rinode = + const_cast<NodeVector_t const&>(captureVector).rbegin(); + if (rinode != const_cast<NodeVector_t const&>(captureVector).rend()) { // capturing phase: pEvent->m_phase = PhaseType_CAPTURING_PHASE; - while (inode != captureVector.begin()) - { - //pEvent->m_currentTarget = *inode; - pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode)); - callListeners(*inode, aType, xEvent, sal_True); + while (rinode != + const_cast<NodeVector_t const&>(captureVector).rend()) + { + pEvent->m_currentTarget = rinode->first; + callListeners(captureListeners, rinode->second, aType, xEvent); if (pEvent->m_canceled) return sal_True; - inode--; + rinode++; } + NodeVector_t::const_iterator inode = captureVector.begin(); + // target phase pEvent->m_phase = PhaseType_AT_TARGET; - callListeners(*inode, aType, xEvent, sal_False); + pEvent->m_currentTarget = inode->first; + callListeners(targetListeners, inode->second, aType, xEvent); if (pEvent->m_canceled) return sal_True; // bubbeling phase inode++; - if (aEvent->getBubbles()) { + if (i_xEvent->getBubbles()) { pEvent->m_phase = PhaseType_BUBBLING_PHASE; while (inode != captureVector.end()) { - pEvent->m_currentTarget = Reference< XEventTarget >(DOM::CNode::get(*inode)); - callListeners(*inode, aType, xEvent, sal_False); + pEvent->m_currentTarget = inode->first; + callListeners(targetListeners, + inode->second, aType, xEvent); if (pEvent->m_canceled) return sal_True; inode++; } } - } + } return sal_True; } }} diff --git a/unoxml/source/events/eventdispatcher.hxx b/unoxml/source/events/eventdispatcher.hxx index 08b4fe124..62cb2d38b 100644 --- a/unoxml/source/events/eventdispatcher.hxx +++ b/unoxml/source/events/eventdispatcher.hxx @@ -1,51 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef EVENT_EVENT_DISPATCHER_HXX +#define EVENT_EVENT_DISPATCHER_HXX -//#include <multimap> #include <map> #include <vector> +#include <libxml/tree.h> + +#include <rtl/ustring.hxx> + #include <com/sun/star/uno/Reference.h> +#include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/events/EventType.hpp> #include <com/sun/star/xml/dom/events/PhaseType.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> -#include "event.hxx" + using namespace com::sun::star::uno; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::dom::events; -namespace DOM { namespace events -{ +namespace DOM { + +class CDocument; + +namespace events { -typedef std::vector< xmlNodePtr > NodeVector; typedef std::multimap< xmlNodePtr, Reference< com::sun::star::xml::dom::events::XEventListener> > ListenerMap; -typedef std::map<OUString, ListenerMap*> TypeListenerMap; +typedef std::map< ::rtl::OUString, ListenerMap*> TypeListenerMap; typedef std::vector<ListenerMap::value_type> ListenerPairVector; class CEventDispatcher { private: - static TypeListenerMap captureListeners; - static TypeListenerMap targetListeners; + TypeListenerMap m_CaptureListeners; + TypeListenerMap m_TargetListeners; public: - static sal_Bool dispatchEvent(xmlNodePtr aNode, const Reference< XEvent >& aEvent); - - static void addListener( - xmlNodePtr pNode, - OUString aType, + void addListener( + xmlNodePtr pNode, + ::rtl::OUString aType, const Reference<com::sun::star::xml::dom::events::XEventListener>& aListener, sal_Bool bCapture); - static void removeListener( + void removeListener( xmlNodePtr pNode, - OUString aType, + ::rtl::OUString aType, const Reference<com::sun::star::xml::dom::events::XEventListener>& aListener, sal_Bool bCapture); static void callListeners( - xmlNodePtr pNode, - OUString aType, - const Reference< XEvent >& xEvent, - sal_Bool bCapture); + TypeListenerMap const& rTMap, + xmlNodePtr const pNode, + ::rtl::OUString aType, + const Reference< XEvent >& xEvent); + + bool dispatchEvent( + DOM::CDocument & rDocument, + ::osl::Mutex & rMutex, + xmlNodePtr const pNode, + Reference<XNode> const& xNode, + Reference< XEvent > const& xEvent) const; }; + }} + +#endif + diff --git a/unoxml/source/events/mouseevent.cxx b/unoxml/source/events/mouseevent.cxx index 1110b22a1..02d1ea619 100644 --- a/unoxml/source/events/mouseevent.cxx +++ b/unoxml/source/events/mouseevent.cxx @@ -1,67 +1,119 @@ -#include "mouseevent.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <mouseevent.hxx> namespace DOM { namespace events -{ +{ + CMouseEvent::CMouseEvent() + : CMouseEvent_Base() + , m_screenX(0) + , m_screenY(0) + , m_clientX(0) + , m_clientY(0) + , m_ctrlKey(sal_False) + , m_shiftKey(sal_False) + , m_altKey(sal_False) + , m_metaKey(sal_False) + , m_button(0) + { + } sal_Int32 SAL_CALL CMouseEvent::getScreenX() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_screenX; } sal_Int32 SAL_CALL CMouseEvent::getScreenY() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_screenY; } sal_Int32 SAL_CALL CMouseEvent::getClientX() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_clientX; } sal_Int32 SAL_CALL CMouseEvent::getClientY() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_clientY; } sal_Bool SAL_CALL CMouseEvent::getCtrlKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_ctrlKey; } sal_Bool SAL_CALL CMouseEvent::getShiftKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_shiftKey; } sal_Bool SAL_CALL CMouseEvent::getAltKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_altKey; } sal_Bool SAL_CALL CMouseEvent::getMetaKey() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_metaKey; } sal_Int16 SAL_CALL CMouseEvent::getButton() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_button; } Reference< XEventTarget > SAL_CALL CMouseEvent::getRelatedTarget() throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_relatedTarget; } void SAL_CALL CMouseEvent::initMouseEvent( - const OUString& typeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg, - const Reference< XAbstractView >& viewArg, - sal_Int32 detailArg, - sal_Int32 screenXArg, - sal_Int32 screenYArg, - sal_Int32 clientXArg, - sal_Int32 clientYArg, - sal_Bool ctrlKeyArg, - sal_Bool altKeyArg, - sal_Bool shiftKeyArg, - sal_Bool metaKeyArg, - sal_Int16 buttonArg, + const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg, + sal_Int32 screenXArg, + sal_Int32 screenYArg, + sal_Int32 clientXArg, + sal_Int32 clientYArg, + sal_Bool ctrlKeyArg, + sal_Bool altKeyArg, + sal_Bool shiftKeyArg, + sal_Bool metaKeyArg, + sal_Int16 buttonArg, const Reference< XEventTarget >& /*relatedTargetArg*/) throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + CUIEvent::initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); m_screenX = screenXArg; m_screenY = screenYArg; @@ -85,10 +137,10 @@ namespace DOM { namespace events return CUIEvent::getDetail(); } - void SAL_CALL CMouseEvent::initUIEvent(const OUString& typeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg, - const Reference< XAbstractView >& viewArg, + void SAL_CALL CMouseEvent::initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, sal_Int32 detailArg) throw(RuntimeException) { CUIEvent::initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg); @@ -139,7 +191,7 @@ namespace DOM { namespace events CUIEvent::preventDefault(); } - void SAL_CALL CMouseEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + void SAL_CALL CMouseEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, sal_Bool cancelableArg) throw (RuntimeException) { // base initializer diff --git a/unoxml/source/events/mouseevent.hxx b/unoxml/source/events/mouseevent.hxx index b4a9adeae..0bbcbf769 100644 --- a/unoxml/source/events/mouseevent.hxx +++ b/unoxml/source/events/mouseevent.hxx @@ -1,27 +1,51 @@ -#ifndef __MOUSEEVENT_HXX -#define __MOUSEEVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef EVENT_MOUSEEVENT_HXX +#define EVENT_MOUSEEVENT_HXX -#include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> -#include <com/sun/star/uno/Reference.h> -#include <com/sun/star/xml/dom/events/EventType.hpp> #include <com/sun/star/xml/dom/events/PhaseType.hpp> -#include <com/sun/star/xml/dom/events/AttrChangeType.hpp> -#include <com/sun/star/xml/dom/events/XEvent.hpp> -#include <com/sun/star/xml/dom/events/XUIEvent.hpp> #include <com/sun/star/xml/dom/events/XMouseEvent.hpp> -#include "event.hxx" + +#include <cppuhelper/implbase1.hxx> + #include "uievent.hxx" + using ::rtl::OUString; namespace DOM { namespace events { -class CMouseEvent : public cppu::ImplInheritanceHelper1< CUIEvent, XMouseEvent > +typedef ::cppu::ImplInheritanceHelper1< CUIEvent, XMouseEvent > + CMouseEvent_Base; + +class CMouseEvent + : public CMouseEvent_Base { - friend class CEventDispatcher; protected: sal_Int32 m_screenX; sal_Int32 m_screenY; @@ -35,6 +59,7 @@ protected: Reference< XEventTarget > m_relatedTarget; public: + explicit CMouseEvent(); virtual sal_Int32 SAL_CALL getScreenX() throw (RuntimeException); virtual sal_Int32 SAL_CALL getScreenY() throw (RuntimeException); @@ -48,30 +73,30 @@ public: virtual Reference< XEventTarget > SAL_CALL getRelatedTarget() throw(RuntimeException); virtual void SAL_CALL initMouseEvent( - const OUString& typeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg, - const Reference< XAbstractView >& viewArg, - sal_Int32 detailArg, - sal_Int32 screenXArg, - sal_Int32 screenYArg, - sal_Int32 clientXArg, - sal_Int32 clientYArg, - sal_Bool ctrlKeyArg, - sal_Bool altKeyArg, - sal_Bool shiftKeyArg, - sal_Bool metaKeyArg, - sal_Int16 buttonArg, + const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, + sal_Int32 detailArg, + sal_Int32 screenXArg, + sal_Int32 screenYArg, + sal_Int32 clientXArg, + sal_Int32 clientYArg, + sal_Bool ctrlKeyArg, + sal_Bool altKeyArg, + sal_Bool shiftKeyArg, + sal_Bool metaKeyArg, + sal_Int16 buttonArg, const Reference< XEventTarget >& relatedTargetArg) throw(RuntimeException); - // delegate to CUIevent + // delegate to CUIevent virtual Reference< XAbstractView > SAL_CALL getView() throw (RuntimeException); virtual sal_Int32 SAL_CALL getDetail() throw (RuntimeException); - virtual void SAL_CALL initUIEvent(const OUString& typeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg, - const Reference< XAbstractView >& viewArg, + virtual void SAL_CALL initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, sal_Int32 detailArg) throw (RuntimeException); virtual OUString SAL_CALL getType() throw (RuntimeException); virtual Reference< XEventTarget > SAL_CALL getTarget() throw (RuntimeException); @@ -83,10 +108,10 @@ public: virtual void SAL_CALL stopPropagation() throw (RuntimeException); virtual void SAL_CALL preventDefault() throw (RuntimeException); virtual void SAL_CALL initEvent( - const OUString& eventTypeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg) - throw (RuntimeException); + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) + throw (RuntimeException); }; }} #endif diff --git a/unoxml/source/events/mutationevent.cxx b/unoxml/source/events/mutationevent.cxx index c7709710c..201fbe9e0 100644 --- a/unoxml/source/events/mutationevent.cxx +++ b/unoxml/source/events/mutationevent.cxx @@ -1,43 +1,83 @@ -#include "mutationevent.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <mutationevent.hxx> namespace DOM { namespace events -{ +{ + CMutationEvent::CMutationEvent() + : CMutationEvent_Base() + , m_attrChangeType(AttrChangeType_MODIFICATION) + { + } + CMutationEvent::~CMutationEvent() { } Reference< XNode > SAL_CALL CMutationEvent::getRelatedNode() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_relatedNode; } OUString SAL_CALL CMutationEvent::getPrevValue() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_prevValue; } OUString SAL_CALL CMutationEvent::getNewValue() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_newValue; } OUString SAL_CALL CMutationEvent::getAttrName() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_attrName; } AttrChangeType SAL_CALL CMutationEvent::getAttrChange() throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_attrChangeType; } - void SAL_CALL CMutationEvent::initMutationEvent(const OUString& typeArg, - sal_Bool canBubbleArg, sal_Bool cancelableArg, - const Reference< XNode >& relatedNodeArg, const OUString& prevValueArg, - const OUString& newValueArg, const OUString& attrNameArg, + void SAL_CALL CMutationEvent::initMutationEvent(const OUString& typeArg, + sal_Bool canBubbleArg, sal_Bool cancelableArg, + const Reference< XNode >& relatedNodeArg, const OUString& prevValueArg, + const OUString& newValueArg, const OUString& attrNameArg, AttrChangeType attrChangeArg) throw (RuntimeException) { - initEvent(typeArg, canBubbleArg, cancelableArg); + ::osl::MutexGuard const g(m_Mutex); + + CEvent::initEvent(typeArg, canBubbleArg, cancelableArg); m_relatedNode = relatedNodeArg; m_prevValue = prevValueArg; m_newValue = newValueArg; @@ -90,7 +130,7 @@ namespace DOM { namespace events CEvent::preventDefault(); } - void SAL_CALL CMutationEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + void SAL_CALL CMutationEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, sal_Bool cancelableArg) throw (RuntimeException) { // base initializer diff --git a/unoxml/source/events/mutationevent.hxx b/unoxml/source/events/mutationevent.hxx index 5ff545f1c..20b8dbf45 100644 --- a/unoxml/source/events/mutationevent.hxx +++ b/unoxml/source/events/mutationevent.hxx @@ -1,25 +1,56 @@ -#ifndef __MUTATIONEVENT_HXX -#define __MUTATIONEVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef EVENT_MUTATIONEVENT_HXX +#define EVENT_MUTATIONEVENT_HXX #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/xml/dom/events/EventType.hpp> + #include <com/sun/star/xml/dom/events/PhaseType.hpp> #include <com/sun/star/xml/dom/events/AttrChangeType.hpp> -#include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XMutationEvent.hpp> + +#include <cppuhelper/implbase1.hxx> + #include "event.hxx" + using ::rtl::OUString; namespace DOM { namespace events { -class CMutationEvent : public cppu::ImplInheritanceHelper1< CEvent, XMutationEvent > +typedef ::cppu::ImplInheritanceHelper1< CEvent, XMutationEvent > + CMutationEvent_Base; + +class CMutationEvent + : public CMutationEvent_Base { - friend class CEventDispatcher; protected: Reference< XNode > m_relatedNode; OUString m_prevValue; @@ -28,6 +59,7 @@ protected: AttrChangeType m_attrChangeType; public: + explicit CMutationEvent(); virtual ~CMutationEvent(); @@ -37,13 +69,13 @@ public: virtual OUString SAL_CALL getAttrName() throw (RuntimeException); virtual AttrChangeType SAL_CALL getAttrChange() throw (RuntimeException); virtual void SAL_CALL initMutationEvent( - const OUString& typeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg, - const Reference< XNode >& relatedNodeArg, - const OUString& prevValueArg, - const OUString& newValueArg, - const OUString& attrNameArg, + const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XNode >& relatedNodeArg, + const OUString& prevValueArg, + const OUString& newValueArg, + const OUString& attrNameArg, AttrChangeType attrChangeArg) throw (RuntimeException); // delegate to CEvent, since we are inheriting from CEvent and XEvent @@ -57,10 +89,10 @@ public: virtual void SAL_CALL stopPropagation() throw (RuntimeException); virtual void SAL_CALL preventDefault() throw (RuntimeException); virtual void SAL_CALL initEvent( - const OUString& eventTypeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg) - throw (RuntimeException); + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) + throw (RuntimeException); }; }} #endif diff --git a/unoxml/source/events/testlistener.cxx b/unoxml/source/events/testlistener.cxx index 93b6f0fd3..a493aefb5 100644 --- a/unoxml/source/events/testlistener.cxx +++ b/unoxml/source/events/testlistener.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -33,6 +33,10 @@ #define U2S(s) OUStringToOString(s, RTL_TEXTENCODING_UTF8).getStr() +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::lang::IllegalArgumentException; + + namespace DOM { namespace events { @@ -112,7 +116,7 @@ namespace DOM { namespace events m_capture = bCapture; m_target->addEventListener(m_type, Reference< XEventListener >(this), m_capture); - + } @@ -129,7 +133,7 @@ namespace DOM { namespace events { FILE* f = fopen("C:\\listener.out", "a"); fprintf(f, "CTestListener::handleEvent in %s\n", U2S(m_name)); - fprintf(f, " type: %s\n\n", OUStringToOString(evt->getType(), RTL_TEXTENCODING_ASCII_US).getStr()); + fprintf(f, " type: %s\n\n", OUStringToOString(evt->getType(), RTL_TEXTENCODING_ASCII_US).getStr()); fclose(f); } diff --git a/unoxml/source/events/testlistener.hxx b/unoxml/source/events/testlistener.hxx index 62bdc1942..1d96edefc 100644 --- a/unoxml/source/events/testlistener.hxx +++ b/unoxml/source/events/testlistener.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,52 +25,51 @@ * ************************************************************************/ -#ifndef _TESTLISTENER_HXX -#define _TESTLISTENER_HXX - -#include <map> +#ifndef EVENT_TESTLISTENER_HXX +#define EVENT_TESTLISTENER_HXX #include <sal/types.h> -#include <cppuhelper/implbase3.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> #include <com/sun/star/uno/XInterface.hpp> #include <com/sun/star/uno/Exception.hpp> -#include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/lang/XInitialization.hpp> -#include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/xml/dom/events/XEventTarget.hpp> #include <com/sun/star/xml/dom/events/XEventListener.hpp> #include <com/sun/star/xml/dom/events/XEvent.hpp> -#include <com/sun/star/xml/dom/events/EventType.hpp> -#include <com/sun/star/xml/dom/events/XMutationEvent.hpp> -#include "libxml/tree.h" +#include <cppuhelper/implbase3.hxx> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::dom::events; namespace DOM { namespace events { - + + typedef ::cppu::WeakImplHelper3 + < ::com::sun::star::xml::dom::events::XEventListener + , ::com::sun::star::lang::XInitialization + , ::com::sun::star::lang::XServiceInfo + > CTestListener_Base; + class CTestListener - : public ::cppu::WeakImplHelper3< com::sun::star::xml::dom::events::XEventListener, XInitialization, XServiceInfo > + : public CTestListener_Base { private: - Reference< XMultiServiceFactory > m_factory; + Reference< ::com::sun::star::lang::XMultiServiceFactory > m_factory; Reference <XEventTarget> m_target; OUString m_type; sal_Bool m_capture; OUString m_name; - + public: // static helpers for service info and component management @@ -78,9 +77,13 @@ namespace DOM { namespace events static const char* aSupportedServiceNames[]; static OUString _getImplementationName(); static Sequence< OUString > _getSupportedServiceNames(); - static Reference< XInterface > _getInstance(const Reference< XMultiServiceFactory >& rSMgr); + static Reference< XInterface > _getInstance( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); - CTestListener(const Reference< XMultiServiceFactory >& rSMgr) + CTestListener( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr) : m_factory(rSMgr){}; virtual ~CTestListener(); diff --git a/unoxml/source/events/uievent.cxx b/unoxml/source/events/uievent.cxx index fd4563532..68e5dbbc6 100644 --- a/unoxml/source/events/uievent.cxx +++ b/unoxml/source/events/uievent.cxx @@ -1,26 +1,62 @@ -#include "event.hxx" -#include "uievent.hxx" +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include <uievent.hxx> namespace DOM { namespace events -{ +{ + CUIEvent::CUIEvent() + : CUIEvent_Base() + , m_detail(0) + { + } - Reference< XAbstractView > SAL_CALL CUIEvent::getView() throw(RuntimeException) + Reference< XAbstractView > SAL_CALL + CUIEvent::getView() throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_view; } sal_Int32 SAL_CALL CUIEvent::getDetail() throw(RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); return m_detail; } - void SAL_CALL CUIEvent::initUIEvent(const OUString& typeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg, - const Reference< XAbstractView >& viewArg, + void SAL_CALL CUIEvent::initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, sal_Int32 detailArg) throw(RuntimeException) { - initEvent(typeArg, canBubbleArg, cancelableArg); + ::osl::MutexGuard const g(m_Mutex); + + CEvent::initEvent(typeArg, canBubbleArg, cancelableArg); m_view = viewArg; m_detail = detailArg; } @@ -72,7 +108,7 @@ namespace DOM { namespace events CEvent::preventDefault(); } - void SAL_CALL CUIEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, + void SAL_CALL CUIEvent::initEvent(const OUString& eventTypeArg, sal_Bool canBubbleArg, sal_Bool cancelableArg) throw (RuntimeException) { // base initializer diff --git a/unoxml/source/events/uievent.hxx b/unoxml/source/events/uievent.hxx index d9cd5cc01..2f1c6f28d 100644 --- a/unoxml/source/events/uievent.hxx +++ b/unoxml/source/events/uievent.hxx @@ -1,38 +1,67 @@ -#ifndef __UIEVENT_HXX -#define __UIEVENT_HXX +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef EVENT_UIEVENT_HXX +#define EVENT_UIEVENT_HXX #include <sal/types.h> -#include <cppuhelper/implbase1.hxx> -#include <cppuhelper/implbase2.hxx> -#include <cppuhelper/implbase3.hxx> -#include <com/sun/star/uno/Reference.h> -#include <com/sun/star/xml/dom/events/EventType.hpp> + #include <com/sun/star/xml/dom/events/PhaseType.hpp> -#include <com/sun/star/xml/dom/events/AttrChangeType.hpp> -#include <com/sun/star/xml/dom/events/XEvent.hpp> #include <com/sun/star/xml/dom/events/XUIEvent.hpp> #include <com/sun/star/xml/dom/views/XAbstractView.hpp> + +#include <cppuhelper/implbase1.hxx> + #include "event.hxx" + using ::rtl::OUString; using namespace com::sun::star::xml::dom::views; namespace DOM { namespace events { -class CUIEvent : public cppu::ImplInheritanceHelper1< CEvent, XUIEvent > +typedef ::cppu::ImplInheritanceHelper1< CEvent, XUIEvent > CUIEvent_Base; + +class CUIEvent + : public CUIEvent_Base { - friend class CEventDispatcher; protected: sal_Int32 m_detail; Reference< XAbstractView > m_view; public: + explicit CUIEvent(); + virtual Reference< XAbstractView > SAL_CALL getView() throw(RuntimeException); virtual sal_Int32 SAL_CALL getDetail() throw(RuntimeException); - virtual void SAL_CALL initUIEvent(const OUString& typeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg, - const Reference< XAbstractView >& viewArg, + virtual void SAL_CALL initUIEvent(const OUString& typeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg, + const Reference< XAbstractView >& viewArg, sal_Int32 detailArg) throw(RuntimeException); // delegate to CEvent, since we are inheriting from CEvent and XEvent @@ -46,10 +75,10 @@ public: virtual void SAL_CALL stopPropagation() throw (RuntimeException); virtual void SAL_CALL preventDefault() throw (RuntimeException); virtual void SAL_CALL initEvent( - const OUString& eventTypeArg, - sal_Bool canBubbleArg, - sal_Bool cancelableArg) - throw (RuntimeException); + const OUString& eventTypeArg, + sal_Bool canBubbleArg, + sal_Bool cancelableArg) + throw (RuntimeException); }; }} #endif diff --git a/unoxml/source/rdf/librdf_repository.cxx b/unoxml/source/rdf/librdf_repository.cxx index 13dd5b0bb..bb81d2cb6 100644 --- a/unoxml/source/rdf/librdf_repository.cxx +++ b/unoxml/source/rdf/librdf_repository.cxx @@ -1069,8 +1069,9 @@ throw (uno::RuntimeException, lang::IllegalArgumentException, "librdf_Repository::exportGraph: " "librdf_model_context_as_stream failed"), *this); } -// const char *format("rdfxml"); - const char *format("rdfxml-abbrev"); + const char *format("rdfxml"); + // #i116443#: abbrev breaks when certain URIs are used as data types +// const char *format("rdfxml-abbrev"); const boost::shared_ptr<librdf_serializer> pSerializer( librdf_new_serializer(m_pWorld.get(), format, NULL, NULL), safe_librdf_free_serializer); diff --git a/unoxml/source/rdf/librdf_services.cxx b/unoxml/source/rdf/librdf_services.cxx index f107aa150..caecfc977 100644 --- a/unoxml/source/rdf/librdf_services.cxx +++ b/unoxml/source/rdf/librdf_services.cxx @@ -38,7 +38,7 @@ using namespace ::com::sun::star; extern "C" { -void SAL_CALL +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(const sal_Char **o_ppEnvironmentTypeName, uno_Environment ** /* ppEnvironment */) { @@ -65,7 +65,8 @@ static ::cppu::ImplementationEntry const entries[] = { { 0, 0, 0, 0, 0, 0 } }; -extern "C" void * SAL_CALL component_getFactory( +SAL_DLLPUBLIC_EXPORT void * SAL_CALL +component_getFactory( const char * implName, void * serviceManager, void * registryKey) { return ::cppu::component_getFactoryHelper( diff --git a/unoxml/source/rdf/makefile.mk b/unoxml/source/rdf/makefile.mk deleted file mode 100644 index 1dbcffb8b..000000000 --- a/unoxml/source/rdf/makefile.mk +++ /dev/null @@ -1,92 +0,0 @@ -#************************************************************************* -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. -# -# OpenOffice.org - a multi-platform office productivity suite -# -# This file is part of OpenOffice.org. -# -# OpenOffice.org is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# only, as published by the Free Software Foundation. -# -# OpenOffice.org is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License version 3 for more details -# (a copy is included in the LICENSE file that accompanied this code). -# -# You should have received a copy of the GNU Lesser General Public License -# version 3 along with OpenOffice.org. If not, see -# <http://www.openoffice.org/license.html> -# for a copy of the LGPLv3 License. -# -#************************************************************************* - -PRJ=..$/.. - -PRJNAME=unoxml -TARGET=unordf -LIBTARGET=NO - -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_REDLAND)" == "YES" -CFLAGS+=-DSYSTEM_REDLAND $(REDLAND_CFLAGS) -.ENDIF - -.IF "$(SYSTEM_LIBXSLT)" == "YES" -CFLAGS+= $(LIBXSLT_CFLAGS) -.ELSE -LIBXSLTINCDIR=external$/libxslt -CFLAGS+= -I$(SOLARINCDIR)$/$(LIBXSLTINCDIR) -.ENDIF - -# --- Files -------------------------------------------------------- -.IF "$(L10N_framework)"=="" - -SLOFILES = \ - $(SLO)$/CBlankNode.obj \ - $(SLO)$/CURI.obj \ - $(SLO)$/CLiteral.obj \ - $(SLO)$/librdf_repository.obj \ - $(SLO)$/librdf_services.obj - - -SHL1DEPN= makefile.mk -SHL1OBJS= $(SLOFILES) - -SHL1TARGET= $(TARGET)$(DLLPOSTFIX) -SHL1IMPLIB= i$(TARGET) - -SHL1VERSIONMAP=$(SOLARENV)/src/component.map -SHL1DEF=$(MISC)$/$(SHL1TARGET).def -DEF1NAME=$(SHL1TARGET) - -SHL1STDLIBS= \ - $(REDLANDLIB) \ - $(XSLTLIB) \ - $(CPPUHELPERLIB) \ - $(CPPULIB) \ - $(SALLIB) \ - -.ENDIF - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - - -ALLTAR : $(MISC)/unordf.component - -$(MISC)/unordf.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ - unordf.component - $(XSLTPROC) --nonet --stringparam uri \ - '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ - $(SOLARENV)/bin/createcomponent.xslt unordf.component diff --git a/unoxml/source/service/makefile.mk b/unoxml/source/service/makefile.mk deleted file mode 100644 index 5fbe62f67..000000000 --- a/unoxml/source/service/makefile.mk +++ /dev/null @@ -1,86 +0,0 @@ -#************************************************************************* -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# Copyright 2000, 2010 Oracle and/or its affiliates. -# -# OpenOffice.org - a multi-platform office productivity suite -# -# This file is part of OpenOffice.org. -# -# OpenOffice.org is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License version 3 -# only, as published by the Free Software Foundation. -# -# OpenOffice.org is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License version 3 for more details -# (a copy is included in the LICENSE file that accompanied this code). -# -# You should have received a copy of the GNU Lesser General Public License -# version 3 along with OpenOffice.org. If not, see -# <http://www.openoffice.org/license.html> -# for a copy of the LGPLv3 License. -# -#************************************************************************* - -PRJ=..$/.. - -PRJNAME=unoxml -TARGET=unoxml -LIBTARGET=NO - -ENABLE_EXCEPTIONS=TRUE - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -.IF "$(SYSTEM_LIBXML)" == "YES" -CFLAGS+=-DSYSTEM_LIBXML $(LIBXML_CFLAGS) -.ENDIF - -# --- Files -------------------------------------------------------- - -SLOFILES = \ - $(SLO)$/services.obj - - -SHL1DEPN= makefile.mk -SHL1OBJS= $(SLOFILES) - -SHL1TARGET= $(TARGET)$(DLLPOSTFIX) -SHL1IMPLIB= i$(TARGET) - -SHL1VERSIONMAP=$(SOLARENV)/src/component.map -SHL1DEF=$(MISC)$/$(SHL1TARGET).def -DEF1NAME=$(SHL1TARGET) - -SHL1LIBS= \ - $(SLB)$/domimpl.lib \ - $(SLB)$/xpathimpl.lib \ - $(SLB)$/eventsimpl.lib - -SHL1STDLIBS= \ - $(UCBHELPERLIB) \ - $(LIBXML2LIB) \ - $(COMPHELPERLIB) \ - $(CPPUHELPERLIB) \ - $(CPPULIB) \ - $(SAXLIB) \ - $(SALLIB)\ - $(EXPATASCII3RDLIB) - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - - -ALLTAR : $(MISC)/unoxml.component - -$(MISC)/unoxml.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ - unoxml.component - $(XSLTPROC) --nonet --stringparam uri \ - '$(COMPONENTPREFIX_BASIS_NATIVE)$(SHL1TARGETN:f)' -o $@ \ - $(SOLARENV)/bin/createcomponent.xslt unoxml.component diff --git a/unoxml/source/service/services.cxx b/unoxml/source/service/services.cxx index 458e185a7..95ec56413 100644 --- a/unoxml/source/service/services.cxx +++ b/unoxml/source/service/services.cxx @@ -54,13 +54,13 @@ using namespace ::com::sun::star::registry; extern "C" { -void SAL_CALL +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment ** /*ppEnvironment */) { *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; } -void* SAL_CALL +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void * /*pRegistryKey*/) { void* pReturn = NULL ; diff --git a/unoxml/source/xpath/nodelist.cxx b/unoxml/source/xpath/nodelist.cxx index 71f99ebf9..05add3ca4 100644 --- a/unoxml/source/xpath/nodelist.cxx +++ b/unoxml/source/xpath/nodelist.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,41 +25,54 @@ * ************************************************************************/ -#include "nodelist.hxx" -#include "../dom/node.hxx" +#include <nodelist.hxx> + +#include "../dom/document.hxx" namespace XPath { - CNodeList::CNodeList(boost::shared_ptr<xmlXPathObject>& rxpathObj) - : m_pNodeSet(0) + CNodeList::CNodeList( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + boost::shared_ptr<xmlXPathObject> const& rxpathObj) + : m_pDocument(pDocument) + , m_rMutex(rMutex) + , m_pNodeSet(0) { if (rxpathObj != NULL && rxpathObj->type == XPATH_NODESET) { m_pNodeSet = rxpathObj->nodesetval; m_pXPathObj = rxpathObj; - } + } } - + /** The number of nodes in the list. */ sal_Int32 SAL_CALL CNodeList::getLength() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + sal_Int32 value = 0; if (m_pNodeSet != NULL) value = xmlXPathNodeSetGetLength(m_pNodeSet); return value; } - + /** Returns the indexth item in the collection. */ - Reference< XNode > SAL_CALL CNodeList::item(sal_Int32 index) throw (RuntimeException) + Reference< XNode > SAL_CALL CNodeList::item(sal_Int32 index) + throw (RuntimeException) { - Reference< XNode > aNode; - if (m_pNodeSet != NULL) - aNode = Reference< XNode >(DOM::CNode::get(xmlXPathNodeSetItem(m_pNodeSet, index))); - return aNode; + ::osl::MutexGuard const g(m_rMutex); + + if (0 == m_pNodeSet) { + return 0; + } + xmlNodePtr const pNode = xmlXPathNodeSetItem(m_pNodeSet, index); + Reference< XNode > const xNode(m_pDocument->GetCNode(pNode).get()); + return xNode; } } diff --git a/unoxml/source/xpath/nodelist.hxx b/unoxml/source/xpath/nodelist.hxx index 6c7ae1c26..fd6b428af 100644 --- a/unoxml/source/xpath/nodelist.hxx +++ b/unoxml/source/xpath/nodelist.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,38 +25,52 @@ * ************************************************************************/ -#ifndef _NODELIST_HXX -#define _NODELIST_HXX +#ifndef XPATH_NODELIST_HXX +#define XPATH_NODELIST_HXX -#include <vector> #include <sal/types.h> +#include <rtl/ref.hxx> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> #include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/xpath/XXPathObject.hpp> + #include "libxml/tree.h" #include "libxml/xpath.h" + #include <boost/shared_ptr.hpp> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::xpath; +namespace DOM { + class CDocument; +} + namespace XPath { class CNodeList : public cppu::WeakImplHelper1< XNodeList > { private: + /// #i115995# keep document alive + ::rtl::Reference< DOM::CDocument > const m_pDocument; + ::osl::Mutex & m_rMutex; + /// retain the result set in case the CXPathObject is released boost::shared_ptr<xmlXPathObject> m_pXPathObj; xmlNodeSetPtr m_pNodeSet; public: - CNodeList(boost::shared_ptr<xmlXPathObject> &rxpathObj); + CNodeList( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + boost::shared_ptr<xmlXPathObject> const& rxpathObj); /** The number of nodes in the list. */ @@ -64,7 +78,8 @@ namespace XPath /** Returns the indexth item in the collection. */ - virtual Reference< XNode > SAL_CALL item(sal_Int32 index) throw (RuntimeException); + virtual Reference< XNode > SAL_CALL item(sal_Int32 index) + throw (RuntimeException); }; } diff --git a/unoxml/source/xpath/xpathapi.cxx b/unoxml/source/xpath/xpathapi.cxx index 426aead47..00d13be63 100644 --- a/unoxml/source/xpath/xpathapi.cxx +++ b/unoxml/source/xpath/xpathapi.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,19 +25,26 @@ * ************************************************************************/ -#include "xpathapi.hxx" -#include "nodelist.hxx" -#include "xpathobject.hxx" -#include "../dom/node.hxx" +#include <xpathapi.hxx> -#include <rtl/ustrbuf.hxx> +#include <stdarg.h> +#include <string.h> +#include <libxml/tree.h> #include <libxml/xmlerror.h> #include <libxml/xpath.h> #include <libxml/xpathInternals.h> -#include <stdarg.h> -#include <string.h> +#include <rtl/ustrbuf.hxx> + +#include <nodelist.hxx> +#include <xpathobject.hxx> + +#include "../dom/node.hxx" +#include "../dom/document.hxx" + + +using ::com::sun::star::lang::XMultiServiceFactory; namespace XPath @@ -105,6 +112,8 @@ namespace XPath const OUString& aURI) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + m_nsmap.insert(nsmap_t::value_type(aPrefix, aURI)); } @@ -113,13 +122,16 @@ namespace XPath const OUString& aURI) throw (RuntimeException) { - if ((m_nsmap.find(aPrefix))->second.equals(aURI)) + ::osl::MutexGuard const g(m_Mutex); + + if ((m_nsmap.find(aPrefix))->second.equals(aURI)) { m_nsmap.erase(aPrefix); + } } // register all namespaces stored in the namespace list for this object // with the current xpath evaluation context - static void _registerNamespaces( + static void lcl_registerNamespaces( xmlXPathContextPtr ctx, const nsmap_t& nsmap) { @@ -137,30 +149,49 @@ namespace XPath } } - // get all ns decls on a node (and parent nodes, if any) and register them - static void _collectNamespaces( - CXPathAPI* pAPI, - const Reference< XNode >& namespaceNode) + // get all ns decls on a node (and parent nodes, if any) + static void lcl_collectNamespaces( + nsmap_t & rNamespaces, Reference< XNode > const& xNamespaceNode) { - // get namespace decls from node... - xmlNodePtr pNode = DOM::CNode::getNodePtr(namespaceNode); + DOM::CNode *const pCNode(DOM::CNode::GetImplementation(xNamespaceNode)); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCNode->GetOwnerDocument().GetMutex()); + + xmlNodePtr pNode = pCNode->GetNodePtr(); while (pNode != 0) { xmlNsPtr curDef = pNode->nsDef; while (curDef != 0) { - const xmlChar* xHref = curDef->href; + const xmlChar* xHref = curDef->href; OUString aURI((sal_Char*)xHref, strlen((char*)xHref), RTL_TEXTENCODING_UTF8); - const xmlChar* xPre = curDef->prefix; + const xmlChar* xPre = curDef->prefix; OUString aPrefix((sal_Char*)xPre, strlen((char*)xPre), RTL_TEXTENCODING_UTF8); - pAPI->registerNS(aPrefix, aURI); + // we could already have this prefix from a child node + if (rNamespaces.find(aPrefix) == rNamespaces.end()) + { + rNamespaces.insert(::std::make_pair(aPrefix, aURI)); + } curDef = curDef->next; } pNode = pNode->parent; } } + static void lcl_collectRegisterNamespaces( + CXPathAPI & rAPI, Reference< XNode > const& xNamespaceNode) + { + nsmap_t namespaces; + lcl_collectNamespaces(namespaces, xNamespaceNode); + for (nsmap_t::const_iterator iter = namespaces.begin(); + iter != namespaces.end(); ++iter) + { + rAPI.registerNS(iter->first, iter->second); + } + } + // register function and variable lookup functions with the current // xpath evaluation context - static void _registerExtensions( + static void lcl_registerExtensions( xmlXPathContextPtr ctx, const extensions_t& extensions) { @@ -168,17 +199,17 @@ namespace XPath while (i != extensions.end()) { Libxml2ExtensionHandle aHandle = (*i)->getLibxml2ExtensionHandle(); - if ( aHandle.functionLookupFunction != 0 ) + if ( aHandle.functionLookupFunction != 0 ) { - xmlXPathRegisterFuncLookup(ctx, + xmlXPathRegisterFuncLookup(ctx, reinterpret_cast<xmlXPathFuncLookupFunc>( sal::static_int_cast<sal_IntPtr>(aHandle.functionLookupFunction)), reinterpret_cast<void*>( sal::static_int_cast<sal_IntPtr>(aHandle.functionData))); } - if ( aHandle.variableLookupFunction != 0 ) + if ( aHandle.variableLookupFunction != 0 ) { - xmlXPathRegisterVariableLookup(ctx, + xmlXPathRegisterVariableLookup(ctx, reinterpret_cast<xmlXPathVariableLookupFunc>( sal::static_int_cast<sal_IntPtr>(aHandle.variableLookupFunction)), reinterpret_cast<void*>( @@ -209,7 +240,7 @@ namespace XPath const Reference< XNode >& namespaceNode) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return selectNodeList(contextNode, expr); } @@ -236,7 +267,7 @@ namespace XPath const Reference< XNode >& namespaceNode ) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return selectSingleNode(contextNode, expr); } @@ -307,15 +338,34 @@ namespace XPath * the context Node */ Reference< XXPathObject > SAL_CALL CXPathAPI::eval( - const Reference< XNode >& contextNode, + Reference< XNode > const& xContextNode, const OUString& expr) throw (RuntimeException, XPathException) { - xmlXPathContextPtr xpathCtx; - xmlXPathObjectPtr xpathObj; + if (!xContextNode.is()) { throw RuntimeException(); } + + nsmap_t nsmap; + extensions_t extensions; + + { + ::osl::MutexGuard const g(m_Mutex); + nsmap = m_nsmap; + extensions = m_extensions; + } // get the node and document - xmlNodePtr pNode = DOM::CNode::getNodePtr(contextNode); + ::rtl::Reference<DOM::CDocument> const pCDoc( + dynamic_cast<DOM::CDocument*>( DOM::CNode::GetImplementation( + xContextNode->getOwnerDocument()))); + if (!pCDoc.is()) { throw RuntimeException(); } + + DOM::CNode *const pCNode = DOM::CNode::GetImplementation(xContextNode); + if (!pCNode) { throw RuntimeException(); } + + ::osl::MutexGuard const g(pCDoc->GetMutex()); // lock the document! + + xmlNodePtr const pNode = pCNode->GetNodePtr(); + if (!pNode) { throw RuntimeException(); } xmlDocPtr pDoc = pNode->doc; /* NB: workaround for #i87252#: @@ -330,8 +380,9 @@ namespace XPath } /* Create xpath evaluation context */ - xpathCtx = xmlXPathNewContext(pDoc); - if (xpathCtx == NULL) throw XPathException(); + ::boost::shared_ptr<xmlXPathContext> const xpathCtx( + xmlXPathNewContext(pDoc), xmlXPathFreeContext); + if (xpathCtx == NULL) { throw XPathException(); } // set context node xpathCtx->node = pNode; @@ -340,20 +391,21 @@ namespace XPath xmlSetGenericErrorFunc(NULL, generic_error_func); // register namespaces and extension - _registerNamespaces(xpathCtx, m_nsmap); - _registerExtensions(xpathCtx, m_extensions); + lcl_registerNamespaces(xpathCtx.get(), nsmap); + lcl_registerExtensions(xpathCtx.get(), extensions); /* run the query */ OString o1 = OUStringToOString(expr, RTL_TEXTENCODING_UTF8); xmlChar *xStr = (xmlChar*)o1.getStr(); - if ((xpathObj = xmlXPathEval(xStr, xpathCtx)) == NULL) { + ::boost::shared_ptr<xmlXPathObject> const xpathObj( + xmlXPathEval(xStr, xpathCtx.get()), xmlXPathFreeObject); + if (0 == xpathObj) { // OSL_ENSURE(xpathCtx->lastError == NULL, xpathCtx->lastError->message); - xmlXPathFreeContext(xpathCtx); throw XPathException(); } - xmlXPathFreeContext(xpathCtx); - Reference< XXPathObject > aObj(new CXPathObject(xpathObj, contextNode)); - return aObj; + Reference<XXPathObject> const xObj( + new CXPathObject(pCDoc, pCDoc->GetMutex(), xpathObj)); + return xObj; } /** @@ -365,7 +417,7 @@ namespace XPath const Reference< XNode >& namespaceNode) throw (RuntimeException, XPathException) { - _collectNamespaces(this, namespaceNode); + lcl_collectRegisterNamespaces(*this, namespaceNode); return eval(contextNode, expr); } @@ -378,23 +430,26 @@ namespace XPath const OUString& aName) throw (RuntimeException) { + ::osl::MutexGuard const g(m_Mutex); + // get extension from service manager - Reference< XXPathExtension > aExtension(m_aFactory->createInstance(aName), UNO_QUERY_THROW); - m_extensions.push_back( aExtension ); + Reference< XXPathExtension > const xExtension( + m_aFactory->createInstance(aName), UNO_QUERY_THROW); + m_extensions.push_back(xExtension); } /** - * registers the given extension instance to be used by XPath evaluations performed through this + * registers the given extension instance to be used by XPath evaluations performed through this * XPathAPI instance */ void SAL_CALL CXPathAPI::registerExtensionInstance( - const Reference< XXPathExtension>& aExtension) + Reference< XXPathExtension> const& xExtension) throw (RuntimeException) { - if (aExtension.is()) { - m_extensions.push_back( aExtension ); - } else { + if (!xExtension.is()) { throw RuntimeException(); } + ::osl::MutexGuard const g(m_Mutex); + m_extensions.push_back( xExtension ); } } diff --git a/unoxml/source/xpath/xpathapi.hxx b/unoxml/source/xpath/xpathapi.hxx index fd4fe1df4..a64eff744 100644 --- a/unoxml/source/xpath/xpathapi.hxx +++ b/unoxml/source/xpath/xpathapi.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,14 +25,16 @@ * ************************************************************************/ -#ifndef _XPATHAPI_HXX -#define _XPATHAPI_HXX +#ifndef XPATH_XPATHAPI_HXX +#define XPATH_XPATHAPI_HXX #include <map> #include <vector> #include <sal/types.h> + #include <cppuhelper/implbase2.hxx> + #include <com/sun/star/uno/Reference.h> #include <com/sun/star/uno/Sequence.h> @@ -50,11 +52,9 @@ #include <com/sun/star/lang/XSingleServiceFactory.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include "libxml/tree.h" using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::xpath; @@ -63,28 +63,40 @@ namespace XPath typedef std::map<OUString, OUString> nsmap_t; typedef std::vector< Reference<XXPathExtension> > extensions_t; + typedef ::cppu::WeakImplHelper2 + < XXPathAPI + , ::com::sun::star::lang::XServiceInfo + > CXPathAPI_Base; + class CXPathAPI - : public ::cppu::WeakImplHelper2< XXPathAPI, XServiceInfo > + : public CXPathAPI_Base { private: + ::osl::Mutex m_Mutex; nsmap_t m_nsmap; - const Reference< XMultiServiceFactory > m_aFactory; + const Reference< ::com::sun::star::lang::XMultiServiceFactory > m_aFactory; extensions_t m_extensions; public: // ctor - CXPathAPI(const Reference< XMultiServiceFactory >& rSMgr); + CXPathAPI( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); // call for factory - static Reference< XInterface > getInstance(const Reference < XMultiServiceFactory >& xFactory); + static Reference< XInterface > getInstance( + const Reference < ::com::sun::star::lang::XMultiServiceFactory >& + xFactory); // static helpers for service info and component management static const char* aImplementationName; static const char* aSupportedServiceNames[]; static OUString _getImplementationName(); static Sequence< OUString > _getSupportedServiceNames(); - static Reference< XInterface > _getInstance(const Reference< XMultiServiceFactory >& rSMgr); + static Reference< XInterface > _getInstance( + const Reference< ::com::sun::star::lang::XMultiServiceFactory >& + rSMgr); // XServiceInfo virtual OUString SAL_CALL getImplementationName() diff --git a/unoxml/source/xpath/xpathobject.cxx b/unoxml/source/xpath/xpathobject.cxx index 815d17abf..36fdf1ba9 100644 --- a/unoxml/source/xpath/xpathobject.cxx +++ b/unoxml/source/xpath/xpathobject.cxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,74 +25,84 @@ * ************************************************************************/ +#include <xpathobject.hxx> + #include <string.h> -#include "xpathobject.hxx" -#include "nodelist.hxx" + +#include "../dom/document.hxx" +#include <nodelist.hxx> + namespace XPath { - CXPathObject::CXPathObject(xmlXPathObjectPtr xpathObj, const Reference< XNode >& contextNode) - : m_pXPathObj(xpathObj, xmlXPathFreeObject), m_xContextNode(contextNode) + static XPathObjectType lcl_GetType(xmlXPathObjectPtr const pXPathObj) { - switch (m_pXPathObj->type) + switch (pXPathObj->type) { - case XPATH_UNDEFINED: - m_xPathObjectType = XPathObjectType_XPATH_UNDEFINED; - break; - case XPATH_NODESET: - m_xPathObjectType = XPathObjectType_XPATH_NODESET; - break; - case XPATH_BOOLEAN: - m_xPathObjectType = XPathObjectType_XPATH_BOOLEAN; - break; - case XPATH_NUMBER: - m_xPathObjectType = XPathObjectType_XPATH_NUMBER; - break; - case XPATH_STRING: - m_xPathObjectType = XPathObjectType_XPATH_STRING; - break; - case XPATH_POINT: - m_xPathObjectType = XPathObjectType_XPATH_POINT; - break; - case XPATH_RANGE: - m_xPathObjectType = XPathObjectType_XPATH_RANGE; - break; - case XPATH_LOCATIONSET: - m_xPathObjectType = XPathObjectType_XPATH_LOCATIONSET; - break; - case XPATH_USERS: - m_xPathObjectType = XPathObjectType_XPATH_USERS; - break; - case XPATH_XSLT_TREE: - m_xPathObjectType = XPathObjectType_XPATH_XSLT_TREE; - break; - default: - m_xPathObjectType = XPathObjectType_XPATH_UNDEFINED; - break; + case XPATH_UNDEFINED: + return XPathObjectType_XPATH_UNDEFINED; + case XPATH_NODESET: + return XPathObjectType_XPATH_NODESET; + case XPATH_BOOLEAN: + return XPathObjectType_XPATH_BOOLEAN; + case XPATH_NUMBER: + return XPathObjectType_XPATH_NUMBER; + case XPATH_STRING: + return XPathObjectType_XPATH_STRING; + case XPATH_POINT: + return XPathObjectType_XPATH_POINT; + case XPATH_RANGE: + return XPathObjectType_XPATH_RANGE; + case XPATH_LOCATIONSET: + return XPathObjectType_XPATH_LOCATIONSET; + case XPATH_USERS: + return XPathObjectType_XPATH_USERS; + case XPATH_XSLT_TREE: + return XPathObjectType_XPATH_XSLT_TREE; + default: + return XPathObjectType_XPATH_UNDEFINED; } } - - /** + + CXPathObject::CXPathObject( + ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + ::boost::shared_ptr<xmlXPathObject> const& pXPathObj) + : m_pDocument(pDocument) + , m_rMutex(rMutex) + , m_pXPathObj(pXPathObj) + , m_XPathObjectType(lcl_GetType(pXPathObj.get())) + { + } + + /** get object type */ XPathObjectType CXPathObject::getObjectType() throw (RuntimeException) { - return m_xPathObjectType; + return m_XPathObjectType; } /** get the nodes from a nodelist type object */ - Reference< XNodeList > SAL_CALL CXPathObject::getNodeList() throw (RuntimeException) + Reference< XNodeList > SAL_CALL + CXPathObject::getNodeList() throw (RuntimeException) { - return Reference< XNodeList >(new CNodeList(m_pXPathObj)); + ::osl::MutexGuard const g(m_rMutex); + + Reference< XNodeList > const xRet( + new CNodeList(m_pDocument, m_rMutex, m_pXPathObj)); + return xRet; } - + /** get value of a boolean object */ sal_Bool SAL_CALL CXPathObject::getBoolean() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Bool) xmlXPathCastToBoolean(m_pXPathObj.get()); } @@ -101,6 +111,8 @@ namespace XPath */ sal_Int8 SAL_CALL CXPathObject::getByte() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int8) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -109,6 +121,8 @@ namespace XPath */ sal_Int16 SAL_CALL CXPathObject::getShort() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int16) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -117,6 +131,8 @@ namespace XPath */ sal_Int32 SAL_CALL CXPathObject::getLong() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int32) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -125,6 +141,8 @@ namespace XPath */ sal_Int64 SAL_CALL CXPathObject::getHyper() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (sal_Int64) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -133,6 +151,8 @@ namespace XPath */ float SAL_CALL CXPathObject::getFloat() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return (float) xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -141,6 +161,8 @@ namespace XPath */ double SAL_CALL CXPathObject::getDouble() throw (RuntimeException) { + ::osl::MutexGuard const g(m_rMutex); + return xmlXPathCastToNumber(m_pXPathObj.get()); } @@ -149,9 +171,13 @@ namespace XPath */ OUString SAL_CALL CXPathObject::getString() throw (RuntimeException) { - const sal_Char* x1 = (sal_Char*) xmlXPathCastToString(m_pXPathObj.get()); - return OUString(x1, strlen(x1), RTL_TEXTENCODING_UTF8); + ::osl::MutexGuard const g(m_rMutex); + + ::boost::shared_ptr<xmlChar const> str( + xmlXPathCastToString(m_pXPathObj.get()), xmlFree); + sal_Char const*const pS(reinterpret_cast<sal_Char const*>(str.get())); + return OUString(pS, strlen(pS), RTL_TEXTENCODING_UTF8); } - + } diff --git a/unoxml/source/xpath/xpathobject.hxx b/unoxml/source/xpath/xpathobject.hxx index 95c2e785e..f15aed9de 100644 --- a/unoxml/source/xpath/xpathobject.hxx +++ b/unoxml/source/xpath/xpathobject.hxx @@ -1,7 +1,7 @@ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * + * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite @@ -25,40 +25,50 @@ * ************************************************************************/ -#ifndef _XPATHOBJECT_HXX -#define _XPATHOBJECT_HXX +#ifndef XPATH_XPATHOBJECT_HXX +#define XPATH_XPATHOBJECT_HXX + +#include <boost/shared_ptr.hpp> + +#include <libxml/tree.h> +#include <libxml/xpath.h> -#include <map> #include <sal/types.h> +#include <rtl/ref.hxx> + #include <cppuhelper/implbase1.hxx> + #include <com/sun/star/uno/Reference.h> -#include <com/sun/star/uno/Exception.hpp> -#include <com/sun/star/xml/dom/XNode.hpp> #include <com/sun/star/xml/dom/XNodeList.hpp> #include <com/sun/star/xml/xpath/XXPathObject.hpp> -#include <libxml/tree.h> -#include <libxml/xpath.h> -#include <boost/shared_ptr.hpp> + using ::rtl::OUString; using namespace com::sun::star::uno; -using namespace com::sun::star::lang; using namespace com::sun::star::xml::dom; using namespace com::sun::star::xml::xpath; + +namespace DOM { + class CDocument; +} + namespace XPath { class CXPathObject : public cppu::WeakImplHelper1< XXPathObject > { private: - boost::shared_ptr<xmlXPathObject> m_pXPathObj; - const Reference< XNode > m_xContextNode; - XPathObjectType m_xPathObjectType; + ::rtl::Reference< DOM::CDocument > const m_pDocument; + ::osl::Mutex & m_rMutex; + boost::shared_ptr<xmlXPathObject> const m_pXPathObj; + XPathObjectType const m_XPathObjectType; public: - CXPathObject(xmlXPathObjectPtr xpathObj, const Reference< XNode >& contextNode); + CXPathObject( ::rtl::Reference<DOM::CDocument> const& pDocument, + ::osl::Mutex & rMutex, + ::boost::shared_ptr<xmlXPathObject> const& pXPathObj); - /** + /** get object type */ virtual XPathObjectType SAL_CALL getObjectType() throw (RuntimeException); @@ -66,7 +76,8 @@ namespace XPath /** get the nodes from a nodelist type object */ - virtual Reference< XNodeList > SAL_CALL getNodeList() throw (RuntimeException); + virtual Reference< XNodeList > SAL_CALL getNodeList() + throw (RuntimeException); /** get value of a boolean object @@ -107,7 +118,7 @@ namespace XPath get string value */ virtual OUString SAL_CALL getString() throw (RuntimeException); - + }; } diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index c66d81bb7..1f4e5bd11 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -1201,7 +1201,8 @@ void DomainMapper_Impl::CreateRedline( uno::Reference< text::XTextRange > xRange catch( const uno::Exception & rEx ) { ( void ) rEx; - OSL_ENSURE( false, "Exception in makeRedline" ); +// disabled: current writer redline impl. rather primitive, so it gets annoying +// OSL_ENSURE( false, "Exception in makeRedline" ); } } } diff --git a/writerfilter/source/ooxml/dummyannotate.xsl b/writerfilter/source/ooxml/dummyannotate.xsl index 0fcc1e0dc..d457d0c07 100644 --- a/writerfilter/source/ooxml/dummyannotate.xsl +++ b/writerfilter/source/ooxml/dummyannotate.xsl @@ -838,7 +838,7 @@ sed "s/wml/</xsl:text> <xsl:template match="/"> <out> - <xsl:apply-templates select="//rng:define[@name='CT_DocGrid']" + <xsl:apply-templates select="//rng:define[@name='CT_SdtContentCell']" mode='resourcesPropertySetValue'/> </out> </xsl:template> diff --git a/writerfilter/source/ooxml/makefile.mk b/writerfilter/source/ooxml/makefile.mk index c6a40b4cc..df0e26d1f 100644 --- a/writerfilter/source/ooxml/makefile.mk +++ b/writerfilter/source/ooxml/makefile.mk @@ -174,8 +174,8 @@ GENERATEDFILES= \ $(TOKENXMLTMP) \ $(TOKENXML) -$(TOKENXMLTMP): $(SOLARVER)$/$(INPATH)$/inc$(UPDMINOREXT)$/oox$/token.txt - @$(TYPE) $(SOLARVER)$/$(INPATH)$/inc$(UPDMINOREXT)$/oox$/token.txt | $(SED) "s#\(.*\)#<fasttoken>\1</fasttoken>#" > $@ +$(TOKENXMLTMP): $(SOLARVER)$/$(INPATH)$/inc$(UPDMINOREXT)$/oox$/token$/tokens.txt + @$(TYPE) $(SOLARVER)$/$(INPATH)$/inc$(UPDMINOREXT)$/oox$/token$/tokens.txt | $(SED) "s#\(.*\)#<fasttoken>\1</fasttoken>#" > $@ $(TOKENXML): tokenxmlheader $(TOKENXMLTMP) tokenxmlfooter @$(TYPE) tokenxmlheader $(TOKENXMLTMP) tokenxmlfooter > $@ diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 49998622e..be239665b 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -21113,7 +21113,7 @@ <resource name="ST_EighthPointMeasure" resource="Integer"/> <resource name="ST_PointMeasure" resource="Integer"/> <resource name="ST_String" resource="String"/> - <resource name="CT_String" resource="Value" tag="attribute" > + <resource name="CT_String" resource="Value" tag="attribute"> <attribute name="val" tokenid="ooxml:CT_String_val" action="setValue"/> <action name="start" action="setDefaultStringValue"/> </resource> @@ -21642,6 +21642,7 @@ <value name="bestFit" tokenid="ooxml:Value_wordprocessingml_ST_Zoom_bestFit">bestFit</value> <value name="textFit" tokenid="ooxml:Value_wordprocessingml_ST_Zoom_textFit">textFit</value> </resource> + <resource name="ST_Percentage" resource="Integer" generated="yes"/> <resource name="CT_Zoom" resource="Properties" tag="settings"> <attribute name="val" tokenid="ooxml:CT_Zoom_val"/> <attribute name="percent" tokenid="ooxml:CT_Zoom_percent"/> @@ -22552,7 +22553,56 @@ <attribute name="val" tokenid="ooxml:CT_CalendarType_val" action="setValue"/> <action name="start" action="setDefaultStringValue"/> </resource> - <resource name="CT_SdtContentRun" resource="Properties" tag="content"/> + <resource name="CT_SdtPr" resource="Properties" tag="field"> + <element name="rPr" tokenid="ooxml:CT_SdtPr_rPr"/> + <element name="alias" tokenid="ooxml:CT_SdtPr_alias"/> + <element name="lock" tokenid="ooxml:CT_SdtPr_lock"/> + <element name="placeholder" tokenid="ooxml:CT_SdtPr_placeholder"/> + <element name="showingPlcHdr" tokenid="ooxml:CT_SdtPr_showingPlcHdr"/> + <element name="dataBinding" tokenid="ooxml:CT_SdtPr_dataBinding"/> + <element name="temporary" tokenid="ooxml:CT_SdtPr_temporary"/> + <element name="id" tokenid="ooxml:CT_SdtPr_id"/> + <element name="tag" tokenid="ooxml:CT_SdtPr_tag"/> + <element name="equation" tokenid="ooxml:CT_SdtPr_equation"/> + <element name="comboBox" tokenid="ooxml:CT_SdtPr_comboBox"/> + <element name="date" tokenid="ooxml:CT_SdtPr_date"/> + <element name="docPartObj" tokenid="ooxml:CT_SdtPr_docPartObj"/> + <element name="docPartList" tokenid="ooxml:CT_SdtPr_docPartList"/> + <element name="dropDownList" tokenid="ooxml:CT_SdtPr_dropDownList"/> + <element name="picture" tokenid="ooxml:CT_SdtPr_picture"/> + <element name="richText" tokenid="ooxml:CT_SdtPr_richText"/> + <element name="text" tokenid="ooxml:CT_SdtPr_text"/> + <element name="citation" tokenid="ooxml:CT_SdtPr_citation"/> + <element name="group" tokenid="ooxml:CT_SdtPr_group"/> + <element name="bibliography" tokenid="ooxml:CT_SdtPr_bibliography"/> + </resource> + <resource name="CT_SdtEndPr" resource="Properties" tag="field"> + <element name="rPr" tokenid="ooxml:CT_SdtEndPr_rPr"/> + </resource> + <resource name="CT_SdtContentRun" resource="Stream" tag="field"/> + <resource name="CT_SdtContentBlock" resource="Stream" tag="field"/> + <resource name="CT_SdtContentRow" resource="Stream" tag="field"/> + <resource name="CT_SdtContentCell" resource="Stream" tag="field"/> + <resource name="CT_SdtBlock" resource="Stream" tag="field"> + <element name="sdtPr" tokenid="ooxml:CT_SdtBlock_sdtPr"/> + <element name="sdtEndPr" tokenid="ooxml:CT_SdtBlock_sdtEndPr"/> + <element name="sdtContent" tokenid="ooxml:CT_SdtBlock_sdtContent"/> + </resource> + <resource name="CT_SdtRun" resource="Stream" tag="field"> + <element name="sdtPr" tokenid="ooxml:CT_SdtRun_sdtPr"/> + <element name="sdtEndPr" tokenid="ooxml:CT_SdtRun_sdtEndPr"/> + <element name="sdtContent" tokenid="ooxml:CT_SdtRun_sdtContent"/> + </resource> + <resource name="CT_SdtCell" resource="Stream" tag="field"> + <element name="sdtPr" tokenid="ooxml:CT_SdtCell_sdtPr"/> + <element name="sdtEndPr" tokenid="ooxml:CT_SdtCell_sdtEndPr"/> + <element name="sdtContent" tokenid="ooxml:CT_SdtCell_sdtContent"/> + </resource> + <resource name="CT_SdtRow" resource="Stream" tag="field"> + <element name="sdtPr" tokenid="ooxml:CT_SdtRow_sdtPr"/> + <element name="sdtEndPr" tokenid="ooxml:CT_SdtRow_sdtEndPr"/> + <element name="sdtContent" tokenid="ooxml:CT_SdtRow_sdtContent"/> + </resource> <resource name="CT_Attr" resource="Properties" tag="content"> <attribute name="uri" tokenid="ooxml:CT_Attr_uri"/> <attribute name="name" tokenid="ooxml:CT_Attr_name"/> diff --git a/writerfilter/source/ooxml/modelcleanup.xsl b/writerfilter/source/ooxml/modelcleanup.xsl index d7a9aec40..69e73d868 100644 --- a/writerfilter/source/ooxml/modelcleanup.xsl +++ b/writerfilter/source/ooxml/modelcleanup.xsl @@ -40,6 +40,9 @@ <xsl:key name="resources" match="resource[not(@generated)]" use="@name" /> + <xsl:key name="resourcetags" + match="resource/@tag" use="ancestor::resource/@name"/> + <xsl:template name="generateresource"> <xsl:param name="resource"/> <xsl:element name="resource"> @@ -52,6 +55,11 @@ <xsl:attribute name="generated"> <xsl:text>yes</xsl:text> </xsl:attribute> + <xsl:for-each select="key('resourcetags', @name)"> + <xsl:attribute name="tag"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:for-each> </xsl:element> </xsl:template> @@ -66,6 +74,11 @@ </xsl:attribute> <xsl:attribute name="resource">List</xsl:attribute> <xsl:attribute name="generated">yes</xsl:attribute> + <xsl:for-each select="key('resourcetags', @name)"> + <xsl:attribute name="tag"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:for-each> <xsl:for-each select=".//rng:value"> <xsl:element name="value"> <xsl:attribute name="name"> @@ -148,12 +161,18 @@ <xsl:template name="generatevalueresource"> <xsl:variable name="name" select="@name"/> + <xsl:variable name="ns_id" select="generate-id(ancestor::namespace)"/> <resource> <xsl:attribute name="name"> <xsl:value-of select="@name"/> </xsl:attribute> <xsl:attribute name="resource">Value</xsl:attribute> <xsl:attribute name="generated">yes</xsl:attribute> + <xsl:for-each select="key('resourcetags', @name)[generate-id(ancestor::namespace) = $ns_id]"> + <xsl:attribute name="tag"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:for-each> <xsl:for-each select=".//rng:attribute"> <xsl:variable name="type"> <xsl:choose> diff --git a/writerfilter/source/resourcemodel/makefile.mk b/writerfilter/source/resourcemodel/makefile.mk index 1bc260455..cf7941b3e 100644 --- a/writerfilter/source/resourcemodel/makefile.mk +++ b/writerfilter/source/resourcemodel/makefile.mk @@ -133,7 +133,7 @@ SPRMIDSHXX=$(DOCTOKHXXOUTDIR)$/sprmids.hxx OOXMLRESOURCEIDSHXX=$(OOXMLHXXOUTDIR)$/resourceids.hxx NSXSL=$(MISC)$/namespacesmap.xsl -NAMESPACESTXT=$(SOLARVER)$/$(INPATH)$/inc$(UPDMINOREXT)$/oox$/namespaces.txt +NAMESPACESTXT=$(SOLARVER)$/$(INPATH)$/inc$(UPDMINOREXT)$/oox$/token$/namespaces.txt GENERATEDHEADERS=$(DOCTOKRESOURCEIDSHXX) $(OOXMLRESOURCEIDSHXX) $(SPRMIDSHXX) GENERATEDFILES= \ |