android: Update app-specific/MIME type icons
[LibreOffice.git] / sd / source / filter / html / htmlex.cxx
blobc3f1625dad59210c0d442288e0271756a4d0e6ce
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include "htmlex.hxx"
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>
38 #include <utility>
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>
74 #include <sdpage.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[] =
95 "first-inactive.png",
96 "first.png",
97 "left-inactive.png",
98 "left.png",
99 "right-inactive.png",
100 "right.png",
101 "last-inactive.png",
102 "last.png",
103 "home.png",
104 "text.png",
105 "expand.png",
106 "collapse.png",
109 #define BTN_FIRST_0 0
110 #define BTN_FIRST_1 1
111 #define BTN_PREV_0 2
112 #define BTN_PREV_1 3
113 #define BTN_NEXT_0 4
114 #define BTN_NEXT_1 5
115 #define BTN_LAST_0 6
116 #define BTN_LAST_1 7
117 #define BTN_INDEX 8
118 #define BTN_TEXT 9
119 #define BTN_MORE 10
120 #define BTN_LESS 11
122 namespace {
124 // Helper class for the simple creation of files local/remote
125 class EasyFile
127 private:
128 std::unique_ptr<SvStream> pOStm;
129 bool bOpen;
131 public:
133 EasyFile();
134 ~EasyFile();
136 ErrCode createStream( const OUString& rUrl, SvStream*& rpStr );
137 void createFileName( const OUString& rUrl, OUString& rFileName );
138 void close();
143 // Helper class for the embedding of text attributes into the html output
144 class HtmlState
146 private:
147 bool mbColor;
148 bool mbWeight;
149 bool mbItalic;
150 bool mbUnderline;
151 bool mbStrike;
152 bool mbLink;
153 Color maColor;
154 Color maDefColor;
155 OUString maLink;
156 OUString maTarget;
158 public:
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 );
167 OUString Flush();
170 // close all still open tags
171 OUString HtmlState::Flush()
173 OUString aStr = SetWeight(false)
174 + SetItalic(false)
175 + SetUnderline(false)
176 + SetStrikeout(false)
177 + SetColor(maDefColor)
178 + SetLink("","");
180 return aStr;
183 // c'tor with default color for the page
184 HtmlState::HtmlState( Color aDefColor )
185 : mbColor(false),
186 mbWeight(false),
187 mbItalic(false),
188 mbUnderline(false),
189 mbStrike(false),
190 mbLink(false),
191 maDefColor(aDefColor)
195 // enables/disables bold print
196 OUString HtmlState::SetWeight( bool bWeight )
198 OUString aStr;
200 if(bWeight && !mbWeight)
201 aStr = "<b>";
202 else if(!bWeight && mbWeight)
203 aStr = "</b>";
205 mbWeight = bWeight;
206 return aStr;
209 // enables/disables italic
211 OUString HtmlState::SetItalic( bool bItalic )
213 OUString aStr;
215 if(bItalic && !mbItalic)
216 aStr = "<i>";
217 else if(!bItalic && mbItalic)
218 aStr = "</i>";
220 mbItalic = bItalic;
221 return aStr;
224 // enables/disables underlines
226 OUString HtmlState::SetUnderline( bool bUnderline )
228 OUString aStr;
230 if(bUnderline && !mbUnderline)
231 aStr = "<u>";
232 else if(!bUnderline && mbUnderline)
233 aStr = "</u>";
235 mbUnderline = bUnderline;
236 return aStr;
239 // enables/disables strike through
240 OUString HtmlState::SetStrikeout( bool bStrike )
242 OUString aStr;
244 if(bStrike && !mbStrike)
245 aStr = "<strike>";
246 else if(!bStrike && mbStrike)
247 aStr = "</strike>";
249 mbStrike = bStrike;
250 return aStr;
253 // Sets the specified text color
254 OUString HtmlState::SetColor( Color aColor )
256 OUString aStr;
258 if(mbColor && aColor == maColor)
259 return aStr;
261 if(mbColor)
263 aStr = "</font>";
264 mbColor = false;
267 if(aColor != maDefColor)
269 maColor = aColor;
270 aStr += "<font color=\"" + HtmlExport::ColorToHTMLString(aColor) + "\">";
271 mbColor = true;
274 return aStr;
277 // enables/disables a hyperlink
278 OUString HtmlState::SetLink( const OUString& aLink, const OUString& aTarget )
280 OUString aStr;
282 if(mbLink&&maLink == aLink&&maTarget==aTarget)
283 return aStr;
285 if(mbLink)
287 aStr = "</a>";
288 mbLink = false;
291 if (!aLink.isEmpty())
293 aStr += "<a href=\"" + comphelper::string::encodeForXml(aLink);
294 if (!aTarget.isEmpty())
296 aStr += "\" target=\"" + comphelper::string::encodeForXml(aTarget);
298 aStr += "\">";
299 mbLink = true;
300 maLink = aLink;
301 maTarget = aTarget;
304 return aStr;
306 namespace
309 OUString getParagraphStyle( const SdrOutliner* pOutliner, sal_Int32 nPara )
311 SfxItemSet aParaSet( pOutliner->GetParaAttribs( nPara ) );
313 OUString sStyle;
315 if( aParaSet.GetItem<SvxFrameDirectionItem>( EE_PARA_WRITINGDIR )->GetValue() == SvxFrameDirection::Horizontal_RL_TB )
318 sStyle = "direction: rtl;";
320 else
322 // This is the default so don't write it out
323 // sStyle += "direction: ltr;";
325 return sStyle;
328 void lclAppendStyle(OUStringBuffer& aBuffer, std::u16string_view aTag, std::u16string_view aStyle)
330 if (aStyle.empty())
331 aBuffer.append(OUString::Concat("<") + aTag + ">");
332 else
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(
347 OUString aPath,
348 const Sequence< PropertyValue >& rParams,
349 SdDrawDocument* pExpDoc,
350 sd::DrawDocShell* pDocShell )
351 : maPath(std::move( aPath )),
352 mpDoc(pExpDoc),
353 mpDocSh( pDocShell ),
354 meMode( PUBLISH_SINGLE_DOCUMENT ),
355 mbContentsPage(false),
356 mnButtonThema(-1),
357 mnWidthPixel( PUB_MEDRES_WIDTH ),
358 meFormat( FORMAT_JPG ),
359 mbNotes(false),
360 mnCompression( -1 ),
361 mbDownload( false ),
362 mbSlideSound(true),
363 mbHiddenSlides(true),
364 mbUserAttr(false),
365 maTextColor(COL_BLACK),
366 maBackColor(COL_WHITE),
367 mbDocColors(false),
368 maIndexUrl("index"),
369 meScript( SCRIPT_ASP ),
370 mpButtonSet( new ButtonSet() )
372 bool bChange = mpDoc->IsChanged();
374 maIndexUrl += gaHTMLExtension;
376 InitExportParameters( rParams );
378 switch( meMode )
380 case PUBLISH_HTML:
381 case PUBLISH_FRAMES:
382 ExportHtml();
383 break;
384 case PUBLISH_WEBCAST:
385 ExportWebCast();
386 break;
387 case PUBLISH_KIOSK:
388 ExportKiosk();
389 break;
390 case PUBLISH_SINGLE_DOCUMENT:
391 ExportSingleDocument();
392 break;
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;
407 OUString aStr;
408 for( const PropertyValue& rParam : rParams )
410 if ( rParam.Name == "PublishMode" )
412 sal_Int32 temp = 0;
413 rParam.Value >>= temp;
414 meMode = static_cast<HtmlPublishMode>(temp);
416 else if ( rParam.Name == "IndexURL" )
418 rParam.Value >>= aStr;
419 maIndexUrl = aStr;
421 else if ( rParam.Name == "Format" )
423 sal_Int32 temp = 0;
424 rParam.Value >>= temp;
425 meFormat = static_cast<PublishingFormat>(temp);
427 else if ( rParam.Name == "Compression" )
429 rParam.Value >>= aStr;
430 OUString aTmp( aStr );
431 if(!aTmp.isEmpty())
433 aTmp = aTmp.replaceFirst("%", "");
434 mnCompression = static_cast<sal_Int16>(aTmp.toInt32());
437 else if ( rParam.Name == "Width" )
439 sal_Int32 temp = 0;
440 rParam.Value >>= temp;
441 mnWidthPixel = static_cast<sal_uInt16>(temp);
443 else if ( rParam.Name == "UseButtonSet" )
445 sal_Int32 temp = 0;
446 rParam.Value >>= temp;
447 mnButtonThema = static_cast<sal_Int16>(temp);
449 else if ( rParam.Name == "IsExportNotes" )
451 if( mbImpress )
453 bool temp = false;
454 rParam.Value >>= temp;
455 mbNotes = temp;
458 else if ( rParam.Name == "IsExportContentsPage" )
460 bool temp = false;
461 rParam.Value >>= temp;
462 mbContentsPage = temp;
464 else if ( rParam.Name == "Author" )
466 rParam.Value >>= aStr;
467 maAuthor = aStr;
469 else if ( rParam.Name == "EMail" )
471 rParam.Value >>= aStr;
472 maEMail = aStr;
474 else if ( rParam.Name == "HomepageURL" )
476 rParam.Value >>= aStr;
477 maHomePage = aStr;
479 else if ( rParam.Name == "UserText" )
481 rParam.Value >>= aStr;
482 maInfo = aStr;
484 else if ( rParam.Name == "EnableDownload" )
486 bool temp = false;
487 rParam.Value >>= temp;
488 mbDownload = temp;
490 else if ( rParam.Name == "SlideSound" )
492 bool temp = true;
493 rParam.Value >>= temp;
494 mbSlideSound = temp;
496 else if ( rParam.Name == "HiddenSlides" )
498 bool temp = true;
499 rParam.Value >>= temp;
500 mbHiddenSlides = temp;
502 else if ( rParam.Name == "BackColor" )
504 Color temp;
505 rParam.Value >>= temp;
506 maBackColor = temp;
507 mbUserAttr = true;
509 else if ( rParam.Name == "TextColor" )
511 Color temp;
512 rParam.Value >>= temp;
513 maTextColor = temp;
514 mbUserAttr = true;
516 else if ( rParam.Name == "LinkColor" )
518 Color temp ;
519 rParam.Value >>= temp;
520 maLinkColor = temp;
521 mbUserAttr = true;
523 else if ( rParam.Name == "VLinkColor" )
525 Color temp;
526 rParam.Value >>= temp;
527 maVLinkColor = temp;
528 mbUserAttr = true;
530 else if ( rParam.Name == "ALinkColor" )
532 Color temp;
533 rParam.Value >>= temp;
534 maALinkColor = temp;
535 mbUserAttr = true;
537 else if ( rParam.Name == "IsUseDocumentColors" )
539 bool temp = false;
540 rParam.Value >>= temp;
541 mbDocColors = temp;
543 else if ( rParam.Name == "KioskSlideDuration" )
545 double temp = 0.0;
546 rParam.Value >>= temp;
547 mfSlideDuration = temp;
548 mbAutoSlide = true;
550 else if ( rParam.Name == "KioskEndless" )
552 bool temp = false;
553 rParam.Value >>= temp;
554 mbEndless = temp;
556 else if ( rParam.Name == "WebCastCGIURL" )
558 rParam.Value >>= aStr;
559 maCGIPath = aStr;
561 else if ( rParam.Name == "WebCastTargetURL" )
563 rParam.Value >>= aStr;
564 maURLPath = aStr;
566 else if ( rParam.Name == "WebCastScriptLanguage" )
568 rParam.Value >>= aStr;
569 if ( aStr == "asp" )
571 meScript = SCRIPT_ASP;
573 else
575 meScript = SCRIPT_PERL;
578 else
580 OSL_FAIL("Unknown property for html export detected!");
584 if( meMode == PUBLISH_KIOSK )
586 mbContentsPage = false;
587 mbNotes = 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);
630 mnPagesWritten = 0;
631 InitProgress(mnSdPageCount);
633 OUStringBuffer aStr(gaHTMLHeader
634 + DocumentMetadata()
635 + "\r\n"
636 "</head>\r\n"
637 + CreateBodyTag());
639 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; ++nSdPage)
641 SdPage* pPage = maPages[nSdPage];
642 maPageNames[nSdPage] = pPage->GetName();
644 if( mbDocColors )
646 SetDocColors( pPage );
649 // page title
650 OUString sTitleText(CreateTextForTitle(pOutliner, pPage, pPage->GetPageBackgroundColor()));
651 OUString sStyle;
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() ));
664 // notes
665 if(mbNotes)
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)
674 + ":</h3>\r\n"
675 + aNotesStr);
679 if (mpProgress)
680 mpProgress->SetState(++mnPagesWritten);
684 // close page
685 aStr.append("</body>\r\n</html>");
687 WriteHtml(maDocFileName, false, aStr);
689 pOutliner->Clear();
690 ResetProgress();
693 // exports the (in the c'tor specified impress document) to html
694 void HtmlExport::ExportHtml()
696 if(mbUserAttr)
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'
707 SetDocColors();
708 maFirstPageColor = maBackColor;
711 // get name for downloadable presentation if needed
712 if( mbDownload )
714 // fade out separator search and extension
715 sal_Int32 nSepPos = maDocFileName.indexOf('.');
716 if (nSepPos != -1)
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...
733 CreateFileNames();
735 // this is not a true while
736 while( true )
738 if( checkForExistingFiles() )
739 break;
741 if( !CreateImagesForPresPages() )
742 break;
744 if( mbContentsPage &&
745 !CreateImagesForPresPages( true ) )
746 break;
748 if( !CreateHtmlForPresPages() )
749 break;
751 if( mbImpress )
752 if( !CreateHtmlTextForPresPages() )
753 break;
755 if( mbFrames )
757 if( !CreateFrames() )
758 break;
760 if( !CreateOutlinePages() )
761 break;
763 if( !CreateNavBarFrames() )
764 break;
766 if( mbNotes && mbImpress )
767 if( !CreateNotesPages() )
768 break;
772 if( mbContentsPage )
773 if( !CreateContentPage() )
774 break;
776 CreateBitmaps();
778 mpDocSh->SetWaitCursor( false );
779 ResetProgress();
781 if( mbDownload )
782 SavePresentation();
784 return;
787 // if we get to this point the export was
788 // canceled by the user after an error
789 mpDocSh->SetWaitCursor( false );
790 ResetProgress();
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();
819 if(pSheet)
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()
843 mpProgress.reset();
846 void HtmlExport::ExportKiosk()
848 mnPagesWritten = 0;
849 InitProgress( 2*mnSdPageCount );
851 CreateFileNames();
852 if( !checkForExistingFiles() )
854 if( CreateImagesForPresPages() )
855 CreateHtmlForPresPages();
858 ResetProgress();
861 // Export Document with WebCast (TM) Technology
862 void HtmlExport::ExportWebCast()
864 mnPagesWritten = 0;
865 InitProgress( mnSdPageCount + 9 );
867 mpDocSh->SetWaitCursor( true );
869 CreateFileNames();
871 if (maCGIPath.isEmpty())
872 maCGIPath = ".";
874 if (!maCGIPath.endsWith("/"))
875 maCGIPath += "/";
877 if( meScript == SCRIPT_ASP )
879 maURLPath = "./";
881 else
883 if (maURLPath.isEmpty())
884 maURLPath = ".";
886 if (!maURLPath.endsWith("/"))
887 maURLPath += "/";
890 // this is not a true while
891 while(true)
893 if( checkForExistingFiles() )
894 break;
896 if(!CreateImagesForPresPages())
897 break;
899 if( meScript == SCRIPT_ASP )
901 if(!CreateASPScripts())
902 break;
904 else
906 if(!CreatePERLScripts())
907 break;
910 if(!CreateImageFileList())
911 break;
913 if(!CreateImageNumberFile())
914 break;
916 break;
919 mpDocSh->SetWaitCursor( false );
920 ResetProgress();
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 );
935 if( xStorable.is() )
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 );
945 return true;
948 catch( Exception& )
952 mpDocSh->EnableSetModified( false );
954 return 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);
978 OUString sFormat;
979 if( meFormat == FORMAT_PNG )
980 sFormat = "PNG";
981 else if( meFormat == FORMAT_GIF )
982 sFormat = "GIF";
983 else
984 sFormat = "JPG";
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);
998 if (bThumbnail)
999 aFull += maThumbnailFiles[nSdPage];
1000 else
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 );
1009 if (mpProgress)
1010 mpProgress->SetState(++mnPagesWritten);
1013 catch( Exception& )
1015 return false;
1018 return true;
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);
1034 break;
1037 return pResult;
1040 // create HTML text version of impress pages
1041 OUString HtmlExport::CreateMetaCharset()
1043 OUString aStr;
1044 const char *pCharSet = rtl_getBestMimeCharsetFromTextEncoding( RTL_TEXTENCODING_UTF8 );
1045 if ( pCharSet )
1047 aStr = " <meta HTTP-EQUIV=CONTENT-TYPE CONTENT=\"text/html; charset=" +
1048 OUString::createFromAscii(pCharSet) + "\">\r\n";
1050 return aStr;
1053 OUString HtmlExport::DocumentMetadata() const
1055 SvMemoryStream aStream;
1057 uno::Reference<document::XDocumentProperties> xDocProps;
1058 if (mpDocSh)
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,
1066 " ");
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()
1077 bool bOk = true;
1079 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
1081 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount && bOk; nSdPage++)
1083 SdPage* pPage = maPages[ nSdPage ];
1085 if( mbDocColors )
1087 SetDocColors( pPage );
1090 // HTML head
1091 OUStringBuffer aStr(gaHTMLHeader
1092 + CreateMetaCharset()
1093 + " <title>"
1094 + StringToHTMLString(maPageNames[nSdPage])
1095 + "</title>\r\n"
1096 "</head>\r\n"
1097 + CreateBodyTag());
1099 // navigation bar
1100 aStr.append(CreateNavBar(nSdPage, true));
1102 // page title
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() ));
1110 // notes
1111 if(mbNotes)
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)
1120 + ":</h3>\r\n"
1121 + aNotesStr);
1125 // close page
1126 aStr.append("</body>\r\n</html>");
1128 bOk = WriteHtml(maTextFiles[nSdPage], false, aStr);
1130 if (mpProgress)
1131 mpProgress->SetState(++mnPagesWritten);
1135 pOutliner->Clear();
1137 return bOk;
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 );
1147 if( bAddExtension )
1148 aFileName += gaHTMLExtension;
1150 meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, rFileName );
1151 EasyFile aFile;
1152 SvStream* pStr;
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 );
1159 aFile.close();
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));
1173 if(!pTO)
1174 pTO = GetLayoutTextObject(pPage);
1176 if (pTO && !pTO->IsEmptyPresObj())
1178 OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1179 if(pOPO && pOutliner->GetParagraphCount() != 0)
1181 pOutliner->Clear();
1182 pOutliner->SetText(*pOPO);
1183 return ParagraphToHTMLString(pOutliner,0, rBackgroundColor);
1187 return OUString();
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);
1201 switch (eKind)
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);
1215 else
1217 if (pObject->GetOutlinerParaObject())
1219 WriteOutlinerParagraph(aStr, pOutliner, pObject->GetOutlinerParaObject(), rBackgroundColor, false);
1223 break;
1225 case PresObjKind::Table:
1227 SdrTableObj* pTableObject = static_cast<SdrTableObj*>(pObject);
1228 WriteTable(aStr, pTableObject, pOutliner, rBackgroundColor);
1230 break;
1232 case PresObjKind::Text:
1233 case PresObjKind::Outline:
1235 SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject);
1236 if (pTextObject->IsEmptyPresObj())
1237 continue;
1238 WriteOutlinerParagraph(aStr, pOutliner, pTextObject->GetOutlinerParaObject(), rBackgroundColor, bHeadLine);
1240 break;
1242 default:
1243 break;
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)
1268 continue;
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);
1289 else
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)
1305 return;
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)
1318 continue;
1320 const sal_Int16 nDepth = static_cast<sal_uInt16>(pOutliner->GetDepth(nIndex));
1321 OUString aParaText = ParagraphToHTMLString(pOutliner, nIndex, rBackgroundColor);
1323 if (aParaText.isEmpty())
1324 continue;
1326 if (nDepth < 0)
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");
1334 else
1336 while(nCurrentDepth < nDepth)
1338 aStr.append("<ul>\r\n");
1339 nCurrentDepth++;
1341 while(nCurrentDepth > nDepth)
1343 aStr.append("</ul>\r\n");
1344 nCurrentDepth--;
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");
1354 nCurrentDepth--;
1356 pOutliner->Clear();
1359 // creates an outliner text for a note page
1360 OUString HtmlExport::CreateTextForNotesPage( SdrOutliner* pOutliner,
1361 SdPage* pPage,
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();
1371 if (pOPO)
1373 pOutliner->Clear();
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)
1381 + "</p>\r\n");
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)
1395 return OUString();
1397 // TODO: MALTE!!!
1398 EditEngine& rEditEngine = *const_cast<EditEngine*>(&pOutliner->GetEditEngine());
1399 bool bOldUpdateMode = rEditEngine.SetUpdateLayout(true);
1401 Paragraph* pPara = pOutliner->GetParagraph(nPara);
1402 if(nullptr == pPara)
1403 return OUString();
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 )));
1419 nPos1 = nPos2;
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
1429 // attributes
1430 OUString HtmlExport::TextAttribToHTMLString( SfxItemSet const * pSet, HtmlState* pState, const Color& rBackgroundColor )
1432 OUStringBuffer aStr;
1434 if(nullptr == pSet)
1435 return OUString();
1437 OUString aLink, aTarget;
1438 if ( pSet->GetItemState( EE_FEATURE_FIELD ) == SfxItemState::SET )
1440 const SvxFieldItem* pItem = pSet->GetItem<SvxFieldItem>( EE_FEATURE_FIELD );
1441 if(pItem)
1443 const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pItem->GetField() );
1444 if(pURL)
1446 aLink = pURL->GetURL();
1447 aTarget = pURL->GetTargetFrame();
1452 bool bTemp;
1453 OUString aTemp;
1455 if ( pSet->GetItemState( EE_CHAR_WEIGHT ) == SfxItemState::SET )
1457 bTemp = pSet->Get( EE_CHAR_WEIGHT ).GetWeight() == WEIGHT_BOLD;
1458 aTemp = pState->SetWeight( bTemp );
1459 if( bTemp )
1460 aStr.insert(0, aTemp);
1461 else
1462 aStr.append(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 );
1469 if( bTemp )
1470 aStr.insert(0, aTemp);
1471 else
1472 aStr.append(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 );
1479 if( bTemp )
1480 aStr.insert(0, aTemp);
1481 else
1482 aStr.append(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 );
1489 if( bTemp )
1490 aStr.insert(0, aTemp);
1491 else
1492 aStr.append(aTemp);
1495 if(mbDocColors)
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));
1511 else
1512 aStr.append(pState->SetLink(aLink, aTarget));
1514 return aStr.makeStringAndClear();
1517 // create HTML wrapper for picture files
1518 bool HtmlExport::CreateHtmlForPresPages()
1520 bool bOk = true;
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 ];
1531 if( mbDocColors )
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();
1544 while (pObject)
1546 SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObject);
1547 SvxIMapInfo* pIMapInfo = SvxIMapInfo::GetIMapInfo(pObject);
1549 if ((pInfo &&
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)) ||
1556 pIMapInfo)
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()));
1566 else
1567 bMasterDone = true;
1570 // HTML Head
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 )
1579 double fSecs = 0;
1580 bool bEndless = false;
1581 if( !mbAutoSlide )
1583 if( pPage->GetPresChange() != PresChange::Manual )
1585 fSecs = pPage->GetTime();
1586 bEndless = mpDoc->getPresentationSettings().mbEndless;
1589 else
1591 fSecs = mfSlideDuration;
1592 bEndless = mbEndless;
1595 if( fSecs != 0 )
1597 if( nSdPage < (mnSdPageCount-1) || bEndless )
1599 aStr.append("<meta http-equiv=\"refresh\" content=\""
1600 + OUString::number(fSecs)
1601 + "; URL=");
1603 int nPage = nSdPage + 1;
1604 if( nPage == mnSdPageCount )
1605 nPage = 0;
1607 aStr.append(maHTMLFiles[nPage]
1608 + "\">\r\n");
1613 aStr.append("</head>\r\n");
1615 // HTML Body
1616 aStr.append(CreateBodyTag());
1618 if( mbSlideSound && pPage->IsSoundOn() )
1619 aStr.append(InsertSound(pPage->GetSoundFile()));
1621 // navigation bar
1622 if(!mbFrames )
1623 aStr.append(CreateNavBar(nSdPage, false));
1624 // Image
1625 aStr.append("<center>"
1626 "<img src=\""
1627 + maImageFiles[nSdPage]
1628 + "\" alt=\"\"");
1630 if (!aClickableObjects.empty())
1631 aStr.append(" USEMAP=\"#map0\"");
1633 aStr.append("></center>\r\n");
1635 // notes
1636 if(mbNotes && !mbFrames)
1638 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
1639 SdPage* pNotesPage = maNotesPages[ nSdPage ];
1640 OUString aNotesStr( CreateTextForNotesPage( pOutliner, pNotesPage, maBackColor) );
1641 pOutliner->Clear();
1643 if (!aNotesStr.isEmpty())
1645 aStr.append("<h3>"
1646 + RESTOHTML(STR_HTMLEXP_NOTES)
1647 + ":</h3><br>\r\n\r\n<p>"
1648 + aNotesStr
1649 + "\r\n</p>\r\n");
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
1683 such an Imagemap
1685 if (pIMapInfo)
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
1697 bool bIsMasterPage;
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 );
1704 if (pObj)
1705 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1707 if (nPgNum != SDRPAGE_NOTFOUND)
1709 nPgNum = (nPgNum - 1) / 2; // SdrPageNum --> SdPageNum
1710 aURL = CreatePageURL(nPgNum);
1713 switch(nType)
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));
1730 break;
1732 case IMapObjectType::Circle:
1734 Point aCenter(static_cast<IMapCircleObject*>(pArea)->
1735 GetCenter(false));
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)->
1742 GetRadius(false);
1743 nCircleRadius = static_cast<sal_uLong>(nCircleRadius * fLogicToPixel);
1744 aStr.append(CreateHTMLCircleArea(nCircleRadius,
1745 aCenter.X(), aCenter.Y(),
1746 aURL));
1748 break;
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));
1758 break;
1760 default:
1762 SAL_INFO("sd", "unknown IMapObjectType");
1764 break;
1770 if there is a presentation::ClickAction, determine bookmark
1771 and create area for the whole object
1773 if( pInfo )
1775 OUString aHRef;
1776 presentation::ClickAction eClickAction = pInfo->meClickAction;
1778 switch( eClickAction )
1780 case presentation::ClickAction_BOOKMARK:
1782 bool bIsMasterPage;
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());
1789 if (pObj)
1790 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1793 if( SDRPAGE_NOTFOUND != nPgNum )
1794 aHRef = CreatePageURL(( nPgNum - 1 ) / 2 );
1796 break;
1798 case presentation::ClickAction_DOCUMENT:
1799 aHRef = pInfo->GetBookmark();
1800 break;
1802 case presentation::ClickAction_PREVPAGE:
1804 sal_uLong nPage;
1806 if (nSdPage == 0)
1807 nPage = 0;
1808 else
1809 nPage = nSdPage - 1;
1811 aHRef = CreatePageURL( static_cast<sal_uInt16>(nPage));
1813 break;
1815 case presentation::ClickAction_NEXTPAGE:
1817 sal_uLong nPage;
1818 if (nSdPage == mnSdPageCount - 1)
1819 nPage = mnSdPageCount - 1;
1820 else
1821 nPage = nSdPage + 1;
1823 aHRef = CreatePageURL( static_cast<sal_uInt16>(nPage));
1825 break;
1827 case presentation::ClickAction_FIRSTPAGE:
1828 aHRef = CreatePageURL(0);
1829 break;
1831 case presentation::ClickAction_LASTPAGE:
1832 aHRef = CreatePageURL(mnSdPageCount - 1);
1833 break;
1835 default:
1836 break;
1839 // and now the areas
1840 if (!aHRef.isEmpty())
1842 // a circle?
1843 if (pObject->GetObjInventor() == SdrInventor::Default &&
1844 pObject->GetObjIdentifier() == SdrObjKind::CircleOrEllipse &&
1845 bIsSquare )
1847 aStr.append(CreateHTMLCircleArea(aRect.GetWidth() / 2,
1848 aRect.Left() + nRadius,
1849 aRect.Top() + nRadius,
1850 aHRef));
1852 // a polygon?
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
1861 else
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);
1877 aStr.setLength(0);
1879 if (mpProgress)
1880 mpProgress->SetState(++mnPagesWritten);
1883 return bOk;
1886 // create overview pages
1887 bool HtmlExport::CreateContentPage()
1889 if( mbDocColors )
1890 SetDocColors();
1892 // html head
1893 OUStringBuffer aStr(
1894 gaHTMLHeader
1895 + CreateMetaCharset()
1896 + " <title>"
1897 + StringToHTMLString(maPageNames[0])
1898 + "</title>\r\n</head>\r\n"
1899 + CreateBodyTag());
1901 // page head
1902 aStr.append("<center>\r\n");
1904 if(mbHeader)
1906 aStr.append("<h1>" + getDocumentTitle() + "</h1><br>\r\n");
1909 aStr.append("<h2>");
1911 // Solaris compiler bug workaround
1912 if( mbFrames )
1913 aStr.append(CreateLink(maFramePage,
1914 RESTOHTML(STR_HTMLEXP_CLICKSTART)));
1915 else
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");
1922 // table of content
1923 aStr.append("<td valign=\"top\" align=\"left\" width=\"25%\">\r\n"
1924 "<h3>"
1925 + RESTOHTML(STR_HTMLEXP_CONTENTS)
1926 + "</h3>");
1928 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++)
1930 OUString aPageName = maPageNames[nSdPage];
1931 aStr.append("<div align=\"left\">");
1932 if(mbFrames)
1933 aStr.append(StringToHTMLString(aPageName));
1934 else
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)
1947 + ":</strong> "
1948 + StringToHTMLString(maAuthor)
1949 + "</p>\r\n");
1952 if (!maEMail.isEmpty())
1954 aStr.append("<p><strong>"
1955 + RESTOHTML(STR_HTMLEXP_EMAIL)
1956 + ":</strong> <a href=\"mailto:"
1957 + maEMail
1958 + "\">"
1959 + StringToHTMLString(maEMail)
1960 + "</a></p>\r\n");
1963 if (!maHomePage.isEmpty())
1965 aStr.append("<p><strong>"
1966 + RESTOHTML(STR_HTMLEXP_HOMEPAGE)
1967 + ":</strong> <a href=\""
1968 + maHomePage
1969 + "\">"
1970 + StringToHTMLString(maHomePage)
1971 + "</a> </p>\r\n");
1974 if (!maInfo.isEmpty())
1976 aStr.append("<p><strong>"
1977 + RESTOHTML(STR_HTMLEXP_INFO)
1978 + ":</strong><br>\r\n"
1979 + StringToHTMLString(maInfo)
1980 + "</p>\r\n");
1983 if(mbDownload)
1985 aStr.append("<p><a href=\""
1986 + maDocFileName
1987 + "\">"
1988 + RESTOHTML(STR_HTMLEXP_DOWNLOAD)
1989 + "</a></p>\r\n");
1992 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++)
1994 OUString aText(
1995 "<img src=\"" +
1996 maThumbnailFiles[nSdPage] +
1997 "\" width=\"256\" height=\"192\" alt=\"" +
1998 StringToHTMLString(maPageNames[nSdPage]) +
1999 "\">");
2001 aStr.append(CreateLink(maHTMLFiles[nSdPage], aText)
2002 + "\r\n");
2005 aStr.append("</td></tr></table></center>\r\n"
2006 "</body>\r\n</html>");
2008 bool bOk = WriteHtml(maIndex, false, aStr);
2010 if (mpProgress)
2011 mpProgress->SetState(++mnPagesWritten);
2013 return bOk;
2016 // create note pages (for frames)
2018 bool HtmlExport::CreateNotesPages()
2020 bool bOk = true;
2022 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
2023 for( sal_uInt16 nSdPage = 0; bOk && nSdPage < mnSdPageCount; nSdPage++ )
2025 SdPage* pPage = maNotesPages[nSdPage];
2026 if( mbDocColors )
2027 SetDocColors( pPage );
2029 // Html head
2030 OUStringBuffer aStr(gaHTMLHeader
2031 + CreateMetaCharset()
2032 + " <title>"
2033 + StringToHTMLString(maPageNames[0])
2034 + "</title>\r\n</head>\r\n"
2035 + CreateBodyTag());
2037 if(pPage)
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);
2045 if (mpProgress)
2046 mpProgress->SetState(++mnPagesWritten);
2049 pOutliner->Clear();
2051 return bOk;
2054 // create outline pages (for frames)
2056 bool HtmlExport::CreateOutlinePages()
2058 bool bOk = true;
2060 if( mbDocColors )
2062 SetDocColors();
2065 // page 0 will be the closed outline, page 1 the opened
2066 for (sal_Int32 nPage = 0; nPage < (mbImpress?2:1) && bOk; ++nPage)
2068 // Html head
2069 OUStringBuffer aStr(gaHTMLHeader
2070 + CreateMetaCharset()
2071 + " <title>"
2072 + StringToHTMLString(maPageNames[0])
2073 + "</title>\r\n</head>\r\n"
2074 + CreateBodyTag());
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)
2091 + "</p>");
2093 if(nPage==1)
2095 aStr.append(CreateTextForPage( pOutliner, pPage, false, maBackColor ));
2097 aStr.append("</div>\r\n");
2099 pOutliner->Clear();
2101 aStr.append("</body>\r\n</html>");
2103 OUString aFileName("outline" + OUString::number(nPage));
2104 bOk = WriteHtml(aFileName, true, aStr);
2105 aStr.setLength(0);
2107 if (mpProgress)
2108 mpProgress->SetState(++mnPagesWritten);
2111 return bOk;
2114 // set file name
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;
2131 else
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";
2143 else
2144 aImageFileName += ".png";
2146 maImageFiles[nSdPage] = aImageFileName;
2148 OUString aThumbnailFileName = "thumb" + OUString::number(nSdPage);
2149 if( meFormat!=FORMAT_JPG )
2150 aThumbnailFileName += ".png";
2151 else
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;
2166 else
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
2176 // page
2177 if( !mbHeader )
2179 if(mbImpress)
2181 // if there is a non-empty title object, use their first passage
2182 // as page title
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();
2188 if (pParaObject)
2190 const EditTextObject& rEditTextObject =
2191 pParaObject->GetTextObject();
2192 OUString aTest(rEditTextObject.GetText(0));
2193 if (!aTest.isEmpty())
2194 mDocTitle = aTest;
2198 mDocTitle = mDocTitle.replace(0xff, ' ');
2201 if (mDocTitle.isEmpty())
2203 mDocTitle = maDocFileName;
2204 sal_Int32 nDot = mDocTitle.indexOf('.');
2205 if (nDot > 0)
2206 mDocTitle = mDocTitle.copy(0, nDot);
2208 mbHeader = true;
2211 return mDocTitle;
2214 constexpr OUStringLiteral JS_NavigateAbs =
2215 u"function NavigateAbs( nPage )\r\n"
2216 "{\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"
2221 " {\r\n"
2222 " frames[\"navbar1\"].location.href = \"navbar0.$EXT\";\r\n"
2223 " }\r\n"
2224 " else if(nCurrentPage==nPageCount-1)\r\n"
2225 " {\r\n"
2226 " frames[\"navbar1\"].location.href = \"navbar2.$EXT\";\r\n"
2227 " }\r\n"
2228 " else\r\n"
2229 " {\r\n"
2230 " frames[\"navbar1\"].location.href = \"navbar1.$EXT\";\r\n"
2231 " }\r\n"
2232 "}\r\n\r\n";
2234 constexpr OUStringLiteral JS_NavigateRel =
2235 u"function NavigateRel( nDelta )\r\n"
2236 "{\r\n"
2237 " var nPage = parseInt(nCurrentPage) + parseInt(nDelta);\r\n"
2238 " if( (nPage >= 0) && (nPage < nPageCount) )\r\n"
2239 " {\r\n"
2240 " NavigateAbs( nPage );\r\n"
2241 " }\r\n"
2242 "}\r\n\r\n";
2244 constexpr OUStringLiteral JS_ExpandOutline =
2245 u"function ExpandOutline()\r\n"
2246 "{\r\n"
2247 " frames[\"navbar2\"].location.href = \"navbar4.$EXT\";\r\n"
2248 " frames[\"outline\"].location.href = \"outline1.$EXT\";\r\n"
2249 "}\r\n\r\n";
2251 constexpr OUStringLiteral JS_CollapseOutline =
2252 u"function CollapseOutline()\r\n"
2253 "{\r\n"
2254 " frames[\"navbar2\"].location.href = \"navbar3.$EXT\";\r\n"
2255 " frames[\"outline\"].location.href = \"outline0.$EXT\";\r\n"
2256 "}\r\n\r\n";
2258 // create page with the frames
2260 bool HtmlExport::CreateFrames()
2262 OUString aTmp;
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()
2269 + " <title>"
2270 + StringToHTMLString(maPageNames[0])
2271 + "</title>\r\n"
2273 "<script type=\"text/javascript\">\r\n<!--\r\n"
2275 "var nCurrentPage = 0;\r\nvar nPageCount = "
2276 + OUString::number(static_cast<sal_Int32>(mnSdPageCount))
2277 + ";\r\n\r\n");
2279 OUString aFunction = JS_NavigateAbs;
2281 if(mbNotes)
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);
2293 aStr.append(aTmp);
2295 if(mbImpress)
2297 aTmp = JS_ExpandOutline;
2298 aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension);
2299 aStr.append(aTmp);
2301 aTmp = JS_CollapseOutline;
2302 aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension);
2303 aStr.append(aTmp);
2305 aStr.append("// -->\r\n</script>\r\n"
2307 "</head>\r\n"
2309 "<frameset cols=\"*,"
2310 + OUString::number(static_cast<sal_Int32>(mnWidthPixel + 16))
2311 + "\">\r\n");
2312 if(mbImpress)
2314 aStr.append(
2315 " <frameset rows=\"42,*\">\r\n"
2316 " <frame src=\"navbar3"
2317 + gaHTMLExtension
2318 + "\" name=\"navbar2\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n");
2320 aStr.append(" <frame src=\"outline0"
2321 + gaHTMLExtension
2322 + "\" name=\"outline\">\r\n");
2323 if(mbImpress)
2324 aStr.append(" </frameset>\r\n");
2326 if(mbNotes)
2328 aStr.append(" <frameset rows=\"42,"
2329 + OUString::number(static_cast<sal_Int32>(static_cast<double>(mnWidthPixel) * 0.75) + 16)
2330 + ",*\">\r\n");
2332 else
2333 aStr.append(" <frameset rows=\"42,*\">\r\n");
2335 aStr.append(
2336 " <frame src=\"navbar0"
2337 + gaHTMLExtension
2338 + "\" name=\"navbar1\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n"
2340 " <frame src=\""
2341 + maHTMLFiles[0]
2342 + "\" name=\"show\" marginwidth=\"4\" marginheight=\"4\">\r\n");
2344 if(mbNotes)
2346 aStr.append(" <frame src=\"note0"
2347 + gaHTMLExtension
2348 + "\" name=\"notes\">\r\n");
2350 aStr.append(" </frameset>\r\n"
2352 "<noframes>\r\n"
2353 + CreateBodyTag()
2354 + RESTOHTML(STR_HTMLEXP_NOFRAMES)
2355 + "\r\n</noframes>\r\n</frameset>\r\n</html>");
2357 bool bOk = WriteHtml(maFramePage, false, aStr);
2359 if (mpProgress)
2360 mpProgress->SetState(++mnPagesWritten);
2362 return bOk;
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()
2374 bool bOk = true;
2375 OUString aButton;
2377 if( mbDocColors )
2379 SetDocColors();
2380 maBackColor = maFirstPageColor;
2383 for( int nFile = 0; nFile < 3 && bOk; nFile++ )
2385 OUStringBuffer aStr(
2386 gaHTMLHeader
2387 + CreateMetaCharset()
2388 + " <title>"
2389 + StringToHTMLString(maPageNames[0])
2390 + "</title>\r\n</head>\r\n"
2391 + CreateBodyTag()
2392 + "<center>\r\n");
2394 // first page
2395 aButton = SdResId(STR_HTMLEXP_FIRSTPAGE);
2396 if(mnButtonThema != -1)
2397 aButton = CreateImage(GetButtonName(nFile == 0 || mnSdPageCount == 1 ? BTN_FIRST_0 : BTN_FIRST_1),
2398 aButton);
2400 if(nFile != 0 && mnSdPageCount > 1)
2401 aButton = CreateLink(u"JavaScript:parent.NavigateAbs(0)", aButton);
2403 aStr.append(aButton
2404 + "\r\n");
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),
2411 aButton);
2413 if(nFile != 0 && mnSdPageCount > 1)
2414 aButton = CreateLink(u"JavaScript:parent.NavigateRel(-1)", aButton);
2416 aStr.append(aButton
2417 + "\r\n");
2419 // to the next page
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),
2424 aButton);
2426 if(nFile != 2 && mnSdPageCount > 1)
2427 aButton = CreateLink(u"JavaScript:parent.NavigateRel(1)", aButton);
2429 aStr.append(aButton
2430 + "\r\n");
2432 // to the last page
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),
2437 aButton);
2439 if(nFile != 2 && mnSdPageCount > 1)
2441 OUString aLink("JavaScript:parent.NavigateAbs(" +
2442 OUString::number(mnSdPageCount-1) + ")");
2444 aButton = CreateLink(aLink, aButton);
2447 aStr.append(aButton
2448 + "\r\n");
2450 // content
2451 if (mbContentsPage)
2453 aButton = SdResId(STR_PUBLISH_OUTLINE);
2454 if(mnButtonThema != -1)
2455 aButton = CreateImage(GetButtonName(BTN_INDEX), aButton);
2457 // to the overview
2458 aStr.append(CreateLink(maIndex, aButton, u"_top")
2459 + "\r\n");
2462 // text mode
2463 if(mbImpress)
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")
2471 + "\r\n");
2474 // and finished...
2475 aStr.append(
2476 "</center>\r\n"
2477 "</body>\r\n</html>");
2479 OUString aFileName("navbar" + OUString::number(nFile));
2481 bOk = WriteHtml(aFileName, true, aStr);
2482 aStr.setLength(0);
2484 if (mpProgress)
2485 mpProgress->SetState(++mnPagesWritten);
2488 // the navigation bar outliner closed...
2489 if(bOk)
2491 aButton = SdResId(STR_HTMLEXP_OUTLINE);
2492 if(mnButtonThema != -1)
2493 aButton = CreateImage(GetButtonName(BTN_MORE), aButton);
2495 bOk = WriteHtml(
2496 "navbar3", true,
2497 Concat2View(
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>"));
2503 if (mpProgress)
2504 mpProgress->SetState(++mnPagesWritten);
2507 // ... and the outliner open
2508 if( bOk )
2510 aButton = SdResId(STR_HTMLEXP_NOOUTLINE);
2511 if(mnButtonThema != -1)
2512 aButton = CreateImage(GetButtonName(BTN_LESS), aButton);
2514 bOk = WriteHtml(
2515 "navbar4", true,
2516 Concat2View(
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>"));
2522 if (mpProgress)
2523 mpProgress->SetState(++mnPagesWritten);
2527 return bOk;
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;
2540 if( bIsText )
2542 aStrNavText = SdResId(STR_HTMLEXP_SETGRAPHIC);
2544 else
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);
2556 else
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);
2567 else
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");
2579 // first page
2580 if(nSdPage > 0)
2581 aStr.append(CreateLink( bIsText ? maTextFiles[0] : maHTMLFiles[0],aStrNavFirst));
2582 else
2583 aStr.append(aStrNavFirst);
2584 aStr.append(' ');
2586 // to Previous page
2587 if(nSdPage > 0)
2588 aStr.append(CreateLink( bIsText ? maTextFiles[nSdPage-1]
2589 : maHTMLFiles[nSdPage-1], aStrNavPrev));
2590 else
2591 aStr.append(aStrNavPrev);
2592 aStr.append(' ');
2594 // to Next page
2595 if(nSdPage < mnSdPageCount-1)
2596 aStr.append(CreateLink( bIsText ? maTextFiles[nSdPage+1]
2597 : maHTMLFiles[nSdPage+1], aStrNavNext));
2598 else
2599 aStr.append(aStrNavNext);
2600 aStr.append(' ');
2602 // to Last page
2603 if(nSdPage < mnSdPageCount-1)
2604 aStr.append(CreateLink( bIsText ? maTextFiles[mnSdPageCount-1]
2605 : maHTMLFiles[mnSdPageCount-1],
2606 aStrNavLast));
2607 else
2608 aStr.append(aStrNavLast);
2609 aStr.append(' ');
2611 // to Index page
2612 if (mbContentsPage)
2614 aStr.append(CreateLink(maIndex, aStrNavContent) + " ");
2617 // Text/Graphics
2618 if(mbImpress)
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)
2634 return;
2636 for( int nButton = 0; nButton != SAL_N_ELEMENTS(pButtonNames); nButton++ )
2638 if(!mbFrames && (nButton == BTN_MORE || nButton == BTN_LESS))
2639 continue;
2641 if(!mbImpress && (nButton == BTN_TEXT || nButton == BTN_MORE || nButton == BTN_LESS ))
2642 continue;
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 )
2662 + "\" bgcolor=\""
2663 + ColorToHTMLString( maBackColor )
2664 + "\" link=\""
2665 + ColorToHTMLString( maLinkColor )
2666 + "\" vlink=\""
2667 + ColorToHTMLString( maVLinkColor )
2668 + "\" alink=\""
2669 + ColorToHTMLString( maALinkColor )
2670 + "\"");
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 + "\"");
2702 else
2704 // Agerskov: HTML 4.01 has to have an alt attribute even if it is an empty string
2705 aStr.append(" alt=\"\"");
2708 aStr.append('>');
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,
2730 sal_uLong nCenterX,
2731 sal_uLong nCenterY,
2732 std::u16string_view rHRef )
2734 OUString aStr(
2735 "<area shape=\"circle\" alt=\"\" coords=\"" +
2736 OUString::number(nCenterX) + "," +
2737 OUString::number(nCenterY) + "," +
2738 OUString::number(nRadius) +
2739 "\" href=\"" + rHRef + "\">\n");
2741 return aStr;
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)
2771 aStr.append(',');
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 )
2783 OUString aStr(
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");
2791 return aStr;
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 )
2807 if(mbFrames)
2809 return OUString("JavaScript:parent.NavigateAbs(" +
2810 OUString::number(nPgNum) + ")");
2812 else
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 );
2829 if( pIStm )
2831 OStringBuffer aLine;
2833 while( pIStm->ReadLine( aLine ) )
2835 aScriptBuf.appendAscii( aLine.getStr(), aLine.getLength() );
2836 if( bUnix )
2838 aScriptBuf.append("\n");
2840 else
2842 aScriptBuf.append("\r\n");
2846 nErr = pIStm->GetError();
2847 pIStm.reset();
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
2868 EasyFile aFile;
2869 SvStream* pStr;
2870 nErr = aFile.createStream(aDest, pStr);
2871 if(nErr == ERRCODE_NONE)
2873 OString aStr(OUStringToOString(aScript, RTL_TEXTENCODING_UTF8));
2874 pStr->WriteOString( aStr );
2875 aFile.close();
2879 if (mpProgress)
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))
2898 return false;
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))
2914 return false;
2917 if (!CopyScript(maExportPath, "edit.pl", maIndex, true))
2918 return false;
2920 if (!CopyScript(maExportPath, "index.pl", maIndexUrl, true))
2921 return false;
2923 return 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++)
2932 aStr.append(
2933 OUString::number(static_cast<sal_Int32>(nSdPage + 1))
2934 + ";"
2935 + maURLPath
2936 + maImageFiles[nSdPage]
2937 + "\r\n");
2940 bool bOk = WriteHtml("picture.txt", false, aStr);
2942 if (mpProgress)
2943 mpProgress->SetState(++mnPagesWritten);
2945 return bOk;
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 );
2955 EasyFile aFile;
2956 SvStream* pStr;
2957 ErrCode nErr = aFile.createStream(aFull, pStr);
2958 if(nErr == ERRCODE_NONE)
2960 pStr->WriteOString( "1" );
2961 aFile.close();
2964 if (mpProgress)
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())
2976 return rSoundFile;
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);
2988 return aStr;
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));
2999 return false;
3001 else
3003 return true;
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()" );
3019 return false;
3022 bool HtmlExport::checkForExistingFiles()
3024 bool bFound = false;
3028 Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
3029 uno::Reference<ucb::XSimpleFileAccess3> xFA(ucb::SimpleFileAccess::create(xContext));
3031 sal_uInt16 nSdPage;
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] ) )
3040 bFound = true;
3044 if( !bFound && mbDownload )
3045 bFound = checkFileExists( xFA, maDocFileName );
3047 if( !bFound && mbFrames )
3048 bFound = checkFileExists( xFA, maFramePage );
3050 if( bFound )
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,
3059 aMsg));
3060 xWarn->set_default_response(RET_YES);
3061 bFound = (RET_NO == xWarn->run());
3064 catch( Exception& )
3066 TOOLS_WARN_EXCEPTION( "sd", "sd::HtmlExport::checkForExistingFiles()" );
3067 bFound = false;
3070 return bFound;
3073 OUString HtmlExport::GetButtonName( int nButton )
3075 return OUString::createFromAscii(pButtonNames[nButton]);
3078 EasyFile::EasyFile() : bOpen(false)
3082 EasyFile::~EasyFile()
3084 if( bOpen )
3085 close();
3088 ErrCode EasyFile::createStream( const OUString& rUrl, SvStream* &rpStr )
3090 if(bOpen)
3091 close();
3093 OUString aFileName;
3094 createFileName( rUrl, aFileName );
3096 ErrCode nErr = ERRCODE_NONE;
3097 pOStm = ::utl::UcbStreamHelper::CreateStream( aFileName, StreamMode::WRITE | StreamMode::TRUNC );
3098 if( pOStm )
3100 bOpen = true;
3101 nErr = pOStm->GetError();
3103 else
3105 nErr = ERRCODE_SFX_CANTCREATECONTENT;
3108 if( nErr != ERRCODE_NONE )
3110 bOpen = false;
3111 pOStm.reset();
3114 rpStr = pOStm.get();
3116 return nErr;
3119 void EasyFile::createFileName( const OUString& rURL, OUString& rFileName )
3121 if( bOpen )
3122 close();
3124 INetURLObject aURL( rURL );
3126 if( aURL.GetProtocol() == INetProtocol::NotValid )
3128 OUString aURLStr;
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()
3138 pOStm.reset();
3139 bOpen = false;
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");
3151 if (!mpResId)
3152 return false;
3154 rCtxStr = SdResId(mpResId);
3156 rCtxStr = rCtxStr.replaceAll( "$(URL1)", maURL1 );
3157 rCtxStr = rCtxStr.replaceAll( "$(URL2)", maURL2 );
3159 return true;
3162 void HtmlErrorContext::SetContext(TranslateId pResId, const OUString& rURL)
3164 mpResId = pResId;
3165 maURL1 = rURL;
3166 maURL2.clear();
3169 void HtmlErrorContext::SetContext(TranslateId pResId, const OUString& rURL1, const OUString& rURL2 )
3171 mpResId = pResId;
3172 maURL1 = rURL1;
3173 maURL2 = rURL2;
3176 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */