diff options
Diffstat (limited to 'sd/source/filter/html')
-rw-r--r-- | sd/source/filter/html/HtmlOptionsDialog.cxx | 203 | ||||
-rw-r--r-- | sd/source/filter/html/buttonset.cxx | 290 | ||||
-rw-r--r-- | sd/source/filter/html/buttonset.hxx | 46 | ||||
-rw-r--r-- | sd/source/filter/html/htmlattr.cxx | 72 | ||||
-rw-r--r-- | sd/source/filter/html/htmlattr.hxx | 40 | ||||
-rw-r--r-- | sd/source/filter/html/htmlex.cxx | 3186 | ||||
-rw-r--r-- | sd/source/filter/html/htmlex.hxx | 237 | ||||
-rw-r--r-- | sd/source/filter/html/htmlpublishmode.hxx | 31 | ||||
-rw-r--r-- | sd/source/filter/html/pubdlg.cxx | 1539 | ||||
-rw-r--r-- | sd/source/filter/html/sdhtmlfilter.cxx | 51 |
10 files changed, 5695 insertions, 0 deletions
diff --git a/sd/source/filter/html/HtmlOptionsDialog.cxx b/sd/source/filter/html/HtmlOptionsDialog.cxx new file mode 100644 index 000000000..78939dc4d --- /dev/null +++ b/sd/source/filter/html/HtmlOptionsDialog.cxx @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <com/sun/star/uno/Any.h> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/document/XExporter.hpp> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <vcl/svapp.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::document; +using namespace com::sun::star::beans; +using namespace com::sun::star::ui::dialogs; + +#include <pres.hxx> +#include <sdabstdlg.hxx> + +namespace { + +class SdHtmlOptionsDialog : public cppu::WeakImplHelper +< + XExporter, + XExecutableDialog, + XPropertyAccess, + XInitialization, + XServiceInfo +> +{ + Sequence< PropertyValue > maMediaDescriptor; + Sequence< PropertyValue > maFilterDataSequence; + DocumentType meDocType; + +public: + + SdHtmlOptionsDialog(); + + // XInterface + virtual void SAL_CALL acquire() noexcept override; + virtual void SAL_CALL release() noexcept override; + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any > & aArguments ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override; + + // XPropertyAccess + virtual Sequence< PropertyValue > SAL_CALL getPropertyValues() override; + virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< css::beans::PropertyValue > & aProps ) override; + + // XExecuteDialog + virtual sal_Int16 SAL_CALL execute() override; + virtual void SAL_CALL setTitle( const OUString& aTitle ) override; + + // XExporter + virtual void SAL_CALL setSourceDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override; + +}; + +} + +SdHtmlOptionsDialog::SdHtmlOptionsDialog() : + meDocType ( DocumentType::Draw ) +{ +} + +void SAL_CALL SdHtmlOptionsDialog::acquire() noexcept +{ + OWeakObject::acquire(); +} + +void SAL_CALL SdHtmlOptionsDialog::release() noexcept +{ + OWeakObject::release(); +} + +// XInitialization +void SAL_CALL SdHtmlOptionsDialog::initialize( const Sequence< Any > & ) +{ +} + +// XServiceInfo +OUString SAL_CALL SdHtmlOptionsDialog::getImplementationName() +{ + return "com.sun.star.comp.draw.SdHtmlOptionsDialog"; +} + +sal_Bool SAL_CALL SdHtmlOptionsDialog::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +Sequence< OUString > SAL_CALL SdHtmlOptionsDialog::getSupportedServiceNames() +{ + return { "com.sun.star.ui.dialog.FilterOptionsDialog" }; +} + +// XPropertyAccess +Sequence< PropertyValue > SdHtmlOptionsDialog::getPropertyValues() +{ + auto pProp = std::find_if(std::cbegin(maMediaDescriptor), std::cend(maMediaDescriptor), + [](const PropertyValue& rProp) { return rProp.Name == "FilterData"; }); + auto i = static_cast<sal_Int32>(std::distance(std::cbegin(maMediaDescriptor), pProp)); + sal_Int32 nCount = maMediaDescriptor.getLength(); + if ( i == nCount ) + maMediaDescriptor.realloc( ++nCount ); + + // the "FilterData" Property is an Any that will contain our PropertySequence of Values + auto& el = maMediaDescriptor.getArray()[ i ]; + el.Name = "FilterData"; + el.Value <<= maFilterDataSequence; + return maMediaDescriptor; +} + +void SdHtmlOptionsDialog::setPropertyValues( const Sequence< PropertyValue > & aProps ) +{ + maMediaDescriptor = aProps; + + auto pProp = std::find_if(std::cbegin(maMediaDescriptor), std::cend(maMediaDescriptor), + [](const PropertyValue& rProp) { return rProp.Name == "FilterData"; }); + if (pProp != std::cend(maMediaDescriptor)) + pProp->Value >>= maFilterDataSequence; +} + +// XExecutableDialog +void SdHtmlOptionsDialog::setTitle( const OUString& ) +{ +} + +sal_Int16 SdHtmlOptionsDialog::execute() +{ + sal_Int16 nRet = ExecutableDialogResults::CANCEL; + + SdAbstractDialogFactory* pFact = SdAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSdPublishingDlg> pDlg(pFact->CreateSdPublishingDlg(nullptr /*TODO*/, meDocType)); + if( pDlg->Execute() ) + { + pDlg->GetParameterSequence( maFilterDataSequence ); + nRet = ExecutableDialogResults::OK; + } + else + { + nRet = ExecutableDialogResults::CANCEL; + } + return nRet; +} + +// XEmporter +void SdHtmlOptionsDialog::setSourceDocument( const Reference< XComponent >& xDoc ) +{ + // try to set the corresponding metric unit + Reference< XServiceInfo > xServiceInfo(xDoc, UNO_QUERY); + if ( xServiceInfo.is() ) + { + if ( xServiceInfo->supportsService( "com.sun.star.presentation.PresentationDocument" ) ) + { + meDocType = DocumentType::Impress; + return; + } + else if ( xServiceInfo->supportsService( "com.sun.star.drawing.DrawingDocument" ) ) + { + meDocType = DocumentType::Draw; + return; + } + } + throw IllegalArgumentException(); +} + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +com_sun_star_comp_draw_SdHtmlOptionsDialog_get_implementation(css::uno::XComponentContext*, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new SdHtmlOptionsDialog()); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/buttonset.cxx b/sd/source/filter/html/buttonset.cxx new file mode 100644 index 000000000..3929f7422 --- /dev/null +++ b/sd/source/filter/html/buttonset.cxx @@ -0,0 +1,290 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <com/sun/star/embed/ElementModes.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/graphic/GraphicProvider.hpp> +#include <com/sun/star/graphic/XGraphicProvider.hpp> +#include <com/sun/star/io/XStream.hpp> + +#include <o3tl/safeint.hxx> +#include <osl/file.hxx> +#include <comphelper/storagehelper.hxx> +#include <comphelper/oslfile2streamwrap.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <vcl/graph.hxx> +#include <vcl/virdev.hxx> +#include <vcl/image.hxx> +#include <unotools/pathoptions.hxx> +#include <tools/diagnose_ex.h> + +#include <memory> + +#include "buttonset.hxx" + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::graphic; +using namespace ::com::sun::star::embed; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; + +namespace { + +class ButtonsImpl +{ +public: + explicit ButtonsImpl( const OUString& rURL ); + + Reference< XInputStream > getInputStream( const OUString& rName ); + + bool getGraphic( const Reference< XGraphicProvider >& xGraphicProvider, const OUString& rName, Graphic& rGraphic ); + + bool copyGraphic( const OUString& rName, const OUString& rPath ); + +private: + Reference< XStorage > mxStorage; +}; + +} + +ButtonsImpl::ButtonsImpl( const OUString& rURL ) +{ + try + { + mxStorage = comphelper::OStorageHelper::GetStorageOfFormatFromURL( ZIP_STORAGE_FORMAT_STRING, rURL, ElementModes::READ ); + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "sd::ButtonsImpl::ButtonsImpl()" ); + } +} + +Reference< XInputStream > ButtonsImpl::getInputStream( const OUString& rName ) +{ + Reference< XInputStream > xInputStream; + if( mxStorage.is() ) try + { + Reference< XStream > xStream( mxStorage->openStreamElement( rName, ElementModes::READ ) ); + if( xStream.is() ) + xInputStream = xStream->getInputStream(); + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "sd::ButtonsImpl::getInputStream()" ); + } + return xInputStream; +} + +bool ButtonsImpl::getGraphic( const Reference< XGraphicProvider >& xGraphicProvider, const OUString& rName, Graphic& rGraphic ) +{ + Reference< XInputStream > xInputStream( getInputStream( rName ) ); + if( xInputStream.is() && xGraphicProvider.is() ) try + { + Sequence< PropertyValue > aMediaProperties{ comphelper::makePropertyValue( + "InputStream", xInputStream) }; + Reference< XGraphic > xGraphic( xGraphicProvider->queryGraphic( aMediaProperties ) ); + + if( xGraphic.is() ) + { + rGraphic = Graphic( xGraphic ); + return true; + } + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "sd::ButtonsImpl::getGraphic()" ); + } + return false; +} + +bool ButtonsImpl::copyGraphic( const OUString& rName, const OUString& rPath ) +{ + Reference< XInputStream > xInput( getInputStream( rName ) ); + if( xInput.is() ) try + { + osl::File::remove( rPath ); + osl::File aOutputFile( rPath ); + if( aOutputFile.open( osl_File_OpenFlag_Write|osl_File_OpenFlag_Create ) == osl::FileBase::E_None ) + { + Reference< XOutputStream > xOutput( new comphelper::OSLOutputStreamWrapper( aOutputFile ) ); + comphelper::OStorageHelper::CopyInputToOutput( xInput, xOutput ); + return true; + } + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "sd::ButtonsImpl::copyGraphic()" ); + } + + return false; +} + +class ButtonSetImpl +{ +public: + ButtonSetImpl(); + + int getCount() const; + + bool getPreview( int nSet, const std::vector< OUString >& rButtons, Image& rImage ); + bool exportButton( int nSet, const OUString& rPath, const OUString& rName ); + + void scanForButtonSets( const OUString& rPath ); + + Reference< XGraphicProvider > const & getGraphicProvider(); + + std::vector< std::shared_ptr< ButtonsImpl > > maButtons; + Reference< XGraphicProvider > mxGraphicProvider; +}; + +ButtonSetImpl::ButtonSetImpl() +{ + static const char sSubPath[] = "/wizard/web/buttons" ; + + OUString sSharePath = SvtPathOptions().GetConfigPath() + + sSubPath; + scanForButtonSets( sSharePath ); + + OUString sUserPath = SvtPathOptions().GetUserConfigPath() + + sSubPath; + scanForButtonSets( sUserPath ); +} + +void ButtonSetImpl::scanForButtonSets( const OUString& rPath ) +{ + osl::Directory aDirectory( rPath ); + if( aDirectory.open() != osl::FileBase::E_None ) + return; + + osl::DirectoryItem aItem; + while( aDirectory.getNextItem( aItem, 2211 ) == osl::FileBase::E_None ) + { + osl::FileStatus aStatus( osl_FileStatus_Mask_FileName|osl_FileStatus_Mask_FileURL ); + if( aItem.getFileStatus( aStatus ) == osl::FileBase::E_None ) + { + OUString sFileName( aStatus.getFileName() ); + if( sFileName.endsWithIgnoreAsciiCase( ".zip" ) ) + maButtons.push_back( std::make_shared< ButtonsImpl >( aStatus.getFileURL() ) ); + } + } +} + +int ButtonSetImpl::getCount() const +{ + return maButtons.size(); +} + +bool ButtonSetImpl::getPreview( int nSet, const std::vector< OUString >& rButtons, Image& rImage ) +{ + if( (nSet >= 0) && (o3tl::make_unsigned(nSet) < maButtons.size())) + { + ButtonsImpl& rSet = *maButtons[nSet]; + + std::vector< Graphic > aGraphics; + + ScopedVclPtrInstance< VirtualDevice > pDev; + pDev->SetMapMode(MapMode(MapUnit::MapPixel)); + + Size aSize; + std::vector< OUString >::const_iterator aIter( rButtons.begin() ); + while( aIter != rButtons.end() ) + { + Graphic aGraphic; + if( !rSet.getGraphic( getGraphicProvider(), (*aIter++), aGraphic ) ) + return false; + + aGraphics.push_back(aGraphic); + + Size aGraphicSize( aGraphic.GetSizePixel( pDev ) ); + aSize.AdjustWidth(aGraphicSize.Width() ); + + if( aSize.Height() < aGraphicSize.Height() ) + aSize.setHeight( aGraphicSize.Height() ); + + if( aIter != rButtons.end() ) + aSize.AdjustWidth(3 ); + } + + pDev->SetOutputSizePixel( aSize ); + + Point aPos; + + for( const Graphic& aGraphic : aGraphics ) + { + aGraphic.Draw(*pDev, aPos); + + aPos.AdjustX(aGraphic.GetSizePixel().Width() + 3 ); + } + + rImage = Image( pDev->GetBitmapEx( Point(), aSize ) ); + return true; + } + return false; +} + +bool ButtonSetImpl::exportButton( int nSet, const OUString& rPath, const OUString& rName ) +{ + if( (nSet >= 0) && (o3tl::make_unsigned(nSet) < maButtons.size())) + { + ButtonsImpl& rSet = *maButtons[nSet]; + + return rSet.copyGraphic( rName, rPath ); + } + return false; +} + +Reference< XGraphicProvider > const & ButtonSetImpl::getGraphicProvider() +{ + if( !mxGraphicProvider.is() ) + { + Reference< XComponentContext > xComponentContext = ::comphelper::getProcessComponentContext(); + mxGraphicProvider = GraphicProvider::create(xComponentContext); + } + return mxGraphicProvider; +} + +ButtonSet::ButtonSet() +: mpImpl( new ButtonSetImpl() ) +{ +} + +ButtonSet::~ButtonSet() +{ +} + +int ButtonSet::getCount() const +{ + return mpImpl->getCount(); +} + +bool ButtonSet::getPreview( int nSet, const std::vector< OUString >& rButtons, Image& rImage ) +{ + return mpImpl->getPreview( nSet, rButtons, rImage ); +} + +bool ButtonSet::exportButton( int nSet, const OUString& rPath, const OUString& rName ) +{ + return mpImpl->exportButton( nSet, rPath, rName ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/buttonset.hxx b/sd/source/filter/html/buttonset.hxx new file mode 100644 index 000000000..4289c10e9 --- /dev/null +++ b/sd/source/filter/html/buttonset.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sddllapi.h> + +#include <rtl/ustring.hxx> +#include <vector> +#include <memory> + +class Image; +class ButtonSetImpl; + +class SD_DLLPUBLIC ButtonSet +{ +public: + ButtonSet(); + ~ButtonSet(); + + int getCount() const; + + bool getPreview(int nSet, const std::vector<OUString>& rButtons, Image& rImage); + bool exportButton(int nSet, const OUString& rPath, const OUString& rName); + +private: + std::unique_ptr<ButtonSetImpl> mpImpl; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/htmlattr.cxx b/sd/source/filter/html/htmlattr.cxx new file mode 100644 index 000000000..b89ac9b6b --- /dev/null +++ b/sd/source/filter/html/htmlattr.cxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "htmlattr.hxx" +#include <sdresid.hxx> +#include <strings.hrc> +#include <vcl/outdev.hxx> + +SdHtmlAttrPreview::SdHtmlAttrPreview() +{ +} + +SdHtmlAttrPreview::~SdHtmlAttrPreview() +{ +} + +void SdHtmlAttrPreview::Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) +{ + ::tools::Rectangle aTextRect; + aTextRect.SetSize(GetOutputSizePixel()); + + rRenderContext.SetLineColor(m_aBackColor); + rRenderContext.SetFillColor(m_aBackColor); + rRenderContext.DrawRect(rRect); + rRenderContext.SetFillColor(); + + int nHeight = (aTextRect.Bottom() - aTextRect.Top()) >> 2; + aTextRect.SetBottom( nHeight + aTextRect.Top() ); + + rRenderContext.SetTextColor(m_aTextColor); + rRenderContext.DrawText(aTextRect, SdResId(STR_HTMLATTR_TEXT), DrawTextFlags::Center | DrawTextFlags::VCenter); + + aTextRect.Move(0,nHeight); + rRenderContext.SetTextColor(m_aLinkColor); + rRenderContext.DrawText(aTextRect, SdResId(STR_HTMLATTR_LINK), DrawTextFlags::Center | DrawTextFlags::VCenter); + + aTextRect.Move(0,nHeight); + rRenderContext.SetTextColor(m_aALinkColor); + rRenderContext.DrawText(aTextRect, SdResId(STR_HTMLATTR_ALINK), DrawTextFlags::Center | DrawTextFlags::VCenter); + + aTextRect.Move(0,nHeight); + rRenderContext.SetTextColor(m_aVLinkColor); + rRenderContext.DrawText(aTextRect, SdResId(STR_HTMLATTR_VLINK), DrawTextFlags::Center | DrawTextFlags::VCenter); +} + +void SdHtmlAttrPreview::SetColors(Color const & aBack, Color const & aText, Color const & aLink, + Color const & aVLink, Color const & aALink) +{ + m_aBackColor = aBack; + m_aTextColor = aText; + m_aLinkColor = aLink; + m_aVLinkColor = aVLink; + m_aALinkColor = aALink; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/htmlattr.hxx b/sd/source/filter/html/htmlattr.hxx new file mode 100644 index 000000000..bf80b9e4b --- /dev/null +++ b/sd/source/filter/html/htmlattr.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <vcl/customweld.hxx> +#include <tools/color.hxx> + +class SdHtmlAttrPreview final : public weld::CustomWidgetController +{ + Color m_aBackColor, m_aTextColor, m_aLinkColor; + Color m_aVLinkColor, m_aALinkColor; + +public: + SdHtmlAttrPreview(); + virtual ~SdHtmlAttrPreview() override; + + virtual void Paint(vcl::RenderContext& rRenderContext, const ::tools::Rectangle& rRect) override; + + void SetColors( Color const & aBack, Color const & aText, Color const & aLink, + Color const & aVLink, Color const & aALink ); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/htmlex.cxx b/sd/source/filter/html/htmlex.cxx new file mode 100644 index 000000000..072ac3c27 --- /dev/null +++ b/sd/source/filter/html/htmlex.cxx @@ -0,0 +1,3186 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include "htmlex.hxx" +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/drawing/GraphicExportFilter.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/ucb/SimpleFileAccess.hpp> + +#include <sal/log.hxx> +#include <rtl/tencinfo.h> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <o3tl/safeint.hxx> +#include <osl/file.hxx> +#include <unotools/pathoptions.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <com/sun/star/frame/XStorable.hpp> +#include <sfx2/frmhtmlw.hxx> +#include <sfx2/progress.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svx/svditer.hxx> +#include <vcl/imaprect.hxx> +#include <vcl/imapcirc.hxx> +#include <vcl/imappoly.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <svx/svdopath.hxx> +#include <svtools/htmlout.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/colritem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/wghtitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/flditem.hxx> +#include <svl/style.hxx> +#include <editeng/frmdiritem.hxx> +#include <svx/svdoutl.hxx> +#include <svx/svdogrp.hxx> +#include <svx/svdotable.hxx> +#include <svx/ImageMapInfo.hxx> +#include <tools/urlobj.hxx> +#include <svtools/sfxecode.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <tools/debug.hxx> +#include <tools/diagnose_ex.h> + +#include <drawdoc.hxx> +#include <DrawDocShell.hxx> +#include "htmlpublishmode.hxx" +#include <Outliner.hxx> +#include <sdpage.hxx> +#include <strings.hrc> +#include <strings.hxx> +#include <anminfo.hxx> +#include <sdresid.hxx> +#include "buttonset.hxx" + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::document; + +using namespace sdr::table; + +// get parameter from Itemset +#define RESTOHTML( res ) StringToHTMLString(SdResId(res)) + +const char * const pButtonNames[] = +{ + "first-inactive.png", + "first.png", + "left-inactive.png", + "left.png", + "right-inactive.png", + "right.png", + "last-inactive.png", + "last.png", + "home.png", + "text.png", + "expand.png", + "collapse.png", +}; + +#define BTN_FIRST_0 0 +#define BTN_FIRST_1 1 +#define BTN_PREV_0 2 +#define BTN_PREV_1 3 +#define BTN_NEXT_0 4 +#define BTN_NEXT_1 5 +#define BTN_LAST_0 6 +#define BTN_LAST_1 7 +#define BTN_INDEX 8 +#define BTN_TEXT 9 +#define BTN_MORE 10 +#define BTN_LESS 11 + +namespace { + +// Helper class for the simple creation of files local/remote +class EasyFile +{ +private: + std::unique_ptr<SvStream> pOStm; + bool bOpen; + +public: + + EasyFile(); + ~EasyFile(); + + ErrCode createStream( const OUString& rUrl, SvStream*& rpStr ); + void createFileName( const OUString& rUrl, OUString& rFileName ); + void close(); +}; + +} + +// Helper class for the embedding of text attributes into the html output +class HtmlState +{ +private: + bool mbColor; + bool mbWeight; + bool mbItalic; + bool mbUnderline; + bool mbStrike; + bool mbLink; + Color maColor; + Color maDefColor; + OUString maLink; + OUString maTarget; + +public: + explicit HtmlState( Color aDefColor ); + + OUString SetWeight( bool bWeight ); + OUString SetItalic( bool bItalic ); + OUString SetUnderline( bool bUnderline ); + OUString SetColor( Color aColor ); + OUString SetStrikeout( bool bStrike ); + OUString SetLink( const OUString& aLink, const OUString& aTarget ); + OUString Flush(); +}; + +// close all still open tags +OUString HtmlState::Flush() +{ + OUString aStr = SetWeight(false) + + SetItalic(false) + + SetUnderline(false) + + SetStrikeout(false) + + SetColor(maDefColor) + + SetLink("",""); + + return aStr; +} + +// c'tor with default color for the page +HtmlState::HtmlState( Color aDefColor ) + : mbColor(false), + mbWeight(false), + mbItalic(false), + mbUnderline(false), + mbStrike(false), + mbLink(false), + maDefColor(aDefColor) +{ +} + +// enables/disables bold print +OUString HtmlState::SetWeight( bool bWeight ) +{ + OUString aStr; + + if(bWeight && !mbWeight) + aStr = "<b>"; + else if(!bWeight && mbWeight) + aStr = "</b>"; + + mbWeight = bWeight; + return aStr; +} + +// enables/disables italic + +OUString HtmlState::SetItalic( bool bItalic ) +{ + OUString aStr; + + if(bItalic && !mbItalic) + aStr = "<i>"; + else if(!bItalic && mbItalic) + aStr = "</i>"; + + mbItalic = bItalic; + return aStr; +} + +// enables/disables underlines + +OUString HtmlState::SetUnderline( bool bUnderline ) +{ + OUString aStr; + + if(bUnderline && !mbUnderline) + aStr = "<u>"; + else if(!bUnderline && mbUnderline) + aStr = "</u>"; + + mbUnderline = bUnderline; + return aStr; +} + +// enables/disables strike through +OUString HtmlState::SetStrikeout( bool bStrike ) +{ + OUString aStr; + + if(bStrike && !mbStrike) + aStr = "<strike>"; + else if(!bStrike && mbStrike) + aStr = "</strike>"; + + mbStrike = bStrike; + return aStr; +} + +// Sets the specified text color +OUString HtmlState::SetColor( Color aColor ) +{ + OUString aStr; + + if(mbColor && aColor == maColor) + return aStr; + + if(mbColor) + { + aStr = "</font>"; + mbColor = false; + } + + if(aColor != maDefColor) + { + maColor = aColor; + aStr += "<font color=\"" + HtmlExport::ColorToHTMLString(aColor) + "\">"; + mbColor = true; + } + + return aStr; +} + +// enables/disables a hyperlink +OUString HtmlState::SetLink( const OUString& aLink, const OUString& aTarget ) +{ + OUString aStr; + + if(mbLink&&maLink == aLink&&maTarget==aTarget) + return aStr; + + if(mbLink) + { + aStr = "</a>"; + mbLink = false; + } + + if (!aLink.isEmpty()) + { + aStr += "<a href=\"" + aLink; + if (!aTarget.isEmpty()) + { + aStr += "\" target=\"" + aTarget; + } + aStr += "\">"; + mbLink = true; + maLink = aLink; + maTarget = aTarget; + } + + return aStr; +} +namespace +{ + +OUString getParagraphStyle( const SdrOutliner* pOutliner, sal_Int32 nPara ) +{ + SfxItemSet aParaSet( pOutliner->GetParaAttribs( nPara ) ); + + OUString sStyle; + + if( aParaSet.GetItem<SvxFrameDirectionItem>( EE_PARA_WRITINGDIR )->GetValue() == SvxFrameDirection::Horizontal_RL_TB ) + { + + sStyle = "direction: rtl;"; + } + else + { + // This is the default so don't write it out + // sStyle += "direction: ltr;"; + } + return sStyle; +} + +void lclAppendStyle(OUStringBuffer& aBuffer, std::u16string_view aTag, std::u16string_view aStyle) +{ + if (aStyle.empty()) + aBuffer.append(OUString::Concat("<") + aTag + ">"); + else + aBuffer.append(OUString::Concat("<") + aTag + " style=\"" + aStyle + "\">"); +} + +} // anonymous namespace + +constexpr OUStringLiteral gaHTMLHeader( + u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n" + " \"http://www.w3.org/TR/html4/transitional.dtd\">\r\n" + "<html>\r\n<head>\r\n" ); + +constexpr OUStringLiteral gaHTMLExtension = u"" STR_HTMLEXP_DEFAULT_EXTENSION; + +// constructor for the html export helper classes +HtmlExport::HtmlExport( + const OUString& aPath, + const Sequence< PropertyValue >& rParams, + SdDrawDocument* pExpDoc, + sd::DrawDocShell* pDocShell ) + : maPath( aPath ), + mpDoc(pExpDoc), + mpDocSh( pDocShell ), + meMode( PUBLISH_SINGLE_DOCUMENT ), + mbContentsPage(false), + mnButtonThema(-1), + mnWidthPixel( PUB_MEDRES_WIDTH ), + meFormat( FORMAT_JPG ), + mbNotes(false), + mnCompression( -1 ), + mbDownload( false ), + mbSlideSound(true), + mbHiddenSlides(true), + mbUserAttr(false), + maTextColor(COL_BLACK), + maBackColor(COL_WHITE), + mbDocColors(false), + maIndexUrl("index"), + meScript( SCRIPT_ASP ), + mpButtonSet( new ButtonSet() ) +{ + bool bChange = mpDoc->IsChanged(); + + maIndexUrl += gaHTMLExtension; + + InitExportParameters( rParams ); + + switch( meMode ) + { + case PUBLISH_HTML: + case PUBLISH_FRAMES: + ExportHtml(); + break; + case PUBLISH_WEBCAST: + ExportWebCast(); + break; + case PUBLISH_KIOSK: + ExportKiosk(); + break; + case PUBLISH_SINGLE_DOCUMENT: + ExportSingleDocument(); + break; + } + + mpDoc->SetChanged(bChange); +} + +HtmlExport::~HtmlExport() +{ +} + +// get common export parameters from item set +void HtmlExport::InitExportParameters( const Sequence< PropertyValue >& rParams ) +{ + mbImpress = mpDoc->GetDocumentType() == DocumentType::Impress; + + OUString aStr; + for( const PropertyValue& rParam : rParams ) + { + if ( rParam.Name == "PublishMode" ) + { + sal_Int32 temp = 0; + rParam.Value >>= temp; + meMode = static_cast<HtmlPublishMode>(temp); + } + else if ( rParam.Name == "IndexURL" ) + { + rParam.Value >>= aStr; + maIndexUrl = aStr; + } + else if ( rParam.Name == "Format" ) + { + sal_Int32 temp = 0; + rParam.Value >>= temp; + meFormat = static_cast<PublishingFormat>(temp); + } + else if ( rParam.Name == "Compression" ) + { + rParam.Value >>= aStr; + OUString aTmp( aStr ); + if(!aTmp.isEmpty()) + { + aTmp = aTmp.replaceFirst("%", ""); + mnCompression = static_cast<sal_Int16>(aTmp.toInt32()); + } + } + else if ( rParam.Name == "Width" ) + { + sal_Int32 temp = 0; + rParam.Value >>= temp; + mnWidthPixel = static_cast<sal_uInt16>(temp); + } + else if ( rParam.Name == "UseButtonSet" ) + { + sal_Int32 temp = 0; + rParam.Value >>= temp; + mnButtonThema = static_cast<sal_Int16>(temp); + } + else if ( rParam.Name == "IsExportNotes" ) + { + if( mbImpress ) + { + bool temp = false; + rParam.Value >>= temp; + mbNotes = temp; + } + } + else if ( rParam.Name == "IsExportContentsPage" ) + { + bool temp = false; + rParam.Value >>= temp; + mbContentsPage = temp; + } + else if ( rParam.Name == "Author" ) + { + rParam.Value >>= aStr; + maAuthor = aStr; + } + else if ( rParam.Name == "EMail" ) + { + rParam.Value >>= aStr; + maEMail = aStr; + } + else if ( rParam.Name == "HomepageURL" ) + { + rParam.Value >>= aStr; + maHomePage = aStr; + } + else if ( rParam.Name == "UserText" ) + { + rParam.Value >>= aStr; + maInfo = aStr; + } + else if ( rParam.Name == "EnableDownload" ) + { + bool temp = false; + rParam.Value >>= temp; + mbDownload = temp; + } + else if ( rParam.Name == "SlideSound" ) + { + bool temp = true; + rParam.Value >>= temp; + mbSlideSound = temp; + } + else if ( rParam.Name == "HiddenSlides" ) + { + bool temp = true; + rParam.Value >>= temp; + mbHiddenSlides = temp; + } + else if ( rParam.Name == "BackColor" ) + { + Color temp; + rParam.Value >>= temp; + maBackColor = temp; + mbUserAttr = true; + } + else if ( rParam.Name == "TextColor" ) + { + Color temp; + rParam.Value >>= temp; + maTextColor = temp; + mbUserAttr = true; + } + else if ( rParam.Name == "LinkColor" ) + { + Color temp ; + rParam.Value >>= temp; + maLinkColor = temp; + mbUserAttr = true; + } + else if ( rParam.Name == "VLinkColor" ) + { + Color temp; + rParam.Value >>= temp; + maVLinkColor = temp; + mbUserAttr = true; + } + else if ( rParam.Name == "ALinkColor" ) + { + Color temp; + rParam.Value >>= temp; + maALinkColor = temp; + mbUserAttr = true; + } + else if ( rParam.Name == "IsUseDocumentColors" ) + { + bool temp = false; + rParam.Value >>= temp; + mbDocColors = temp; + } + else if ( rParam.Name == "KioskSlideDuration" ) + { + double temp = 0.0; + rParam.Value >>= temp; + mfSlideDuration = temp; + mbAutoSlide = true; + } + else if ( rParam.Name == "KioskEndless" ) + { + bool temp = false; + rParam.Value >>= temp; + mbEndless = temp; + } + else if ( rParam.Name == "WebCastCGIURL" ) + { + rParam.Value >>= aStr; + maCGIPath = aStr; + } + else if ( rParam.Name == "WebCastTargetURL" ) + { + rParam.Value >>= aStr; + maURLPath = aStr; + } + else if ( rParam.Name == "WebCastScriptLanguage" ) + { + rParam.Value >>= aStr; + if ( aStr == "asp" ) + { + meScript = SCRIPT_ASP; + } + else + { + meScript = SCRIPT_PERL; + } + } + else + { + OSL_FAIL("Unknown property for html export detected!"); + } + } + + if( meMode == PUBLISH_KIOSK ) + { + mbContentsPage = false; + mbNotes = false; + + } + + // calculate image sizes + SdPage* pPage = mpDoc->GetSdPage(0, PageKind::Standard); + Size aTmpSize( pPage->GetSize() ); + double dRatio=static_cast<double>(aTmpSize.Width())/aTmpSize.Height(); + + mnHeightPixel = static_cast<sal_uInt16>(mnWidthPixel/dRatio); + + // we come up with a destination... + + INetURLObject aINetURLObj( maPath ); + DBG_ASSERT( aINetURLObj.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + maExportPath = aINetURLObj.GetPartBeforeLastName(); // with trailing '/' + maIndex = aINetURLObj.GetLastName(); + + mnSdPageCount = mpDoc->GetSdPageCount( PageKind::Standard ); + for( sal_uInt16 nPage = 0; nPage < mnSdPageCount; nPage++ ) + { + pPage = mpDoc->GetSdPage( nPage, PageKind::Standard ); + + if( mbHiddenSlides || !pPage->IsExcluded() ) + { + maPages.push_back( pPage ); + maNotesPages.push_back( mpDoc->GetSdPage( nPage, PageKind::Notes ) ); + } + } + mnSdPageCount = maPages.size(); + + mbFrames = meMode == PUBLISH_FRAMES; + + maDocFileName = maIndex; +} + +void HtmlExport::ExportSingleDocument() +{ + SdrOutliner* pOutliner = mpDoc->GetInternalOutliner(); + + maPageNames.resize(mnSdPageCount); + + mnPagesWritten = 0; + InitProgress(mnSdPageCount); + + OUStringBuffer aStr(gaHTMLHeader); + aStr.append(DocumentMetadata()); + aStr.append("\r\n"); + aStr.append("</head>\r\n"); + aStr.append(CreateBodyTag()); + + for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; ++nSdPage) + { + SdPage* pPage = maPages[nSdPage]; + maPageNames[nSdPage] = pPage->GetName(); + + if( mbDocColors ) + { + SetDocColors( pPage ); + } + + // page title + OUString sTitleText(CreateTextForTitle(pOutliner, pPage, pPage->GetPageBackgroundColor())); + OUString sStyle; + + if (nSdPage != 0) // First page - no need for a page break here + sStyle += "page-break-before:always; "; + sStyle += getParagraphStyle(pOutliner, 0); + + lclAppendStyle(aStr, u"h1", sStyle); + + aStr.append(sTitleText); + aStr.append("</h1>\r\n"); + + // write outline text + aStr.append(CreateTextForPage( pOutliner, pPage, true, pPage->GetPageBackgroundColor() )); + + // notes + if(mbNotes) + { + SdPage* pNotesPage = maNotesPages[ nSdPage ]; + OUString aNotesStr( CreateTextForNotesPage( pOutliner, pNotesPage, maBackColor) ); + + if (!aNotesStr.isEmpty()) + { + aStr.append("<br>\r\n<h3>"); + aStr.append(RESTOHTML(STR_HTMLEXP_NOTES)); + aStr.append(":</h3>\r\n"); + + aStr.append(aNotesStr); + } + } + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + } + + // close page + aStr.append("</body>\r\n</html>"); + + WriteHtml(maDocFileName, false, aStr.makeStringAndClear()); + + pOutliner->Clear(); + ResetProgress(); +} + +// exports the (in the c'tor specified impress document) to html +void HtmlExport::ExportHtml() +{ + if(mbUserAttr) + { + if( maTextColor == COL_AUTO ) + { + if( !maBackColor.IsDark() ) + maTextColor = COL_BLACK; + } + } + else if( mbDocColors ) + { + // default colors for the color schema 'From Document' + SetDocColors(); + maFirstPageColor = maBackColor; + } + + // get name for downloadable presentation if needed + if( mbDownload ) + { + // fade out separator search and extension + sal_Int32 nSepPos = maDocFileName.indexOf('.'); + if (nSepPos != -1) + maDocFileName = maDocFileName.copy(0, nSepPos); + + maDocFileName += ".odp"; + } + + sal_uInt16 nProgrCount = mnSdPageCount; + nProgrCount += mbImpress?mnSdPageCount:0; + nProgrCount += mbContentsPage?1:0; + nProgrCount += (mbFrames && mbNotes)?mnSdPageCount:0; + nProgrCount += mbFrames ? 8 : 0; + InitProgress( nProgrCount ); + + mpDocSh->SetWaitCursor( true ); + + // Exceptions are cool... + + CreateFileNames(); + + // this is not a true while + while( true ) + { + if( checkForExistingFiles() ) + break; + + if( !CreateImagesForPresPages() ) + break; + + if( mbContentsPage && + !CreateImagesForPresPages( true ) ) + break; + + if( !CreateHtmlForPresPages() ) + break; + + if( mbImpress ) + if( !CreateHtmlTextForPresPages() ) + break; + + if( mbFrames ) + { + if( !CreateFrames() ) + break; + + if( !CreateOutlinePages() ) + break; + + if( !CreateNavBarFrames() ) + break; + + if( mbNotes && mbImpress ) + if( !CreateNotesPages() ) + break; + + } + + if( mbContentsPage ) + if( !CreateContentPage() ) + break; + + CreateBitmaps(); + + mpDocSh->SetWaitCursor( false ); + ResetProgress(); + + if( mbDownload ) + SavePresentation(); + + return; + } + + // if we get to this point the export was + // canceled by the user after an error + mpDocSh->SetWaitCursor( false ); + ResetProgress(); +} + +void HtmlExport::SetDocColors( SdPage* pPage ) +{ + if( pPage == nullptr ) + pPage = mpDoc->GetSdPage(0, PageKind::Standard); + + svtools::ColorConfig aConfig; + maVLinkColor = aConfig.GetColorValue(svtools::LINKSVISITED).nColor; + maALinkColor = aConfig.GetColorValue(svtools::LINKS).nColor; + maLinkColor = aConfig.GetColorValue(svtools::LINKS).nColor; + maTextColor = COL_BLACK; + + SfxStyleSheet* pSheet = nullptr; + + if( mpDoc->GetDocumentType() == DocumentType::Impress ) + { + // default text color from the outline template of the first page + pSheet = pPage->GetStyleSheetForPresObj(PresObjKind::Outline); + if(pSheet == nullptr) + pSheet = pPage->GetStyleSheetForPresObj(PresObjKind::Text); + if(pSheet == nullptr) + pSheet = pPage->GetStyleSheetForPresObj(PresObjKind::Title); + } + + if(pSheet == nullptr) + pSheet = mpDoc->GetDefaultStyleSheet(); + + if(pSheet) + { + SfxItemSet& rSet = pSheet->GetItemSet(); + if(rSet.GetItemState(EE_CHAR_COLOR) == SfxItemState::SET) + maTextColor = rSet.GetItem<SvxColorItem>(EE_CHAR_COLOR)->GetValue(); + } + + // default background from the background of the master page of the first page + maBackColor = pPage->GetPageBackgroundColor(); + + if( maTextColor == COL_AUTO ) + { + if( !maBackColor.IsDark() ) + maTextColor = COL_BLACK; + } +} + +void HtmlExport::InitProgress( sal_uInt16 nProgrCount ) +{ + mpProgress.reset(new SfxProgress( mpDocSh, SdResId(STR_CREATE_PAGES), nProgrCount )); +} + +void HtmlExport::ResetProgress() +{ + mpProgress.reset(); +} + +void HtmlExport::ExportKiosk() +{ + mnPagesWritten = 0; + InitProgress( 2*mnSdPageCount ); + + CreateFileNames(); + if( !checkForExistingFiles() ) + { + if( CreateImagesForPresPages() ) + CreateHtmlForPresPages(); + } + + ResetProgress(); +} + +// Export Document with WebCast (TM) Technology +void HtmlExport::ExportWebCast() +{ + mnPagesWritten = 0; + InitProgress( mnSdPageCount + 9 ); + + mpDocSh->SetWaitCursor( true ); + + CreateFileNames(); + + if (maCGIPath.isEmpty()) + maCGIPath = "."; + + if (!maCGIPath.endsWith("/")) + maCGIPath += "/"; + + if( meScript == SCRIPT_ASP ) + { + maURLPath = "./"; + } + else + { + if (maURLPath.isEmpty()) + maURLPath = "."; + + if (!maURLPath.endsWith("/")) + maURLPath += "/"; + } + + // this is not a true while + while(true) + { + if( checkForExistingFiles() ) + break; + + if(!CreateImagesForPresPages()) + break; + + if( meScript == SCRIPT_ASP ) + { + if(!CreateASPScripts()) + break; + } + else + { + if(!CreatePERLScripts()) + break; + } + + if(!CreateImageFileList()) + break; + + if(!CreateImageNumberFile()) + break; + + break; + } + + mpDocSh->SetWaitCursor( false ); + ResetProgress(); +} + +// Save the presentation as a downloadable file in the dest directory +bool HtmlExport::SavePresentation() +{ + meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, maDocFileName ); + + OUString aURL(maExportPath + maDocFileName); + + mpDocSh->EnableSetModified(); + + try + { + uno::Reference< frame::XStorable > xStorable( mpDoc->getUnoModel(), uno::UNO_QUERY ); + if( xStorable.is() ) + { + uno::Sequence< beans::PropertyValue > aProperties{ + comphelper::makePropertyValue("Overwrite", true), + comphelper::makePropertyValue("FilterName", OUString("impress8")) + }; + xStorable->storeToURL( aURL, aProperties ); + + mpDocSh->EnableSetModified( false ); + + return true; + } + } + catch( Exception& ) + { + } + + mpDocSh->EnableSetModified( false ); + + return false; +} + +// create image files +bool HtmlExport::CreateImagesForPresPages( bool bThumbnail) +{ + try + { + Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + + Reference< drawing::XGraphicExportFilter > xGraphicExporter = drawing::GraphicExportFilter::create( xContext ); + + Sequence< PropertyValue > aFilterData(((meFormat==FORMAT_JPG)&&(mnCompression != -1))? 3 : 2); + auto pFilterData = aFilterData.getArray(); + pFilterData[0].Name = "PixelWidth"; + pFilterData[0].Value <<= static_cast<sal_Int32>(bThumbnail ? PUB_THUMBNAIL_WIDTH : mnWidthPixel ); + pFilterData[1].Name = "PixelHeight"; + pFilterData[1].Value <<= static_cast<sal_Int32>(bThumbnail ? PUB_THUMBNAIL_HEIGHT : mnHeightPixel); + if((meFormat==FORMAT_JPG)&&(mnCompression != -1)) + { + pFilterData[2].Name = "Quality"; + pFilterData[2].Value <<= static_cast<sal_Int32>(mnCompression); + } + + OUString sFormat; + if( meFormat == FORMAT_PNG ) + sFormat = "PNG"; + else if( meFormat == FORMAT_GIF ) + sFormat = "GIF"; + else + sFormat = "JPG"; + + Sequence< PropertyValue > aDescriptor{ + comphelper::makePropertyValue("URL", Any()), + comphelper::makePropertyValue("FilterName", sFormat), + comphelper::makePropertyValue("FilterData", aFilterData) + }; + auto pDescriptor = aDescriptor.getArray(); + + for (sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++) + { + SdPage* pPage = maPages[ nSdPage ]; + + OUString aFull(maExportPath); + if (bThumbnail) + aFull += maThumbnailFiles[nSdPage]; + else + aFull += maImageFiles[nSdPage]; + + pDescriptor[0].Value <<= aFull; + + Reference< XComponent > xPage( pPage->getUnoPage(), UNO_QUERY ); + xGraphicExporter->setSourceDocument( xPage ); + xGraphicExporter->filter( aDescriptor ); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + } + } + catch( Exception& ) + { + return false; + } + + return true; +} + +// get SdrTextObject with layout text of this page +SdrTextObj* HtmlExport::GetLayoutTextObject(SdrPage const * pPage) +{ + const size_t nObjectCount = pPage->GetObjCount(); + SdrTextObj* pResult = nullptr; + + for (size_t nObject = 0; nObject < nObjectCount; ++nObject) + { + SdrObject* pObject = pPage->GetObj(nObject); + if (pObject->GetObjInventor() == SdrInventor::Default && + pObject->GetObjIdentifier() == SdrObjKind::OutlineText) + { + pResult = static_cast<SdrTextObj*>(pObject); + break; + } + } + return pResult; +} + +// create HTML text version of impress pages +OUString HtmlExport::CreateMetaCharset() +{ + OUString aStr; + const char *pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 ); + if ( pCharSet ) + { + aStr = " <meta HTTP-EQUIV=CONTENT-TYPE CONTENT=\"text/html; charset=" + + OUString::createFromAscii(pCharSet) + "\">\r\n"; + } + return aStr; +} + +OUString HtmlExport::DocumentMetadata() const +{ + SvMemoryStream aStream; + + uno::Reference<document::XDocumentProperties> xDocProps; + if (mpDocSh) + { + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + mpDocSh->GetModel(), uno::UNO_QUERY_THROW); + xDocProps.set(xDPS->getDocumentProperties()); + } + + SfxFrameHTMLWriter::Out_DocInfo(aStream, maDocFileName, xDocProps, + " "); + + const sal_uInt64 nLen = aStream.GetSize(); + OSL_ENSURE(nLen < o3tl::make_unsigned(SAL_MAX_INT32), "Stream can't fit in OString"); + OString aData(static_cast<const char*>(aStream.GetData()), static_cast<sal_Int32>(nLen)); + + return OStringToOUString(aData, RTL_TEXTENCODING_UTF8); +} + +bool HtmlExport::CreateHtmlTextForPresPages() +{ + bool bOk = true; + + SdrOutliner* pOutliner = mpDoc->GetInternalOutliner(); + + for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount && bOk; nSdPage++) + { + SdPage* pPage = maPages[ nSdPage ]; + + if( mbDocColors ) + { + SetDocColors( pPage ); + } + + // HTML head + OUStringBuffer aStr(gaHTMLHeader); + aStr.append(CreateMetaCharset()); + aStr.append(" <title>"); + aStr.append(StringToHTMLString(maPageNames[nSdPage])); + aStr.append("</title>\r\n"); + aStr.append("</head>\r\n"); + aStr.append(CreateBodyTag()); + + // navigation bar + aStr.append(CreateNavBar(nSdPage, true)); + + // page title + OUString sTitleText( CreateTextForTitle(pOutliner,pPage, pPage->GetPageBackgroundColor()) ); + lclAppendStyle(aStr, u"h1", getParagraphStyle(pOutliner, 0)); + aStr.append(sTitleText); + aStr.append("</h1>\r\n"); + + // write outline text + aStr.append(CreateTextForPage( pOutliner, pPage, true, pPage->GetPageBackgroundColor() )); + + // notes + if(mbNotes) + { + SdPage* pNotesPage = maNotesPages[ nSdPage ]; + OUString aNotesStr( CreateTextForNotesPage( pOutliner, pNotesPage, maBackColor) ); + + if (!aNotesStr.isEmpty()) + { + aStr.append("<br>\r\n<h3>"); + aStr.append(RESTOHTML(STR_HTMLEXP_NOTES)); + aStr.append(":</h3>\r\n"); + + aStr.append(aNotesStr); + } + } + + // close page + aStr.append("</body>\r\n</html>"); + + bOk = WriteHtml(maTextFiles[nSdPage], false, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + } + + pOutliner->Clear(); + + return bOk; +} + +/** exports the given html data into a non unicode file in the current export path with + the given filename */ +bool HtmlExport::WriteHtml( const OUString& rFileName, bool bAddExtension, std::u16string_view rHtmlData ) +{ + ErrCode nErr = ERRCODE_NONE; + + OUString aFileName( rFileName ); + if( bAddExtension ) + aFileName += gaHTMLExtension; + + meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, rFileName ); + EasyFile aFile; + SvStream* pStr; + OUString aFull(maExportPath + aFileName); + nErr = aFile.createStream(aFull , pStr); + if(nErr == ERRCODE_NONE) + { + OString aStr(OUStringToOString(rHtmlData, RTL_TEXTENCODING_UTF8)); + pStr->WriteOString( aStr ); + aFile.close(); + } + + if( nErr != ERRCODE_NONE ) + ErrorHandler::HandleError(nErr); + + return nErr == ERRCODE_NONE; +} + +/** creates an outliner text for the title objects of a page + */ +OUString HtmlExport::CreateTextForTitle( SdrOutliner* pOutliner, SdPage* pPage, const Color& rBackgroundColor ) +{ + SdrTextObj* pTO = static_cast<SdrTextObj*>(pPage->GetPresObj(PresObjKind::Title)); + if(!pTO) + pTO = GetLayoutTextObject(pPage); + + if (pTO && !pTO->IsEmptyPresObj()) + { + OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject(); + if(pOPO && pOutliner->GetParagraphCount() != 0) + { + pOutliner->Clear(); + pOutliner->SetText(*pOPO); + return ParagraphToHTMLString(pOutliner,0, rBackgroundColor); + } + } + + return OUString(); +} + +// creates an outliner text for a page +OUString HtmlExport::CreateTextForPage(SdrOutliner* pOutliner, SdPage const * pPage, + bool bHeadLine, const Color& rBackgroundColor) +{ + OUStringBuffer aStr; + + for (size_t i = 0; i <pPage->GetObjCount(); ++i ) + { + SdrObject* pObject = pPage->GetObj(i); + PresObjKind eKind = pPage->GetPresObjKind(pObject); + + switch (eKind) + { + case PresObjKind::NONE: + { + if (pObject->GetObjIdentifier() == SdrObjKind::Group) + { + SdrObjGroup* pObjectGroup = static_cast<SdrObjGroup*>(pObject); + WriteObjectGroup(aStr, pObjectGroup, pOutliner, rBackgroundColor, false); + } + else if (pObject->GetObjIdentifier() == SdrObjKind::Table) + { + SdrTableObj* pTableObject = static_cast<SdrTableObj*>(pObject); + WriteTable(aStr, pTableObject, pOutliner, rBackgroundColor); + } + else + { + if (pObject->GetOutlinerParaObject()) + { + WriteOutlinerParagraph(aStr, pOutliner, pObject->GetOutlinerParaObject(), rBackgroundColor, false); + } + } + } + break; + + case PresObjKind::Table: + { + SdrTableObj* pTableObject = static_cast<SdrTableObj*>(pObject); + WriteTable(aStr, pTableObject, pOutliner, rBackgroundColor); + } + break; + + case PresObjKind::Text: + case PresObjKind::Outline: + { + SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject); + if (pTextObject->IsEmptyPresObj()) + continue; + WriteOutlinerParagraph(aStr, pOutliner, pTextObject->GetOutlinerParaObject(), rBackgroundColor, bHeadLine); + } + break; + + default: + break; + } + } + return aStr.makeStringAndClear(); +} + +void HtmlExport::WriteTable(OUStringBuffer& aStr, SdrTableObj const * pTableObject, SdrOutliner* pOutliner, const Color& rBackgroundColor) +{ + CellPos aStart, aEnd; + + aStart = SdrTableObj::getFirstCell(); + aEnd = pTableObject->getLastCell(); + + sal_Int32 nColCount = pTableObject->getColumnCount(); + aStr.append("<table>\r\n"); + for (sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++) + { + aStr.append(" <tr>\r\n"); + for (sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++) + { + aStr.append(" <td>\r\n"); + sal_Int32 nCellIndex = nRow * nColCount + nCol; + SdrText* pText = pTableObject->getText(nCellIndex); + + if (pText == nullptr) + continue; + WriteOutlinerParagraph(aStr, pOutliner, pText->GetOutlinerParaObject(), rBackgroundColor, false); + aStr.append(" </td>\r\n"); + } + aStr.append(" </tr>\r\n"); + } + aStr.append("</table>\r\n"); +} + +void HtmlExport::WriteObjectGroup(OUStringBuffer& aStr, SdrObjGroup const * pObjectGroup, SdrOutliner* pOutliner, + const Color& rBackgroundColor, bool bHeadLine) +{ + SdrObjListIter aGroupIterator(pObjectGroup->GetSubList(), SdrIterMode::DeepNoGroups); + while (aGroupIterator.IsMore()) + { + SdrObject* pCurrentObject = aGroupIterator.Next(); + if (pCurrentObject->GetObjIdentifier() == SdrObjKind::Group) + { + SdrObjGroup* pCurrentGroupObject = static_cast<SdrObjGroup*>(pCurrentObject); + WriteObjectGroup(aStr, pCurrentGroupObject, pOutliner, rBackgroundColor, bHeadLine); + } + else + { + OutlinerParaObject* pOutlinerParagraphObject = pCurrentObject->GetOutlinerParaObject(); + if (pOutlinerParagraphObject != nullptr) + { + WriteOutlinerParagraph(aStr, pOutliner, pOutlinerParagraphObject, rBackgroundColor, bHeadLine); + } + } + } +} + +void HtmlExport::WriteOutlinerParagraph(OUStringBuffer& aStr, SdrOutliner* pOutliner, + OutlinerParaObject const * pOutlinerParagraphObject, + const Color& rBackgroundColor, bool bHeadLine) +{ + if (pOutlinerParagraphObject == nullptr) + return; + + pOutliner->SetText(*pOutlinerParagraphObject); + + sal_Int32 nCount = pOutliner->GetParagraphCount(); + + + sal_Int16 nCurrentDepth = -1; + + for (sal_Int32 nIndex = 0; nIndex < nCount; nIndex++) + { + Paragraph* pParagraph = pOutliner->GetParagraph(nIndex); + if(pParagraph == nullptr) + continue; + + const sal_Int16 nDepth = static_cast<sal_uInt16>(pOutliner->GetDepth(nIndex)); + OUString aParaText = ParagraphToHTMLString(pOutliner, nIndex, rBackgroundColor); + + if (aParaText.isEmpty()) + continue; + + if (nDepth < 0) + { + OUString aTag = bHeadLine ? OUString("h2") : OUString("p"); + lclAppendStyle(aStr, aTag, getParagraphStyle(pOutliner, nIndex)); + + aStr.append(aParaText); + aStr.append("</" + aTag + ">\r\n"); + } + else + { + while(nCurrentDepth < nDepth) + { + aStr.append("<ul>\r\n"); + nCurrentDepth++; + } + while(nCurrentDepth > nDepth) + { + aStr.append("</ul>\r\n"); + nCurrentDepth--; + } + lclAppendStyle(aStr, u"li", getParagraphStyle(pOutliner, nIndex)); + aStr.append(aParaText); + aStr.append("</li>\r\n"); + } + } + while(nCurrentDepth >= 0) + { + aStr.append("</ul>\r\n"); + nCurrentDepth--; + } + pOutliner->Clear(); +} + +// creates an outliner text for a note page +OUString HtmlExport::CreateTextForNotesPage( SdrOutliner* pOutliner, + SdPage* pPage, + const Color& rBackgroundColor ) +{ + OUStringBuffer aStr; + + SdrTextObj* pTO = static_cast<SdrTextObj*>(pPage->GetPresObj(PresObjKind::Notes)); + + if (pTO && !pTO->IsEmptyPresObj()) + { + OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject(); + if (pOPO) + { + pOutliner->Clear(); + pOutliner->SetText( *pOPO ); + + sal_Int32 nCount = pOutliner->GetParagraphCount(); + for (sal_Int32 nPara = 0; nPara < nCount; nPara++) + { + lclAppendStyle(aStr, u"p", getParagraphStyle(pOutliner, nPara)); + aStr.append(ParagraphToHTMLString(pOutliner, nPara, rBackgroundColor)); + aStr.append("</p>\r\n"); + } + } + } + + return aStr.makeStringAndClear(); +} + +// converts a paragraph of the outliner to html +OUString HtmlExport::ParagraphToHTMLString( SdrOutliner const * pOutliner, sal_Int32 nPara, const Color& rBackgroundColor ) +{ + OUStringBuffer aStr; + + if(nullptr == pOutliner) + return OUString(); + + // TODO: MALTE!!! + EditEngine& rEditEngine = *const_cast<EditEngine*>(&pOutliner->GetEditEngine()); + bool bOldUpdateMode = rEditEngine.SetUpdateLayout(true); + + Paragraph* pPara = pOutliner->GetParagraph(nPara); + if(nullptr == pPara) + return OUString(); + + HtmlState aState( (mbUserAttr || mbDocColors) ? maTextColor : COL_BLACK ); + std::vector<sal_Int32> aPortionList; + rEditEngine.GetPortions( nPara, aPortionList ); + + sal_Int32 nPos1 = 0; + for( sal_Int32 nPos2 : aPortionList ) + { + ESelection aSelection( nPara, nPos1, nPara, nPos2); + + SfxItemSet aSet( rEditEngine.GetAttribs( aSelection ) ); + + OUString aPortion(StringToHTMLString(rEditEngine.GetText( aSelection ))); + + aStr.append(TextAttribToHTMLString( &aSet, &aState, rBackgroundColor )); + aStr.append(aPortion); + + nPos1 = nPos2; + } + aStr.append(aState.Flush()); + rEditEngine.SetUpdateLayout(bOldUpdateMode); + + return aStr.makeStringAndClear(); +} + +// Depending on the attributes of the specified set and the specified +// HtmlState, it creates the needed html tags in order to get the +// attributes +OUString HtmlExport::TextAttribToHTMLString( SfxItemSet const * pSet, HtmlState* pState, const Color& rBackgroundColor ) +{ + OUStringBuffer aStr; + + if(nullptr == pSet) + return OUString(); + + OUString aLink, aTarget; + if ( pSet->GetItemState( EE_FEATURE_FIELD ) == SfxItemState::SET ) + { + const SvxFieldItem* pItem = pSet->GetItem<SvxFieldItem>( EE_FEATURE_FIELD ); + if(pItem) + { + const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pItem->GetField() ); + if(pURL) + { + aLink = pURL->GetURL(); + aTarget = pURL->GetTargetFrame(); + } + } + } + + bool bTemp; + OUString aTemp; + + if ( pSet->GetItemState( EE_CHAR_WEIGHT ) == SfxItemState::SET ) + { + bTemp = pSet->Get( EE_CHAR_WEIGHT ).GetWeight() == WEIGHT_BOLD; + aTemp = pState->SetWeight( bTemp ); + if( bTemp ) + aStr.insert(0, aTemp); + else + aStr.append(aTemp); + } + + if ( pSet->GetItemState( EE_CHAR_UNDERLINE ) == SfxItemState::SET ) + { + bTemp = pSet->Get( EE_CHAR_UNDERLINE ).GetLineStyle() != LINESTYLE_NONE; + aTemp = pState->SetUnderline( bTemp ); + if( bTemp ) + aStr.insert(0, aTemp); + else + aStr.append(aTemp); + } + + if ( pSet->GetItemState( EE_CHAR_STRIKEOUT ) == SfxItemState::SET ) + { + bTemp = pSet->Get( EE_CHAR_STRIKEOUT ).GetStrikeout() != STRIKEOUT_NONE; + aTemp = pState->SetStrikeout( bTemp ); + if( bTemp ) + aStr.insert(0, aTemp); + else + aStr.append(aTemp); + } + + if ( pSet->GetItemState( EE_CHAR_ITALIC ) == SfxItemState::SET ) + { + bTemp = pSet->Get( EE_CHAR_ITALIC ).GetPosture() != ITALIC_NONE; + aTemp = pState->SetItalic( bTemp ); + if( bTemp ) + aStr.insert(0, aTemp); + else + aStr.append(aTemp); + } + + if(mbDocColors) + { + if ( pSet->GetItemState( EE_CHAR_COLOR ) == SfxItemState::SET ) + { + Color aTextColor = pSet->Get( EE_CHAR_COLOR ).GetValue(); + if( aTextColor == COL_AUTO ) + { + if( !rBackgroundColor.IsDark() ) + aTextColor = COL_BLACK; + } + aStr.append(pState->SetColor( aTextColor )); + } + } + + if (!aLink.isEmpty()) + aStr.insert(0, pState->SetLink(aLink, aTarget)); + else + aStr.append(pState->SetLink(aLink, aTarget)); + + return aStr.makeStringAndClear(); +} + +// create HTML wrapper for picture files +bool HtmlExport::CreateHtmlForPresPages() +{ + bool bOk = true; + + std::vector<SdrObject*> aClickableObjects; + + for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount && bOk; nSdPage++) + { + // find clickable objects (also on the master page) and put it in the + // list. This in reverse order character order since in html the first + // area is taken in the case they overlap. + SdPage* pPage = maPages[ nSdPage ]; + + if( mbDocColors ) + { + SetDocColors( pPage ); + } + + bool bMasterDone = false; + + while (!bMasterDone) + { + // sal_True = backwards + SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups, true); + + SdrObject* pObject = aIter.Next(); + while (pObject) + { + SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObject); + SvxIMapInfo* pIMapInfo = SvxIMapInfo::GetIMapInfo(pObject); + + if ((pInfo && + (pInfo->meClickAction == presentation::ClickAction_BOOKMARK || + pInfo->meClickAction == presentation::ClickAction_DOCUMENT || + pInfo->meClickAction == presentation::ClickAction_PREVPAGE || + pInfo->meClickAction == presentation::ClickAction_NEXTPAGE || + pInfo->meClickAction == presentation::ClickAction_FIRSTPAGE || + pInfo->meClickAction == presentation::ClickAction_LASTPAGE)) || + pIMapInfo) + { + aClickableObjects.push_back(pObject); + } + + pObject = aIter.Next(); + } + // now to the master page or finishing + if (!pPage->IsMasterPage()) + pPage = static_cast<SdPage*>(&(pPage->TRG_GetMasterPage())); + else + bMasterDone = true; + } + + // HTML Head + OUStringBuffer aStr(gaHTMLHeader); + aStr.append(CreateMetaCharset()); + aStr.append(" <title>" + StringToHTMLString(maPageNames[nSdPage]) + "</title>\r\n"); + + // insert timing information + pPage = maPages[ nSdPage ]; + if( meMode == PUBLISH_KIOSK ) + { + double fSecs = 0; + bool bEndless = false; + if( !mbAutoSlide ) + { + if( pPage->GetPresChange() != PresChange::Manual ) + { + fSecs = pPage->GetTime(); + bEndless = mpDoc->getPresentationSettings().mbEndless; + } + } + else + { + fSecs = mfSlideDuration; + bEndless = mbEndless; + } + + if( fSecs != 0 ) + { + if( nSdPage < (mnSdPageCount-1) || bEndless ) + { + aStr.append("<meta http-equiv=\"refresh\" content=\""); + aStr.append(fSecs); + aStr.append("; URL="); + + int nPage = nSdPage + 1; + if( nPage == mnSdPageCount ) + nPage = 0; + + aStr.append(maHTMLFiles[nPage]); + + aStr.append("\">\r\n"); + } + } + } + + aStr.append("</head>\r\n"); + + // HTML Body + aStr.append(CreateBodyTag()); + + if( mbSlideSound && pPage->IsSoundOn() ) + aStr.append(InsertSound(pPage->GetSoundFile())); + + // navigation bar + if(!mbFrames ) + aStr.append(CreateNavBar(nSdPage, false)); + // Image + aStr.append("<center>"); + aStr.append("<img src=\""); + aStr.append(maImageFiles[nSdPage]); + aStr.append("\" alt=\"\""); + + if (!aClickableObjects.empty()) + aStr.append(" USEMAP=\"#map0\""); + + aStr.append("></center>\r\n"); + + // notes + if(mbNotes && !mbFrames) + { + SdrOutliner* pOutliner = mpDoc->GetInternalOutliner(); + SdPage* pNotesPage = maNotesPages[ nSdPage ]; + OUString aNotesStr( CreateTextForNotesPage( pOutliner, pNotesPage, maBackColor) ); + pOutliner->Clear(); + + if (!aNotesStr.isEmpty()) + { + aStr.append("<h3>"); + aStr.append(RESTOHTML(STR_HTMLEXP_NOTES)); + aStr.append(":</h3><br>\r\n\r\n<p>"); + + aStr.append(aNotesStr); + aStr.append("\r\n</p>\r\n"); + } + } + + // create Imagemap if necessary + if (!aClickableObjects.empty()) + { + aStr.append("<map name=\"map0\">\r\n"); + + for (SdrObject* pObject : aClickableObjects) + { + SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObject); + SvxIMapInfo* pIMapInfo = SvxIMapInfo::GetIMapInfo(pObject); + + ::tools::Rectangle aRect(pObject->GetCurrentBoundRect()); + Point aLogPos(aRect.TopLeft()); + bool bIsSquare = aRect.GetWidth() == aRect.GetHeight(); + + sal_uLong nPageWidth = pPage->GetSize().Width() - pPage->GetLeftBorder() - + pPage->GetRightBorder(); + + // BoundRect is relative to the physical page origin, not the + // origin of ordinates + aRect.Move(-pPage->GetLeftBorder(), -pPage->GetUpperBorder()); + + double fLogicToPixel = static_cast<double>(mnWidthPixel) / nPageWidth; + aRect.SetLeft( static_cast<tools::Long>(aRect.Left() * fLogicToPixel) ); + aRect.SetTop( static_cast<tools::Long>(aRect.Top() * fLogicToPixel) ); + aRect.SetRight( static_cast<tools::Long>(aRect.Right() * fLogicToPixel) ); + aRect.SetBottom( static_cast<tools::Long>(aRect.Bottom() * fLogicToPixel) ); + tools::Long nRadius = aRect.GetWidth() / 2; + + /** + insert areas into Imagemap of the object, if the object has + such an Imagemap + */ + if (pIMapInfo) + { + const ImageMap& rIMap = pIMapInfo->GetImageMap(); + sal_uInt16 nAreaCount = rIMap.GetIMapObjectCount(); + for (sal_uInt16 nArea = 0; nArea < nAreaCount; nArea++) + { + IMapObject* pArea = rIMap.GetIMapObject(nArea); + IMapObjectType nType = pArea->GetType(); + OUString aURL( pArea->GetURL() ); + + // if necessary, convert page and object names into the + // corresponding names of the html file + bool bIsMasterPage; + sal_uInt16 nPgNum = mpDoc->GetPageByName( aURL, bIsMasterPage ); + + if (nPgNum == SDRPAGE_NOTFOUND) + { + // is the bookmark an object? + SdrObject* pObj = mpDoc->GetObj( aURL ); + if (pObj) + nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum(); + } + if (nPgNum != SDRPAGE_NOTFOUND) + { + nPgNum = (nPgNum - 1) / 2; // SdrPageNum --> SdPageNum + aURL = CreatePageURL(nPgNum); + } + + switch(nType) + { + case IMapObjectType::Rectangle: + { + ::tools::Rectangle aArea(static_cast<IMapRectangleObject*>(pArea)-> + GetRectangle(false)); + + // conversion into pixel coordinates + aArea.Move(aLogPos.X() - pPage->GetLeftBorder(), + aLogPos.Y() - pPage->GetUpperBorder()); + aArea.SetLeft( static_cast<tools::Long>(aArea.Left() * fLogicToPixel) ); + aArea.SetTop( static_cast<tools::Long>(aArea.Top() * fLogicToPixel) ); + aArea.SetRight( static_cast<tools::Long>(aArea.Right() * fLogicToPixel) ); + aArea.SetBottom( static_cast<tools::Long>(aArea.Bottom() * fLogicToPixel) ); + + aStr.append(CreateHTMLRectArea(aArea, aURL)); + } + break; + + case IMapObjectType::Circle: + { + Point aCenter(static_cast<IMapCircleObject*>(pArea)-> + GetCenter(false)); + aCenter += Point(aLogPos.X() - pPage->GetLeftBorder(), + aLogPos.Y() - pPage->GetUpperBorder()); + aCenter.setX( static_cast<tools::Long>(aCenter.X() * fLogicToPixel) ); + aCenter.setY( static_cast<tools::Long>(aCenter.Y() * fLogicToPixel) ); + + sal_uLong nCircleRadius = static_cast<IMapCircleObject*>(pArea)-> + GetRadius(false); + nCircleRadius = static_cast<sal_uLong>(nCircleRadius * fLogicToPixel); + aStr.append(CreateHTMLCircleArea(nCircleRadius, + aCenter.X(), aCenter.Y(), + aURL)); + } + break; + + case IMapObjectType::Polygon: + { + tools::Polygon aArea(static_cast<IMapPolygonObject*>(pArea)->GetPolygon(false)); + aStr.append(CreateHTMLPolygonArea(::basegfx::B2DPolyPolygon(aArea.getB2DPolygon()), + Size(aLogPos.X() - pPage->GetLeftBorder(), + aLogPos.Y() - pPage->GetUpperBorder()), + fLogicToPixel, aURL)); + } + break; + + default: + { + SAL_INFO("sd", "unknown IMapObjectType"); + } + break; + } + } + } + + /** + if there is a presentation::ClickAction, determine bookmark + and create area for the whole object + */ + if( pInfo ) + { + OUString aHRef; + presentation::ClickAction eClickAction = pInfo->meClickAction; + + switch( eClickAction ) + { + case presentation::ClickAction_BOOKMARK: + { + bool bIsMasterPage; + sal_uInt16 nPgNum = mpDoc->GetPageByName( pInfo->GetBookmark(), bIsMasterPage ); + + if( nPgNum == SDRPAGE_NOTFOUND ) + { + // is the bookmark an object? + SdrObject* pObj = mpDoc->GetObj(pInfo->GetBookmark()); + if (pObj) + nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum(); + } + + if( SDRPAGE_NOTFOUND != nPgNum ) + aHRef = CreatePageURL(( nPgNum - 1 ) / 2 ); + } + break; + + case presentation::ClickAction_DOCUMENT: + aHRef = pInfo->GetBookmark(); + break; + + case presentation::ClickAction_PREVPAGE: + { + sal_uLong nPage; + + if (nSdPage == 0) + nPage = 0; + else + nPage = nSdPage - 1; + + aHRef = CreatePageURL( static_cast<sal_uInt16>(nPage)); + } + break; + + case presentation::ClickAction_NEXTPAGE: + { + sal_uLong nPage; + if (nSdPage == mnSdPageCount - 1) + nPage = mnSdPageCount - 1; + else + nPage = nSdPage + 1; + + aHRef = CreatePageURL( static_cast<sal_uInt16>(nPage)); + } + break; + + case presentation::ClickAction_FIRSTPAGE: + aHRef = CreatePageURL(0); + break; + + case presentation::ClickAction_LASTPAGE: + aHRef = CreatePageURL(mnSdPageCount - 1); + break; + + default: + break; + } + + // and now the areas + if (!aHRef.isEmpty()) + { + // a circle? + if (pObject->GetObjInventor() == SdrInventor::Default && + pObject->GetObjIdentifier() == SdrObjKind::CircleOrEllipse && + bIsSquare ) + { + aStr.append(CreateHTMLCircleArea(aRect.GetWidth() / 2, + aRect.Left() + nRadius, + aRect.Top() + nRadius, + aHRef)); + } + // a polygon? + else if (pObject->GetObjInventor() == SdrInventor::Default && + (pObject->GetObjIdentifier() == SdrObjKind::PathLine || + pObject->GetObjIdentifier() == SdrObjKind::PolyLine || + pObject->GetObjIdentifier() == SdrObjKind::Polygon)) + { + aStr.append(CreateHTMLPolygonArea(static_cast<SdrPathObj*>(pObject)->GetPathPoly(), Size(-pPage->GetLeftBorder(), -pPage->GetUpperBorder()), fLogicToPixel, aHRef)); + } + // something completely different: use the BoundRect + else + { + aStr.append(CreateHTMLRectArea(aRect, aHRef)); + } + + } + } + } + + aStr.append("</map>\r\n"); + } + aClickableObjects.clear(); + + aStr.append("</body>\r\n</html>"); + + bOk = WriteHtml(maHTMLFiles[nSdPage], false, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + } + + return bOk; +} + +// create overview pages +bool HtmlExport::CreateContentPage() +{ + if( mbDocColors ) + SetDocColors(); + + // html head + OUStringBuffer aStr(gaHTMLHeader); + aStr.append(CreateMetaCharset()); + aStr.append(" <title>"); + aStr.append(StringToHTMLString(maPageNames[0])); + aStr.append("</title>\r\n</head>\r\n"); + aStr.append(CreateBodyTag()); + + // page head + aStr.append("<center>\r\n"); + + if(mbHeader) + { + aStr.append("<h1>"); + aStr.append(getDocumentTitle()); + aStr.append("</h1><br>\r\n"); + } + + aStr.append("<h2>"); + + // Solaris compiler bug workaround + if( mbFrames ) + aStr.append(CreateLink(maFramePage, + RESTOHTML(STR_HTMLEXP_CLICKSTART))); + else + aStr.append(CreateLink(StringToHTMLString(maHTMLFiles[0]), + RESTOHTML(STR_HTMLEXP_CLICKSTART))); + + aStr.append("</h2>\r\n</center>\r\n"); + + aStr.append("<center><table width=\"90%\"><tr>\r\n"); + + // table of content + aStr.append("<td valign=\"top\" align=\"left\" width=\"25%\">\r\n"); + aStr.append("<h3>"); + aStr.append(RESTOHTML(STR_HTMLEXP_CONTENTS)); + aStr.append("</h3>"); + + for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++) + { + OUString aPageName = maPageNames[nSdPage]; + aStr.append("<div align=\"left\">"); + if(mbFrames) + aStr.append(StringToHTMLString(aPageName)); + else + aStr.append(CreateLink(maHTMLFiles[nSdPage], aPageName)); + aStr.append("</div>\r\n"); + } + aStr.append("</td>\r\n"); + + // document information + aStr.append("<td valign=\"top\" align=\"left\" width=\"75%\">\r\n"); + + if (!maAuthor.isEmpty()) + { + aStr.append("<p><strong>"); + aStr.append(RESTOHTML(STR_HTMLEXP_AUTHOR)); + aStr.append(":</strong> "); + aStr.append(StringToHTMLString(maAuthor)); + aStr.append("</p>\r\n"); + } + + if (!maEMail.isEmpty()) + { + aStr.append("<p><strong>"); + aStr.append(RESTOHTML(STR_HTMLEXP_EMAIL)); + aStr.append(":</strong> <a href=\"mailto:"); + aStr.append(maEMail); + aStr.append("\">"); + aStr.append(StringToHTMLString(maEMail)); + aStr.append("</a></p>\r\n"); + } + + if (!maHomePage.isEmpty()) + { + aStr.append("<p><strong>"); + aStr.append(RESTOHTML(STR_HTMLEXP_HOMEPAGE)); + aStr.append(":</strong> <a href=\""); + aStr.append(maHomePage); + aStr.append("\">"); + aStr.append(StringToHTMLString(maHomePage)); + aStr.append("</a> </p>\r\n"); + } + + if (!maInfo.isEmpty()) + { + aStr.append("<p><strong>"); + aStr.append(RESTOHTML(STR_HTMLEXP_INFO)); + aStr.append(":</strong><br>\r\n"); + aStr.append(StringToHTMLString(maInfo)); + aStr.append("</p>\r\n"); + } + + if(mbDownload) + { + aStr.append("<p><a href=\""); + aStr.append(maDocFileName); + aStr.append("\">"); + aStr.append(RESTOHTML(STR_HTMLEXP_DOWNLOAD)); + aStr.append("</a></p>\r\n"); + } + + for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++) + { + OUString aText( + "<img src=\"" + + maThumbnailFiles[nSdPage] + + "\" width=\"256\" height=\"192\" alt=\"" + + StringToHTMLString(maPageNames[nSdPage]) + + "\">"); + + aStr.append(CreateLink(maHTMLFiles[nSdPage], aText)); + aStr.append("\r\n"); + } + + aStr.append("</td></tr></table></center>\r\n"); + + aStr.append("</body>\r\n</html>"); + + bool bOk = WriteHtml(maIndex, false, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + return bOk; +} + +// create note pages (for frames) + +bool HtmlExport::CreateNotesPages() +{ + bool bOk = true; + + SdrOutliner* pOutliner = mpDoc->GetInternalOutliner(); + for( sal_uInt16 nSdPage = 0; bOk && nSdPage < mnSdPageCount; nSdPage++ ) + { + SdPage* pPage = maNotesPages[nSdPage]; + if( mbDocColors ) + SetDocColors( pPage ); + + // Html head + OUStringBuffer aStr(gaHTMLHeader); + aStr.append(CreateMetaCharset()); + aStr.append(" <title>"); + aStr.append(StringToHTMLString(maPageNames[0])); + aStr.append("</title>\r\n</head>\r\n"); + aStr.append(CreateBodyTag()); + + if(pPage) + aStr.append(CreateTextForNotesPage( pOutliner, pPage, maBackColor )); + + aStr.append("</body>\r\n</html>"); + + OUString aFileName("note" + OUString::number(nSdPage)); + bOk = WriteHtml(aFileName, true, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + } + + pOutliner->Clear(); + + return bOk; +} + +// create outline pages (for frames) + +bool HtmlExport::CreateOutlinePages() +{ + bool bOk = true; + + if( mbDocColors ) + { + SetDocColors(); + } + + // page 0 will be the closed outline, page 1 the opened + for (sal_Int32 nPage = 0; nPage < (mbImpress?2:1) && bOk; ++nPage) + { + // Html head + OUStringBuffer aStr(gaHTMLHeader); + aStr.append(CreateMetaCharset()); + aStr.append(" <title>"); + aStr.append(StringToHTMLString(maPageNames[0])); + aStr.append("</title>\r\n</head>\r\n"); + aStr.append(CreateBodyTag()); + + SdrOutliner* pOutliner = mpDoc->GetInternalOutliner(); + for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++) + { + SdPage* pPage = maPages[ nSdPage ]; + + aStr.append("<div align=\"left\">"); + OUString aLink("JavaScript:parent.NavigateAbs(" + + OUString::number(nSdPage) + ")"); + + OUString aTitle = CreateTextForTitle(pOutliner, pPage, maBackColor); + if (aTitle.isEmpty()) + aTitle = maPageNames[nSdPage]; + + lclAppendStyle(aStr, u"p", getParagraphStyle(pOutliner, 0)); + aStr.append(CreateLink(aLink, aTitle)); + aStr.append("</p>"); + + if(nPage==1) + { + aStr.append(CreateTextForPage( pOutliner, pPage, false, maBackColor )); + } + aStr.append("</div>\r\n"); + } + pOutliner->Clear(); + + aStr.append("</body>\r\n</html>"); + + OUString aFileName("outline" + OUString::number(nPage)); + bOk = WriteHtml(aFileName, true, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + } + + return bOk; +} + +// set file name +void HtmlExport::CreateFileNames() +{ + // create lists with new file names + maHTMLFiles.resize(mnSdPageCount); + maImageFiles.resize(mnSdPageCount); + maThumbnailFiles.resize(mnSdPageCount); + maPageNames.resize(mnSdPageCount); + maTextFiles.resize(mnSdPageCount); + + mbHeader = false; // headline on overview page? + + for (sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++) + { + OUString aHTMLFileName; + if(nSdPage == 0 && !mbContentsPage && !mbFrames ) + aHTMLFileName = maIndex; + else + { + aHTMLFileName = "img" + OUString::number(nSdPage) + gaHTMLExtension; + } + + maHTMLFiles[nSdPage] = aHTMLFileName; + + OUString aImageFileName = "img" + OUString::number(nSdPage); + if( meFormat==FORMAT_GIF ) + aImageFileName += ".gif"; + else if( meFormat==FORMAT_JPG ) + aImageFileName += ".jpg"; + else + aImageFileName += ".png"; + + maImageFiles[nSdPage] = aImageFileName; + + OUString aThumbnailFileName = "thumb" + OUString::number(nSdPage); + if( meFormat!=FORMAT_JPG ) + aThumbnailFileName += ".png"; + else + aThumbnailFileName += ".jpg"; + + maThumbnailFiles[nSdPage] = aThumbnailFileName; + + maTextFiles[nSdPage] = "text" + OUString::number(nSdPage) + gaHTMLExtension; + + SdPage* pSdPage = maPages[ nSdPage ]; + + // get slide title from page name + maPageNames[nSdPage] = pSdPage->GetName(); + } + + if(!mbContentsPage && mbFrames) + maFramePage = maIndex; + else + { + maFramePage = "siframes" + gaHTMLExtension; + } +} + +OUString const & HtmlExport::getDocumentTitle() +{ + // check for a title object in this page, if it's the first + // title it becomes this documents title for the content + // page + if( !mbHeader ) + { + if(mbImpress) + { + // if there is a non-empty title object, use their first passage + // as page title + SdPage* pSdPage = mpDoc->GetSdPage(0, PageKind::Standard); + SdrObject* pTitleObj = pSdPage->GetPresObj(PresObjKind::Title); + if (pTitleObj && !pTitleObj->IsEmptyPresObj()) + { + OutlinerParaObject* pParaObject = pTitleObj->GetOutlinerParaObject(); + if (pParaObject) + { + const EditTextObject& rEditTextObject = + pParaObject->GetTextObject(); + OUString aTest(rEditTextObject.GetText(0)); + if (!aTest.isEmpty()) + mDocTitle = aTest; + } + } + + mDocTitle = mDocTitle.replace(0xff, ' '); + } + + if (mDocTitle.isEmpty()) + { + mDocTitle = maDocFileName; + sal_Int32 nDot = mDocTitle.indexOf('.'); + if (nDot > 0) + mDocTitle = mDocTitle.copy(0, nDot); + } + mbHeader = true; + } + + return mDocTitle; +} + +constexpr OUStringLiteral JS_NavigateAbs = + u"function NavigateAbs( nPage )\r\n" + "{\r\n" + " frames[\"show\"].location.href = \"img\" + nPage + \".$EXT\";\r\n" + " //frames[\"notes\"].location.href = \"note\" + nPage + \".$EXT\";\r\n" + " nCurrentPage = nPage;\r\n" + " if(nCurrentPage==0)\r\n" + " {\r\n" + " frames[\"navbar1\"].location.href = \"navbar0.$EXT\";\r\n" + " }\r\n" + " else if(nCurrentPage==nPageCount-1)\r\n" + " {\r\n" + " frames[\"navbar1\"].location.href = \"navbar2.$EXT\";\r\n" + " }\r\n" + " else\r\n" + " {\r\n" + " frames[\"navbar1\"].location.href = \"navbar1.$EXT\";\r\n" + " }\r\n" + "}\r\n\r\n"; + +constexpr OUStringLiteral JS_NavigateRel = + u"function NavigateRel( nDelta )\r\n" + "{\r\n" + " var nPage = parseInt(nCurrentPage) + parseInt(nDelta);\r\n" + " if( (nPage >= 0) && (nPage < nPageCount) )\r\n" + " {\r\n" + " NavigateAbs( nPage );\r\n" + " }\r\n" + "}\r\n\r\n"; + +constexpr OUStringLiteral JS_ExpandOutline = + u"function ExpandOutline()\r\n" + "{\r\n" + " frames[\"navbar2\"].location.href = \"navbar4.$EXT\";\r\n" + " frames[\"outline\"].location.href = \"outline1.$EXT\";\r\n" + "}\r\n\r\n"; + +constexpr OUStringLiteral JS_CollapseOutline = + u"function CollapseOutline()\r\n" + "{\r\n" + " frames[\"navbar2\"].location.href = \"navbar3.$EXT\";\r\n" + " frames[\"outline\"].location.href = \"outline0.$EXT\";\r\n" + "}\r\n\r\n"; + +// create page with the frames + +bool HtmlExport::CreateFrames() +{ + OUString aTmp; + OUStringBuffer aStr( + "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\"\r\n" + " \"http://www.w3.org/TR/html4/frameset.dtd\">\r\n" + "<html>\r\n<head>\r\n"); + + aStr.append(CreateMetaCharset()); + aStr.append(" <title>"); + aStr.append(StringToHTMLString(maPageNames[0])); + aStr.append("</title>\r\n"); + + aStr.append("<script type=\"text/javascript\">\r\n<!--\r\n"); + + aStr.append("var nCurrentPage = 0;\r\nvar nPageCount = "); + aStr.append(static_cast<sal_Int32>(mnSdPageCount)); + aStr.append(";\r\n\r\n"); + + OUString aFunction = JS_NavigateAbs; + + if(mbNotes) + { + aFunction = aFunction.replaceAll("//", ""); + } + + // substitute HTML file extension + OUString aPlaceHolder(".$EXT"); + aFunction = aFunction.replaceAll(aPlaceHolder, gaHTMLExtension); + aStr.append(aFunction); + + aTmp = JS_NavigateRel; + aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension); + aStr.append(aTmp); + + if(mbImpress) + { + aTmp = JS_ExpandOutline; + aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension); + aStr.append(aTmp); + + aTmp = JS_CollapseOutline; + aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension); + aStr.append(aTmp); + } + aStr.append("// -->\r\n</script>\r\n"); + + aStr.append("</head>\r\n"); + + aStr.append("<frameset cols=\"*,"); + aStr.append(static_cast<sal_Int32>(mnWidthPixel + 16)); + aStr.append("\">\r\n"); + if(mbImpress) + { + aStr.append(" <frameset rows=\"42,*\">\r\n"); + aStr.append(" <frame src=\"navbar3"); + aStr.append(gaHTMLExtension); + aStr.append("\" name=\"navbar2\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n"); + } + aStr.append(" <frame src=\"outline0"); + aStr.append(gaHTMLExtension); + aStr.append("\" name=\"outline\">\r\n"); + if(mbImpress) + aStr.append(" </frameset>\r\n"); + + if(mbNotes) + { + aStr.append(" <frameset rows=\"42,"); + aStr.append(static_cast<sal_Int32>(static_cast<double>(mnWidthPixel) * 0.75) + 16); + aStr.append(",*\">\r\n"); + } + else + aStr.append(" <frameset rows=\"42,*\">\r\n"); + + aStr.append(" <frame src=\"navbar0"); + aStr.append(gaHTMLExtension); + aStr.append("\" name=\"navbar1\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n"); + + aStr.append(" <frame src=\""); + aStr.append(maHTMLFiles[0]); + aStr.append("\" name=\"show\" marginwidth=\"4\" marginheight=\"4\">\r\n"); + + if(mbNotes) + { + aStr.append(" <frame src=\"note0"); + aStr.append(gaHTMLExtension); + aStr.append("\" name=\"notes\">\r\n"); + } + aStr.append(" </frameset>\r\n"); + + aStr.append("<noframes>\r\n"); + aStr.append(CreateBodyTag()); + aStr.append(RESTOHTML(STR_HTMLEXP_NOFRAMES)); + aStr.append("\r\n</noframes>\r\n</frameset>\r\n</html>"); + + bool bOk = WriteHtml(maFramePage, false, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + return bOk; +} + +// create button bar for standard +// we create the following html files +// navbar0.htm navigation bar graphic for the first page +// navbar1.htm navigation bar graphic for the second until second last page +// navbar2.htm navigation bar graphic for the last page +// navbar3.htm navigation outline closed +// navbar4.htm navigation outline open +bool HtmlExport::CreateNavBarFrames() +{ + bool bOk = true; + OUString aButton; + + if( mbDocColors ) + { + SetDocColors(); + maBackColor = maFirstPageColor; + } + + for( int nFile = 0; nFile < 3 && bOk; nFile++ ) + { + OUStringBuffer aStr(gaHTMLHeader); + aStr.append(CreateMetaCharset()); + aStr.append(" <title>"); + aStr.append(StringToHTMLString(maPageNames[0])); + aStr.append("</title>\r\n</head>\r\n"); + aStr.append(CreateBodyTag()); + aStr.append("<center>\r\n"); + + // first page + aButton = SdResId(STR_HTMLEXP_FIRSTPAGE); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(nFile == 0 || mnSdPageCount == 1 ? BTN_FIRST_0 : BTN_FIRST_1), + aButton); + + if(nFile != 0 && mnSdPageCount > 1) + aButton = CreateLink(u"JavaScript:parent.NavigateAbs(0)", aButton); + + aStr.append(aButton); + aStr.append("\r\n"); + + // to the previous page + aButton = SdResId(STR_PUBLISH_BACK); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(nFile == 0 || mnSdPageCount == 1? + BTN_PREV_0:BTN_PREV_1), + aButton); + + if(nFile != 0 && mnSdPageCount > 1) + aButton = CreateLink(u"JavaScript:parent.NavigateRel(-1)", aButton); + + aStr.append(aButton); + aStr.append("\r\n"); + + // to the next page + aButton = SdResId(STR_PUBLISH_NEXT); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(nFile ==2 || mnSdPageCount == 1? + BTN_NEXT_0:BTN_NEXT_1), + aButton); + + if(nFile != 2 && mnSdPageCount > 1) + aButton = CreateLink(u"JavaScript:parent.NavigateRel(1)", aButton); + + aStr.append(aButton); + aStr.append("\r\n"); + + // to the last page + aButton = SdResId(STR_HTMLEXP_LASTPAGE); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(nFile ==2 || mnSdPageCount == 1? + BTN_LAST_0:BTN_LAST_1), + aButton); + + if(nFile != 2 && mnSdPageCount > 1) + { + OUString aLink("JavaScript:parent.NavigateAbs(" + + OUString::number(mnSdPageCount-1) + ")"); + + aButton = CreateLink(aLink, aButton); + } + + aStr.append(aButton); + aStr.append("\r\n"); + + // content + if (mbContentsPage) + { + aButton = SdResId(STR_PUBLISH_OUTLINE); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(BTN_INDEX), aButton); + + // to the overview + aStr.append(CreateLink(maIndex, aButton, u"_top")); + aStr.append("\r\n"); + } + + // text mode + if(mbImpress) + { + aButton = SdResId(STR_HTMLEXP_SETTEXT); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(BTN_TEXT), aButton); + + OUString aText0("text0" + gaHTMLExtension); + aStr.append(CreateLink(aText0, aButton, u"_top")); + aStr.append("\r\n"); + } + + // and finished... + aStr.append("</center>\r\n"); + aStr.append("</body>\r\n</html>"); + + OUString aFileName("navbar" + OUString::number(nFile)); + + bOk = WriteHtml(aFileName, true, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + } + + // the navigation bar outliner closed... + if(bOk) + { + aButton = SdResId(STR_HTMLEXP_OUTLINE); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(BTN_MORE), aButton); + + bOk = WriteHtml( + "navbar3", true, + OUStringConcatenation( + gaHTMLHeader + CreateMetaCharset() + " <title>" + + StringToHTMLString(maPageNames[0]) + "</title>\r\n</head>\r\n" + CreateBodyTag() + + CreateLink(u"JavaScript:parent.ExpandOutline()", aButton) + + "</body>\r\n</html>")); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + } + + // ... and the outliner open + if( bOk ) + { + aButton = SdResId(STR_HTMLEXP_NOOUTLINE); + if(mnButtonThema != -1) + aButton = CreateImage(GetButtonName(BTN_LESS), aButton); + + bOk = WriteHtml( + "navbar4", true, + OUStringConcatenation( + gaHTMLHeader + CreateMetaCharset() + " <title>" + + StringToHTMLString(maPageNames[0]) + "</title>\r\n</head>\r\n" + CreateBodyTag() + + CreateLink(u"JavaScript:parent.CollapseOutline()", aButton) + + "</body>\r\n</html>")); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + } + + return bOk; +} + +// create button bar for standard +OUString HtmlExport::CreateNavBar( sal_uInt16 nSdPage, bool bIsText ) const +{ + // prepare button bar + OUString aStrNavFirst(SdResId(STR_HTMLEXP_FIRSTPAGE)); + OUString aStrNavPrev(SdResId(STR_PUBLISH_BACK)); + OUString aStrNavNext(SdResId(STR_PUBLISH_NEXT)); + OUString aStrNavLast(SdResId(STR_HTMLEXP_LASTPAGE)); + OUString aStrNavContent(SdResId(STR_PUBLISH_OUTLINE)); + OUString aStrNavText; + if( bIsText ) + { + aStrNavText = SdResId(STR_HTMLEXP_SETGRAPHIC); + } + else + { + aStrNavText = SdResId(STR_HTMLEXP_SETTEXT); + } + + if(!bIsText && mnButtonThema != -1) + { + if(nSdPage<1 || mnSdPageCount == 1) + { + aStrNavFirst = CreateImage(GetButtonName(BTN_FIRST_0), aStrNavFirst); + aStrNavPrev = CreateImage(GetButtonName(BTN_PREV_0), aStrNavPrev); + } + else + { + aStrNavFirst = CreateImage(GetButtonName(BTN_FIRST_1), aStrNavFirst); + aStrNavPrev = CreateImage(GetButtonName(BTN_PREV_1), aStrNavPrev); + } + + if(nSdPage == mnSdPageCount-1 || mnSdPageCount == 1) + { + aStrNavNext = CreateImage(GetButtonName(BTN_NEXT_0), aStrNavNext); + aStrNavLast = CreateImage(GetButtonName(BTN_LAST_0), aStrNavLast); + } + else + { + aStrNavNext = CreateImage(GetButtonName(BTN_NEXT_1), aStrNavNext); + aStrNavLast = CreateImage(GetButtonName(BTN_LAST_1), aStrNavLast); + } + + aStrNavContent = CreateImage(GetButtonName(BTN_INDEX), aStrNavContent); + aStrNavText = CreateImage(GetButtonName(BTN_TEXT), aStrNavText); + } + + OUStringBuffer aStr("<center>\r\n"); //<table><tr>\r\n"); + + // first page + if(nSdPage > 0) + aStr.append(CreateLink( bIsText ? maTextFiles[0] : maHTMLFiles[0],aStrNavFirst)); + else + aStr.append(aStrNavFirst); + aStr.append(' '); + + // to Previous page + if(nSdPage > 0) + aStr.append(CreateLink( bIsText ? maTextFiles[nSdPage-1] + : maHTMLFiles[nSdPage-1], aStrNavPrev)); + else + aStr.append(aStrNavPrev); + aStr.append(' '); + + // to Next page + if(nSdPage < mnSdPageCount-1) + aStr.append(CreateLink( bIsText ? maTextFiles[nSdPage+1] + : maHTMLFiles[nSdPage+1], aStrNavNext)); + else + aStr.append(aStrNavNext); + aStr.append(' '); + + // to Last page + if(nSdPage < mnSdPageCount-1) + aStr.append(CreateLink( bIsText ? maTextFiles[mnSdPageCount-1] + : maHTMLFiles[mnSdPageCount-1], + aStrNavLast)); + else + aStr.append(aStrNavLast); + aStr.append(' '); + + // to Index page + if (mbContentsPage) + { + aStr.append(CreateLink(maIndex, aStrNavContent)); + aStr.append(' '); + } + + // Text/Graphics + if(mbImpress) + { + aStr.append(CreateLink( bIsText ? (mbFrames ? maFramePage : maHTMLFiles[nSdPage]) + : maTextFiles[nSdPage], aStrNavText)); + + } + + aStr.append("</center><br>\r\n"); + + return aStr.makeStringAndClear(); +} + +// export navigation graphics from button set +void HtmlExport::CreateBitmaps() +{ + if(mnButtonThema == -1 || !mpButtonSet) + return; + + for( int nButton = 0; nButton != SAL_N_ELEMENTS(pButtonNames); nButton++ ) + { + if(!mbFrames && (nButton == BTN_MORE || nButton == BTN_LESS)) + continue; + + if(!mbImpress && (nButton == BTN_TEXT || nButton == BTN_MORE || nButton == BTN_LESS )) + continue; + + OUString aFull = maExportPath + GetButtonName(nButton); + mpButtonSet->exportButton( mnButtonThema, aFull, GetButtonName(nButton) ); + } +} + +// creates the <body> tag, including the specified color attributes +OUString HtmlExport::CreateBodyTag() const +{ + OUStringBuffer aStr( "<body" ); + + if( mbUserAttr || mbDocColors ) + { + Color aTextColor( maTextColor ); + if( (aTextColor == COL_AUTO) && (!maBackColor.IsDark()) ) + aTextColor = COL_BLACK; + + aStr.append(" text=\""); + aStr.append(ColorToHTMLString( aTextColor )); + aStr.append("\" bgcolor=\""); + aStr.append(ColorToHTMLString( maBackColor )); + aStr.append("\" link=\""); + aStr.append(ColorToHTMLString( maLinkColor )); + aStr.append("\" vlink=\""); + aStr.append(ColorToHTMLString( maVLinkColor )); + aStr.append("\" alink=\""); + aStr.append(ColorToHTMLString( maALinkColor )); + aStr.append("\""); + } + + aStr.append(">\r\n"); + + return aStr.makeStringAndClear(); +} + +// creates a hyperlink +OUString HtmlExport::CreateLink( std::u16string_view aLink, + std::u16string_view aText, + std::u16string_view aTarget ) +{ + OUStringBuffer aStr( "<a href=\"" ); + aStr.append(aLink); + if (!aTarget.empty()) + { + aStr.append("\" target=\""); + aStr.append(aTarget); + } + aStr.append("\">"); + aStr.append(aText); + aStr.append("</a>"); + + return aStr.makeStringAndClear(); +} + +// creates an image tag +OUString HtmlExport::CreateImage( std::u16string_view aImage, std::u16string_view aAltText ) +{ + OUStringBuffer aStr( "<img src=\""); + aStr.append(aImage); + aStr.append("\" border=0"); + + if (!aAltText.empty()) + { + aStr.append(" alt=\""); + aStr.append(aAltText); + aStr.append('"'); + } + else + { + // Agerskov: HTML 4.01 has to have an alt attribute even if it is an empty string + aStr.append(" alt=\"\""); + } + + aStr.append('>'); + + return aStr.makeStringAndClear(); +} + +// create area for a circle; we expect pixel coordinates +OUString HtmlExport::ColorToHTMLString( Color aColor ) +{ + static const char hex[] = "0123456789ABCDEF"; + OUStringBuffer aStr( "#xxxxxx" ); + aStr[1] = hex[(aColor.GetRed() >> 4) & 0xf]; + aStr[2] = hex[aColor.GetRed() & 0xf]; + aStr[3] = hex[(aColor.GetGreen() >> 4) & 0xf]; + aStr[4] = hex[aColor.GetGreen() & 0xf]; + aStr[5] = hex[(aColor.GetBlue() >> 4) & 0xf]; + aStr[6] = hex[aColor.GetBlue() & 0xf]; + + return aStr.makeStringAndClear(); +} + +// create area for a circle; we expect pixel coordinates +OUString HtmlExport::CreateHTMLCircleArea( sal_uLong nRadius, + sal_uLong nCenterX, + sal_uLong nCenterY, + std::u16string_view rHRef ) +{ + OUString aStr( + "<area shape=\"circle\" alt=\"\" coords=\"" + + OUString::number(nCenterX) + "," + + OUString::number(nCenterY) + "," + + OUString::number(nRadius) + + "\" href=\"" + rHRef + "\">\n"); + + return aStr; +} + +// create area for a polygon; we expect pixel coordinates +OUString HtmlExport::CreateHTMLPolygonArea( const ::basegfx::B2DPolyPolygon& rPolyPolygon, + Size aShift, double fFactor, std::u16string_view rHRef ) +{ + OUStringBuffer aStr; + const sal_uInt32 nNoOfPolygons(rPolyPolygon.count()); + + for ( sal_uInt32 nXPoly = 0; nXPoly < nNoOfPolygons; nXPoly++ ) + { + const ::basegfx::B2DPolygon& aPolygon = rPolyPolygon.getB2DPolygon(nXPoly); + const sal_uInt32 nNoOfPoints(aPolygon.count()); + + aStr.append("<area shape=\"polygon\" alt=\"\" coords=\""); + + for ( sal_uInt32 nPoint = 0; nPoint < nNoOfPoints; nPoint++ ) + { + const ::basegfx::B2DPoint aB2DPoint(aPolygon.getB2DPoint(nPoint)); + Point aPnt(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY())); + // coordinates are relative to the physical page origin, not the + // origin of ordinates + aPnt.Move(aShift.Width(), aShift.Height()); + + aPnt.setX( static_cast<tools::Long>(aPnt.X() * fFactor) ); + aPnt.setY( static_cast<tools::Long>(aPnt.Y() * fFactor) ); + aStr.append( OUString::number(aPnt.X()) + "," + OUString::number(aPnt.Y()) ); + + if (nPoint < nNoOfPoints - 1) + aStr.append(','); + } + aStr.append(OUString::Concat("\" href=\"") + rHRef + "\">\n"); + } + + return aStr.makeStringAndClear(); +} + +// create area for a rectangle; we expect pixel coordinates +OUString HtmlExport::CreateHTMLRectArea( const ::tools::Rectangle& rRect, + std::u16string_view rHRef ) +{ + OUString aStr( + "<area shape=\"rect\" alt=\"\" coords=\"" + + OUString::number(rRect.Left()) + "," + + OUString::number(rRect.Top()) + "," + + OUString::number(rRect.Right()) + "," + + OUString::number(rRect.Bottom()) + + "\" href=\"" + rHRef + "\">\n"); + + return aStr; +} + +// escapes a string for html +OUString HtmlExport::StringToHTMLString( const OUString& rString ) +{ + SvMemoryStream aMemStm; + HTMLOutFuncs::Out_String( aMemStm, rString ); + aMemStm.WriteChar( char(0) ); + sal_Int32 nLength = strlen(static_cast<char const *>(aMemStm.GetData())); + return OUString( static_cast<char const *>(aMemStm.GetData()), nLength, RTL_TEXTENCODING_UTF8 ); +} + +// creates a URL for a specific page +OUString HtmlExport::CreatePageURL( sal_uInt16 nPgNum ) +{ + if(mbFrames) + { + return OUString("JavaScript:parent.NavigateAbs(" + + OUString::number(nPgNum) + ")"); + } + else + return maHTMLFiles[nPgNum]; +} + +bool HtmlExport::CopyScript( std::u16string_view rPath, const OUString& rSource, const OUString& rDest, bool bUnix /* = false */ ) +{ + INetURLObject aURL( SvtPathOptions().GetConfigPath() ); + OUStringBuffer aScriptBuf; + + aURL.Append( u"webcast" ); + aURL.Append( rSource ); + + meEC.SetContext( STR_HTMLEXP_ERROR_OPEN_FILE, rSource ); + + ErrCode nErr = ERRCODE_NONE; + std::unique_ptr<SvStream> pIStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ); + + if( pIStm ) + { + OStringBuffer aLine; + + while( pIStm->ReadLine( aLine ) ) + { + aScriptBuf.appendAscii( aLine.getStr(), aLine.getLength() ); + if( bUnix ) + { + aScriptBuf.append("\n"); + } + else + { + aScriptBuf.append("\r\n"); + } + } + + nErr = pIStm->GetError(); + pIStm.reset(); + } + + if( nErr != ERRCODE_NONE ) + { + ErrorHandler::HandleError( nErr ); + return static_cast<bool>(nErr); + } + + OUString aScript(aScriptBuf.makeStringAndClear()); + aScript = aScript.replaceAll("$$1", getDocumentTitle()); + aScript = aScript.replaceAll("$$2", RESTOHTML(STR_WEBVIEW_SAVE)); + aScript = aScript.replaceAll("$$3", maCGIPath); + aScript = aScript.replaceAll("$$4", OUString::number(mnWidthPixel)); + aScript = aScript.replaceAll("$$5", OUString::number(mnHeightPixel)); + + OUString aDest(rPath + rDest); + + meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, rDest ); + // write script file + { + EasyFile aFile; + SvStream* pStr; + nErr = aFile.createStream(aDest, pStr); + if(nErr == ERRCODE_NONE) + { + OString aStr(OUStringToOString(aScript, RTL_TEXTENCODING_UTF8)); + pStr->WriteOString( aStr ); + aFile.close(); + } + } + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + if( nErr != ERRCODE_NONE ) + ErrorHandler::HandleError( nErr ); + + return nErr == ERRCODE_NONE; +} + +static const char * ASP_Scripts[] = { "common.inc", "webcast.asp", "show.asp", "savepic.asp", "poll.asp", "editpic.asp" }; + +/** creates and saves the ASP scripts for WebShow */ +bool HtmlExport::CreateASPScripts() +{ + for(const char * p : ASP_Scripts) + { + OUString aScript = OUString::createFromAscii(p); + + if(!CopyScript(maExportPath, aScript, aScript)) + return false; + } + + return CopyScript(maExportPath, "edit.asp", maIndex); +} + +static const char *PERL_Scripts[] = { "webcast.pl", "common.pl", "editpic.pl", "poll.pl", "savepic.pl", "show.pl" }; + +// creates and saves the PERL scripts for WebShow +bool HtmlExport::CreatePERLScripts() +{ + for(const char * p : PERL_Scripts) + { + OUString aScript = OUString::createFromAscii(p); + + if(!CopyScript(maExportPath, aScript, aScript, true)) + return false; + } + + if (!CopyScript(maExportPath, "edit.pl", maIndex, true)) + return false; + + if (!CopyScript(maExportPath, "index.pl", maIndexUrl, true)) + return false; + + return true; +} + +// creates a list with names of the saved images +bool HtmlExport::CreateImageFileList() +{ + OUStringBuffer aStr; + for( sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++) + { + aStr.append(static_cast<sal_Int32>(nSdPage + 1)); + aStr.append(';'); + aStr.append(maURLPath); + aStr.append(maImageFiles[nSdPage]); + aStr.append("\r\n"); + } + + bool bOk = WriteHtml("picture.txt", false, aStr.makeStringAndClear()); + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + return bOk; +} + +// creates a file with the actual page number +bool HtmlExport::CreateImageNumberFile() +{ + OUString aFileName("currpic.txt"); + OUString aFull(maExportPath + aFileName); + + meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, aFileName ); + EasyFile aFile; + SvStream* pStr; + ErrCode nErr = aFile.createStream(aFull, pStr); + if(nErr == ERRCODE_NONE) + { + pStr->WriteCharPtr( "1" ); + aFile.close(); + } + + if (mpProgress) + mpProgress->SetState(++mnPagesWritten); + + if( nErr != ERRCODE_NONE ) + ErrorHandler::HandleError( nErr ); + + return nErr == ERRCODE_NONE; +} + +OUString HtmlExport::InsertSound( const OUString& rSoundFile ) +{ + if (rSoundFile.isEmpty()) + return rSoundFile; + + INetURLObject aURL( rSoundFile ); + OUString aSoundFileName = aURL.getName(); + + DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + + OUString aStr("<embed src=\"" + aSoundFileName + + "\" hidden=\"true\" autostart=\"true\">"); + + CopyFile(rSoundFile, maExportPath + aSoundFileName); + + return aStr; +} + +bool HtmlExport::CopyFile( const OUString& rSourceFile, const OUString& rDestFile ) +{ + meEC.SetContext( STR_HTMLEXP_ERROR_COPY_FILE, rSourceFile, rDestFile ); + osl::FileBase::RC Error = osl::File::copy( rSourceFile, rDestFile ); + + if( Error != osl::FileBase::E_None ) + { + ErrorHandler::HandleError(ErrCode(Error)); + return false; + } + else + { + return true; + } +} + +bool HtmlExport::checkFileExists( Reference< css::ucb::XSimpleFileAccess3 > const & xFileAccess, std::u16string_view aFileName ) +{ + try + { + OUString url = maExportPath + aFileName; + return xFileAccess->exists( url ); + } + catch( css::uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "sd::HtmlExport::checkFileExists()" ); + } + + return false; +} + +bool HtmlExport::checkForExistingFiles() +{ + bool bFound = false; + + try + { + Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); + uno::Reference<ucb::XSimpleFileAccess3> xFA(ucb::SimpleFileAccess::create(xContext)); + + sal_uInt16 nSdPage; + for( nSdPage = 0; !bFound && (nSdPage < mnSdPageCount); nSdPage++) + { + if( checkFileExists( xFA, maImageFiles[nSdPage] ) || + checkFileExists( xFA, maHTMLFiles[nSdPage] ) || + checkFileExists( xFA, maThumbnailFiles[nSdPage] ) || + checkFileExists( xFA, maPageNames[nSdPage] ) || + checkFileExists( xFA, maTextFiles[nSdPage] ) ) + { + bFound = true; + } + } + + if( !bFound && mbDownload ) + bFound = checkFileExists( xFA, maDocFileName ); + + if( !bFound && mbFrames ) + bFound = checkFileExists( xFA, maFramePage ); + + if( bFound ) + { + OUString aSystemPath; + osl::FileBase::getSystemPathFromFileURL( maExportPath, aSystemPath ); + OUString aMsg(SdResId(STR_OVERWRITE_WARNING)); + aMsg = aMsg.replaceFirst( "%FILENAME", aSystemPath ); + + std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr, + VclMessageType::Warning, VclButtonsType::YesNo, + aMsg)); + xWarn->set_default_response(RET_YES); + bFound = (RET_NO == xWarn->run()); + } + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION( "sd", "sd::HtmlExport::checkForExistingFiles()" ); + bFound = false; + } + + return bFound; +} + +OUString HtmlExport::GetButtonName( int nButton ) +{ + return OUString::createFromAscii(pButtonNames[nButton]); +} + +EasyFile::EasyFile() : bOpen(false) +{ +} + +EasyFile::~EasyFile() +{ + if( bOpen ) + close(); +} + +ErrCode EasyFile::createStream( const OUString& rUrl, SvStream* &rpStr ) +{ + if(bOpen) + close(); + + OUString aFileName; + createFileName( rUrl, aFileName ); + + ErrCode nErr = ERRCODE_NONE; + pOStm = ::utl::UcbStreamHelper::CreateStream( aFileName, StreamMode::WRITE | StreamMode::TRUNC ); + if( pOStm ) + { + bOpen = true; + nErr = pOStm->GetError(); + } + else + { + nErr = ERRCODE_SFX_CANTCREATECONTENT; + } + + if( nErr != ERRCODE_NONE ) + { + bOpen = false; + pOStm.reset(); + } + + rpStr = pOStm.get(); + + return nErr; +} + +void EasyFile::createFileName( const OUString& rURL, OUString& rFileName ) +{ + if( bOpen ) + close(); + + INetURLObject aURL( rURL ); + + if( aURL.GetProtocol() == INetProtocol::NotValid ) + { + OUString aURLStr; + osl::FileBase::getFileURLFromSystemPath( rURL, aURLStr ); + aURL = INetURLObject( aURLStr ); + } + DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" ); + rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); +} + +void EasyFile::close() +{ + pOStm.reset(); + bOpen = false; +} + +// This class helps reporting errors during file i/o +HtmlErrorContext::HtmlErrorContext() + : ErrorContext(nullptr) +{ +} + +bool HtmlErrorContext::GetString( ErrCode, OUString& rCtxStr ) +{ + DBG_ASSERT(mpResId, "No error context set"); + if (!mpResId) + return false; + + rCtxStr = SdResId(mpResId); + + rCtxStr = rCtxStr.replaceAll( "$(URL1)", maURL1 ); + rCtxStr = rCtxStr.replaceAll( "$(URL2)", maURL2 ); + + return true; +} + +void HtmlErrorContext::SetContext(TranslateId pResId, const OUString& rURL) +{ + mpResId = pResId; + maURL1 = rURL; + maURL2.clear(); +} + +void HtmlErrorContext::SetContext(TranslateId pResId, const OUString& rURL1, const OUString& rURL2 ) +{ + mpResId = pResId; + maURL1 = rURL1; + maURL2 = rURL2; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/htmlex.hxx b/sd/source/filter/html/htmlex.hxx new file mode 100644 index 000000000..5f6f06e49 --- /dev/null +++ b/sd/source/filter/html/htmlex.hxx @@ -0,0 +1,237 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <resltn.hxx> +#include <rtl/ustrbuf.hxx> +#include <tools/color.hxx> +#include <tools/solar.h> +#include <vcl/errinf.hxx> +#include <unotools/resmgr.hxx> + +#include "htmlpublishmode.hxx" + +#include <memory> +#include <string_view> +#include <vector> + +namespace basegfx { class B2DPolyPolygon; } +namespace com::sun::star::beans { struct PropertyValue; } +namespace com::sun::star::ucb { class XSimpleFileAccess3; } +namespace sd { class DrawDocShell; } +namespace tools { class Rectangle; } + +#define PUB_LOWRES_WIDTH 640 +#define PUB_MEDRES_WIDTH 800 +#define PUB_HIGHRES_WIDTH 1024 +#define PUB_FHDRES_WIDTH 1920 + +#define PUB_THUMBNAIL_WIDTH 256 +#define PUB_THUMBNAIL_HEIGHT 192 + +class ErrCode; +class OutlinerParaObject; +class SfxItemSet; +class Size; +class SfxProgress; +class SdrOutliner; +class SdPage; +class HtmlState; +class SdrTextObj; +class SdrObjGroup; +namespace sdr::table { class SdrTableObj; } +class SdrPage; +class SdDrawDocument; +class ButtonSet; + +class HtmlErrorContext : public ErrorContext +{ +private: + TranslateId mpResId; + OUString maURL1; + OUString maURL2; + +public: + explicit HtmlErrorContext(); + + virtual bool GetString( ErrCode nErrId, OUString& rCtxStr ) override; + + void SetContext(TranslateId pResId, const OUString& rURL); + void SetContext(TranslateId pResId, const OUString& rURL1, const OUString& rURL2); +}; + +/// this class exports an Impress Document as a HTML Presentation. +class HtmlExport final +{ + std::vector< SdPage* > maPages; + std::vector< SdPage* > maNotesPages; + + OUString maPath; + + SdDrawDocument* mpDoc; + ::sd::DrawDocShell* mpDocSh; + + HtmlErrorContext meEC; + + HtmlPublishMode meMode; + std::unique_ptr<SfxProgress> mpProgress; + bool mbImpress; + sal_uInt16 mnSdPageCount; + sal_uInt16 mnPagesWritten; + bool mbContentsPage; + sal_Int16 mnButtonThema; + sal_uInt16 mnWidthPixel; + sal_uInt16 mnHeightPixel; + PublishingFormat meFormat; + bool mbHeader; + bool mbNotes; + bool mbFrames; + OUString maIndex; + OUString maEMail; + OUString maAuthor; + OUString maHomePage; + OUString maInfo; + sal_Int16 mnCompression; + OUString maDocFileName; + OUString maFramePage; + OUString mDocTitle; + bool mbDownload; + + bool mbAutoSlide; + double mfSlideDuration; + bool mbSlideSound; + bool mbHiddenSlides; + bool mbEndless; + + bool mbUserAttr; + Color maTextColor; ///< The following colors are used for the <body> tag if mbUserAttr is true. + Color maBackColor; + Color maLinkColor; + Color maVLinkColor; + Color maALinkColor; + Color maFirstPageColor; + bool mbDocColors; + + std::vector<OUString> maHTMLFiles; + std::vector<OUString> maImageFiles; + std::vector<OUString> maThumbnailFiles; + std::vector<OUString> maPageNames; + std::vector<OUString> maTextFiles; + + OUString maExportPath; ///< output directory or URL. + OUString maIndexUrl; + OUString maURLPath; + OUString maCGIPath; + PublishingScript meScript; + + std::unique_ptr< ButtonSet > mpButtonSet; + + static SdrTextObj* GetLayoutTextObject(SdrPage const * pPage); + + void SetDocColors( SdPage* pPage = nullptr ); + + bool CreateImagesForPresPages( bool bThumbnails = false ); + bool CreateHtmlTextForPresPages(); + bool CreateHtmlForPresPages(); + bool CreateContentPage(); + void CreateFileNames(); + void CreateBitmaps(); + bool CreateOutlinePages(); + bool CreateFrames(); + bool CreateNotesPages(); + bool CreateNavBarFrames(); + + bool CreateASPScripts(); + bool CreatePERLScripts(); + bool CreateImageFileList(); + bool CreateImageNumberFile(); + + bool checkForExistingFiles(); + bool checkFileExists( css::uno::Reference< css::ucb::XSimpleFileAccess3 > const & xFileAccess, std::u16string_view aFileName ); + + OUString const & getDocumentTitle(); + bool SavePresentation(); + + static OUString CreateLink( std::u16string_view aLink, std::u16string_view aText, + std::u16string_view aTarget = std::u16string_view()); + static OUString CreateImage( std::u16string_view aImage, std::u16string_view aAltText ); + OUString CreateNavBar( sal_uInt16 nSdPage, bool bIsText ) const; + OUString CreateBodyTag() const; + + OUString ParagraphToHTMLString( SdrOutliner const * pOutliner, sal_Int32 nPara, const Color& rBackgroundColor ); + OUString TextAttribToHTMLString( SfxItemSet const * pSet, HtmlState* pState, const Color& rBackgroundColor ); + + OUString CreateTextForTitle( SdrOutliner* pOutliner, SdPage* pPage, const Color& rBackgroundColor ); + OUString CreateTextForPage( SdrOutliner* pOutliner, SdPage const * pPage, bool bHeadLine, const Color& rBackgroundColor ); + OUString CreateTextForNotesPage( SdrOutliner* pOutliner, SdPage* pPage, const Color& rBackgroundColor ); + + static OUString CreateHTMLCircleArea( sal_uLong nRadius, sal_uLong nCenterX, + sal_uLong nCenterY, std::u16string_view rHRef ); + static OUString CreateHTMLPolygonArea( const ::basegfx::B2DPolyPolygon& rPolyPoly, Size aShift, double fFactor, std::u16string_view rHRef ); + static OUString CreateHTMLRectArea( const ::tools::Rectangle& rRect, + std::u16string_view rHRef ); + + OUString CreatePageURL( sal_uInt16 nPgNum ); + + OUString InsertSound( const OUString& rSoundFile ); + bool CopyFile( const OUString& rSourceFile, const OUString& rDestFile ); + bool CopyScript( std::u16string_view rPath, const OUString& rSource, const OUString& rDest, bool bUnix = false ); + + void InitProgress( sal_uInt16 nProgrCount ); + void ResetProgress(); + + /// Output only the charset metadata, title etc. will be handled separately. + static OUString CreateMetaCharset(); + + /// Output document metadata. + OUString DocumentMetadata() const; + + void InitExportParameters( const css::uno::Sequence< css::beans::PropertyValue >& rParams); + void ExportHtml(); + void ExportKiosk(); + void ExportWebCast(); + void ExportSingleDocument(); + + bool WriteHtml( const OUString& rFileName, bool bAddExtension, std::u16string_view rHtmlData ); + static OUString GetButtonName( int nButton ); + + void WriteOutlinerParagraph(OUStringBuffer& aStr, SdrOutliner* pOutliner, + OutlinerParaObject const * pOutlinerParagraphObject, + const Color& rBackgroundColor, bool bHeadLine); + + void WriteObjectGroup(OUStringBuffer& aStr, SdrObjGroup const * pObjectGroup, + SdrOutliner* pOutliner, const Color& rBackgroundColor, bool bHeadLine); + + void WriteTable(OUStringBuffer& aStr, sdr::table::SdrTableObj const * pTableObject, + SdrOutliner* pOutliner, const Color& rBackgroundColor); + + public: + HtmlExport(const OUString& aPath, + const css::uno::Sequence<css::beans::PropertyValue>& rParams, + SdDrawDocument* pExpDoc, + sd::DrawDocShell* pDocShell); + + ~HtmlExport(); + + static OUString ColorToHTMLString( Color aColor ); + static OUString StringToHTMLString( const OUString& rString ); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/htmlpublishmode.hxx b/sd/source/filter/html/htmlpublishmode.hxx new file mode 100644 index 000000000..3ba7eeb80 --- /dev/null +++ b/sd/source/filter/html/htmlpublishmode.hxx @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +enum HtmlPublishMode +{ + PUBLISH_HTML, + PUBLISH_FRAMES, + PUBLISH_WEBCAST, + PUBLISH_KIOSK, + PUBLISH_SINGLE_DOCUMENT +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/pubdlg.cxx b/sd/source/filter/html/pubdlg.cxx new file mode 100644 index 000000000..257021d96 --- /dev/null +++ b/sd/source/filter/html/pubdlg.cxx @@ -0,0 +1,1539 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <comphelper/sequence.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <vcl/FilterConfigItem.hxx> +#include <vcl/image.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <sal/log.hxx> +#include <svtools/valueset.hxx> +#include <svtools/colrdlg.hxx> +#include <tools/debug.hxx> +#include <tools/urlobj.hxx> +#include <tools/GenericTypeSerializer.hxx> +#include <sdiocmpt.hxx> +#include <sfx2/docfile.hxx> +#include <pres.hxx> +#include <unotools/useroptions.hxx> +#include <unotools/pathoptions.hxx> + +#include <sdresid.hxx> +#include <strings.hrc> +#include <pubdlg.hxx> +#include "htmlattr.hxx" +#include "htmlex.hxx" +#include "htmlpublishmode.hxx" +#include <helpids.h> +#include "buttonset.hxx" +#include <strings.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; + +#define NOOFPAGES 6 + +//ID for the config-data with the HTML-settings +const sal_uInt16 nMagic = sal_uInt16(0x1977); + +// Key for the soffice.ini +constexpr OUStringLiteral KEY_QUALITY = u"JPG-EXPORT-QUALITY"; + +// The Help-IDs of the pages +const char* const aPageHelpIds[NOOFPAGES] = +{ + HID_SD_HTMLEXPORT_PAGE1, + HID_SD_HTMLEXPORT_PAGE2, + HID_SD_HTMLEXPORT_PAGE3, + HID_SD_HTMLEXPORT_PAGE4, + HID_SD_HTMLEXPORT_PAGE5, + HID_SD_HTMLEXPORT_PAGE6 +}; + +static SvStream& operator >> (SvStream& rIn, SdPublishingDesign& rDesign); + +static SvStream& WriteSdPublishingDesign(SvStream& rOut, const SdPublishingDesign& rDesign); + +// This class has all the settings for the HTML-export autopilot +class SdPublishingDesign +{ +public: + OUString m_aDesignName; + + HtmlPublishMode m_eMode; + + // special WebCast options + PublishingScript m_eScript; + OUString m_aCGI; + OUString m_aURL; + + // special Kiosk options + bool m_bAutoSlide; + sal_uInt32 m_nSlideDuration; + bool m_bEndless; + + // special HTML options + bool m_bContentPage; + bool m_bNotes; + + // misc options + sal_uInt16 m_nResolution; + OUString m_aCompression; + PublishingFormat m_eFormat; + bool m_bSlideSound; + bool m_bHiddenSlides; + + // title page information + OUString m_aAuthor; + OUString m_aEMail; + OUString m_aWWW; + OUString m_aMisc; + bool m_bDownload; + bool m_bCreated; // not used + + // buttons and colorscheme + sal_Int16 m_nButtonThema; + bool m_bUserAttr; + Color m_aBackColor; + Color m_aTextColor; + Color m_aLinkColor; + Color m_aVLinkColor; + Color m_aALinkColor; + bool m_bUseAttribs; + bool m_bUseColor; + + SdPublishingDesign(); + + bool operator ==(const SdPublishingDesign & rDesign) const; + friend SvStream& operator >> (SvStream& rIn, SdPublishingDesign& rDesign); + friend SvStream& WriteSdPublishingDesign(SvStream& rOut, const SdPublishingDesign& rDesign); +}; + +// load Default-settings +SdPublishingDesign::SdPublishingDesign() + : m_eMode(PUBLISH_HTML) + , m_eScript(SCRIPT_ASP) + , m_bAutoSlide(true) + , m_nSlideDuration(15) + , m_bEndless(true) + , m_bContentPage(true) + , m_bNotes(true) + , m_nResolution(PUB_LOWRES_WIDTH) + , m_eFormat(FORMAT_PNG) + , m_bSlideSound(true) + , m_bHiddenSlides(false) + , m_bDownload(false) + , m_bCreated(false) + , m_nButtonThema(-1) + , m_bUserAttr(false) + , m_aBackColor(COL_WHITE) + , m_aTextColor(COL_BLACK) + , m_aLinkColor(COL_BLUE) + , m_aVLinkColor(COL_LIGHTGRAY) + , m_aALinkColor(COL_GRAY) + , m_bUseAttribs(true) + , m_bUseColor(true) +{ + FilterConfigItem aFilterConfigItem(u"Office.Common/Filter/Graphic/Export/JPG"); + sal_Int32 nCompression = aFilterConfigItem.ReadInt32( KEY_QUALITY, 75 ); + m_aCompression = OUString::number(nCompression) + "%"; + + SvtUserOptions aUserOptions; + m_aAuthor = aUserOptions.GetFirstName(); + if (!m_aAuthor.isEmpty() && !aUserOptions.GetLastName().isEmpty()) + m_aAuthor += " "; + m_aAuthor += aUserOptions.GetLastName(); + m_aEMail = aUserOptions.GetEmail(); +} + +// Compares the values without paying attention to the name +bool SdPublishingDesign::operator ==(const SdPublishingDesign & rDesign) const +{ + return + ( + m_eMode == rDesign.m_eMode && + m_nResolution == rDesign.m_nResolution && + m_aCompression == rDesign.m_aCompression && + m_eFormat == rDesign.m_eFormat && + m_bHiddenSlides == rDesign.m_bHiddenSlides && + ( // compare html options + (m_eMode != PUBLISH_HTML && m_eMode != PUBLISH_FRAMES) || + ( + m_bContentPage == rDesign.m_bContentPage && + m_bNotes == rDesign.m_bNotes && + m_aAuthor == rDesign.m_aAuthor && + m_aEMail == rDesign.m_aEMail && + m_aWWW == rDesign.m_aWWW && + m_aMisc == rDesign.m_aMisc && + m_bDownload == rDesign.m_bDownload && + m_nButtonThema == rDesign.m_nButtonThema && + m_bUserAttr == rDesign.m_bUserAttr && + m_aBackColor == rDesign.m_aBackColor && + m_aTextColor == rDesign.m_aTextColor && + m_aLinkColor == rDesign.m_aLinkColor && + m_aVLinkColor == rDesign.m_aVLinkColor && + m_aALinkColor == rDesign.m_aALinkColor && + m_bUseAttribs == rDesign.m_bUseAttribs && + m_bSlideSound == rDesign.m_bSlideSound && + m_bUseColor == rDesign.m_bUseColor + ) + ) && + ( // compare kiosk options + (m_eMode != PUBLISH_KIOSK) || + ( + m_bAutoSlide == rDesign.m_bAutoSlide && + m_bSlideSound == rDesign.m_bSlideSound && + ( + !m_bAutoSlide || + ( + m_nSlideDuration == rDesign.m_nSlideDuration && + m_bEndless == rDesign.m_bEndless + ) + ) + ) + ) && + ( // compare WebCast options + (m_eMode != PUBLISH_WEBCAST) || + ( + m_eScript == rDesign.m_eScript && + ( + m_eScript != SCRIPT_PERL || + ( + m_aURL == rDesign.m_aURL && + m_aCGI == rDesign.m_aCGI + ) + ) + ) + ) + ); +} + +// Load the design from the stream +SvStream& operator >> (SvStream& rIn, SdPublishingDesign& rDesign) +{ + SdIOCompat aIO(rIn, StreamMode::READ); + + sal_uInt16 nTemp16; + tools::GenericTypeSerializer aSerializer(rIn); + + rDesign.m_aDesignName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + rIn.ReadUInt16( nTemp16 ); + rDesign.m_eMode = static_cast<HtmlPublishMode>(nTemp16); + rIn.ReadCharAsBool( rDesign.m_bContentPage ); + rIn.ReadCharAsBool( rDesign.m_bNotes ); + rIn.ReadUInt16( rDesign.m_nResolution ); + rDesign.m_aCompression = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + rIn.ReadUInt16( nTemp16 ); + rDesign.m_eFormat = static_cast<PublishingFormat>(nTemp16); + rDesign.m_aAuthor = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + rDesign.m_aEMail = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + rDesign.m_aWWW = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + rDesign.m_aMisc = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + rIn.ReadCharAsBool( rDesign.m_bDownload ); + rIn.ReadCharAsBool( rDesign.m_bCreated ); // not used + rIn.ReadInt16( rDesign.m_nButtonThema ); + rIn.ReadCharAsBool( rDesign.m_bUserAttr ); + aSerializer.readColor(rDesign.m_aBackColor); + aSerializer.readColor(rDesign.m_aTextColor); + aSerializer.readColor(rDesign.m_aLinkColor); + aSerializer.readColor(rDesign.m_aVLinkColor); + aSerializer.readColor(rDesign.m_aALinkColor); + rIn.ReadCharAsBool( rDesign.m_bUseAttribs ); + rIn.ReadCharAsBool( rDesign.m_bUseColor ); + + rIn.ReadUInt16( nTemp16 ); + rDesign.m_eScript = static_cast<PublishingScript>(nTemp16); + rDesign.m_aURL = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + rDesign.m_aCGI = read_uInt16_lenPrefixed_uInt8s_ToOUString(rIn, + RTL_TEXTENCODING_UTF8); + + rIn.ReadCharAsBool( rDesign.m_bAutoSlide ); + rIn.ReadUInt32( rDesign.m_nSlideDuration ); + rIn.ReadCharAsBool( rDesign.m_bEndless ); + rIn.ReadCharAsBool( rDesign.m_bSlideSound ); + rIn.ReadCharAsBool( rDesign.m_bHiddenSlides ); + + return rIn; +} + +// Set the design to the stream +SvStream& WriteSdPublishingDesign(SvStream& rOut, const SdPublishingDesign& rDesign) +{ + // The last parameter is the versionnumber of the code + SdIOCompat aIO(rOut, StreamMode::WRITE, 0); + + tools::GenericTypeSerializer aSerializer(rOut); + + // Name + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aDesignName, + RTL_TEXTENCODING_UTF8); + + rOut.WriteUInt16( rDesign.m_eMode ); + rOut.WriteBool( rDesign.m_bContentPage ); + rOut.WriteBool( rDesign.m_bNotes ); + rOut.WriteUInt16( rDesign.m_nResolution ); + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aCompression, + RTL_TEXTENCODING_UTF8); + rOut.WriteUInt16( rDesign.m_eFormat ); + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aAuthor, + RTL_TEXTENCODING_UTF8); + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aEMail, + RTL_TEXTENCODING_UTF8); + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aWWW, + RTL_TEXTENCODING_UTF8); + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aMisc, + RTL_TEXTENCODING_UTF8); + rOut.WriteBool( rDesign.m_bDownload ); + rOut.WriteBool( rDesign.m_bCreated ); // not used + rOut.WriteInt16( rDesign.m_nButtonThema ); + rOut.WriteBool( rDesign.m_bUserAttr ); + aSerializer.writeColor(rDesign.m_aBackColor); + aSerializer.writeColor(rDesign.m_aTextColor); + aSerializer.writeColor(rDesign.m_aLinkColor); + aSerializer.writeColor(rDesign.m_aVLinkColor); + aSerializer.writeColor(rDesign.m_aALinkColor); + rOut.WriteBool( rDesign.m_bUseAttribs ); + rOut.WriteBool( rDesign.m_bUseColor ); + + rOut.WriteUInt16( rDesign.m_eScript ); + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aURL, + RTL_TEXTENCODING_UTF8); + write_uInt16_lenPrefixed_uInt8s_FromOUString(rOut, rDesign.m_aCGI, + RTL_TEXTENCODING_UTF8); + + rOut.WriteBool( rDesign.m_bAutoSlide ); + rOut.WriteUInt32( rDesign.m_nSlideDuration ); + rOut.WriteBool( rDesign.m_bEndless ); + rOut.WriteBool( rDesign.m_bSlideSound ); + rOut.WriteBool( rDesign.m_bHiddenSlides ); + + return rOut; +} + +namespace { + +// Dialog for the entry of the name of the design +class SdDesignNameDlg : public weld::GenericDialogController +{ +private: + std::unique_ptr<weld::Entry> m_xEdit; + std::unique_ptr<weld::Button> m_xBtnOK; + +public: + SdDesignNameDlg(weld::Window* pWindow, const OUString& aName ); + OUString GetDesignName() const; + DECL_LINK(ModifyHdl, weld::Entry&, void); +}; + +} + +// SdPublishingDlg Methods + +SdPublishingDlg::SdPublishingDlg(weld::Window* pWindow, DocumentType eDocType) + : GenericDialogController(pWindow, "modules/simpress/ui/publishingdialog.ui", "PublishingDialog") + , m_xPage1_Designs(m_xBuilder->weld_tree_view("designsTreeview")) + , m_xPage2_Standard_FB(m_xBuilder->weld_image("standardFBImage")) + , m_xPage2_Frames_FB(m_xBuilder->weld_image("framesFBImage")) + , m_xPage2_Kiosk_FB(m_xBuilder->weld_image("kioskFBImage")) + , m_xPage2_WebCast_FB(m_xBuilder->weld_image("webCastFBImage")) + , m_xPage4_Misc(m_xBuilder->weld_text_view("miscTextview")) + , m_xButtonSet(new ButtonSet()) + , m_xLastPageButton(m_xBuilder->weld_button("lastPageButton")) + , m_xNextPageButton(m_xBuilder->weld_button("nextPageButton")) + , m_xFinishButton(m_xBuilder->weld_button("finishButton")) + , aAssistentFunc(NOOFPAGES) + , m_bButtonsDirty(true) + , m_bDesignListDirty(false) + , m_pDesign(nullptr) +{ + m_bImpress = eDocType == DocumentType::Impress; + + Size aSize(m_xPage2_Standard_FB->get_approximate_digit_width() * 12, + m_xPage2_Standard_FB->get_text_height() * 6); + m_xPage2_Standard_FB->set_size_request(aSize.Width(), aSize.Height()); + m_xPage2_Frames_FB->set_size_request(aSize.Width(), aSize.Height()); + m_xPage2_Kiosk_FB->set_size_request(aSize.Width(), aSize.Height()); + m_xPage2_WebCast_FB->set_size_request(aSize.Width(), aSize.Height()); + + m_xPage4_Misc->set_size_request(m_xPage4_Misc->get_approximate_digit_width() * 40, + m_xPage4_Misc->get_height_rows(8)); + + m_xPage1_Designs->set_size_request(m_xPage4_Misc->get_approximate_digit_width() * 40, + m_xPage4_Misc->get_height_rows(8)); + + //Lock down the preferred size based on the + //initial max-size configuration + aSize = m_xDialog->get_preferred_size(); + m_xDialog->set_size_request(aSize.Width(), aSize.Height()); + + CreatePages(); + Load(); + + // sets the output page + aAssistentFunc.GotoPage(1); + m_xLastPageButton->set_sensitive(false); + + // button assignment + m_xFinishButton->connect_clicked(LINK(this,SdPublishingDlg,FinishHdl)); + m_xLastPageButton->connect_clicked(LINK(this,SdPublishingDlg,LastPageHdl)); + m_xNextPageButton->connect_clicked(LINK(this,SdPublishingDlg,NextPageHdl)); + + m_xPage1_NewDesign->connect_toggled(LINK(this,SdPublishingDlg,DesignHdl)); + m_xPage1_OldDesign->connect_toggled(LINK(this,SdPublishingDlg,DesignHdl)); + m_xPage1_Designs->connect_changed(LINK(this,SdPublishingDlg,DesignSelectHdl)); + m_xPage1_DelDesign->connect_clicked(LINK(this,SdPublishingDlg,DesignDeleteHdl)); + + m_xPage2_Standard->connect_toggled(LINK(this,SdPublishingDlg,BaseHdl)); + m_xPage2_Frames->connect_toggled(LINK(this,SdPublishingDlg,BaseHdl)); + m_xPage2_SingleDocument->connect_toggled(LINK(this,SdPublishingDlg,BaseHdl)); + m_xPage2_Kiosk->connect_toggled(LINK(this,SdPublishingDlg,BaseHdl)); + m_xPage2_WebCast->connect_toggled(LINK(this,SdPublishingDlg,BaseHdl)); + + m_xPage2_Content->connect_toggled(LINK(this,SdPublishingDlg,ContentHdl)); + + m_xPage2_ASP->connect_toggled(LINK(this,SdPublishingDlg,WebServerHdl)); + m_xPage2_PERL->connect_toggled(LINK(this,SdPublishingDlg,WebServerHdl)); + m_xPage2_Index->set_text("index" STR_HTMLEXP_DEFAULT_EXTENSION); + m_xPage2_CGI->set_text("/cgi-bin/"); + + m_xPage3_Png->connect_toggled(LINK(this,SdPublishingDlg, GfxFormatHdl)); + m_xPage3_Gif->connect_toggled(LINK(this,SdPublishingDlg, GfxFormatHdl)); + m_xPage3_Jpg->connect_toggled(LINK(this,SdPublishingDlg, GfxFormatHdl)); + m_xPage3_Quality->set_sensitive(false); + + m_xPage3_Resolution_1->connect_toggled(LINK(this,SdPublishingDlg, ResolutionHdl )); + m_xPage3_Resolution_2->connect_toggled(LINK(this,SdPublishingDlg, ResolutionHdl )); + m_xPage3_Resolution_3->connect_toggled(LINK(this,SdPublishingDlg, ResolutionHdl )); + m_xPage3_Resolution_4->connect_toggled(LINK(this, SdPublishingDlg, ResolutionHdl)); + + m_xPage2_ChgDefault->connect_toggled(LINK(this,SdPublishingDlg, SlideChgHdl)); + m_xPage2_ChgAuto->connect_toggled(LINK(this,SdPublishingDlg, SlideChgHdl)); + + m_xPage5_Buttons->SetSelectHdl(LINK(this,SdPublishingDlg, ButtonsHdl )); + m_xPage5_Buttons->SetStyle( m_xPage5_Buttons->GetStyle() | WB_VSCROLL ); + + m_xPage6_Back->connect_clicked(LINK(this,SdPublishingDlg, ColorHdl )); + m_xPage6_Text->connect_clicked(LINK(this,SdPublishingDlg, ColorHdl )); + m_xPage6_Link->connect_clicked(LINK(this,SdPublishingDlg, ColorHdl )); + m_xPage6_VLink->connect_clicked(LINK(this,SdPublishingDlg, ColorHdl )); + m_xPage6_ALink->connect_clicked(LINK(this,SdPublishingDlg, ColorHdl )); + + m_xPage6_DocColors->set_active(true); + + m_xPage3_Quality->append_text( "25%" ); + m_xPage3_Quality->append_text( "50%" ); + m_xPage3_Quality->append_text( "75%" ); + m_xPage3_Quality->append_text( "100%" ); + + m_xPage5_Buttons->SetColCount(); + m_xPage5_Buttons->SetLineCount( 4 ); + m_xPage5_Buttons->SetExtraSpacing( 1 ); + + for( const auto& rDesign : m_aDesignList ) + m_xPage1_Designs->append_text(rDesign.m_aDesignName); + + SetDefaults(); + + m_xDialog->set_help_id(aPageHelpIds[0]); + + m_xNextPageButton->grab_focus(); +} + +SdPublishingDlg::~SdPublishingDlg() +{ +} + +// Generate dialog controls and embed them in the pages +void SdPublishingDlg::CreatePages() +{ + // Page 1 + m_xPage1 = m_xBuilder->weld_container("page1"); + m_xPage1_Title = m_xBuilder->weld_label("assignLabel"); + m_xPage1_NewDesign = m_xBuilder->weld_radio_button("newDesignRadiobutton"); + m_xPage1_OldDesign = m_xBuilder->weld_radio_button("oldDesignRadiobutton"); + m_xPage1_DelDesign = m_xBuilder->weld_button("delDesingButton"); + m_xPage1_Desc = m_xBuilder->weld_label("descLabel"); + aAssistentFunc.InsertControl(1, m_xPage1.get()); + aAssistentFunc.InsertControl(1, m_xPage1_Title.get()); + aAssistentFunc.InsertControl(1, m_xPage1_NewDesign.get()); + aAssistentFunc.InsertControl(1, m_xPage1_OldDesign.get()); + aAssistentFunc.InsertControl(1, m_xPage1_Designs.get()); + aAssistentFunc.InsertControl(1, m_xPage1_DelDesign.get()); + aAssistentFunc.InsertControl(1, m_xPage1_Desc.get()); + + // Page 2 + m_xPage2 = m_xBuilder->weld_container("page2"); + m_xPage2Frame2 = m_xBuilder->weld_container("page2.2"); + m_xPage2Frame3 = m_xBuilder->weld_container("page2.3"); + m_xPage2Frame4 = m_xBuilder->weld_container("page2.4"); + m_xPage2_Title = m_xBuilder->weld_label("publicationLabel"); + m_xPage2_Standard = m_xBuilder->weld_radio_button("standardRadiobutton"); + m_xPage2_Frames = m_xBuilder->weld_radio_button("framesRadiobutton"); + m_xPage2_SingleDocument = m_xBuilder->weld_radio_button("singleDocumentRadiobutton"); + m_xPage2_Kiosk = m_xBuilder->weld_radio_button("kioskRadiobutton"); + m_xPage2_WebCast = m_xBuilder->weld_radio_button("webCastRadiobutton"); + aAssistentFunc.InsertControl(2, m_xPage2.get()); + aAssistentFunc.InsertControl(2, m_xPage2Frame2.get()); + aAssistentFunc.InsertControl(2, m_xPage2Frame3.get()); + aAssistentFunc.InsertControl(2, m_xPage2Frame4.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Title.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Standard.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Frames.get()); + aAssistentFunc.InsertControl(2, m_xPage2_SingleDocument.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Kiosk.get()); + aAssistentFunc.InsertControl(2, m_xPage2_WebCast.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Standard_FB.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Frames_FB.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Kiosk_FB.get()); + aAssistentFunc.InsertControl(2, m_xPage2_WebCast_FB.get()); + + m_xPage2_Title_Html = m_xBuilder->weld_label( "htmlOptionsLabel"); + m_xPage2_Content = m_xBuilder->weld_check_button("contentCheckbutton"); + m_xPage2_Notes = m_xBuilder->weld_check_button("notesCheckbutton"); + aAssistentFunc.InsertControl(2, m_xPage2_Title_Html.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Content.get()); + if (m_bImpress) + aAssistentFunc.InsertControl(2, m_xPage2_Notes.get()); + + m_xPage2_Title_WebCast = m_xBuilder->weld_label("webCastLabel"); + m_xPage2_ASP = m_xBuilder->weld_radio_button("ASPRadiobutton"); + m_xPage2_PERL = m_xBuilder->weld_radio_button("perlRadiobutton"); + m_xPage2_URL_txt = m_xBuilder->weld_label("URLTxtLabel"); + m_xPage2_URL = m_xBuilder->weld_entry("URLEntry"); + m_xPage2_CGI_txt = m_xBuilder->weld_label("CGITxtLabel"); + m_xPage2_CGI = m_xBuilder->weld_entry("CGIEntry"); + m_xPage2_Index_txt = m_xBuilder->weld_label("indexTxtLabel"); + m_xPage2_Index = m_xBuilder->weld_entry("indexEntry"); + m_xPage2_Title_Kiosk = m_xBuilder->weld_label("kioskLabel"); + m_xPage2_ChgDefault = m_xBuilder->weld_radio_button("chgDefaultRadiobutton"); + m_xPage2_ChgAuto = m_xBuilder->weld_radio_button("chgAutoRadiobutton"); + m_xPage2_Duration_txt = m_xBuilder->weld_label("durationTxtLabel"); + m_xPage2_Duration = m_xBuilder->weld_formatted_spin_button("durationSpinbutton"); + m_xFormatter.reset(new weld::TimeFormatter(*m_xPage2_Duration)); + m_xFormatter->SetExtFormat(ExtTimeFieldFormat::LongDuration); + m_xPage2_Endless = m_xBuilder->weld_check_button("endlessCheckbutton"); + aAssistentFunc.InsertControl(2, m_xPage2_Title_WebCast.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Index_txt.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Index.get()); + aAssistentFunc.InsertControl(2, m_xPage2_ASP.get()); + aAssistentFunc.InsertControl(2, m_xPage2_PERL.get()); + aAssistentFunc.InsertControl(2, m_xPage2_URL_txt.get()); + aAssistentFunc.InsertControl(2, m_xPage2_URL.get()); + aAssistentFunc.InsertControl(2, m_xPage2_CGI_txt.get()); + aAssistentFunc.InsertControl(2, m_xPage2_CGI.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Title_Kiosk.get()); + aAssistentFunc.InsertControl(2, m_xPage2_ChgDefault.get()); + aAssistentFunc.InsertControl(2, m_xPage2_ChgAuto.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Duration_txt.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Duration.get()); + aAssistentFunc.InsertControl(2, m_xPage2_Endless.get()); + + // Page 3 + m_xPage3 = m_xBuilder->weld_container("page3"); + m_xPage3_Title1 = m_xBuilder->weld_label("saveImgAsLabel"); + m_xPage3_Png = m_xBuilder->weld_radio_button("pngRadiobutton"); + m_xPage3_Gif = m_xBuilder->weld_radio_button("gifRadiobutton"); + m_xPage3_Jpg = m_xBuilder->weld_radio_button("jpgRadiobutton"); + m_xPage3_Quality_txt = m_xBuilder->weld_label("qualityTxtLabel"); + m_xPage3_Quality= m_xBuilder->weld_combo_box("qualityCombobox"); + m_xPage3_Title2 = m_xBuilder->weld_label("monitorResolutionLabel"); + m_xPage3_Resolution_1 = m_xBuilder->weld_radio_button("resolution1Radiobutton"); + m_xPage3_Resolution_2 = m_xBuilder->weld_radio_button("resolution2Radiobutton"); + m_xPage3_Resolution_3 = m_xBuilder->weld_radio_button("resolution3Radiobutton"); + m_xPage3_Resolution_4 = m_xBuilder->weld_radio_button("resolution4Radiobutton"); + m_xPage3_Title3 = m_xBuilder->weld_label("effectsLabel"); + m_xPage3_SldSound = m_xBuilder->weld_check_button("sldSoundCheckbutton"); + m_xPage3_HiddenSlides = m_xBuilder->weld_check_button("hiddenSlidesCheckbutton"); + aAssistentFunc.InsertControl(3, m_xPage3.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Title1.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Png.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Gif.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Jpg.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Quality_txt.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Quality.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Title2.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Resolution_1.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Resolution_2.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Resolution_3.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Resolution_4.get()); + aAssistentFunc.InsertControl(3, m_xPage3_Title3.get()); + aAssistentFunc.InsertControl(3, m_xPage3_SldSound.get()); + aAssistentFunc.InsertControl(3, m_xPage3_HiddenSlides.get()); + + // Page 4 + m_xPage4 = m_xBuilder->weld_container("page4"); + m_xPage4_Title1 = m_xBuilder->weld_label("infTitlePageLabel"); + m_xPage4_Author_txt = m_xBuilder->weld_label("authorTxtLabel"); + m_xPage4_Author = m_xBuilder->weld_entry("authorEntry"); + m_xPage4_Email_txt = m_xBuilder->weld_label("emailTxtLabel"); + m_xPage4_Email = m_xBuilder->weld_entry("emailEntry"); + m_xPage4_WWW_txt = m_xBuilder->weld_label("wwwTxtLabel"); + m_xPage4_WWW = m_xBuilder->weld_entry("wwwEntry"); + m_xPage4_Title2 = m_xBuilder->weld_label("addInformLabel"); + m_xPage4_Download = m_xBuilder->weld_check_button("downloadCheckbutton"); + aAssistentFunc.InsertControl(4, m_xPage4.get()); + aAssistentFunc.InsertControl(4, m_xPage4_Title1.get()); + aAssistentFunc.InsertControl(4, m_xPage4_Author_txt.get()); + aAssistentFunc.InsertControl(4, m_xPage4_Author.get()); + aAssistentFunc.InsertControl(4, m_xPage4_Email_txt.get()); + aAssistentFunc.InsertControl(4, m_xPage4_Email.get()); + aAssistentFunc.InsertControl(4, m_xPage4_WWW_txt.get()); + aAssistentFunc.InsertControl(4, m_xPage4_WWW.get()); + aAssistentFunc.InsertControl(4, m_xPage4_Title2.get()); + aAssistentFunc.InsertControl(4, m_xPage4_Misc.get()); + if(m_bImpress) + aAssistentFunc.InsertControl(4, m_xPage4_Download.get()); + + // Page 5 + m_xPage5 = m_xBuilder->weld_container("page5"); + m_xPage5_Title = m_xBuilder->weld_label("buttonStyleLabel"); + m_xPage5_TextOnly = m_xBuilder->weld_check_button("textOnlyCheckbutton"); + m_xPage5_Buttons.reset(new ValueSet(m_xBuilder->weld_scrolled_window("buttonsDrawingareawin", true))); + m_xPage5_ButtonsWnd.reset(new weld::CustomWeld(*m_xBuilder, "buttonsDrawingarea", *m_xPage5_Buttons)); + aAssistentFunc.InsertControl(5, m_xPage5.get()); + aAssistentFunc.InsertControl(5, m_xPage5_Title.get()); + aAssistentFunc.InsertControl(5, m_xPage5_TextOnly.get()); + aAssistentFunc.InsertControl(5, m_xPage5_Buttons->GetDrawingArea()); + + // Page 6 + m_xPage6 = m_xBuilder->weld_container("page6"); + m_xPage6_Title = m_xBuilder->weld_label("selectColorLabel"); + m_xPage6_Default = m_xBuilder->weld_radio_button("defaultRadiobutton"); + m_xPage6_User = m_xBuilder->weld_radio_button("userRadiobutton"); + m_xPage6_Back = m_xBuilder->weld_button("backButton"); + m_xPage6_Text = m_xBuilder->weld_button("textButton"); + m_xPage6_Link = m_xBuilder->weld_button("linkButton"); + m_xPage6_VLink = m_xBuilder->weld_button("vLinkButton"); + m_xPage6_ALink = m_xBuilder->weld_button("aLinkButton"); + m_xPage6_DocColors = m_xBuilder->weld_radio_button("docColorsRadiobutton"); + m_xPage6_Preview.reset(new SdHtmlAttrPreview); + m_xPage6_PreviewWnd.reset(new weld::CustomWeld(*m_xBuilder, "previewDrawingarea", *m_xPage6_Preview)); + aAssistentFunc.InsertControl(6, m_xPage6.get()); + aAssistentFunc.InsertControl(6, m_xPage6_Title.get()); + aAssistentFunc.InsertControl(6, m_xPage6_DocColors.get()); + aAssistentFunc.InsertControl(6, m_xPage6_Default.get()); + aAssistentFunc.InsertControl(6, m_xPage6_User.get()); + aAssistentFunc.InsertControl(6, m_xPage6_Text.get()); + aAssistentFunc.InsertControl(6, m_xPage6_Link.get()); + aAssistentFunc.InsertControl(6, m_xPage6_ALink.get()); + aAssistentFunc.InsertControl(6, m_xPage6_VLink.get()); + aAssistentFunc.InsertControl(6, m_xPage6_Back.get()); + aAssistentFunc.InsertControl(6, m_xPage6_Preview->GetDrawingArea()); +} + +// Initialize dialog with default-values +void SdPublishingDlg::SetDefaults() +{ + SdPublishingDesign aDefault; + SetDesign(&aDefault); + + m_xPage1_NewDesign->set_active(true); + m_xPage1_OldDesign->set_active(false); + UpdatePage(); +} + +// Feed the SfxItemSet with the settings of the dialog +void SdPublishingDlg::GetParameterSequence( Sequence< PropertyValue >& rParams ) +{ + std::vector< PropertyValue > aProps; + + PropertyValue aValue; + + // Page 2 + aValue.Name = "PublishMode"; + + HtmlPublishMode ePublishMode; + if (m_xPage2_Frames->get_active()) + ePublishMode = PUBLISH_FRAMES; + else if (m_xPage2_SingleDocument->get_active()) + ePublishMode = PUBLISH_SINGLE_DOCUMENT; + else if (m_xPage2_Kiosk->get_active()) + ePublishMode = PUBLISH_KIOSK; + else if (m_xPage2_WebCast->get_active()) + ePublishMode = PUBLISH_WEBCAST; + else + ePublishMode = PUBLISH_HTML; + + aValue.Value <<= static_cast<sal_Int32>(ePublishMode); + aProps.push_back( aValue ); + + aValue.Name = "IsExportContentsPage"; + aValue.Value <<= m_xPage2_Content->get_active(); + aProps.push_back( aValue ); + + if(m_bImpress) + { + aValue.Name = "IsExportNotes"; + aValue.Value <<= m_xPage2_Notes->get_active(); + aProps.push_back( aValue ); + } + + if( m_xPage2_WebCast->get_active() ) + { + aValue.Name = "WebCastScriptLanguage"; + if( m_xPage2_ASP->get_active() ) + aValue.Value <<= OUString( "asp" ); + else + aValue.Value <<= OUString( "perl" ); + aProps.push_back( aValue ); + + aValue.Name = "WebCastCGIURL"; + aValue.Value <<= m_xPage2_CGI->get_text(); + aProps.push_back( aValue ); + + aValue.Name = "WebCastTargetURL"; + aValue.Value <<= m_xPage2_URL->get_text(); + aProps.push_back( aValue ); + } + aValue.Name = "IndexURL"; + aValue.Value <<= m_xPage2_Index->get_text(); + aProps.push_back( aValue ); + + if( m_xPage2_Kiosk->get_active() && m_xPage2_ChgAuto->get_active() ) + { + aValue.Name = "KioskSlideDuration"; + aValue.Value <<= static_cast<sal_uInt32>(m_xFormatter->GetTime().GetMSFromTime()) / 1000; + aProps.push_back( aValue ); + + aValue.Name = "KioskEndless"; + aValue.Value <<= m_xPage2_Endless->get_active(); + aProps.push_back( aValue ); + } + + // Page 3 + + aValue.Name = "Width"; + sal_Int32 nTmpWidth = PUB_LOWRES_WIDTH; + if( m_xPage3_Resolution_2->get_active() ) + nTmpWidth = PUB_MEDRES_WIDTH; + else if( m_xPage3_Resolution_3->get_active() ) + nTmpWidth = PUB_HIGHRES_WIDTH; + else if (m_xPage3_Resolution_4->get_active()) + nTmpWidth = PUB_FHDRES_WIDTH; + + aValue.Value <<= nTmpWidth; + aProps.push_back( aValue ); + + aValue.Name = "Compression"; + aValue.Value <<= m_xPage3_Quality->get_active_text(); + aProps.push_back( aValue ); + + aValue.Name = "Format"; + sal_Int32 nFormat; + if( m_xPage3_Png->get_active() ) + nFormat = static_cast<sal_Int32>(FORMAT_PNG); + else if( m_xPage3_Gif->get_active() ) + nFormat = static_cast<sal_Int32>(FORMAT_GIF); + else + nFormat = static_cast<sal_Int32>(FORMAT_JPG); + aValue.Value <<= nFormat; + aProps.push_back( aValue ); + + aValue.Name = "SlideSound"; + aValue.Value <<= m_xPage3_SldSound->get_active(); + aProps.push_back( aValue ); + + aValue.Name = "HiddenSlides"; + aValue.Value <<= m_xPage3_HiddenSlides->get_active(); + aProps.push_back( aValue ); + + // Page 4 + aValue.Name = "Author"; + aValue.Value <<= m_xPage4_Author->get_text(); + aProps.push_back( aValue ); + + aValue.Name = "EMail"; + aValue.Value <<= m_xPage4_Email->get_text(); + aProps.push_back( aValue ); + + // try to guess protocol for user's homepage + INetURLObject aHomeURL( m_xPage4_WWW->get_text(), + INetProtocol::Http, // default proto is HTTP + INetURLObject::EncodeMechanism::All ); + + aValue.Name = "HomepageURL"; + aValue.Value <<= aHomeURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); + aProps.push_back( aValue ); + + aValue.Name = "UserText"; + aValue.Value <<= m_xPage4_Misc->get_text(); + aProps.push_back( aValue ); + + if( m_bImpress ) + { + aValue.Name = "EnableDownload"; + aValue.Value <<= m_xPage4_Download->get_active(); + aProps.push_back( aValue ); + } + + // Page 5 + if( !m_xPage5_TextOnly->get_active() ) + { + aValue.Name = "UseButtonSet"; + aValue.Value <<= static_cast<sal_Int32>(m_xPage5_Buttons->GetSelectedItemId() - 1); + aProps.push_back( aValue ); + } + + // Page 6 + if( m_xPage6_User->get_active() ) + { + aValue.Name = "BackColor"; + aValue.Value <<= m_aBackColor; + aProps.push_back( aValue ); + + aValue.Name = "TextColor"; + aValue.Value <<= m_aTextColor; + aProps.push_back( aValue ); + + aValue.Name = "LinkColor"; + aValue.Value <<= m_aLinkColor; + aProps.push_back( aValue ); + + aValue.Name = "VLinkColor"; + aValue.Value <<= m_aVLinkColor; + aProps.push_back( aValue ); + + aValue.Name = "ALinkColor"; + aValue.Value <<= m_aALinkColor; + aProps.push_back( aValue ); + } + + if( m_xPage6_DocColors->get_active() ) + { + aValue.Name = "IsUseDocumentColors"; + aValue.Value <<= true; + aProps.push_back( aValue ); + } + + rParams = comphelper::containerToSequence(aProps); +} + +// Clickhandler for the radiobuttons of the design-selection +IMPL_LINK( SdPublishingDlg, DesignHdl, weld::Toggleable&, rButton, void ) +{ + if (!rButton.get_active()) + return; + + if (m_xPage1_NewDesign->get_active()) + { + m_xPage1_NewDesign->set_active(true); // because of DesignDeleteHdl + m_xPage1_OldDesign->set_active(false); + m_xPage1_Designs->set_sensitive(false); + m_xPage1_DelDesign->set_sensitive(false); + m_pDesign = nullptr; + + SdPublishingDesign aDefault; + SetDesign(&aDefault); + } + else + { + m_xPage1_NewDesign->set_active(false); + m_xPage1_Designs->set_sensitive(true); + m_xPage1_DelDesign->set_sensitive(true); + + if (m_xPage1_Designs->get_selected_index() == -1) + m_xPage1_Designs->select(0); + + const sal_Int32 nPos = m_xPage1_Designs->get_selected_index(); + m_pDesign = &m_aDesignList[nPos]; + DBG_ASSERT(m_pDesign, "No Design? That's not allowed (CL)"); + + if(m_pDesign) + SetDesign(m_pDesign); + } +} + +// Clickhandler for the choice of one design +IMPL_LINK_NOARG(SdPublishingDlg, DesignSelectHdl, weld::TreeView&, void) +{ + const sal_Int32 nPos = m_xPage1_Designs->get_selected_index(); + m_pDesign = &m_aDesignList[nPos]; + DBG_ASSERT(m_pDesign, "No Design? That's not allowed (CL)"); + + if(m_pDesign) + SetDesign(m_pDesign); + + UpdatePage(); +} + +// Clickhandler for the delete of one design +IMPL_LINK_NOARG(SdPublishingDlg, DesignDeleteHdl, weld::Button&, void) +{ + const sal_Int32 nPos = m_xPage1_Designs->get_selected_index(); + + std::vector<SdPublishingDesign>::iterator iter = m_aDesignList.begin()+nPos; + + DBG_ASSERT(iter != m_aDesignList.end(), "No Design? That's not allowed (CL)"); + + m_xPage1_Designs->remove(nPos); + + if(m_pDesign == &(*iter)) + DesignHdl(*m_xPage1_NewDesign); + + m_aDesignList.erase(iter); + + m_bDesignListDirty = true; + + UpdatePage(); +} + +// Clickhandler for the other servertypes +IMPL_LINK(SdPublishingDlg, WebServerHdl, weld::Toggleable&, rButton, void) +{ + if (!rButton.get_active()) + return; + + bool bASP = m_xPage2_ASP->get_active(); + m_xPage2_ASP->set_sensitive( bASP ); + m_xPage2_PERL->set_sensitive( !bASP ); + UpdatePage(); +} + +// Clickhandler for the Radiobuttons of the graphicformat choice +IMPL_LINK(SdPublishingDlg, GfxFormatHdl, weld::Toggleable&, rButton, void) +{ + if (!rButton.get_active()) + return; + + m_xPage3_Png->set_sensitive(m_xPage3_Png->get_active()); + m_xPage3_Gif->set_sensitive(m_xPage3_Gif->get_active()); + m_xPage3_Jpg->set_sensitive(m_xPage3_Jpg->get_active()); + m_xPage3_Quality->set_sensitive(m_xPage3_Jpg->get_active()); +} + +// Clickhandler for the Radiobuttons Standard/Frames +IMPL_LINK(SdPublishingDlg, BaseHdl, weld::Toggleable&, rButton, void) +{ + if (!rButton.get_active()) + return; + + UpdatePage(); +} + +// Clickhandler for the Checkbox of the Title page +IMPL_LINK_NOARG(SdPublishingDlg, ContentHdl, weld::Toggleable&, void) +{ + if(m_xPage2_Content->get_active()) + { + if(!aAssistentFunc.IsEnabled(4)) + { + aAssistentFunc.EnablePage(4); + UpdatePage(); + } + } + else + { + if(aAssistentFunc.IsEnabled(4)) + { + aAssistentFunc.DisablePage(4); + UpdatePage(); + } + } +} + +// Clickhandler for the Resolution Radiobuttons +IMPL_LINK( SdPublishingDlg, ResolutionHdl, weld::Toggleable&, rButton, void ) +{ + if (!rButton.get_active()) + return; + m_xPage3_Resolution_1->set_sensitive(m_xPage3_Resolution_1->get_active()); + m_xPage3_Resolution_2->set_sensitive(m_xPage3_Resolution_2->get_active()); + m_xPage3_Resolution_3->set_sensitive(m_xPage3_Resolution_3->get_active()); + m_xPage3_Resolution_4->set_sensitive(m_xPage3_Resolution_4->get_active()); +} + +// Clickhandler for the ValueSet with the bitmap-buttons +IMPL_LINK_NOARG(SdPublishingDlg, ButtonsHdl, ValueSet*, void) +{ + // if one bitmap-button is chosen, then disable TextOnly + m_xPage5_TextOnly->set_active(false); +} + +// Fill the SfxItemSet with the settings of the dialog +IMPL_LINK( SdPublishingDlg, ColorHdl, weld::Button&, rButton, void) +{ + SvColorDialog aDlg; + + if (&rButton == m_xPage6_Back.get()) + { + aDlg.SetColor( m_aBackColor ); + if(aDlg.Execute(m_xDialog.get()) == RET_OK ) + m_aBackColor = aDlg.GetColor(); + } + else if (&rButton == m_xPage6_Text.get()) + { + aDlg.SetColor( m_aTextColor ); + if(aDlg.Execute(m_xDialog.get()) == RET_OK ) + m_aTextColor = aDlg.GetColor(); + } + else if (&rButton == m_xPage6_Link.get()) + { + aDlg.SetColor( m_aLinkColor ); + if(aDlg.Execute(m_xDialog.get()) == RET_OK ) + m_aLinkColor = aDlg.GetColor(); + } + else if (&rButton == m_xPage6_VLink.get()) + { + aDlg.SetColor( m_aVLinkColor ); + if(aDlg.Execute(m_xDialog.get()) == RET_OK ) + m_aVLinkColor = aDlg.GetColor(); + } + else if (&rButton == m_xPage6_ALink.get()) + { + aDlg.SetColor( m_aALinkColor ); + if(aDlg.Execute(m_xDialog.get()) == RET_OK ) + m_aALinkColor = aDlg.GetColor(); + } + + m_xPage6_User->set_active(true); + m_xPage6_Preview->SetColors( m_aBackColor, m_aTextColor, m_aLinkColor, + m_aVLinkColor, m_aALinkColor ); + m_xPage6_Preview->Invalidate(); +} + +IMPL_LINK(SdPublishingDlg, SlideChgHdl, weld::Toggleable&, rButton, void) +{ + if (!rButton.get_active()) + return; + UpdatePage(); +} + +// Clickhandler for the Ok Button +IMPL_LINK_NOARG(SdPublishingDlg, FinishHdl, weld::Button&, void) +{ + //End + SdPublishingDesign aDesign; + GetDesign(&aDesign); + + bool bSave = false; + + if(m_xPage1_OldDesign->get_active() && m_pDesign) + { + // are there changes? + if(!(aDesign == *m_pDesign)) + bSave = true; + } + else + { + SdPublishingDesign aDefaultDesign; + if(!(aDefaultDesign == aDesign)) + bSave = true; + } + + if(bSave) + { + OUString aName; + if(m_pDesign) + aName = m_pDesign->m_aDesignName; + + bool bRetry; + do + { + bRetry = false; + + SdDesignNameDlg aDlg(m_xDialog.get(), aName); + + if (aDlg.run() == RET_OK) + { + aDesign.m_aDesignName = aDlg.GetDesignName(); + + auto iter = std::find_if(m_aDesignList.begin(), m_aDesignList.end(), + [&aDesign](const SdPublishingDesign& rDesign) { return rDesign.m_aDesignName == aDesign.m_aDesignName; }); + + if (iter != m_aDesignList.end()) + { + std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(m_xDialog.get(), + VclMessageType::Error, VclButtonsType::YesNo, + SdResId(STR_PUBDLG_SAMENAME))); + bRetry = xErrorBox->run() == RET_NO; + + if(!bRetry) + m_aDesignList.erase(iter); + } + + if(!bRetry) + { + m_aDesignList.push_back(aDesign); + m_bDesignListDirty = true; + } + } + } + while(bRetry); + } + + if(m_bDesignListDirty) + Save(); + + m_xDialog->response(RET_OK); +} + +// Refresh the dialogs when changing from pages +void SdPublishingDlg::ChangePage() +{ + int nPage = aAssistentFunc.GetCurrentPage(); + m_xDialog->set_help_id(aPageHelpIds[nPage-1]); + + UpdatePage(); + + if (m_xNextPageButton->get_sensitive()) + m_xNextPageButton->grab_focus(); + else + m_xFinishButton->grab_focus(); +} + +void SdPublishingDlg::UpdatePage() +{ + m_xNextPageButton->set_sensitive(!aAssistentFunc.IsLastPage()); + m_xLastPageButton->set_sensitive(!aAssistentFunc.IsFirstPage()); + + int nPage = aAssistentFunc.GetCurrentPage(); + + switch( nPage ) + { + case 1: + if(m_xPage1_NewDesign->get_active()) + { + m_xPage1_Designs->set_sensitive(false); + m_xPage1_DelDesign->set_sensitive(false); + } + + if(m_aDesignList.empty()) + m_xPage1_OldDesign->set_sensitive(false); + break; + case 2: + m_xPage2_Frames_FB->set_visible(m_xPage2_Frames->get_active()); + m_xPage2_Standard_FB->set_visible(m_xPage2_Standard->get_active()); + m_xPage2_Kiosk_FB->set_visible(m_xPage2_Kiosk->get_active()); + m_xPage2_WebCast_FB->set_visible(m_xPage2_WebCast->get_active()); + + if( m_xPage2_WebCast->get_active() ) + { + m_xPage2Frame4->show(); + m_xPage2_Title_WebCast->show(); + m_xPage2_ASP->show(); + m_xPage2_PERL->show(); + m_xPage2_URL_txt->show(); + m_xPage2_URL->show(); + m_xPage2_CGI_txt->show(); + m_xPage2_CGI->show(); + m_xPage2_Index_txt->show(); + m_xPage2_Index->show(); + + bool bPerl = m_xPage2_PERL->get_active(); + m_xPage2_Index->set_sensitive(bPerl); + m_xPage2_Index_txt->set_sensitive(bPerl); + m_xPage2_URL_txt->set_sensitive(bPerl); + m_xPage2_URL->set_sensitive(bPerl); + m_xPage2_CGI_txt->set_sensitive(bPerl); + m_xPage2_CGI->set_sensitive(bPerl); + } + else + { + m_xPage2Frame4->hide(); + m_xPage2_Title_WebCast->hide(); + m_xPage2_ASP->hide(); + m_xPage2_PERL->hide(); + m_xPage2_URL_txt->hide(); + m_xPage2_URL->hide(); + m_xPage2_CGI_txt->hide(); + m_xPage2_CGI->hide(); + m_xPage2_Index->hide(); + m_xPage2_Index_txt->hide(); + } + + if( m_xPage2_Kiosk->get_active() ) + { + m_xPage2Frame3->show(); + m_xPage2_Title_Kiosk->show(); + m_xPage2_ChgDefault->show(); + m_xPage2_ChgAuto->show(); + m_xPage2_Duration_txt->show(); + m_xPage2_Duration->show(); + m_xPage2_Endless->show(); + bool bAuto = m_xPage2_ChgAuto->get_active(); + m_xPage2_Duration->set_sensitive(bAuto); + m_xPage2_Endless->set_sensitive(bAuto); + } + else + { + m_xPage2Frame3->hide(); + m_xPage2_Title_Kiosk->hide(); + m_xPage2_ChgDefault->hide(); + m_xPage2_ChgAuto->hide(); + m_xPage2_Duration->hide(); + m_xPage2_Duration_txt->hide(); + m_xPage2_Endless->hide(); + } + + if( m_xPage2_Standard->get_active() || m_xPage2_Frames->get_active() ) + { + m_xPage2Frame2->show(); + m_xPage2_Title_Html->show(); + m_xPage2_Content->show(); + if(m_bImpress) + m_xPage2_Notes->show(); + } + else + { + m_xPage2Frame2->hide(); + m_xPage2_Title_Html->hide(); + m_xPage2_Content->hide(); + if(m_bImpress) + m_xPage2_Notes->hide(); + } + break; + case 3: + if( m_xPage2_Kiosk->get_active() || m_xPage2_WebCast->get_active() ) + m_xNextPageButton->set_sensitive(false); + + if( m_xPage2_WebCast->get_active() ) + m_xPage3_SldSound->set_sensitive(false); + + m_xPage3_Quality->set_sensitive(m_xPage3_Jpg->get_active()); + + break; + case 5: + if( m_bButtonsDirty ) + LoadPreviewButtons(); + break; + } +} + +/** loads the html buttons from the button sets, creates a preview and fills the + itemset for page 5 + */ +void SdPublishingDlg::LoadPreviewButtons() +{ + if (!m_xButtonSet) + return; + + const int nButtonCount = 8; + static const char *pButtonNames[nButtonCount] = + { + "first.png", + "left.png", + "right.png", + "last.png", + "home.png", + "text.png", + "expand.png", + "collapse.png", + }; + + std::vector< OUString > aButtonNames; + for(const char * p : pButtonNames) + aButtonNames.push_back( OUString::createFromAscii( p ) ); + + int nSetCount = m_xButtonSet->getCount(); + + int nHeight = 32; + Image aImage; + for( int nSet = 0; nSet < nSetCount; ++nSet ) + { + if( m_xButtonSet->getPreview( nSet, aButtonNames, aImage ) ) + { + m_xPage5_Buttons->InsertItem( static_cast<sal_uInt16>(nSet)+1, aImage ); + if( nHeight < aImage.GetSizePixel().Height() ) + nHeight = aImage.GetSizePixel().Height(); + } + } + + m_xPage5_Buttons->SetItemHeight( nHeight ); + m_bButtonsDirty = false; +} + +// Clickhandler for the Forward Button +IMPL_LINK_NOARG(SdPublishingDlg, NextPageHdl, weld::Button&, void) +{ + aAssistentFunc.NextPage(); + ChangePage(); +} + +// Sets the Controls in the dialog to the settings in the design +void SdPublishingDlg::SetDesign( SdPublishingDesign const * pDesign ) +{ + if(!pDesign) + return; + + m_xPage2_Standard->set_sensitive(pDesign->m_eMode == PUBLISH_HTML); + m_xPage2_Frames->set_sensitive(pDesign->m_eMode == PUBLISH_FRAMES); + m_xPage2_Kiosk->set_sensitive(pDesign->m_eMode == PUBLISH_KIOSK ); + m_xPage2_WebCast->set_sensitive(pDesign->m_eMode == PUBLISH_WEBCAST ); + + m_xPage2_Content->set_sensitive(pDesign->m_bContentPage); + if(pDesign->m_bContentPage) + aAssistentFunc.EnablePage(4); + else + aAssistentFunc.DisablePage(4); + + if(m_bImpress) + m_xPage2_Notes->set_sensitive(pDesign->m_bNotes); + + m_xPage2_ASP->set_sensitive(pDesign->m_eScript == SCRIPT_ASP); + m_xPage2_PERL->set_sensitive(pDesign->m_eScript == SCRIPT_PERL); + m_xPage2_CGI->set_text(pDesign->m_aCGI); + m_xPage2_URL->set_text(pDesign->m_aURL); + + m_xPage2_ChgDefault->set_sensitive( !pDesign->m_bAutoSlide ); + m_xPage2_ChgAuto->set_sensitive( pDesign->m_bAutoSlide ); + + tools::Time aTime( tools::Time::EMPTY ); + aTime.MakeTimeFromMS( pDesign->m_nSlideDuration * 1000 ); + m_xFormatter->SetTime(aTime); + + m_xPage2_Endless->set_sensitive( pDesign->m_bEndless ); + + m_xPage3_Png->set_sensitive(pDesign->m_eFormat == FORMAT_PNG); + m_xPage3_Gif->set_sensitive(pDesign->m_eFormat == FORMAT_GIF); + m_xPage3_Jpg->set_sensitive(pDesign->m_eFormat == FORMAT_JPG); + m_xPage3_Quality->set_sensitive(pDesign->m_eFormat == FORMAT_JPG); + + m_xPage3_Quality->set_entry_text(pDesign->m_aCompression); + m_xPage3_Resolution_1->set_sensitive(pDesign->m_nResolution == PUB_LOWRES_WIDTH); + m_xPage3_Resolution_2->set_sensitive(pDesign->m_nResolution == PUB_MEDRES_WIDTH); + m_xPage3_Resolution_3->set_sensitive(pDesign->m_nResolution == PUB_HIGHRES_WIDTH); + m_xPage3_Resolution_4->set_sensitive(pDesign->m_nResolution == PUB_FHDRES_WIDTH); + + m_xPage3_SldSound->set_sensitive( pDesign->m_bSlideSound ); + m_xPage3_HiddenSlides->set_sensitive( pDesign->m_bHiddenSlides ); + + m_xPage4_Author->set_text(pDesign->m_aAuthor); + m_xPage4_Email->set_text(pDesign->m_aEMail); + m_xPage4_WWW->set_text(pDesign->m_aWWW); + m_xPage4_Misc->set_text(pDesign->m_aMisc); + if(m_bImpress) + m_xPage4_Download->set_sensitive(pDesign->m_bDownload); + + m_xPage5_TextOnly->set_sensitive(pDesign->m_nButtonThema == -1); + if(pDesign->m_nButtonThema != -1) + { + if(m_bButtonsDirty) + LoadPreviewButtons(); + m_xPage5_Buttons->SelectItem(pDesign->m_nButtonThema + 1); + } + else + m_xPage5_Buttons->SetNoSelection(); + + m_xPage6_User->set_sensitive(pDesign->m_bUserAttr); + m_aBackColor = pDesign->m_aBackColor; + m_aTextColor = pDesign->m_aTextColor; + m_aLinkColor = pDesign->m_aLinkColor; + m_aVLinkColor = pDesign->m_aVLinkColor; + m_aALinkColor = pDesign->m_aALinkColor; + + m_xPage6_DocColors->set_sensitive(pDesign->m_bUseColor); + + m_xPage6_Preview->SetColors( m_aBackColor, m_aTextColor, m_aLinkColor, + m_aVLinkColor, m_aALinkColor ); + m_xPage6_Preview->Invalidate(); + + UpdatePage(); +} + +// Transfer the status of the Design Dialog Controls +void SdPublishingDlg::GetDesign( SdPublishingDesign* pDesign ) +{ + if(!pDesign) + return; + + pDesign->m_eMode = m_xPage2_Standard->get_active()?PUBLISH_HTML: + m_xPage2_Frames->get_active()?PUBLISH_FRAMES: + m_xPage2_Kiosk->get_active()?PUBLISH_KIOSK: + PUBLISH_WEBCAST; + + pDesign->m_bContentPage = m_xPage2_Content->get_active(); + if(m_bImpress) + pDesign->m_bNotes = m_xPage2_Notes->get_active(); + + if( m_xPage3_Gif->get_active() ) + pDesign->m_eFormat = FORMAT_GIF; + else if( m_xPage3_Jpg->get_active() ) + pDesign->m_eFormat = FORMAT_JPG; + else + pDesign->m_eFormat = FORMAT_PNG; + + pDesign->m_aCompression = m_xPage3_Quality->get_active_text(); + + if (m_xPage3_Resolution_1->get_active()) + pDesign->m_nResolution = PUB_LOWRES_WIDTH; + else if (m_xPage3_Resolution_2->get_active()) + pDesign->m_nResolution = PUB_MEDRES_WIDTH; + else if (m_xPage3_Resolution_3->get_active()) + pDesign->m_nResolution = PUB_HIGHRES_WIDTH; + else + pDesign->m_nResolution = PUB_FHDRES_WIDTH; + + pDesign->m_bSlideSound = m_xPage3_SldSound->get_active(); + pDesign->m_bHiddenSlides = m_xPage3_HiddenSlides->get_active(); + + pDesign->m_aAuthor = m_xPage4_Author->get_text(); + pDesign->m_aEMail = m_xPage4_Email->get_text(); + pDesign->m_aWWW = m_xPage4_WWW->get_text(); + pDesign->m_aMisc = m_xPage4_Misc->get_text(); + pDesign->m_bDownload = m_bImpress && m_xPage4_Download->get_active(); + + if(m_xPage5_TextOnly->get_active()) + pDesign->m_nButtonThema = -1; + else + pDesign->m_nButtonThema = m_xPage5_Buttons->GetSelectedItemId() - 1; + + pDesign->m_bUserAttr = m_xPage6_User->get_active(); + pDesign->m_aBackColor = m_aBackColor; + pDesign->m_aTextColor = m_aTextColor; + pDesign->m_aLinkColor = m_aLinkColor; + pDesign->m_aVLinkColor = m_aVLinkColor; + pDesign->m_aALinkColor = m_aALinkColor; + pDesign->m_bUseColor = m_xPage6_DocColors->get_active(); + + pDesign->m_eScript = m_xPage2_ASP->get_active()?SCRIPT_ASP:SCRIPT_PERL; + pDesign->m_aCGI = m_xPage2_CGI->get_text(); + pDesign->m_aURL = m_xPage2_URL->get_text(); + + pDesign->m_bAutoSlide = m_xPage2_ChgAuto->get_active(); + pDesign->m_nSlideDuration = static_cast<sal_uInt32>(m_xFormatter->GetTime().GetMSFromTime()) / 1000; + pDesign->m_bEndless = m_xPage2_Endless->get_active(); +} + +// Clickhandler for the back Button +IMPL_LINK_NOARG(SdPublishingDlg, LastPageHdl, weld::Button&, void) +{ + aAssistentFunc.PreviousPage(); + ChangePage(); +} + +// Load Designs +void SdPublishingDlg::Load() +{ + m_bDesignListDirty = false; + + INetURLObject aURL( SvtPathOptions().GetUserConfigPath() ); + aURL.Append( u"designs.sod" ); + + // check if file exists, SfxMedium shows an errorbox else + { + std::unique_ptr<SvStream> pIStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ); + + bool bOk = pIStm && ( pIStm->GetError() == ERRCODE_NONE); + + if( !bOk ) + return; + } + + SfxMedium aMedium( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ | StreamMode::NOCREATE ); + + SvStream* pStream = aMedium.GetInStream(); + + if( !pStream ) + return; + + sal_uInt16 aCheck; + pStream->ReadUInt16( aCheck ); + + if(aCheck != nMagic) + return; + + SdIOCompat aIO(*pStream, StreamMode::READ); + + sal_uInt16 nDesigns(0); + pStream->ReadUInt16(nDesigns); + + // there has to at least be a sal_uInt16 header in each design + const size_t nMaxRecords = pStream->remainingSize() / sizeof(sal_uInt16); + if (nDesigns > nMaxRecords) + { + SAL_WARN("sd", "Parsing error: " << nMaxRecords << + " max possible entries, but " << nDesigns << " claimed, truncating"); + nDesigns = nMaxRecords; + } + + for( sal_uInt16 nIndex = 0; + pStream->GetError() == ERRCODE_NONE && nIndex < nDesigns; + nIndex++ ) + { + SdPublishingDesign aDesign; + *pStream >> aDesign; + + m_aDesignList.push_back(aDesign); + } +} + +// Save Designs +bool SdPublishingDlg::Save() +{ + INetURLObject aURL( SvtPathOptions().GetUserConfigPath() ); + aURL.Append( u"designs.sod" ); + SfxMedium aMedium( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::WRITE | StreamMode::TRUNC ); + + SvStream* pStream = aMedium.GetOutStream(); + + if( !pStream ) + return false; + + pStream->WriteUInt16( nMagic ); + + // Destroys the SdIOCompat before the Stream is being distributed + { + SdIOCompat aIO(*pStream, StreamMode::WRITE, 0); + + sal_uInt16 nDesigns = static_cast<sal_uInt16>(m_aDesignList.size()); + pStream->WriteUInt16( nDesigns ); + + for( sal_uInt16 nIndex = 0; + pStream->GetError() == ERRCODE_NONE && nIndex < nDesigns; + nIndex++ ) + WriteSdPublishingDesign( *pStream, m_aDesignList[nIndex] ); + } + + aMedium.Close(); + aMedium.Commit(); + + return( aMedium.GetError() == ERRCODE_NONE ); +} + +// SdDesignNameDlg Methods +SdDesignNameDlg::SdDesignNameDlg(weld::Window* pWindow, const OUString& rName) + : GenericDialogController(pWindow, "modules/sdraw/ui/namedesign.ui", "NameDesignDialog") + , m_xEdit(m_xBuilder->weld_entry("entry")) + , m_xBtnOK(m_xBuilder->weld_button("ok")) +{ + m_xEdit->connect_changed(LINK(this, SdDesignNameDlg, ModifyHdl )); + m_xEdit->set_text(rName); + m_xBtnOK->set_sensitive(!rName.isEmpty()); +} + +OUString SdDesignNameDlg::GetDesignName() const +{ + return m_xEdit->get_text(); +} + +IMPL_LINK_NOARG(SdDesignNameDlg, ModifyHdl, weld::Entry&, void) +{ + m_xBtnOK->set_sensitive(!m_xEdit->get_text().isEmpty()); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sd/source/filter/html/sdhtmlfilter.cxx b/sd/source/filter/html/sdhtmlfilter.cxx new file mode 100644 index 000000000..f7a3bc10f --- /dev/null +++ b/sd/source/filter/html/sdhtmlfilter.cxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sfx2/docfile.hxx> +#include <sfx2/frame.hxx> +#include <sfx2/sfxsids.hrc> + +#include "htmlex.hxx" +#include <sdhtmlfilter.hxx> + +SdHTMLFilter::SdHTMLFilter(SfxMedium& rMedium, ::sd::DrawDocShell& rDocShell) + : SdFilter(rMedium, rDocShell) +{ +} + +SdHTMLFilter::~SdHTMLFilter() {} + +bool SdHTMLFilter::Export() +{ + mrMedium.Close(); + mrMedium.Commit(); + + SfxItemSet* pSet = mrMedium.GetItemSet(); + + css::uno::Sequence<css::beans::PropertyValue> aParams; + + if (const SfxUnoAnyItem* pItem = pSet->GetItemIfSet(SID_FILTER_DATA, false)) + pItem->GetValue() >>= aParams; + + HtmlExport aExport(mrMedium.GetName(), aParams, &mrDocument, &mrDocShell); + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |