1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
22 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
23 #include <com/sun/star/frame/XModel.hpp>
24 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
26 #include <sal/log.hxx>
27 #include <rtl/tencinfo.h>
28 #include <comphelper/processfactory.hxx>
29 #include <comphelper/propertyvalue.hxx>
30 #include <comphelper/xmlencode.hxx>
31 #include <o3tl/safeint.hxx>
32 #include <osl/file.hxx>
33 #include <unotools/pathoptions.hxx>
34 #include <unotools/ucbstreamhelper.hxx>
35 #include <com/sun/star/frame/XStorable.hpp>
36 #include <sfx2/frmhtmlw.hxx>
37 #include <sfx2/progress.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/weld.hxx>
41 #include <svx/svditer.hxx>
42 #include <vcl/imaprect.hxx>
43 #include <vcl/imapcirc.hxx>
44 #include <vcl/imappoly.hxx>
45 #include <editeng/eeitem.hxx>
46 #include <editeng/outlobj.hxx>
47 #include <editeng/editobj.hxx>
48 #include <svx/svdopath.hxx>
49 #include <svtools/htmlout.hxx>
50 #include <svtools/colorcfg.hxx>
51 #include <editeng/colritem.hxx>
52 #include <editeng/editeng.hxx>
53 #include <editeng/wghtitem.hxx>
54 #include <editeng/udlnitem.hxx>
55 #include <editeng/postitem.hxx>
56 #include <editeng/crossedoutitem.hxx>
57 #include <editeng/flditem.hxx>
58 #include <svl/style.hxx>
59 #include <editeng/frmdiritem.hxx>
60 #include <svx/svdoutl.hxx>
61 #include <svx/svdogrp.hxx>
62 #include <svx/svdotable.hxx>
63 #include <svx/ImageMapInfo.hxx>
64 #include <tools/urlobj.hxx>
65 #include <svtools/sfxecode.hxx>
66 #include <basegfx/polygon/b2dpolygon.hxx>
67 #include <tools/debug.hxx>
68 #include <comphelper/diagnose_ex.hxx>
70 #include <drawdoc.hxx>
71 #include <DrawDocShell.hxx>
72 #include "htmlpublishmode.hxx"
73 #include <Outliner.hxx>
75 #include <strings.hrc>
76 #include <strings.hxx>
77 #include <anminfo.hxx>
78 #include <sdresid.hxx>
79 #include "buttonset.hxx"
81 using namespace ::com::sun::star
;
82 using namespace ::com::sun::star::uno
;
83 using namespace ::com::sun::star::beans
;
84 using namespace ::com::sun::star::frame
;
85 using namespace ::com::sun::star::lang
;
86 using namespace ::com::sun::star::document
;
88 using namespace sdr::table
;
90 // get parameter from Itemset
91 #define RESTOHTML( res ) StringToHTMLString(SdResId(res))
93 const char * const pButtonNames
[] =
109 #define BTN_FIRST_0 0
110 #define BTN_FIRST_1 1
124 // Helper class for the simple creation of files local/remote
128 std::unique_ptr
<SvStream
> pOStm
;
136 ErrCode
createStream( const OUString
& rUrl
, SvStream
*& rpStr
);
137 void createFileName( const OUString
& rUrl
, OUString
& rFileName
);
143 // Helper class for the embedding of text attributes into the html output
159 explicit HtmlState( Color aDefColor
);
161 OUString
SetWeight( bool bWeight
);
162 OUString
SetItalic( bool bItalic
);
163 OUString
SetUnderline( bool bUnderline
);
164 OUString
SetColor( Color aColor
);
165 OUString
SetStrikeout( bool bStrike
);
166 OUString
SetLink( const OUString
& aLink
, const OUString
& aTarget
);
170 // close all still open tags
171 OUString
HtmlState::Flush()
173 OUString aStr
= SetWeight(false)
175 + SetUnderline(false)
176 + SetStrikeout(false)
177 + SetColor(maDefColor
)
183 // c'tor with default color for the page
184 HtmlState::HtmlState( Color aDefColor
)
191 maDefColor(aDefColor
)
195 // enables/disables bold print
196 OUString
HtmlState::SetWeight( bool bWeight
)
200 if(bWeight
&& !mbWeight
)
202 else if(!bWeight
&& mbWeight
)
209 // enables/disables italic
211 OUString
HtmlState::SetItalic( bool bItalic
)
215 if(bItalic
&& !mbItalic
)
217 else if(!bItalic
&& mbItalic
)
224 // enables/disables underlines
226 OUString
HtmlState::SetUnderline( bool bUnderline
)
230 if(bUnderline
&& !mbUnderline
)
232 else if(!bUnderline
&& mbUnderline
)
235 mbUnderline
= bUnderline
;
239 // enables/disables strike through
240 OUString
HtmlState::SetStrikeout( bool bStrike
)
244 if(bStrike
&& !mbStrike
)
246 else if(!bStrike
&& mbStrike
)
253 // Sets the specified text color
254 OUString
HtmlState::SetColor( Color aColor
)
258 if(mbColor
&& aColor
== maColor
)
267 if(aColor
!= maDefColor
)
270 aStr
+= "<font color=\"" + HtmlExport::ColorToHTMLString(aColor
) + "\">";
277 // enables/disables a hyperlink
278 OUString
HtmlState::SetLink( const OUString
& aLink
, const OUString
& aTarget
)
282 if(mbLink
&&maLink
== aLink
&&maTarget
==aTarget
)
291 if (!aLink
.isEmpty())
293 aStr
+= "<a href=\"" + comphelper::string::encodeForXml(aLink
);
294 if (!aTarget
.isEmpty())
296 aStr
+= "\" target=\"" + comphelper::string::encodeForXml(aTarget
);
309 OUString
getParagraphStyle( const SdrOutliner
* pOutliner
, sal_Int32 nPara
)
311 SfxItemSet
aParaSet( pOutliner
->GetParaAttribs( nPara
) );
315 if( aParaSet
.GetItem
<SvxFrameDirectionItem
>( EE_PARA_WRITINGDIR
)->GetValue() == SvxFrameDirection::Horizontal_RL_TB
)
318 sStyle
= "direction: rtl;";
322 // This is the default so don't write it out
323 // sStyle += "direction: ltr;";
328 void lclAppendStyle(OUStringBuffer
& aBuffer
, std::u16string_view aTag
, std::u16string_view aStyle
)
331 aBuffer
.append(OUString::Concat("<") + aTag
+ ">");
333 aBuffer
.append(OUString::Concat("<") + aTag
+ " style=\"" + aStyle
+ "\">");
336 } // anonymous namespace
338 constexpr OUStringLiteral
gaHTMLHeader(
339 u
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
340 " \"http://www.w3.org/TR/html4/transitional.dtd\">\r\n"
341 "<html>\r\n<head>\r\n" );
343 constexpr OUStringLiteral gaHTMLExtension
= u
"" STR_HTMLEXP_DEFAULT_EXTENSION
;
345 // constructor for the html export helper classes
346 HtmlExport::HtmlExport(
348 const Sequence
< PropertyValue
>& rParams
,
349 SdDrawDocument
* pExpDoc
,
350 sd::DrawDocShell
* pDocShell
)
351 : maPath(std::move( aPath
)),
353 mpDocSh( pDocShell
),
354 meMode( PUBLISH_SINGLE_DOCUMENT
),
355 mbContentsPage(false),
357 mnWidthPixel( PUB_MEDRES_WIDTH
),
358 meFormat( FORMAT_JPG
),
363 mbHiddenSlides(true),
365 maTextColor(COL_BLACK
),
366 maBackColor(COL_WHITE
),
369 meScript( SCRIPT_ASP
),
370 mpButtonSet( new ButtonSet() )
372 bool bChange
= mpDoc
->IsChanged();
374 maIndexUrl
+= gaHTMLExtension
;
376 InitExportParameters( rParams
);
384 case PUBLISH_WEBCAST
:
390 case PUBLISH_SINGLE_DOCUMENT
:
391 ExportSingleDocument();
395 mpDoc
->SetChanged(bChange
);
398 HtmlExport::~HtmlExport()
402 // get common export parameters from item set
403 void HtmlExport::InitExportParameters( const Sequence
< PropertyValue
>& rParams
)
405 mbImpress
= mpDoc
->GetDocumentType() == DocumentType::Impress
;
408 for( const PropertyValue
& rParam
: rParams
)
410 if ( rParam
.Name
== "PublishMode" )
413 rParam
.Value
>>= temp
;
414 meMode
= static_cast<HtmlPublishMode
>(temp
);
416 else if ( rParam
.Name
== "IndexURL" )
418 rParam
.Value
>>= aStr
;
421 else if ( rParam
.Name
== "Format" )
424 rParam
.Value
>>= temp
;
425 meFormat
= static_cast<PublishingFormat
>(temp
);
427 else if ( rParam
.Name
== "Compression" )
429 rParam
.Value
>>= aStr
;
430 OUString
aTmp( aStr
);
433 aTmp
= aTmp
.replaceFirst("%", "");
434 mnCompression
= static_cast<sal_Int16
>(aTmp
.toInt32());
437 else if ( rParam
.Name
== "Width" )
440 rParam
.Value
>>= temp
;
441 mnWidthPixel
= static_cast<sal_uInt16
>(temp
);
443 else if ( rParam
.Name
== "UseButtonSet" )
446 rParam
.Value
>>= temp
;
447 mnButtonThema
= static_cast<sal_Int16
>(temp
);
449 else if ( rParam
.Name
== "IsExportNotes" )
454 rParam
.Value
>>= temp
;
458 else if ( rParam
.Name
== "IsExportContentsPage" )
461 rParam
.Value
>>= temp
;
462 mbContentsPage
= temp
;
464 else if ( rParam
.Name
== "Author" )
466 rParam
.Value
>>= aStr
;
469 else if ( rParam
.Name
== "EMail" )
471 rParam
.Value
>>= aStr
;
474 else if ( rParam
.Name
== "HomepageURL" )
476 rParam
.Value
>>= aStr
;
479 else if ( rParam
.Name
== "UserText" )
481 rParam
.Value
>>= aStr
;
484 else if ( rParam
.Name
== "EnableDownload" )
487 rParam
.Value
>>= temp
;
490 else if ( rParam
.Name
== "SlideSound" )
493 rParam
.Value
>>= temp
;
496 else if ( rParam
.Name
== "HiddenSlides" )
499 rParam
.Value
>>= temp
;
500 mbHiddenSlides
= temp
;
502 else if ( rParam
.Name
== "BackColor" )
505 rParam
.Value
>>= temp
;
509 else if ( rParam
.Name
== "TextColor" )
512 rParam
.Value
>>= temp
;
516 else if ( rParam
.Name
== "LinkColor" )
519 rParam
.Value
>>= temp
;
523 else if ( rParam
.Name
== "VLinkColor" )
526 rParam
.Value
>>= temp
;
530 else if ( rParam
.Name
== "ALinkColor" )
533 rParam
.Value
>>= temp
;
537 else if ( rParam
.Name
== "IsUseDocumentColors" )
540 rParam
.Value
>>= temp
;
543 else if ( rParam
.Name
== "KioskSlideDuration" )
546 rParam
.Value
>>= temp
;
547 mfSlideDuration
= temp
;
550 else if ( rParam
.Name
== "KioskEndless" )
553 rParam
.Value
>>= temp
;
556 else if ( rParam
.Name
== "WebCastCGIURL" )
558 rParam
.Value
>>= aStr
;
561 else if ( rParam
.Name
== "WebCastTargetURL" )
563 rParam
.Value
>>= aStr
;
566 else if ( rParam
.Name
== "WebCastScriptLanguage" )
568 rParam
.Value
>>= aStr
;
571 meScript
= SCRIPT_ASP
;
575 meScript
= SCRIPT_PERL
;
580 OSL_FAIL("Unknown property for html export detected!");
584 if( meMode
== PUBLISH_KIOSK
)
586 mbContentsPage
= false;
591 // calculate image sizes
592 SdPage
* pPage
= mpDoc
->GetSdPage(0, PageKind::Standard
);
593 Size
aTmpSize( pPage
->GetSize() );
594 double dRatio
=static_cast<double>(aTmpSize
.Width())/aTmpSize
.Height();
596 mnHeightPixel
= static_cast<sal_uInt16
>(mnWidthPixel
/dRatio
);
598 // we come up with a destination...
600 INetURLObject
aINetURLObj( maPath
);
601 DBG_ASSERT( aINetURLObj
.GetProtocol() != INetProtocol::NotValid
, "invalid URL" );
603 maExportPath
= aINetURLObj
.GetPartBeforeLastName(); // with trailing '/'
604 maIndex
= aINetURLObj
.GetLastName();
606 mnSdPageCount
= mpDoc
->GetSdPageCount( PageKind::Standard
);
607 for( sal_uInt16 nPage
= 0; nPage
< mnSdPageCount
; nPage
++ )
609 pPage
= mpDoc
->GetSdPage( nPage
, PageKind::Standard
);
611 if( mbHiddenSlides
|| !pPage
->IsExcluded() )
613 maPages
.push_back( pPage
);
614 maNotesPages
.push_back( mpDoc
->GetSdPage( nPage
, PageKind::Notes
) );
617 mnSdPageCount
= maPages
.size();
619 mbFrames
= meMode
== PUBLISH_FRAMES
;
621 maDocFileName
= maIndex
;
624 void HtmlExport::ExportSingleDocument()
626 SdrOutliner
* pOutliner
= mpDoc
->GetInternalOutliner();
628 maPageNames
.resize(mnSdPageCount
);
631 InitProgress(mnSdPageCount
);
633 OUStringBuffer
aStr(gaHTMLHeader
639 for(sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
; ++nSdPage
)
641 SdPage
* pPage
= maPages
[nSdPage
];
642 maPageNames
[nSdPage
] = pPage
->GetName();
646 SetDocColors( pPage
);
650 OUString
sTitleText(CreateTextForTitle(pOutliner
, pPage
, pPage
->GetPageBackgroundColor()));
653 if (nSdPage
!= 0) // First page - no need for a page break here
654 sStyle
+= "page-break-before:always; ";
655 sStyle
+= getParagraphStyle(pOutliner
, 0);
657 lclAppendStyle(aStr
, u
"h1", sStyle
);
659 aStr
.append(sTitleText
+ "</h1>\r\n");
661 // write outline text
662 aStr
.append(CreateTextForPage( pOutliner
, pPage
, true, pPage
->GetPageBackgroundColor() ));
667 SdPage
* pNotesPage
= maNotesPages
[ nSdPage
];
668 OUString
aNotesStr( CreateTextForNotesPage( pOutliner
, pNotesPage
, maBackColor
) );
670 if (!aNotesStr
.isEmpty())
672 aStr
.append("<br>\r\n<h3>"
673 + RESTOHTML(STR_HTMLEXP_NOTES
)
680 mpProgress
->SetState(++mnPagesWritten
);
685 aStr
.append("</body>\r\n</html>");
687 WriteHtml(maDocFileName
, false, aStr
);
693 // exports the (in the c'tor specified impress document) to html
694 void HtmlExport::ExportHtml()
698 if( maTextColor
== COL_AUTO
)
700 if( !maBackColor
.IsDark() )
701 maTextColor
= COL_BLACK
;
704 else if( mbDocColors
)
706 // default colors for the color schema 'From Document'
708 maFirstPageColor
= maBackColor
;
711 // get name for downloadable presentation if needed
714 // fade out separator search and extension
715 sal_Int32 nSepPos
= maDocFileName
.indexOf('.');
717 maDocFileName
= maDocFileName
.copy(0, nSepPos
);
719 maDocFileName
+= ".odp";
722 sal_uInt16 nProgrCount
= mnSdPageCount
;
723 nProgrCount
+= mbImpress
?mnSdPageCount
:0;
724 nProgrCount
+= mbContentsPage
?1:0;
725 nProgrCount
+= (mbFrames
&& mbNotes
)?mnSdPageCount
:0;
726 nProgrCount
+= mbFrames
? 8 : 0;
727 InitProgress( nProgrCount
);
729 mpDocSh
->SetWaitCursor( true );
731 // Exceptions are cool...
735 // this is not a true while
738 if( checkForExistingFiles() )
741 if( !CreateImagesForPresPages() )
744 if( mbContentsPage
&&
745 !CreateImagesForPresPages( true ) )
748 if( !CreateHtmlForPresPages() )
752 if( !CreateHtmlTextForPresPages() )
757 if( !CreateFrames() )
760 if( !CreateOutlinePages() )
763 if( !CreateNavBarFrames() )
766 if( mbNotes
&& mbImpress
)
767 if( !CreateNotesPages() )
773 if( !CreateContentPage() )
778 mpDocSh
->SetWaitCursor( false );
787 // if we get to this point the export was
788 // canceled by the user after an error
789 mpDocSh
->SetWaitCursor( false );
793 void HtmlExport::SetDocColors( SdPage
* pPage
)
795 if( pPage
== nullptr )
796 pPage
= mpDoc
->GetSdPage(0, PageKind::Standard
);
798 svtools::ColorConfig aConfig
;
799 maVLinkColor
= aConfig
.GetColorValue(svtools::LINKSVISITED
).nColor
;
800 maALinkColor
= aConfig
.GetColorValue(svtools::LINKS
).nColor
;
801 maLinkColor
= aConfig
.GetColorValue(svtools::LINKS
).nColor
;
802 maTextColor
= COL_BLACK
;
804 SfxStyleSheet
* pSheet
= nullptr;
806 if( mpDoc
->GetDocumentType() == DocumentType::Impress
)
808 // default text color from the outline template of the first page
809 pSheet
= pPage
->GetStyleSheetForPresObj(PresObjKind::Outline
);
810 if(pSheet
== nullptr)
811 pSheet
= pPage
->GetStyleSheetForPresObj(PresObjKind::Text
);
812 if(pSheet
== nullptr)
813 pSheet
= pPage
->GetStyleSheetForPresObj(PresObjKind::Title
);
816 if(pSheet
== nullptr)
817 pSheet
= mpDoc
->GetDefaultStyleSheet();
821 SfxItemSet
& rSet
= pSheet
->GetItemSet();
822 if(rSet
.GetItemState(EE_CHAR_COLOR
) == SfxItemState::SET
)
823 maTextColor
= rSet
.GetItem
<SvxColorItem
>(EE_CHAR_COLOR
)->GetValue();
826 // default background from the background of the master page of the first page
827 maBackColor
= pPage
->GetPageBackgroundColor();
829 if( maTextColor
== COL_AUTO
)
831 if( !maBackColor
.IsDark() )
832 maTextColor
= COL_BLACK
;
836 void HtmlExport::InitProgress( sal_uInt16 nProgrCount
)
838 mpProgress
.reset(new SfxProgress( mpDocSh
, SdResId(STR_CREATE_PAGES
), nProgrCount
));
841 void HtmlExport::ResetProgress()
846 void HtmlExport::ExportKiosk()
849 InitProgress( 2*mnSdPageCount
);
852 if( !checkForExistingFiles() )
854 if( CreateImagesForPresPages() )
855 CreateHtmlForPresPages();
861 // Export Document with WebCast (TM) Technology
862 void HtmlExport::ExportWebCast()
865 InitProgress( mnSdPageCount
+ 9 );
867 mpDocSh
->SetWaitCursor( true );
871 if (maCGIPath
.isEmpty())
874 if (!maCGIPath
.endsWith("/"))
877 if( meScript
== SCRIPT_ASP
)
883 if (maURLPath
.isEmpty())
886 if (!maURLPath
.endsWith("/"))
890 // this is not a true while
893 if( checkForExistingFiles() )
896 if(!CreateImagesForPresPages())
899 if( meScript
== SCRIPT_ASP
)
901 if(!CreateASPScripts())
906 if(!CreatePERLScripts())
910 if(!CreateImageFileList())
913 if(!CreateImageNumberFile())
919 mpDocSh
->SetWaitCursor( false );
923 // Save the presentation as a downloadable file in the dest directory
924 bool HtmlExport::SavePresentation()
926 meEC
.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE
, maDocFileName
);
928 OUString
aURL(maExportPath
+ maDocFileName
);
930 mpDocSh
->EnableSetModified();
934 uno::Reference
< frame::XStorable
> xStorable( mpDoc
->getUnoModel(), uno::UNO_QUERY
);
937 uno::Sequence
< beans::PropertyValue
> aProperties
{
938 comphelper::makePropertyValue("Overwrite", true),
939 comphelper::makePropertyValue("FilterName", OUString("impress8"))
941 xStorable
->storeToURL( aURL
, aProperties
);
943 mpDocSh
->EnableSetModified( false );
952 mpDocSh
->EnableSetModified( false );
957 // create image files
958 bool HtmlExport::CreateImagesForPresPages( bool bThumbnail
)
962 Reference
< XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
964 Reference
< drawing::XGraphicExportFilter
> xGraphicExporter
= drawing::GraphicExportFilter::create( xContext
);
966 Sequence
< PropertyValue
> aFilterData(((meFormat
==FORMAT_JPG
)&&(mnCompression
!= -1))? 3 : 2);
967 auto pFilterData
= aFilterData
.getArray();
968 pFilterData
[0].Name
= "PixelWidth";
969 pFilterData
[0].Value
<<= static_cast<sal_Int32
>(bThumbnail
? PUB_THUMBNAIL_WIDTH
: mnWidthPixel
);
970 pFilterData
[1].Name
= "PixelHeight";
971 pFilterData
[1].Value
<<= static_cast<sal_Int32
>(bThumbnail
? PUB_THUMBNAIL_HEIGHT
: mnHeightPixel
);
972 if((meFormat
==FORMAT_JPG
)&&(mnCompression
!= -1))
974 pFilterData
[2].Name
= "Quality";
975 pFilterData
[2].Value
<<= static_cast<sal_Int32
>(mnCompression
);
979 if( meFormat
== FORMAT_PNG
)
981 else if( meFormat
== FORMAT_GIF
)
986 Sequence
< PropertyValue
> aDescriptor
{
987 comphelper::makePropertyValue("URL", Any()),
988 comphelper::makePropertyValue("FilterName", sFormat
),
989 comphelper::makePropertyValue("FilterData", aFilterData
)
991 auto pDescriptor
= aDescriptor
.getArray();
993 for (sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
; nSdPage
++)
995 SdPage
* pPage
= maPages
[ nSdPage
];
997 OUString
aFull(maExportPath
);
999 aFull
+= maThumbnailFiles
[nSdPage
];
1001 aFull
+= maImageFiles
[nSdPage
];
1003 pDescriptor
[0].Value
<<= aFull
;
1005 Reference
< XComponent
> xPage( pPage
->getUnoPage(), UNO_QUERY
);
1006 xGraphicExporter
->setSourceDocument( xPage
);
1007 xGraphicExporter
->filter( aDescriptor
);
1010 mpProgress
->SetState(++mnPagesWritten
);
1021 // get SdrTextObject with layout text of this page
1022 SdrTextObj
* HtmlExport::GetLayoutTextObject(SdrPage
const * pPage
)
1024 const size_t nObjectCount
= pPage
->GetObjCount();
1025 SdrTextObj
* pResult
= nullptr;
1027 for (size_t nObject
= 0; nObject
< nObjectCount
; ++nObject
)
1029 SdrObject
* pObject
= pPage
->GetObj(nObject
);
1030 if (pObject
->GetObjInventor() == SdrInventor::Default
&&
1031 pObject
->GetObjIdentifier() == SdrObjKind::OutlineText
)
1033 pResult
= static_cast<SdrTextObj
*>(pObject
);
1040 // create HTML text version of impress pages
1041 OUString
HtmlExport::CreateMetaCharset()
1044 const char *pCharSet
= rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8
);
1047 aStr
= " <meta HTTP-EQUIV=CONTENT-TYPE CONTENT=\"text/html; charset=" +
1048 OUString::createFromAscii(pCharSet
) + "\">\r\n";
1053 OUString
HtmlExport::DocumentMetadata() const
1055 SvMemoryStream aStream
;
1057 uno::Reference
<document::XDocumentProperties
> xDocProps
;
1060 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1061 mpDocSh
->GetModel(), uno::UNO_QUERY_THROW
);
1062 xDocProps
.set(xDPS
->getDocumentProperties());
1065 SfxFrameHTMLWriter::Out_DocInfo(aStream
, maDocFileName
, xDocProps
,
1068 const sal_uInt64 nLen
= aStream
.GetSize();
1069 OSL_ENSURE(nLen
< o3tl::make_unsigned(SAL_MAX_INT32
), "Stream can't fit in OString");
1070 std::string_view
aData(static_cast<const char*>(aStream
.GetData()), static_cast<sal_Int32
>(nLen
));
1072 return OStringToOUString(aData
, RTL_TEXTENCODING_UTF8
);
1075 bool HtmlExport::CreateHtmlTextForPresPages()
1079 SdrOutliner
* pOutliner
= mpDoc
->GetInternalOutliner();
1081 for(sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
&& bOk
; nSdPage
++)
1083 SdPage
* pPage
= maPages
[ nSdPage
];
1087 SetDocColors( pPage
);
1091 OUStringBuffer
aStr(gaHTMLHeader
1092 + CreateMetaCharset()
1094 + StringToHTMLString(maPageNames
[nSdPage
])
1100 aStr
.append(CreateNavBar(nSdPage
, true));
1103 OUString
sTitleText( CreateTextForTitle(pOutliner
,pPage
, pPage
->GetPageBackgroundColor()) );
1104 lclAppendStyle(aStr
, u
"h1", getParagraphStyle(pOutliner
, 0));
1105 aStr
.append(sTitleText
+ "</h1>\r\n");
1107 // write outline text
1108 aStr
.append(CreateTextForPage( pOutliner
, pPage
, true, pPage
->GetPageBackgroundColor() ));
1113 SdPage
* pNotesPage
= maNotesPages
[ nSdPage
];
1114 OUString
aNotesStr( CreateTextForNotesPage( pOutliner
, pNotesPage
, maBackColor
) );
1116 if (!aNotesStr
.isEmpty())
1118 aStr
.append("<br>\r\n<h3>"
1119 + RESTOHTML(STR_HTMLEXP_NOTES
)
1126 aStr
.append("</body>\r\n</html>");
1128 bOk
= WriteHtml(maTextFiles
[nSdPage
], false, aStr
);
1131 mpProgress
->SetState(++mnPagesWritten
);
1140 /** exports the given html data into a non unicode file in the current export path with
1141 the given filename */
1142 bool HtmlExport::WriteHtml( const OUString
& rFileName
, bool bAddExtension
, std::u16string_view rHtmlData
)
1144 ErrCode nErr
= ERRCODE_NONE
;
1146 OUString
aFileName( rFileName
);
1148 aFileName
+= gaHTMLExtension
;
1150 meEC
.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE
, rFileName
);
1153 OUString
aFull(maExportPath
+ aFileName
);
1154 nErr
= aFile
.createStream(aFull
, pStr
);
1155 if(nErr
== ERRCODE_NONE
)
1157 OString
aStr(OUStringToOString(rHtmlData
, RTL_TEXTENCODING_UTF8
));
1158 pStr
->WriteOString( aStr
);
1162 if( nErr
!= ERRCODE_NONE
)
1163 ErrorHandler::HandleError(nErr
);
1165 return nErr
== ERRCODE_NONE
;
1168 /** creates an outliner text for the title objects of a page
1170 OUString
HtmlExport::CreateTextForTitle( SdrOutliner
* pOutliner
, SdPage
* pPage
, const Color
& rBackgroundColor
)
1172 SdrTextObj
* pTO
= static_cast<SdrTextObj
*>(pPage
->GetPresObj(PresObjKind::Title
));
1174 pTO
= GetLayoutTextObject(pPage
);
1176 if (pTO
&& !pTO
->IsEmptyPresObj())
1178 OutlinerParaObject
* pOPO
= pTO
->GetOutlinerParaObject();
1179 if(pOPO
&& pOutliner
->GetParagraphCount() != 0)
1182 pOutliner
->SetText(*pOPO
);
1183 return ParagraphToHTMLString(pOutliner
,0, rBackgroundColor
);
1190 // creates an outliner text for a page
1191 OUString
HtmlExport::CreateTextForPage(SdrOutliner
* pOutliner
, SdPage
const * pPage
,
1192 bool bHeadLine
, const Color
& rBackgroundColor
)
1194 OUStringBuffer aStr
;
1196 for (size_t i
= 0; i
<pPage
->GetObjCount(); ++i
)
1198 SdrObject
* pObject
= pPage
->GetObj(i
);
1199 PresObjKind eKind
= pPage
->GetPresObjKind(pObject
);
1203 case PresObjKind::NONE
:
1205 if (pObject
->GetObjIdentifier() == SdrObjKind::Group
)
1207 SdrObjGroup
* pObjectGroup
= static_cast<SdrObjGroup
*>(pObject
);
1208 WriteObjectGroup(aStr
, pObjectGroup
, pOutliner
, rBackgroundColor
, false);
1210 else if (pObject
->GetObjIdentifier() == SdrObjKind::Table
)
1212 SdrTableObj
* pTableObject
= static_cast<SdrTableObj
*>(pObject
);
1213 WriteTable(aStr
, pTableObject
, pOutliner
, rBackgroundColor
);
1217 if (pObject
->GetOutlinerParaObject())
1219 WriteOutlinerParagraph(aStr
, pOutliner
, pObject
->GetOutlinerParaObject(), rBackgroundColor
, false);
1225 case PresObjKind::Table
:
1227 SdrTableObj
* pTableObject
= static_cast<SdrTableObj
*>(pObject
);
1228 WriteTable(aStr
, pTableObject
, pOutliner
, rBackgroundColor
);
1232 case PresObjKind::Text
:
1233 case PresObjKind::Outline
:
1235 SdrTextObj
* pTextObject
= static_cast<SdrTextObj
*>(pObject
);
1236 if (pTextObject
->IsEmptyPresObj())
1238 WriteOutlinerParagraph(aStr
, pOutliner
, pTextObject
->GetOutlinerParaObject(), rBackgroundColor
, bHeadLine
);
1246 return aStr
.makeStringAndClear();
1249 void HtmlExport::WriteTable(OUStringBuffer
& aStr
, SdrTableObj
const * pTableObject
, SdrOutliner
* pOutliner
, const Color
& rBackgroundColor
)
1251 CellPos aStart
, aEnd
;
1253 aStart
= SdrTableObj::getFirstCell();
1254 aEnd
= pTableObject
->getLastCell();
1256 sal_Int32 nColCount
= pTableObject
->getColumnCount();
1257 aStr
.append("<table>\r\n");
1258 for (sal_Int32 nRow
= aStart
.mnRow
; nRow
<= aEnd
.mnRow
; nRow
++)
1260 aStr
.append(" <tr>\r\n");
1261 for (sal_Int32 nCol
= aStart
.mnCol
; nCol
<= aEnd
.mnCol
; nCol
++)
1263 aStr
.append(" <td>\r\n");
1264 sal_Int32 nCellIndex
= nRow
* nColCount
+ nCol
;
1265 SdrText
* pText
= pTableObject
->getText(nCellIndex
);
1267 if (pText
== nullptr)
1269 WriteOutlinerParagraph(aStr
, pOutliner
, pText
->GetOutlinerParaObject(), rBackgroundColor
, false);
1270 aStr
.append(" </td>\r\n");
1272 aStr
.append(" </tr>\r\n");
1274 aStr
.append("</table>\r\n");
1277 void HtmlExport::WriteObjectGroup(OUStringBuffer
& aStr
, SdrObjGroup
const * pObjectGroup
, SdrOutliner
* pOutliner
,
1278 const Color
& rBackgroundColor
, bool bHeadLine
)
1280 SdrObjListIter
aGroupIterator(pObjectGroup
->GetSubList(), SdrIterMode::DeepNoGroups
);
1281 while (aGroupIterator
.IsMore())
1283 SdrObject
* pCurrentObject
= aGroupIterator
.Next();
1284 if (pCurrentObject
->GetObjIdentifier() == SdrObjKind::Group
)
1286 SdrObjGroup
* pCurrentGroupObject
= static_cast<SdrObjGroup
*>(pCurrentObject
);
1287 WriteObjectGroup(aStr
, pCurrentGroupObject
, pOutliner
, rBackgroundColor
, bHeadLine
);
1291 OutlinerParaObject
* pOutlinerParagraphObject
= pCurrentObject
->GetOutlinerParaObject();
1292 if (pOutlinerParagraphObject
!= nullptr)
1294 WriteOutlinerParagraph(aStr
, pOutliner
, pOutlinerParagraphObject
, rBackgroundColor
, bHeadLine
);
1300 void HtmlExport::WriteOutlinerParagraph(OUStringBuffer
& aStr
, SdrOutliner
* pOutliner
,
1301 OutlinerParaObject
const * pOutlinerParagraphObject
,
1302 const Color
& rBackgroundColor
, bool bHeadLine
)
1304 if (pOutlinerParagraphObject
== nullptr)
1307 pOutliner
->SetText(*pOutlinerParagraphObject
);
1309 sal_Int32 nCount
= pOutliner
->GetParagraphCount();
1312 sal_Int16 nCurrentDepth
= -1;
1314 for (sal_Int32 nIndex
= 0; nIndex
< nCount
; nIndex
++)
1316 Paragraph
* pParagraph
= pOutliner
->GetParagraph(nIndex
);
1317 if(pParagraph
== nullptr)
1320 const sal_Int16 nDepth
= static_cast<sal_uInt16
>(pOutliner
->GetDepth(nIndex
));
1321 OUString aParaText
= ParagraphToHTMLString(pOutliner
, nIndex
, rBackgroundColor
);
1323 if (aParaText
.isEmpty())
1328 OUString aTag
= bHeadLine
? OUString("h2") : OUString("p");
1329 lclAppendStyle(aStr
, aTag
, getParagraphStyle(pOutliner
, nIndex
));
1331 aStr
.append(aParaText
);
1332 aStr
.append("</" + aTag
+ ">\r\n");
1336 while(nCurrentDepth
< nDepth
)
1338 aStr
.append("<ul>\r\n");
1341 while(nCurrentDepth
> nDepth
)
1343 aStr
.append("</ul>\r\n");
1346 lclAppendStyle(aStr
, u
"li", getParagraphStyle(pOutliner
, nIndex
));
1347 aStr
.append(aParaText
);
1348 aStr
.append("</li>\r\n");
1351 while(nCurrentDepth
>= 0)
1353 aStr
.append("</ul>\r\n");
1359 // creates an outliner text for a note page
1360 OUString
HtmlExport::CreateTextForNotesPage( SdrOutliner
* pOutliner
,
1362 const Color
& rBackgroundColor
)
1364 OUStringBuffer aStr
;
1366 SdrTextObj
* pTO
= static_cast<SdrTextObj
*>(pPage
->GetPresObj(PresObjKind::Notes
));
1368 if (pTO
&& !pTO
->IsEmptyPresObj())
1370 OutlinerParaObject
* pOPO
= pTO
->GetOutlinerParaObject();
1374 pOutliner
->SetText( *pOPO
);
1376 sal_Int32 nCount
= pOutliner
->GetParagraphCount();
1377 for (sal_Int32 nPara
= 0; nPara
< nCount
; nPara
++)
1379 lclAppendStyle(aStr
, u
"p", getParagraphStyle(pOutliner
, nPara
));
1380 aStr
.append(ParagraphToHTMLString(pOutliner
, nPara
, rBackgroundColor
)
1386 return aStr
.makeStringAndClear();
1389 // converts a paragraph of the outliner to html
1390 OUString
HtmlExport::ParagraphToHTMLString( SdrOutliner
const * pOutliner
, sal_Int32 nPara
, const Color
& rBackgroundColor
)
1392 OUStringBuffer aStr
;
1394 if(nullptr == pOutliner
)
1398 EditEngine
& rEditEngine
= *const_cast<EditEngine
*>(&pOutliner
->GetEditEngine());
1399 bool bOldUpdateMode
= rEditEngine
.SetUpdateLayout(true);
1401 Paragraph
* pPara
= pOutliner
->GetParagraph(nPara
);
1402 if(nullptr == pPara
)
1405 HtmlState
aState( (mbUserAttr
|| mbDocColors
) ? maTextColor
: COL_BLACK
);
1406 std::vector
<sal_Int32
> aPortionList
;
1407 rEditEngine
.GetPortions( nPara
, aPortionList
);
1409 sal_Int32 nPos1
= 0;
1410 for( sal_Int32 nPos2
: aPortionList
)
1412 ESelection
aSelection( nPara
, nPos1
, nPara
, nPos2
);
1414 SfxItemSet
aSet( rEditEngine
.GetAttribs( aSelection
) );
1416 aStr
.append(TextAttribToHTMLString( &aSet
, &aState
, rBackgroundColor
) +
1417 StringToHTMLString(rEditEngine
.GetText( aSelection
)));
1421 aStr
.append(aState
.Flush());
1422 rEditEngine
.SetUpdateLayout(bOldUpdateMode
);
1424 return aStr
.makeStringAndClear();
1427 // Depending on the attributes of the specified set and the specified
1428 // HtmlState, it creates the needed html tags in order to get the
1430 OUString
HtmlExport::TextAttribToHTMLString( SfxItemSet
const * pSet
, HtmlState
* pState
, const Color
& rBackgroundColor
)
1432 OUStringBuffer aStr
;
1437 OUString aLink
, aTarget
;
1438 if ( pSet
->GetItemState( EE_FEATURE_FIELD
) == SfxItemState::SET
)
1440 const SvxFieldItem
* pItem
= pSet
->GetItem
<SvxFieldItem
>( EE_FEATURE_FIELD
);
1443 const SvxURLField
* pURL
= dynamic_cast<const SvxURLField
*>( pItem
->GetField() );
1446 aLink
= pURL
->GetURL();
1447 aTarget
= pURL
->GetTargetFrame();
1455 if ( pSet
->GetItemState( EE_CHAR_WEIGHT
) == SfxItemState::SET
)
1457 bTemp
= pSet
->Get( EE_CHAR_WEIGHT
).GetWeight() == WEIGHT_BOLD
;
1458 aTemp
= pState
->SetWeight( bTemp
);
1460 aStr
.insert(0, aTemp
);
1465 if ( pSet
->GetItemState( EE_CHAR_UNDERLINE
) == SfxItemState::SET
)
1467 bTemp
= pSet
->Get( EE_CHAR_UNDERLINE
).GetLineStyle() != LINESTYLE_NONE
;
1468 aTemp
= pState
->SetUnderline( bTemp
);
1470 aStr
.insert(0, aTemp
);
1475 if ( pSet
->GetItemState( EE_CHAR_STRIKEOUT
) == SfxItemState::SET
)
1477 bTemp
= pSet
->Get( EE_CHAR_STRIKEOUT
).GetStrikeout() != STRIKEOUT_NONE
;
1478 aTemp
= pState
->SetStrikeout( bTemp
);
1480 aStr
.insert(0, aTemp
);
1485 if ( pSet
->GetItemState( EE_CHAR_ITALIC
) == SfxItemState::SET
)
1487 bTemp
= pSet
->Get( EE_CHAR_ITALIC
).GetPosture() != ITALIC_NONE
;
1488 aTemp
= pState
->SetItalic( bTemp
);
1490 aStr
.insert(0, aTemp
);
1497 if ( pSet
->GetItemState( EE_CHAR_COLOR
) == SfxItemState::SET
)
1499 Color aTextColor
= pSet
->Get( EE_CHAR_COLOR
).GetValue();
1500 if( aTextColor
== COL_AUTO
)
1502 if( !rBackgroundColor
.IsDark() )
1503 aTextColor
= COL_BLACK
;
1505 aStr
.append(pState
->SetColor( aTextColor
));
1509 if (!aLink
.isEmpty())
1510 aStr
.insert(0, pState
->SetLink(aLink
, aTarget
));
1512 aStr
.append(pState
->SetLink(aLink
, aTarget
));
1514 return aStr
.makeStringAndClear();
1517 // create HTML wrapper for picture files
1518 bool HtmlExport::CreateHtmlForPresPages()
1522 std::vector
<SdrObject
*> aClickableObjects
;
1524 for(sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
&& bOk
; nSdPage
++)
1526 // find clickable objects (also on the master page) and put it in the
1527 // list. This in reverse order character order since in html the first
1528 // area is taken in the case they overlap.
1529 SdPage
* pPage
= maPages
[ nSdPage
];
1533 SetDocColors( pPage
);
1536 bool bMasterDone
= false;
1538 while (!bMasterDone
)
1540 // sal_True = backwards
1541 SdrObjListIter
aIter(pPage
, SdrIterMode::DeepWithGroups
, true);
1543 SdrObject
* pObject
= aIter
.Next();
1546 SdAnimationInfo
* pInfo
= SdDrawDocument::GetAnimationInfo(pObject
);
1547 SvxIMapInfo
* pIMapInfo
= SvxIMapInfo::GetIMapInfo(pObject
);
1550 (pInfo
->meClickAction
== presentation::ClickAction_BOOKMARK
||
1551 pInfo
->meClickAction
== presentation::ClickAction_DOCUMENT
||
1552 pInfo
->meClickAction
== presentation::ClickAction_PREVPAGE
||
1553 pInfo
->meClickAction
== presentation::ClickAction_NEXTPAGE
||
1554 pInfo
->meClickAction
== presentation::ClickAction_FIRSTPAGE
||
1555 pInfo
->meClickAction
== presentation::ClickAction_LASTPAGE
)) ||
1558 aClickableObjects
.push_back(pObject
);
1561 pObject
= aIter
.Next();
1563 // now to the master page or finishing
1564 if (!pPage
->IsMasterPage())
1565 pPage
= static_cast<SdPage
*>(&(pPage
->TRG_GetMasterPage()));
1571 OUStringBuffer
aStr(gaHTMLHeader
+
1572 CreateMetaCharset() +
1573 " <title>" + StringToHTMLString(maPageNames
[nSdPage
]) + "</title>\r\n");
1575 // insert timing information
1576 pPage
= maPages
[ nSdPage
];
1577 if( meMode
== PUBLISH_KIOSK
)
1580 bool bEndless
= false;
1583 if( pPage
->GetPresChange() != PresChange::Manual
)
1585 fSecs
= pPage
->GetTime();
1586 bEndless
= mpDoc
->getPresentationSettings().mbEndless
;
1591 fSecs
= mfSlideDuration
;
1592 bEndless
= mbEndless
;
1597 if( nSdPage
< (mnSdPageCount
-1) || bEndless
)
1599 aStr
.append("<meta http-equiv=\"refresh\" content=\""
1600 + OUString::number(fSecs
)
1603 int nPage
= nSdPage
+ 1;
1604 if( nPage
== mnSdPageCount
)
1607 aStr
.append(maHTMLFiles
[nPage
]
1613 aStr
.append("</head>\r\n");
1616 aStr
.append(CreateBodyTag());
1618 if( mbSlideSound
&& pPage
->IsSoundOn() )
1619 aStr
.append(InsertSound(pPage
->GetSoundFile()));
1623 aStr
.append(CreateNavBar(nSdPage
, false));
1625 aStr
.append("<center>"
1627 + maImageFiles
[nSdPage
]
1630 if (!aClickableObjects
.empty())
1631 aStr
.append(" USEMAP=\"#map0\"");
1633 aStr
.append("></center>\r\n");
1636 if(mbNotes
&& !mbFrames
)
1638 SdrOutliner
* pOutliner
= mpDoc
->GetInternalOutliner();
1639 SdPage
* pNotesPage
= maNotesPages
[ nSdPage
];
1640 OUString
aNotesStr( CreateTextForNotesPage( pOutliner
, pNotesPage
, maBackColor
) );
1643 if (!aNotesStr
.isEmpty())
1646 + RESTOHTML(STR_HTMLEXP_NOTES
)
1647 + ":</h3><br>\r\n\r\n<p>"
1653 // create Imagemap if necessary
1654 if (!aClickableObjects
.empty())
1656 aStr
.append("<map name=\"map0\">\r\n");
1658 for (SdrObject
* pObject
: aClickableObjects
)
1660 SdAnimationInfo
* pInfo
= SdDrawDocument::GetAnimationInfo(pObject
);
1661 SvxIMapInfo
* pIMapInfo
= SvxIMapInfo::GetIMapInfo(pObject
);
1663 ::tools::Rectangle
aRect(pObject
->GetCurrentBoundRect());
1664 Point
aLogPos(aRect
.TopLeft());
1665 bool bIsSquare
= aRect
.GetWidth() == aRect
.GetHeight();
1667 sal_uLong nPageWidth
= pPage
->GetSize().Width() - pPage
->GetLeftBorder() -
1668 pPage
->GetRightBorder();
1670 // BoundRect is relative to the physical page origin, not the
1671 // origin of ordinates
1672 aRect
.Move(-pPage
->GetLeftBorder(), -pPage
->GetUpperBorder());
1674 double fLogicToPixel
= static_cast<double>(mnWidthPixel
) / nPageWidth
;
1675 aRect
.SetLeft( static_cast<tools::Long
>(aRect
.Left() * fLogicToPixel
) );
1676 aRect
.SetTop( static_cast<tools::Long
>(aRect
.Top() * fLogicToPixel
) );
1677 aRect
.SetRight( static_cast<tools::Long
>(aRect
.Right() * fLogicToPixel
) );
1678 aRect
.SetBottom( static_cast<tools::Long
>(aRect
.Bottom() * fLogicToPixel
) );
1679 tools::Long nRadius
= aRect
.GetWidth() / 2;
1682 insert areas into Imagemap of the object, if the object has
1687 const ImageMap
& rIMap
= pIMapInfo
->GetImageMap();
1688 sal_uInt16 nAreaCount
= rIMap
.GetIMapObjectCount();
1689 for (sal_uInt16 nArea
= 0; nArea
< nAreaCount
; nArea
++)
1691 IMapObject
* pArea
= rIMap
.GetIMapObject(nArea
);
1692 IMapObjectType nType
= pArea
->GetType();
1693 OUString
aURL( pArea
->GetURL() );
1695 // if necessary, convert page and object names into the
1696 // corresponding names of the html file
1698 sal_uInt16 nPgNum
= mpDoc
->GetPageByName( aURL
, bIsMasterPage
);
1700 if (nPgNum
== SDRPAGE_NOTFOUND
)
1702 // is the bookmark an object?
1703 SdrObject
* pObj
= mpDoc
->GetObj( aURL
);
1705 nPgNum
= pObj
->getSdrPageFromSdrObject()->GetPageNum();
1707 if (nPgNum
!= SDRPAGE_NOTFOUND
)
1709 nPgNum
= (nPgNum
- 1) / 2; // SdrPageNum --> SdPageNum
1710 aURL
= CreatePageURL(nPgNum
);
1715 case IMapObjectType::Rectangle
:
1717 ::tools::Rectangle
aArea(static_cast<IMapRectangleObject
*>(pArea
)->
1718 GetRectangle(false));
1720 // conversion into pixel coordinates
1721 aArea
.Move(aLogPos
.X() - pPage
->GetLeftBorder(),
1722 aLogPos
.Y() - pPage
->GetUpperBorder());
1723 aArea
.SetLeft( static_cast<tools::Long
>(aArea
.Left() * fLogicToPixel
) );
1724 aArea
.SetTop( static_cast<tools::Long
>(aArea
.Top() * fLogicToPixel
) );
1725 aArea
.SetRight( static_cast<tools::Long
>(aArea
.Right() * fLogicToPixel
) );
1726 aArea
.SetBottom( static_cast<tools::Long
>(aArea
.Bottom() * fLogicToPixel
) );
1728 aStr
.append(CreateHTMLRectArea(aArea
, aURL
));
1732 case IMapObjectType::Circle
:
1734 Point
aCenter(static_cast<IMapCircleObject
*>(pArea
)->
1736 aCenter
+= Point(aLogPos
.X() - pPage
->GetLeftBorder(),
1737 aLogPos
.Y() - pPage
->GetUpperBorder());
1738 aCenter
.setX( static_cast<tools::Long
>(aCenter
.X() * fLogicToPixel
) );
1739 aCenter
.setY( static_cast<tools::Long
>(aCenter
.Y() * fLogicToPixel
) );
1741 sal_uLong nCircleRadius
= static_cast<IMapCircleObject
*>(pArea
)->
1743 nCircleRadius
= static_cast<sal_uLong
>(nCircleRadius
* fLogicToPixel
);
1744 aStr
.append(CreateHTMLCircleArea(nCircleRadius
,
1745 aCenter
.X(), aCenter
.Y(),
1750 case IMapObjectType::Polygon
:
1752 tools::Polygon
aArea(static_cast<IMapPolygonObject
*>(pArea
)->GetPolygon(false));
1753 aStr
.append(CreateHTMLPolygonArea(::basegfx::B2DPolyPolygon(aArea
.getB2DPolygon()),
1754 Size(aLogPos
.X() - pPage
->GetLeftBorder(),
1755 aLogPos
.Y() - pPage
->GetUpperBorder()),
1756 fLogicToPixel
, aURL
));
1762 SAL_INFO("sd", "unknown IMapObjectType");
1770 if there is a presentation::ClickAction, determine bookmark
1771 and create area for the whole object
1776 presentation::ClickAction eClickAction
= pInfo
->meClickAction
;
1778 switch( eClickAction
)
1780 case presentation::ClickAction_BOOKMARK
:
1783 sal_uInt16 nPgNum
= mpDoc
->GetPageByName( pInfo
->GetBookmark(), bIsMasterPage
);
1785 if( nPgNum
== SDRPAGE_NOTFOUND
)
1787 // is the bookmark an object?
1788 SdrObject
* pObj
= mpDoc
->GetObj(pInfo
->GetBookmark());
1790 nPgNum
= pObj
->getSdrPageFromSdrObject()->GetPageNum();
1793 if( SDRPAGE_NOTFOUND
!= nPgNum
)
1794 aHRef
= CreatePageURL(( nPgNum
- 1 ) / 2 );
1798 case presentation::ClickAction_DOCUMENT
:
1799 aHRef
= pInfo
->GetBookmark();
1802 case presentation::ClickAction_PREVPAGE
:
1809 nPage
= nSdPage
- 1;
1811 aHRef
= CreatePageURL( static_cast<sal_uInt16
>(nPage
));
1815 case presentation::ClickAction_NEXTPAGE
:
1818 if (nSdPage
== mnSdPageCount
- 1)
1819 nPage
= mnSdPageCount
- 1;
1821 nPage
= nSdPage
+ 1;
1823 aHRef
= CreatePageURL( static_cast<sal_uInt16
>(nPage
));
1827 case presentation::ClickAction_FIRSTPAGE
:
1828 aHRef
= CreatePageURL(0);
1831 case presentation::ClickAction_LASTPAGE
:
1832 aHRef
= CreatePageURL(mnSdPageCount
- 1);
1839 // and now the areas
1840 if (!aHRef
.isEmpty())
1843 if (pObject
->GetObjInventor() == SdrInventor::Default
&&
1844 pObject
->GetObjIdentifier() == SdrObjKind::CircleOrEllipse
&&
1847 aStr
.append(CreateHTMLCircleArea(aRect
.GetWidth() / 2,
1848 aRect
.Left() + nRadius
,
1849 aRect
.Top() + nRadius
,
1853 else if (pObject
->GetObjInventor() == SdrInventor::Default
&&
1854 (pObject
->GetObjIdentifier() == SdrObjKind::PathLine
||
1855 pObject
->GetObjIdentifier() == SdrObjKind::PolyLine
||
1856 pObject
->GetObjIdentifier() == SdrObjKind::Polygon
))
1858 aStr
.append(CreateHTMLPolygonArea(static_cast<SdrPathObj
*>(pObject
)->GetPathPoly(), Size(-pPage
->GetLeftBorder(), -pPage
->GetUpperBorder()), fLogicToPixel
, aHRef
));
1860 // something completely different: use the BoundRect
1863 aStr
.append(CreateHTMLRectArea(aRect
, aHRef
));
1870 aStr
.append("</map>\r\n");
1872 aClickableObjects
.clear();
1874 aStr
.append("</body>\r\n</html>");
1876 bOk
= WriteHtml(maHTMLFiles
[nSdPage
], false, aStr
);
1880 mpProgress
->SetState(++mnPagesWritten
);
1886 // create overview pages
1887 bool HtmlExport::CreateContentPage()
1893 OUStringBuffer
aStr(
1895 + CreateMetaCharset()
1897 + StringToHTMLString(maPageNames
[0])
1898 + "</title>\r\n</head>\r\n"
1902 aStr
.append("<center>\r\n");
1906 aStr
.append("<h1>" + getDocumentTitle() + "</h1><br>\r\n");
1909 aStr
.append("<h2>");
1911 // Solaris compiler bug workaround
1913 aStr
.append(CreateLink(maFramePage
,
1914 RESTOHTML(STR_HTMLEXP_CLICKSTART
)));
1916 aStr
.append(CreateLink(StringToHTMLString(maHTMLFiles
[0]),
1917 RESTOHTML(STR_HTMLEXP_CLICKSTART
)));
1919 aStr
.append("</h2>\r\n</center>\r\n"
1920 "<center><table width=\"90%\"><tr>\r\n");
1923 aStr
.append("<td valign=\"top\" align=\"left\" width=\"25%\">\r\n"
1925 + RESTOHTML(STR_HTMLEXP_CONTENTS
)
1928 for(sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
; nSdPage
++)
1930 OUString aPageName
= maPageNames
[nSdPage
];
1931 aStr
.append("<div align=\"left\">");
1933 aStr
.append(StringToHTMLString(aPageName
));
1935 aStr
.append(CreateLink(maHTMLFiles
[nSdPage
], aPageName
));
1936 aStr
.append("</div>\r\n");
1938 aStr
.append("</td>\r\n");
1940 // document information
1941 aStr
.append("<td valign=\"top\" align=\"left\" width=\"75%\">\r\n");
1943 if (!maAuthor
.isEmpty())
1945 aStr
.append("<p><strong>"
1946 + RESTOHTML(STR_HTMLEXP_AUTHOR
)
1948 + StringToHTMLString(maAuthor
)
1952 if (!maEMail
.isEmpty())
1954 aStr
.append("<p><strong>"
1955 + RESTOHTML(STR_HTMLEXP_EMAIL
)
1956 + ":</strong> <a href=\"mailto:"
1959 + StringToHTMLString(maEMail
)
1963 if (!maHomePage
.isEmpty())
1965 aStr
.append("<p><strong>"
1966 + RESTOHTML(STR_HTMLEXP_HOMEPAGE
)
1967 + ":</strong> <a href=\""
1970 + StringToHTMLString(maHomePage
)
1974 if (!maInfo
.isEmpty())
1976 aStr
.append("<p><strong>"
1977 + RESTOHTML(STR_HTMLEXP_INFO
)
1978 + ":</strong><br>\r\n"
1979 + StringToHTMLString(maInfo
)
1985 aStr
.append("<p><a href=\""
1988 + RESTOHTML(STR_HTMLEXP_DOWNLOAD
)
1992 for(sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
; nSdPage
++)
1996 maThumbnailFiles
[nSdPage
] +
1997 "\" width=\"256\" height=\"192\" alt=\"" +
1998 StringToHTMLString(maPageNames
[nSdPage
]) +
2001 aStr
.append(CreateLink(maHTMLFiles
[nSdPage
], aText
)
2005 aStr
.append("</td></tr></table></center>\r\n"
2006 "</body>\r\n</html>");
2008 bool bOk
= WriteHtml(maIndex
, false, aStr
);
2011 mpProgress
->SetState(++mnPagesWritten
);
2016 // create note pages (for frames)
2018 bool HtmlExport::CreateNotesPages()
2022 SdrOutliner
* pOutliner
= mpDoc
->GetInternalOutliner();
2023 for( sal_uInt16 nSdPage
= 0; bOk
&& nSdPage
< mnSdPageCount
; nSdPage
++ )
2025 SdPage
* pPage
= maNotesPages
[nSdPage
];
2027 SetDocColors( pPage
);
2030 OUStringBuffer
aStr(gaHTMLHeader
2031 + CreateMetaCharset()
2033 + StringToHTMLString(maPageNames
[0])
2034 + "</title>\r\n</head>\r\n"
2038 aStr
.append(CreateTextForNotesPage( pOutliner
, pPage
, maBackColor
));
2040 aStr
.append("</body>\r\n</html>");
2042 OUString
aFileName("note" + OUString::number(nSdPage
));
2043 bOk
= WriteHtml(aFileName
, true, aStr
);
2046 mpProgress
->SetState(++mnPagesWritten
);
2054 // create outline pages (for frames)
2056 bool HtmlExport::CreateOutlinePages()
2065 // page 0 will be the closed outline, page 1 the opened
2066 for (sal_Int32 nPage
= 0; nPage
< (mbImpress
?2:1) && bOk
; ++nPage
)
2069 OUStringBuffer
aStr(gaHTMLHeader
2070 + CreateMetaCharset()
2072 + StringToHTMLString(maPageNames
[0])
2073 + "</title>\r\n</head>\r\n"
2076 SdrOutliner
* pOutliner
= mpDoc
->GetInternalOutliner();
2077 for(sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
; nSdPage
++)
2079 SdPage
* pPage
= maPages
[ nSdPage
];
2081 aStr
.append("<div align=\"left\">");
2082 OUString
aLink("JavaScript:parent.NavigateAbs(" +
2083 OUString::number(nSdPage
) + ")");
2085 OUString aTitle
= CreateTextForTitle(pOutliner
, pPage
, maBackColor
);
2086 if (aTitle
.isEmpty())
2087 aTitle
= maPageNames
[nSdPage
];
2089 lclAppendStyle(aStr
, u
"p", getParagraphStyle(pOutliner
, 0));
2090 aStr
.append(CreateLink(aLink
, aTitle
)
2095 aStr
.append(CreateTextForPage( pOutliner
, pPage
, false, maBackColor
));
2097 aStr
.append("</div>\r\n");
2101 aStr
.append("</body>\r\n</html>");
2103 OUString
aFileName("outline" + OUString::number(nPage
));
2104 bOk
= WriteHtml(aFileName
, true, aStr
);
2108 mpProgress
->SetState(++mnPagesWritten
);
2115 void HtmlExport::CreateFileNames()
2117 // create lists with new file names
2118 maHTMLFiles
.resize(mnSdPageCount
);
2119 maImageFiles
.resize(mnSdPageCount
);
2120 maThumbnailFiles
.resize(mnSdPageCount
);
2121 maPageNames
.resize(mnSdPageCount
);
2122 maTextFiles
.resize(mnSdPageCount
);
2124 mbHeader
= false; // headline on overview page?
2126 for (sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
; nSdPage
++)
2128 OUString aHTMLFileName
;
2129 if(nSdPage
== 0 && !mbContentsPage
&& !mbFrames
)
2130 aHTMLFileName
= maIndex
;
2133 aHTMLFileName
= "img" + OUString::number(nSdPage
) + gaHTMLExtension
;
2136 maHTMLFiles
[nSdPage
] = aHTMLFileName
;
2138 OUString aImageFileName
= "img" + OUString::number(nSdPage
);
2139 if( meFormat
==FORMAT_GIF
)
2140 aImageFileName
+= ".gif";
2141 else if( meFormat
==FORMAT_JPG
)
2142 aImageFileName
+= ".jpg";
2144 aImageFileName
+= ".png";
2146 maImageFiles
[nSdPage
] = aImageFileName
;
2148 OUString aThumbnailFileName
= "thumb" + OUString::number(nSdPage
);
2149 if( meFormat
!=FORMAT_JPG
)
2150 aThumbnailFileName
+= ".png";
2152 aThumbnailFileName
+= ".jpg";
2154 maThumbnailFiles
[nSdPage
] = aThumbnailFileName
;
2156 maTextFiles
[nSdPage
] = "text" + OUString::number(nSdPage
) + gaHTMLExtension
;
2158 SdPage
* pSdPage
= maPages
[ nSdPage
];
2160 // get slide title from page name
2161 maPageNames
[nSdPage
] = pSdPage
->GetName();
2164 if(!mbContentsPage
&& mbFrames
)
2165 maFramePage
= maIndex
;
2168 maFramePage
= "siframes" + gaHTMLExtension
;
2172 OUString
const & HtmlExport::getDocumentTitle()
2174 // check for a title object in this page, if it's the first
2175 // title it becomes this documents title for the content
2181 // if there is a non-empty title object, use their first passage
2183 SdPage
* pSdPage
= mpDoc
->GetSdPage(0, PageKind::Standard
);
2184 SdrObject
* pTitleObj
= pSdPage
->GetPresObj(PresObjKind::Title
);
2185 if (pTitleObj
&& !pTitleObj
->IsEmptyPresObj())
2187 OutlinerParaObject
* pParaObject
= pTitleObj
->GetOutlinerParaObject();
2190 const EditTextObject
& rEditTextObject
=
2191 pParaObject
->GetTextObject();
2192 OUString
aTest(rEditTextObject
.GetText(0));
2193 if (!aTest
.isEmpty())
2198 mDocTitle
= mDocTitle
.replace(0xff, ' ');
2201 if (mDocTitle
.isEmpty())
2203 mDocTitle
= maDocFileName
;
2204 sal_Int32 nDot
= mDocTitle
.indexOf('.');
2206 mDocTitle
= mDocTitle
.copy(0, nDot
);
2214 constexpr OUStringLiteral JS_NavigateAbs
=
2215 u
"function NavigateAbs( nPage )\r\n"
2217 " frames[\"show\"].location.href = \"img\" + nPage + \".$EXT\";\r\n"
2218 " //frames[\"notes\"].location.href = \"note\" + nPage + \".$EXT\";\r\n"
2219 " nCurrentPage = nPage;\r\n"
2220 " if(nCurrentPage==0)\r\n"
2222 " frames[\"navbar1\"].location.href = \"navbar0.$EXT\";\r\n"
2224 " else if(nCurrentPage==nPageCount-1)\r\n"
2226 " frames[\"navbar1\"].location.href = \"navbar2.$EXT\";\r\n"
2230 " frames[\"navbar1\"].location.href = \"navbar1.$EXT\";\r\n"
2234 constexpr OUStringLiteral JS_NavigateRel
=
2235 u
"function NavigateRel( nDelta )\r\n"
2237 " var nPage = parseInt(nCurrentPage) + parseInt(nDelta);\r\n"
2238 " if( (nPage >= 0) && (nPage < nPageCount) )\r\n"
2240 " NavigateAbs( nPage );\r\n"
2244 constexpr OUStringLiteral JS_ExpandOutline
=
2245 u
"function ExpandOutline()\r\n"
2247 " frames[\"navbar2\"].location.href = \"navbar4.$EXT\";\r\n"
2248 " frames[\"outline\"].location.href = \"outline1.$EXT\";\r\n"
2251 constexpr OUStringLiteral JS_CollapseOutline
=
2252 u
"function CollapseOutline()\r\n"
2254 " frames[\"navbar2\"].location.href = \"navbar3.$EXT\";\r\n"
2255 " frames[\"outline\"].location.href = \"outline0.$EXT\";\r\n"
2258 // create page with the frames
2260 bool HtmlExport::CreateFrames()
2263 OUStringBuffer
aStr(
2264 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\"\r\n"
2265 " \"http://www.w3.org/TR/html4/frameset.dtd\">\r\n"
2266 "<html>\r\n<head>\r\n"
2268 + CreateMetaCharset()
2270 + StringToHTMLString(maPageNames
[0])
2273 "<script type=\"text/javascript\">\r\n<!--\r\n"
2275 "var nCurrentPage = 0;\r\nvar nPageCount = "
2276 + OUString::number(static_cast<sal_Int32
>(mnSdPageCount
))
2279 OUString aFunction
= JS_NavigateAbs
;
2283 aFunction
= aFunction
.replaceAll("//", "");
2286 // substitute HTML file extension
2287 OUString
aPlaceHolder(".$EXT");
2288 aFunction
= aFunction
.replaceAll(aPlaceHolder
, gaHTMLExtension
);
2289 aStr
.append(aFunction
);
2291 aTmp
= JS_NavigateRel
;
2292 aTmp
= aTmp
.replaceAll(aPlaceHolder
, gaHTMLExtension
);
2297 aTmp
= JS_ExpandOutline
;
2298 aTmp
= aTmp
.replaceAll(aPlaceHolder
, gaHTMLExtension
);
2301 aTmp
= JS_CollapseOutline
;
2302 aTmp
= aTmp
.replaceAll(aPlaceHolder
, gaHTMLExtension
);
2305 aStr
.append("// -->\r\n</script>\r\n"
2309 "<frameset cols=\"*,"
2310 + OUString::number(static_cast<sal_Int32
>(mnWidthPixel
+ 16))
2315 " <frameset rows=\"42,*\">\r\n"
2316 " <frame src=\"navbar3"
2318 + "\" name=\"navbar2\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n");
2320 aStr
.append(" <frame src=\"outline0"
2322 + "\" name=\"outline\">\r\n");
2324 aStr
.append(" </frameset>\r\n");
2328 aStr
.append(" <frameset rows=\"42,"
2329 + OUString::number(static_cast<sal_Int32
>(static_cast<double>(mnWidthPixel
) * 0.75) + 16)
2333 aStr
.append(" <frameset rows=\"42,*\">\r\n");
2336 " <frame src=\"navbar0"
2338 + "\" name=\"navbar1\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n"
2342 + "\" name=\"show\" marginwidth=\"4\" marginheight=\"4\">\r\n");
2346 aStr
.append(" <frame src=\"note0"
2348 + "\" name=\"notes\">\r\n");
2350 aStr
.append(" </frameset>\r\n"
2354 + RESTOHTML(STR_HTMLEXP_NOFRAMES
)
2355 + "\r\n</noframes>\r\n</frameset>\r\n</html>");
2357 bool bOk
= WriteHtml(maFramePage
, false, aStr
);
2360 mpProgress
->SetState(++mnPagesWritten
);
2365 // create button bar for standard
2366 // we create the following html files
2367 // navbar0.htm navigation bar graphic for the first page
2368 // navbar1.htm navigation bar graphic for the second until second last page
2369 // navbar2.htm navigation bar graphic for the last page
2370 // navbar3.htm navigation outline closed
2371 // navbar4.htm navigation outline open
2372 bool HtmlExport::CreateNavBarFrames()
2380 maBackColor
= maFirstPageColor
;
2383 for( int nFile
= 0; nFile
< 3 && bOk
; nFile
++ )
2385 OUStringBuffer
aStr(
2387 + CreateMetaCharset()
2389 + StringToHTMLString(maPageNames
[0])
2390 + "</title>\r\n</head>\r\n"
2395 aButton
= SdResId(STR_HTMLEXP_FIRSTPAGE
);
2396 if(mnButtonThema
!= -1)
2397 aButton
= CreateImage(GetButtonName(nFile
== 0 || mnSdPageCount
== 1 ? BTN_FIRST_0
: BTN_FIRST_1
),
2400 if(nFile
!= 0 && mnSdPageCount
> 1)
2401 aButton
= CreateLink(u
"JavaScript:parent.NavigateAbs(0)", aButton
);
2406 // to the previous page
2407 aButton
= SdResId(STR_PUBLISH_BACK
);
2408 if(mnButtonThema
!= -1)
2409 aButton
= CreateImage(GetButtonName(nFile
== 0 || mnSdPageCount
== 1?
2410 BTN_PREV_0
:BTN_PREV_1
),
2413 if(nFile
!= 0 && mnSdPageCount
> 1)
2414 aButton
= CreateLink(u
"JavaScript:parent.NavigateRel(-1)", aButton
);
2420 aButton
= SdResId(STR_PUBLISH_NEXT
);
2421 if(mnButtonThema
!= -1)
2422 aButton
= CreateImage(GetButtonName(nFile
==2 || mnSdPageCount
== 1?
2423 BTN_NEXT_0
:BTN_NEXT_1
),
2426 if(nFile
!= 2 && mnSdPageCount
> 1)
2427 aButton
= CreateLink(u
"JavaScript:parent.NavigateRel(1)", aButton
);
2433 aButton
= SdResId(STR_HTMLEXP_LASTPAGE
);
2434 if(mnButtonThema
!= -1)
2435 aButton
= CreateImage(GetButtonName(nFile
==2 || mnSdPageCount
== 1?
2436 BTN_LAST_0
:BTN_LAST_1
),
2439 if(nFile
!= 2 && mnSdPageCount
> 1)
2441 OUString
aLink("JavaScript:parent.NavigateAbs(" +
2442 OUString::number(mnSdPageCount
-1) + ")");
2444 aButton
= CreateLink(aLink
, aButton
);
2453 aButton
= SdResId(STR_PUBLISH_OUTLINE
);
2454 if(mnButtonThema
!= -1)
2455 aButton
= CreateImage(GetButtonName(BTN_INDEX
), aButton
);
2458 aStr
.append(CreateLink(maIndex
, aButton
, u
"_top")
2465 aButton
= SdResId(STR_HTMLEXP_SETTEXT
);
2466 if(mnButtonThema
!= -1)
2467 aButton
= CreateImage(GetButtonName(BTN_TEXT
), aButton
);
2469 OUString
aText0("text0" + gaHTMLExtension
);
2470 aStr
.append(CreateLink(aText0
, aButton
, u
"_top")
2477 "</body>\r\n</html>");
2479 OUString
aFileName("navbar" + OUString::number(nFile
));
2481 bOk
= WriteHtml(aFileName
, true, aStr
);
2485 mpProgress
->SetState(++mnPagesWritten
);
2488 // the navigation bar outliner closed...
2491 aButton
= SdResId(STR_HTMLEXP_OUTLINE
);
2492 if(mnButtonThema
!= -1)
2493 aButton
= CreateImage(GetButtonName(BTN_MORE
), aButton
);
2498 gaHTMLHeader
+ CreateMetaCharset() + " <title>"
2499 + StringToHTMLString(maPageNames
[0]) + "</title>\r\n</head>\r\n" + CreateBodyTag()
2500 + CreateLink(u
"JavaScript:parent.ExpandOutline()", aButton
)
2501 + "</body>\r\n</html>"));
2504 mpProgress
->SetState(++mnPagesWritten
);
2507 // ... and the outliner open
2510 aButton
= SdResId(STR_HTMLEXP_NOOUTLINE
);
2511 if(mnButtonThema
!= -1)
2512 aButton
= CreateImage(GetButtonName(BTN_LESS
), aButton
);
2517 gaHTMLHeader
+ CreateMetaCharset() + " <title>"
2518 + StringToHTMLString(maPageNames
[0]) + "</title>\r\n</head>\r\n" + CreateBodyTag()
2519 + CreateLink(u
"JavaScript:parent.CollapseOutline()", aButton
)
2520 + "</body>\r\n</html>"));
2523 mpProgress
->SetState(++mnPagesWritten
);
2530 // create button bar for standard
2531 OUString
HtmlExport::CreateNavBar( sal_uInt16 nSdPage
, bool bIsText
) const
2533 // prepare button bar
2534 OUString
aStrNavFirst(SdResId(STR_HTMLEXP_FIRSTPAGE
));
2535 OUString
aStrNavPrev(SdResId(STR_PUBLISH_BACK
));
2536 OUString
aStrNavNext(SdResId(STR_PUBLISH_NEXT
));
2537 OUString
aStrNavLast(SdResId(STR_HTMLEXP_LASTPAGE
));
2538 OUString
aStrNavContent(SdResId(STR_PUBLISH_OUTLINE
));
2539 OUString aStrNavText
;
2542 aStrNavText
= SdResId(STR_HTMLEXP_SETGRAPHIC
);
2546 aStrNavText
= SdResId(STR_HTMLEXP_SETTEXT
);
2549 if(!bIsText
&& mnButtonThema
!= -1)
2551 if(nSdPage
<1 || mnSdPageCount
== 1)
2553 aStrNavFirst
= CreateImage(GetButtonName(BTN_FIRST_0
), aStrNavFirst
);
2554 aStrNavPrev
= CreateImage(GetButtonName(BTN_PREV_0
), aStrNavPrev
);
2558 aStrNavFirst
= CreateImage(GetButtonName(BTN_FIRST_1
), aStrNavFirst
);
2559 aStrNavPrev
= CreateImage(GetButtonName(BTN_PREV_1
), aStrNavPrev
);
2562 if(nSdPage
== mnSdPageCount
-1 || mnSdPageCount
== 1)
2564 aStrNavNext
= CreateImage(GetButtonName(BTN_NEXT_0
), aStrNavNext
);
2565 aStrNavLast
= CreateImage(GetButtonName(BTN_LAST_0
), aStrNavLast
);
2569 aStrNavNext
= CreateImage(GetButtonName(BTN_NEXT_1
), aStrNavNext
);
2570 aStrNavLast
= CreateImage(GetButtonName(BTN_LAST_1
), aStrNavLast
);
2573 aStrNavContent
= CreateImage(GetButtonName(BTN_INDEX
), aStrNavContent
);
2574 aStrNavText
= CreateImage(GetButtonName(BTN_TEXT
), aStrNavText
);
2577 OUStringBuffer
aStr("<center>\r\n"); //<table><tr>\r\n");
2581 aStr
.append(CreateLink( bIsText
? maTextFiles
[0] : maHTMLFiles
[0],aStrNavFirst
));
2583 aStr
.append(aStrNavFirst
);
2588 aStr
.append(CreateLink( bIsText
? maTextFiles
[nSdPage
-1]
2589 : maHTMLFiles
[nSdPage
-1], aStrNavPrev
));
2591 aStr
.append(aStrNavPrev
);
2595 if(nSdPage
< mnSdPageCount
-1)
2596 aStr
.append(CreateLink( bIsText
? maTextFiles
[nSdPage
+1]
2597 : maHTMLFiles
[nSdPage
+1], aStrNavNext
));
2599 aStr
.append(aStrNavNext
);
2603 if(nSdPage
< mnSdPageCount
-1)
2604 aStr
.append(CreateLink( bIsText
? maTextFiles
[mnSdPageCount
-1]
2605 : maHTMLFiles
[mnSdPageCount
-1],
2608 aStr
.append(aStrNavLast
);
2614 aStr
.append(CreateLink(maIndex
, aStrNavContent
) + " ");
2620 aStr
.append(CreateLink( bIsText
? (mbFrames
? maFramePage
: maHTMLFiles
[nSdPage
])
2621 : maTextFiles
[nSdPage
], aStrNavText
));
2625 aStr
.append("</center><br>\r\n");
2627 return aStr
.makeStringAndClear();
2630 // export navigation graphics from button set
2631 void HtmlExport::CreateBitmaps()
2633 if(mnButtonThema
== -1 || !mpButtonSet
)
2636 for( int nButton
= 0; nButton
!= SAL_N_ELEMENTS(pButtonNames
); nButton
++ )
2638 if(!mbFrames
&& (nButton
== BTN_MORE
|| nButton
== BTN_LESS
))
2641 if(!mbImpress
&& (nButton
== BTN_TEXT
|| nButton
== BTN_MORE
|| nButton
== BTN_LESS
))
2644 OUString aFull
= maExportPath
+ GetButtonName(nButton
);
2645 mpButtonSet
->exportButton( mnButtonThema
, aFull
, GetButtonName(nButton
) );
2649 // creates the <body> tag, including the specified color attributes
2650 OUString
HtmlExport::CreateBodyTag() const
2652 OUStringBuffer
aStr( "<body" );
2654 if( mbUserAttr
|| mbDocColors
)
2656 Color
aTextColor( maTextColor
);
2657 if( (aTextColor
== COL_AUTO
) && (!maBackColor
.IsDark()) )
2658 aTextColor
= COL_BLACK
;
2660 aStr
.append(" text=\""
2661 + ColorToHTMLString( aTextColor
)
2663 + ColorToHTMLString( maBackColor
)
2665 + ColorToHTMLString( maLinkColor
)
2667 + ColorToHTMLString( maVLinkColor
)
2669 + ColorToHTMLString( maALinkColor
)
2673 aStr
.append(">\r\n");
2675 return aStr
.makeStringAndClear();
2678 // creates a hyperlink
2679 OUString
HtmlExport::CreateLink( std::u16string_view aLink
,
2680 std::u16string_view aText
,
2681 std::u16string_view aTarget
)
2683 OUStringBuffer
aStr( OUString::Concat("<a href=\"") + aLink
);
2684 if (!aTarget
.empty())
2686 aStr
.append(OUString::Concat("\" target=\"") + aTarget
);
2688 aStr
.append(OUString::Concat("\">") + aText
+ "</a>");
2690 return aStr
.makeStringAndClear();
2693 // creates an image tag
2694 OUString
HtmlExport::CreateImage( std::u16string_view aImage
, std::u16string_view aAltText
)
2696 OUStringBuffer
aStr( OUString::Concat("<img src=\"") + aImage
+ "\" border=0");
2698 if (!aAltText
.empty())
2700 aStr
.append(OUString::Concat(" alt=\"") + aAltText
+ "\"");
2704 // Agerskov: HTML 4.01 has to have an alt attribute even if it is an empty string
2705 aStr
.append(" alt=\"\"");
2710 return aStr
.makeStringAndClear();
2713 // create area for a circle; we expect pixel coordinates
2714 OUString
HtmlExport::ColorToHTMLString( Color aColor
)
2716 static const char hex
[] = "0123456789ABCDEF";
2717 OUStringBuffer
aStr( "#xxxxxx" );
2718 aStr
[1] = hex
[(aColor
.GetRed() >> 4) & 0xf];
2719 aStr
[2] = hex
[aColor
.GetRed() & 0xf];
2720 aStr
[3] = hex
[(aColor
.GetGreen() >> 4) & 0xf];
2721 aStr
[4] = hex
[aColor
.GetGreen() & 0xf];
2722 aStr
[5] = hex
[(aColor
.GetBlue() >> 4) & 0xf];
2723 aStr
[6] = hex
[aColor
.GetBlue() & 0xf];
2725 return aStr
.makeStringAndClear();
2728 // create area for a circle; we expect pixel coordinates
2729 OUString
HtmlExport::CreateHTMLCircleArea( sal_uLong nRadius
,
2732 std::u16string_view rHRef
)
2735 "<area shape=\"circle\" alt=\"\" coords=\"" +
2736 OUString::number(nCenterX
) + "," +
2737 OUString::number(nCenterY
) + "," +
2738 OUString::number(nRadius
) +
2739 "\" href=\"" + rHRef
+ "\">\n");
2744 // create area for a polygon; we expect pixel coordinates
2745 OUString
HtmlExport::CreateHTMLPolygonArea( const ::basegfx::B2DPolyPolygon
& rPolyPolygon
,
2746 Size aShift
, double fFactor
, std::u16string_view rHRef
)
2748 OUStringBuffer aStr
;
2749 const sal_uInt32
nNoOfPolygons(rPolyPolygon
.count());
2751 for ( sal_uInt32 nXPoly
= 0; nXPoly
< nNoOfPolygons
; nXPoly
++ )
2753 const ::basegfx::B2DPolygon
& aPolygon
= rPolyPolygon
.getB2DPolygon(nXPoly
);
2754 const sal_uInt32
nNoOfPoints(aPolygon
.count());
2756 aStr
.append("<area shape=\"polygon\" alt=\"\" coords=\"");
2758 for ( sal_uInt32 nPoint
= 0; nPoint
< nNoOfPoints
; nPoint
++ )
2760 const ::basegfx::B2DPoint
aB2DPoint(aPolygon
.getB2DPoint(nPoint
));
2761 Point
aPnt(FRound(aB2DPoint
.getX()), FRound(aB2DPoint
.getY()));
2762 // coordinates are relative to the physical page origin, not the
2763 // origin of ordinates
2764 aPnt
.Move(aShift
.Width(), aShift
.Height());
2766 aPnt
.setX( static_cast<tools::Long
>(aPnt
.X() * fFactor
) );
2767 aPnt
.setY( static_cast<tools::Long
>(aPnt
.Y() * fFactor
) );
2768 aStr
.append( OUString::number(aPnt
.X()) + "," + OUString::number(aPnt
.Y()) );
2770 if (nPoint
< nNoOfPoints
- 1)
2773 aStr
.append(OUString::Concat("\" href=\"") + rHRef
+ "\">\n");
2776 return aStr
.makeStringAndClear();
2779 // create area for a rectangle; we expect pixel coordinates
2780 OUString
HtmlExport::CreateHTMLRectArea( const ::tools::Rectangle
& rRect
,
2781 std::u16string_view rHRef
)
2784 "<area shape=\"rect\" alt=\"\" coords=\"" +
2785 OUString::number(rRect
.Left()) + "," +
2786 OUString::number(rRect
.Top()) + "," +
2787 OUString::number(rRect
.Right()) + "," +
2788 OUString::number(rRect
.Bottom()) +
2789 "\" href=\"" + rHRef
+ "\">\n");
2794 // escapes a string for html
2795 OUString
HtmlExport::StringToHTMLString( const OUString
& rString
)
2797 SvMemoryStream aMemStm
;
2798 HTMLOutFuncs::Out_String( aMemStm
, rString
);
2799 aMemStm
.WriteChar( char(0) );
2800 sal_Int32 nLength
= strlen(static_cast<char const *>(aMemStm
.GetData()));
2801 return OUString( static_cast<char const *>(aMemStm
.GetData()), nLength
, RTL_TEXTENCODING_UTF8
);
2804 // creates a URL for a specific page
2805 OUString
HtmlExport::CreatePageURL( sal_uInt16 nPgNum
)
2809 return OUString("JavaScript:parent.NavigateAbs(" +
2810 OUString::number(nPgNum
) + ")");
2813 return maHTMLFiles
[nPgNum
];
2816 bool HtmlExport::CopyScript( std::u16string_view rPath
, const OUString
& rSource
, const OUString
& rDest
, bool bUnix
/* = false */ )
2818 INetURLObject
aURL( SvtPathOptions().GetConfigPath() );
2819 OUStringBuffer aScriptBuf
;
2821 aURL
.Append( u
"webcast" );
2822 aURL
.Append( rSource
);
2824 meEC
.SetContext( STR_HTMLEXP_ERROR_OPEN_FILE
, rSource
);
2826 ErrCode nErr
= ERRCODE_NONE
;
2827 std::unique_ptr
<SvStream
> pIStm
= ::utl::UcbStreamHelper::CreateStream( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
), StreamMode::READ
);
2831 OStringBuffer aLine
;
2833 while( pIStm
->ReadLine( aLine
) )
2835 aScriptBuf
.appendAscii( aLine
.getStr(), aLine
.getLength() );
2838 aScriptBuf
.append("\n");
2842 aScriptBuf
.append("\r\n");
2846 nErr
= pIStm
->GetError();
2850 if( nErr
!= ERRCODE_NONE
)
2852 ErrorHandler::HandleError( nErr
);
2853 return static_cast<bool>(nErr
);
2856 OUString
aScript(aScriptBuf
.makeStringAndClear());
2857 aScript
= aScript
.replaceAll("$$1", getDocumentTitle());
2858 aScript
= aScript
.replaceAll("$$2", RESTOHTML(STR_WEBVIEW_SAVE
));
2859 aScript
= aScript
.replaceAll("$$3", maCGIPath
);
2860 aScript
= aScript
.replaceAll("$$4", OUString::number(mnWidthPixel
));
2861 aScript
= aScript
.replaceAll("$$5", OUString::number(mnHeightPixel
));
2863 OUString
aDest(rPath
+ rDest
);
2865 meEC
.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE
, rDest
);
2866 // write script file
2870 nErr
= aFile
.createStream(aDest
, pStr
);
2871 if(nErr
== ERRCODE_NONE
)
2873 OString
aStr(OUStringToOString(aScript
, RTL_TEXTENCODING_UTF8
));
2874 pStr
->WriteOString( aStr
);
2880 mpProgress
->SetState(++mnPagesWritten
);
2882 if( nErr
!= ERRCODE_NONE
)
2883 ErrorHandler::HandleError( nErr
);
2885 return nErr
== ERRCODE_NONE
;
2888 static const char * ASP_Scripts
[] = { "common.inc", "webcast.asp", "show.asp", "savepic.asp", "poll.asp", "editpic.asp" };
2890 /** creates and saves the ASP scripts for WebShow */
2891 bool HtmlExport::CreateASPScripts()
2893 for(const char * p
: ASP_Scripts
)
2895 OUString aScript
= OUString::createFromAscii(p
);
2897 if(!CopyScript(maExportPath
, aScript
, aScript
))
2901 return CopyScript(maExportPath
, "edit.asp", maIndex
);
2904 static const char *PERL_Scripts
[] = { "webcast.pl", "common.pl", "editpic.pl", "poll.pl", "savepic.pl", "show.pl" };
2906 // creates and saves the PERL scripts for WebShow
2907 bool HtmlExport::CreatePERLScripts()
2909 for(const char * p
: PERL_Scripts
)
2911 OUString aScript
= OUString::createFromAscii(p
);
2913 if(!CopyScript(maExportPath
, aScript
, aScript
, true))
2917 if (!CopyScript(maExportPath
, "edit.pl", maIndex
, true))
2920 if (!CopyScript(maExportPath
, "index.pl", maIndexUrl
, true))
2926 // creates a list with names of the saved images
2927 bool HtmlExport::CreateImageFileList()
2929 OUStringBuffer aStr
;
2930 for( sal_uInt16 nSdPage
= 0; nSdPage
< mnSdPageCount
; nSdPage
++)
2933 OUString::number(static_cast<sal_Int32
>(nSdPage
+ 1))
2936 + maImageFiles
[nSdPage
]
2940 bool bOk
= WriteHtml("picture.txt", false, aStr
);
2943 mpProgress
->SetState(++mnPagesWritten
);
2948 // creates a file with the actual page number
2949 bool HtmlExport::CreateImageNumberFile()
2951 OUString
aFileName("currpic.txt");
2952 OUString
aFull(maExportPath
+ aFileName
);
2954 meEC
.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE
, aFileName
);
2957 ErrCode nErr
= aFile
.createStream(aFull
, pStr
);
2958 if(nErr
== ERRCODE_NONE
)
2960 pStr
->WriteOString( "1" );
2965 mpProgress
->SetState(++mnPagesWritten
);
2967 if( nErr
!= ERRCODE_NONE
)
2968 ErrorHandler::HandleError( nErr
);
2970 return nErr
== ERRCODE_NONE
;
2973 OUString
HtmlExport::InsertSound( const OUString
& rSoundFile
)
2975 if (rSoundFile
.isEmpty())
2978 INetURLObject
aURL( rSoundFile
);
2979 OUString aSoundFileName
= aURL
.getName();
2981 DBG_ASSERT( aURL
.GetProtocol() != INetProtocol::NotValid
, "invalid URL" );
2983 OUString
aStr("<embed src=\"" + aSoundFileName
+
2984 "\" hidden=\"true\" autostart=\"true\">");
2986 CopyFile(rSoundFile
, maExportPath
+ aSoundFileName
);
2991 bool HtmlExport::CopyFile( const OUString
& rSourceFile
, const OUString
& rDestFile
)
2993 meEC
.SetContext( STR_HTMLEXP_ERROR_COPY_FILE
, rSourceFile
, rDestFile
);
2994 osl::FileBase::RC Error
= osl::File::copy( rSourceFile
, rDestFile
);
2996 if( Error
!= osl::FileBase::E_None
)
2998 ErrorHandler::HandleError(ErrCode(Error
));
3007 bool HtmlExport::checkFileExists( Reference
< css::ucb::XSimpleFileAccess3
> const & xFileAccess
, std::u16string_view aFileName
)
3011 OUString url
= maExportPath
+ aFileName
;
3012 return xFileAccess
->exists( url
);
3014 catch( css::uno::Exception
& )
3016 TOOLS_WARN_EXCEPTION( "sd", "sd::HtmlExport::checkFileExists()" );
3022 bool HtmlExport::checkForExistingFiles()
3024 bool bFound
= false;
3028 Reference
< XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
3029 uno::Reference
<ucb::XSimpleFileAccess3
> xFA(ucb::SimpleFileAccess::create(xContext
));
3032 for( nSdPage
= 0; !bFound
&& (nSdPage
< mnSdPageCount
); nSdPage
++)
3034 if( checkFileExists( xFA
, maImageFiles
[nSdPage
] ) ||
3035 checkFileExists( xFA
, maHTMLFiles
[nSdPage
] ) ||
3036 checkFileExists( xFA
, maThumbnailFiles
[nSdPage
] ) ||
3037 checkFileExists( xFA
, maPageNames
[nSdPage
] ) ||
3038 checkFileExists( xFA
, maTextFiles
[nSdPage
] ) )
3044 if( !bFound
&& mbDownload
)
3045 bFound
= checkFileExists( xFA
, maDocFileName
);
3047 if( !bFound
&& mbFrames
)
3048 bFound
= checkFileExists( xFA
, maFramePage
);
3052 OUString aSystemPath
;
3053 osl::FileBase::getSystemPathFromFileURL( maExportPath
, aSystemPath
);
3054 OUString
aMsg(SdResId(STR_OVERWRITE_WARNING
));
3055 aMsg
= aMsg
.replaceFirst( "%FILENAME", aSystemPath
);
3057 std::unique_ptr
<weld::MessageDialog
> xWarn(Application::CreateMessageDialog(nullptr,
3058 VclMessageType::Warning
, VclButtonsType::YesNo
,
3060 xWarn
->set_default_response(RET_YES
);
3061 bFound
= (RET_NO
== xWarn
->run());
3066 TOOLS_WARN_EXCEPTION( "sd", "sd::HtmlExport::checkForExistingFiles()" );
3073 OUString
HtmlExport::GetButtonName( int nButton
)
3075 return OUString::createFromAscii(pButtonNames
[nButton
]);
3078 EasyFile::EasyFile() : bOpen(false)
3082 EasyFile::~EasyFile()
3088 ErrCode
EasyFile::createStream( const OUString
& rUrl
, SvStream
* &rpStr
)
3094 createFileName( rUrl
, aFileName
);
3096 ErrCode nErr
= ERRCODE_NONE
;
3097 pOStm
= ::utl::UcbStreamHelper::CreateStream( aFileName
, StreamMode::WRITE
| StreamMode::TRUNC
);
3101 nErr
= pOStm
->GetError();
3105 nErr
= ERRCODE_SFX_CANTCREATECONTENT
;
3108 if( nErr
!= ERRCODE_NONE
)
3114 rpStr
= pOStm
.get();
3119 void EasyFile::createFileName( const OUString
& rURL
, OUString
& rFileName
)
3124 INetURLObject
aURL( rURL
);
3126 if( aURL
.GetProtocol() == INetProtocol::NotValid
)
3129 osl::FileBase::getFileURLFromSystemPath( rURL
, aURLStr
);
3130 aURL
= INetURLObject( aURLStr
);
3132 DBG_ASSERT( aURL
.GetProtocol() != INetProtocol::NotValid
, "invalid URL" );
3133 rFileName
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
3136 void EasyFile::close()
3142 // This class helps reporting errors during file i/o
3143 HtmlErrorContext::HtmlErrorContext()
3144 : ErrorContext(nullptr)
3148 bool HtmlErrorContext::GetString( ErrCode
, OUString
& rCtxStr
)
3150 DBG_ASSERT(mpResId
, "No error context set");
3154 rCtxStr
= SdResId(mpResId
);
3156 rCtxStr
= rCtxStr
.replaceAll( "$(URL1)", maURL1
);
3157 rCtxStr
= rCtxStr
.replaceAll( "$(URL2)", maURL2
);
3162 void HtmlErrorContext::SetContext(TranslateId pResId
, const OUString
& rURL
)
3169 void HtmlErrorContext::SetContext(TranslateId pResId
, const OUString
& rURL1
, const OUString
& rURL2
)
3176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */