bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / filter / html / htmlex.cxx
blob7b7bb2f9d1bb760862db6413939ef5719e5f89e2
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/ucb/SimpleFileAccess.hpp>
25 #include <sal/log.hxx>
26 #include <rtl/tencinfo.h>
27 #include <comphelper/processfactory.hxx>
28 #include <osl/file.hxx>
29 #include <unotools/pathoptions.hxx>
30 #include <unotools/ucbstreamhelper.hxx>
31 #include <com/sun/star/frame/XStorable.hpp>
32 #include <sfx2/frmhtmlw.hxx>
33 #include <sfx2/progress.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/weld.hxx>
36 #include <svx/svditer.hxx>
37 #include <vcl/imaprect.hxx>
38 #include <vcl/imapcirc.hxx>
39 #include <vcl/imappoly.hxx>
40 #include <editeng/eeitem.hxx>
41 #include <editeng/outlobj.hxx>
42 #include <editeng/editobj.hxx>
43 #include <svx/svdopath.hxx>
44 #include <svtools/htmlout.hxx>
45 #include <svtools/colorcfg.hxx>
46 #include <editeng/colritem.hxx>
47 #include <editeng/editeng.hxx>
48 #include <editeng/wghtitem.hxx>
49 #include <editeng/udlnitem.hxx>
50 #include <editeng/postitem.hxx>
51 #include <editeng/crossedoutitem.hxx>
52 #include <editeng/flditem.hxx>
53 #include <svl/style.hxx>
54 #include <editeng/frmdiritem.hxx>
55 #include <svx/svdoutl.hxx>
56 #include <svx/svdogrp.hxx>
57 #include <svx/svdotable.hxx>
58 #include <tools/urlobj.hxx>
59 #include <svtools/sfxecode.hxx>
60 #include <comphelper/anytostring.hxx>
61 #include <cppuhelper/exc_hlp.hxx>
62 #include <basegfx/polygon/b2dpolygon.hxx>
63 #include <tools/debug.hxx>
64 #include <tools/diagnose_ex.h>
66 #include <drawdoc.hxx>
67 #include <DrawDocShell.hxx>
68 #include "htmlpublishmode.hxx"
69 #include <Outliner.hxx>
70 #include <sdpage.hxx>
71 #include <strings.hrc>
72 #include <strings.hxx>
73 #include <anminfo.hxx>
74 #include <imapinfo.hxx>
75 #include <sdresid.hxx>
76 #include "buttonset.hxx"
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::frame;
82 using namespace ::com::sun::star::lang;
83 using namespace ::com::sun::star::document;
85 using namespace sdr::table;
87 // get parameter from Itemset
88 #define RESTOHTML( res ) StringToHTMLString(SdResId(res))
90 const char * const pButtonNames[] =
92 "first-inactive.png",
93 "first.png",
94 "left-inactive.png",
95 "left.png",
96 "right-inactive.png",
97 "right.png",
98 "last-inactive.png",
99 "last.png",
100 "home.png",
101 "text.png",
102 "expand.png",
103 "collapse.png",
106 #define BTN_FIRST_0 0
107 #define BTN_FIRST_1 1
108 #define BTN_PREV_0 2
109 #define BTN_PREV_1 3
110 #define BTN_NEXT_0 4
111 #define BTN_NEXT_1 5
112 #define BTN_LAST_0 6
113 #define BTN_LAST_1 7
114 #define BTN_INDEX 8
115 #define BTN_TEXT 9
116 #define BTN_MORE 10
117 #define BTN_LESS 11
119 // Helper class for the simple creation of files local/remote
120 class EasyFile
122 private:
123 std::unique_ptr<SvStream> pOStm;
124 bool bOpen;
126 public:
128 EasyFile();
129 ~EasyFile();
131 ErrCode createStream( const OUString& rUrl, SvStream*& rpStr );
132 void createFileName( const OUString& rUrl, OUString& rFileName );
133 void close();
136 // Helper class for the embedding of text attributes into the html output
137 class HtmlState
139 private:
140 bool mbColor;
141 bool mbWeight;
142 bool mbItalic;
143 bool mbUnderline;
144 bool mbStrike;
145 bool mbLink;
146 Color maColor;
147 Color maDefColor;
148 OUString maLink;
149 OUString maTarget;
151 public:
152 explicit HtmlState( Color aDefColor );
154 OUString SetWeight( bool bWeight );
155 OUString SetItalic( bool bItalic );
156 OUString SetUnderline( bool bUnderline );
157 OUString SetColor( Color aColor );
158 OUString SetStrikeout( bool bStrike );
159 OUString SetLink( const OUString& aLink, const OUString& aTarget );
160 OUString Flush();
163 // close all still open tags
164 OUString HtmlState::Flush()
166 OUString aStr = SetWeight(false)
167 + SetItalic(false)
168 + SetUnderline(false)
169 + SetStrikeout(false)
170 + SetColor(maDefColor)
171 + SetLink("","");
173 return aStr;
176 // c'tor with default color for the page
177 HtmlState::HtmlState( Color aDefColor )
179 mbColor = false;
180 mbWeight = false;
181 mbItalic = false;
182 mbUnderline = false;
183 mbLink = false;
184 mbStrike = false;
185 maDefColor = aDefColor;
188 // enables/disables bold print
189 OUString HtmlState::SetWeight( bool bWeight )
191 OUString aStr;
193 if(bWeight && !mbWeight)
194 aStr = "<b>";
195 else if(!bWeight && mbWeight)
196 aStr = "</b>";
198 mbWeight = bWeight;
199 return aStr;
202 // enables/disables italic
204 OUString HtmlState::SetItalic( bool bItalic )
206 OUString aStr;
208 if(bItalic && !mbItalic)
209 aStr = "<i>";
210 else if(!bItalic && mbItalic)
211 aStr = "</i>";
213 mbItalic = bItalic;
214 return aStr;
217 // enables/disables underlines
219 OUString HtmlState::SetUnderline( bool bUnderline )
221 OUString aStr;
223 if(bUnderline && !mbUnderline)
224 aStr = "<u>";
225 else if(!bUnderline && mbUnderline)
226 aStr = "</u>";
228 mbUnderline = bUnderline;
229 return aStr;
232 // enables/disables strike through
233 OUString HtmlState::SetStrikeout( bool bStrike )
235 OUString aStr;
237 if(bStrike && !mbStrike)
238 aStr = "<strike>";
239 else if(!bStrike && mbStrike)
240 aStr = "</strike>";
242 mbStrike = bStrike;
243 return aStr;
246 // Sets the specified text color
247 OUString HtmlState::SetColor( Color aColor )
249 OUString aStr;
251 if(mbColor && aColor == maColor)
252 return aStr;
254 if(mbColor)
256 aStr = "</font>";
257 mbColor = false;
260 if(aColor != maDefColor)
262 maColor = aColor;
263 aStr += "<font color=\"" + HtmlExport::ColorToHTMLString(aColor) + "\">";
264 mbColor = true;
267 return aStr;
270 // enables/disables a hyperlink
271 OUString HtmlState::SetLink( const OUString& aLink, const OUString& aTarget )
273 OUString aStr;
275 if(mbLink&&maLink == aLink&&maTarget==aTarget)
276 return aStr;
278 if(mbLink)
280 aStr = "</a>";
281 mbLink = false;
284 if (!aLink.isEmpty())
286 aStr += "<a href=\"" + aLink;
287 if (!aTarget.isEmpty())
289 aStr += "\" target=\"" + aTarget;
291 aStr += "\">";
292 mbLink = true;
293 maLink = aLink;
294 maTarget = aTarget;
297 return aStr;
299 namespace
302 OUString getParagraphStyle( SdrOutliner* pOutliner, sal_Int32 nPara )
304 SfxItemSet aParaSet( pOutliner->GetParaAttribs( nPara ) );
306 OUString sStyle;
308 if( aParaSet.GetItem<SvxFrameDirectionItem>( EE_PARA_WRITINGDIR )->GetValue() == SvxFrameDirection::Horizontal_RL_TB )
311 sStyle = "direction: rtl;";
313 else
315 // This is the default so don't write it out
316 // sStyle += "direction: ltr;";
318 return sStyle;
321 void lclAppendStyle(OUStringBuffer& aBuffer, const OUString& aTag, const OUString& aStyle)
323 if (aStyle.isEmpty())
324 aBuffer.append("<").append(aTag).append(">");
325 else
326 aBuffer.append("<").append(aTag).append(" style=\"").append(aStyle).append("\">");
329 } // anonymous namespace
331 static constexpr OUStringLiteral gaHTMLHeader(
332 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\r\n"
333 " \"http://www.w3.org/TR/html4/transitional.dtd\">\r\n"
334 "<html>\r\n<head>\r\n" );
336 static constexpr OUStringLiteral gaHTMLExtension = STR_HTMLEXP_DEFAULT_EXTENSION;
338 // constructor for the html export helper classes
339 HtmlExport::HtmlExport(
340 const OUString& aPath,
341 const Sequence< PropertyValue >& rParams,
342 SdDrawDocument* pExpDoc,
343 sd::DrawDocShell* pDocShell )
344 : maPath( aPath ),
345 mpDoc(pExpDoc),
346 mpDocSh( pDocShell ),
347 meEC(),
348 meMode( PUBLISH_SINGLE_DOCUMENT ),
349 mbContentsPage(false),
350 mnButtonThema(-1),
351 mnWidthPixel( PUB_MEDRES_WIDTH ),
352 meFormat( FORMAT_JPG ),
353 mbNotes(false),
354 mnCompression( -1 ),
355 mbDownload( false ),
356 mbSlideSound(true),
357 mbHiddenSlides(true),
358 mbUserAttr(false),
359 maTextColor(COL_BLACK),
360 maBackColor(COL_WHITE),
361 mbDocColors(false),
362 maIndexUrl("index"),
363 meScript( SCRIPT_ASP ),
364 mpButtonSet( new ButtonSet() )
366 bool bChange = mpDoc->IsChanged();
368 maIndexUrl += gaHTMLExtension;
370 InitExportParameters( rParams );
372 switch( meMode )
374 case PUBLISH_HTML:
375 case PUBLISH_FRAMES:
376 ExportHtml();
377 break;
378 case PUBLISH_WEBCAST:
379 ExportWebCast();
380 break;
381 case PUBLISH_KIOSK:
382 ExportKiosk();
383 break;
384 case PUBLISH_SINGLE_DOCUMENT:
385 ExportSingleDocument();
386 break;
389 mpDoc->SetChanged(bChange);
392 HtmlExport::~HtmlExport()
396 // get common export parameters from item set
397 void HtmlExport::InitExportParameters( const Sequence< PropertyValue >& rParams )
399 mbImpress = mpDoc->GetDocumentType() == DocumentType::Impress;
401 sal_Int32 nArgs = rParams.getLength();
402 const PropertyValue* pParams = rParams.getConstArray();
403 OUString aStr;
404 while( nArgs-- )
406 if ( pParams->Name == "PublishMode" )
408 sal_Int32 temp = 0;
409 pParams->Value >>= temp;
410 meMode = static_cast<HtmlPublishMode>(temp);
412 else if ( pParams->Name == "IndexURL" )
414 pParams->Value >>= aStr;
415 maIndexUrl = aStr;
417 else if ( pParams->Name == "Format" )
419 sal_Int32 temp = 0;
420 pParams->Value >>= temp;
421 meFormat = static_cast<PublishingFormat>(temp);
423 else if ( pParams->Name == "Compression" )
425 pParams->Value >>= aStr;
426 OUString aTmp( aStr );
427 if(!aTmp.isEmpty())
429 aTmp = aTmp.replaceFirst("%", "");
430 mnCompression = static_cast<sal_Int16>(aTmp.toInt32());
433 else if ( pParams->Name == "Width" )
435 sal_Int32 temp = 0;
436 pParams->Value >>= temp;
437 mnWidthPixel = static_cast<sal_uInt16>(temp);
439 else if ( pParams->Name == "UseButtonSet" )
441 sal_Int32 temp = 0;
442 pParams->Value >>= temp;
443 mnButtonThema = static_cast<sal_Int16>(temp);
445 else if ( pParams->Name == "IsExportNotes" )
447 if( mbImpress )
449 bool temp = false;
450 pParams->Value >>= temp;
451 mbNotes = temp;
454 else if ( pParams->Name == "IsExportContentsPage" )
456 bool temp = false;
457 pParams->Value >>= temp;
458 mbContentsPage = temp;
460 else if ( pParams->Name == "Author" )
462 pParams->Value >>= aStr;
463 maAuthor = aStr;
465 else if ( pParams->Name == "EMail" )
467 pParams->Value >>= aStr;
468 maEMail = aStr;
470 else if ( pParams->Name == "HomepageURL" )
472 pParams->Value >>= aStr;
473 maHomePage = aStr;
475 else if ( pParams->Name == "UserText" )
477 pParams->Value >>= aStr;
478 maInfo = aStr;
480 else if ( pParams->Name == "EnableDownload" )
482 bool temp = false;
483 pParams->Value >>= temp;
484 mbDownload = temp;
486 else if ( pParams->Name == "SlideSound" )
488 bool temp = true;
489 pParams->Value >>= temp;
490 mbSlideSound = temp;
492 else if ( pParams->Name == "HiddenSlides" )
494 bool temp = true;
495 pParams->Value >>= temp;
496 mbHiddenSlides = temp;
498 else if ( pParams->Name == "BackColor" )
500 sal_Int32 temp = 0;
501 pParams->Value >>= temp;
502 maBackColor = Color(temp);
503 mbUserAttr = true;
505 else if ( pParams->Name == "TextColor" )
507 sal_Int32 temp = 0;
508 pParams->Value >>= temp;
509 maTextColor = Color(temp);
510 mbUserAttr = true;
512 else if ( pParams->Name == "LinkColor" )
514 sal_Int32 temp = 0;
515 pParams->Value >>= temp;
516 maLinkColor = Color(temp);
517 mbUserAttr = true;
519 else if ( pParams->Name == "VLinkColor" )
521 sal_Int32 temp = 0;
522 pParams->Value >>= temp;
523 maVLinkColor = Color(temp);
524 mbUserAttr = true;
526 else if ( pParams->Name == "ALinkColor" )
528 sal_Int32 temp = 0;
529 pParams->Value >>= temp;
530 maALinkColor = Color(temp);
531 mbUserAttr = true;
533 else if ( pParams->Name == "IsUseDocumentColors" )
535 bool temp = false;
536 pParams->Value >>= temp;
537 mbDocColors = temp;
539 else if ( pParams->Name == "KioskSlideDuration" )
541 double temp = 0.0;
542 pParams->Value >>= temp;
543 mfSlideDuration = temp;
544 mbAutoSlide = true;
546 else if ( pParams->Name == "KioskEndless" )
548 bool temp = false;
549 pParams->Value >>= temp;
550 mbEndless = temp;
552 else if ( pParams->Name == "WebCastCGIURL" )
554 pParams->Value >>= aStr;
555 maCGIPath = aStr;
557 else if ( pParams->Name == "WebCastTargetURL" )
559 pParams->Value >>= aStr;
560 maURLPath = aStr;
562 else if ( pParams->Name == "WebCastScriptLanguage" )
564 pParams->Value >>= aStr;
565 if ( aStr == "asp" )
567 meScript = SCRIPT_ASP;
569 else
571 meScript = SCRIPT_PERL;
574 else
576 OSL_FAIL("Unknown property for html export detected!");
579 pParams++;
582 if( meMode == PUBLISH_KIOSK )
584 mbContentsPage = false;
585 mbNotes = false;
589 // calculate image sizes
590 SdPage* pPage = mpDoc->GetSdPage(0, PageKind::Standard);
591 Size aTmpSize( pPage->GetSize() );
592 double dRatio=static_cast<double>(aTmpSize.Width())/aTmpSize.Height();
594 mnHeightPixel = static_cast<sal_uInt16>(mnWidthPixel/dRatio);
596 // we come up with a destination...
598 INetURLObject aINetURLObj( maPath );
599 DBG_ASSERT( aINetURLObj.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
601 maExportPath = aINetURLObj.GetPartBeforeLastName(); // with trailing '/'
602 maIndex = aINetURLObj.GetLastName();
604 mnSdPageCount = mpDoc->GetSdPageCount( PageKind::Standard );
605 for( sal_uInt16 nPage = 0; nPage < mnSdPageCount; nPage++ )
607 pPage = mpDoc->GetSdPage( nPage, PageKind::Standard );
609 if( mbHiddenSlides || !pPage->IsExcluded() )
611 maPages.push_back( pPage );
612 maNotesPages.push_back( mpDoc->GetSdPage( nPage, PageKind::Notes ) );
615 mnSdPageCount = maPages.size();
617 mbFrames = meMode == PUBLISH_FRAMES;
619 maDocFileName = maIndex;
622 void HtmlExport::ExportSingleDocument()
624 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
626 maPageNames.resize(mnSdPageCount);
628 mnPagesWritten = 0;
629 InitProgress(mnSdPageCount);
631 OUStringBuffer aStr(gaHTMLHeader);
632 aStr.append(DocumentMetadata());
633 aStr.append("\r\n");
634 aStr.append("</head>\r\n");
635 aStr.append(CreateBodyTag());
637 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; ++nSdPage)
639 SdPage* pPage = maPages[nSdPage];
640 maPageNames[nSdPage] = pPage->GetName();
642 if( mbDocColors )
644 SetDocColors( pPage );
647 // page title
648 OUString sTitleText(CreateTextForTitle(pOutliner, pPage, pPage->GetPageBackgroundColor()));
649 OUString sStyle;
651 if (nSdPage != 0) // First page - no need for a page brake here
652 sStyle += "page-break-before:always; ";
653 sStyle += getParagraphStyle(pOutliner, 0);
655 lclAppendStyle(aStr, "h1", sStyle);
657 aStr.append(sTitleText);
658 aStr.append("</h1>\r\n");
660 // write outline text
661 aStr.append(CreateTextForPage( pOutliner, pPage, true, pPage->GetPageBackgroundColor() ));
663 // notes
664 if(mbNotes)
666 SdPage* pNotesPage = maNotesPages[ nSdPage ];
667 OUString aNotesStr( CreateTextForNotesPage( pOutliner, pNotesPage, maBackColor) );
669 if (!aNotesStr.isEmpty())
671 aStr.append("<br>\r\n<h3>");
672 aStr.append(RESTOHTML(STR_HTMLEXP_NOTES));
673 aStr.append(":</h3>\r\n");
675 aStr.append(aNotesStr);
679 if (mpProgress)
680 mpProgress->SetState(++mnPagesWritten);
684 // close page
685 aStr.append("</body>\r\n</html>");
687 WriteHtml(maDocFileName, false, aStr.makeStringAndClear());
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(PRESOBJ_OUTLINE);
810 if(pSheet == nullptr)
811 pSheet = pPage->GetStyleSheetForPresObj(PRESOBJ_TEXT);
812 if(pSheet == nullptr)
813 pSheet = pPage->GetStyleSheetForPresObj(PRESOBJ_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( 2 );
938 aProperties[ 0 ].Name = "Overwrite";
939 aProperties[ 0 ].Value <<= true;
940 aProperties[ 1 ].Name = "FilterName";
941 aProperties[ 1 ].Value <<= OUString("impress8");
942 xStorable->storeToURL( aURL, aProperties );
944 mpDocSh->EnableSetModified( false );
946 return true;
949 catch( Exception& )
953 mpDocSh->EnableSetModified( false );
955 return false;
958 // create image files
959 bool HtmlExport::CreateImagesForPresPages( bool bThumbnail)
963 Reference < XComponentContext > xContext = ::comphelper::getProcessComponentContext();
965 Reference< drawing::XGraphicExportFilter > xGraphicExporter = drawing::GraphicExportFilter::create( xContext );
967 Sequence< PropertyValue > aFilterData(((meFormat==FORMAT_JPG)&&(mnCompression != -1))? 3 : 2);
968 aFilterData[0].Name = "PixelWidth";
969 aFilterData[0].Value <<= static_cast<sal_Int32>(bThumbnail ? PUB_THUMBNAIL_WIDTH : mnWidthPixel );
970 aFilterData[1].Name = "PixelHeight";
971 aFilterData[1].Value <<= static_cast<sal_Int32>(bThumbnail ? PUB_THUMBNAIL_HEIGHT : mnHeightPixel);
972 if((meFormat==FORMAT_JPG)&&(mnCompression != -1))
974 aFilterData[2].Name = "Quality";
975 aFilterData[2].Value <<= static_cast<sal_Int32>(mnCompression);
978 Sequence< PropertyValue > aDescriptor( 3 );
979 aDescriptor[0].Name = "URL";
980 aDescriptor[1].Name = "FilterName";
981 OUString sFormat;
982 if( meFormat == FORMAT_PNG )
983 sFormat = "PNG";
984 else if( meFormat == FORMAT_GIF )
985 sFormat = "GIF";
986 else
987 sFormat = "JPG";
989 aDescriptor[1].Value <<= sFormat;
990 aDescriptor[2].Name = "FilterData";
991 aDescriptor[2].Value <<= aFilterData;
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 aDescriptor[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() == OBJ_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 sal_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 OUString aNonConvertableCharacters;
1067 SfxFrameHTMLWriter::Out_DocInfo(aStream, maDocFileName, xDocProps,
1068 " ", RTL_TEXTENCODING_UTF8,
1069 &aNonConvertableCharacters);
1071 const sal_uInt64 nLen = aStream.GetSize();
1072 OSL_ENSURE(nLen < static_cast<sal_uInt64>(SAL_MAX_INT32), "Stream can't fit in OString");
1073 OString aData(static_cast<const char*>(aStream.GetData()), static_cast<sal_Int32>(nLen));
1075 return OStringToOUString(aData, RTL_TEXTENCODING_UTF8);
1078 bool HtmlExport::CreateHtmlTextForPresPages()
1080 bool bOk = true;
1082 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
1084 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount && bOk; nSdPage++)
1086 SdPage* pPage = maPages[ nSdPage ];
1088 if( mbDocColors )
1090 SetDocColors( pPage );
1093 // HTML head
1094 OUStringBuffer aStr(gaHTMLHeader);
1095 aStr.append(CreateMetaCharset());
1096 aStr.append(" <title>");
1097 aStr.append(StringToHTMLString(maPageNames[nSdPage]));
1098 aStr.append("</title>\r\n");
1099 aStr.append("</head>\r\n");
1100 aStr.append(CreateBodyTag());
1102 // navigation bar
1103 aStr.append(CreateNavBar(nSdPage, true));
1105 // page title
1106 OUString sTitleText( CreateTextForTitle(pOutliner,pPage, pPage->GetPageBackgroundColor()) );
1107 lclAppendStyle(aStr, "h1", getParagraphStyle(pOutliner, 0));
1108 aStr.append(sTitleText);
1109 aStr.append("</h1>\r\n");
1111 // write outline text
1112 aStr.append(CreateTextForPage( pOutliner, pPage, true, pPage->GetPageBackgroundColor() ));
1114 // notes
1115 if(mbNotes)
1117 SdPage* pNotesPage = maNotesPages[ nSdPage ];
1118 OUString aNotesStr( CreateTextForNotesPage( pOutliner, pNotesPage, maBackColor) );
1120 if (!aNotesStr.isEmpty())
1122 aStr.append("<br>\r\n<h3>");
1123 aStr.append(RESTOHTML(STR_HTMLEXP_NOTES));
1124 aStr.append(":</h3>\r\n");
1126 aStr.append(aNotesStr);
1130 // close page
1131 aStr.append("</body>\r\n</html>");
1133 bOk = WriteHtml(maTextFiles[nSdPage], false, aStr.makeStringAndClear());
1135 if (mpProgress)
1136 mpProgress->SetState(++mnPagesWritten);
1140 pOutliner->Clear();
1142 return bOk;
1145 /** exports the given html data into a non unicode file in the current export path with
1146 the given filename */
1147 bool HtmlExport::WriteHtml( const OUString& rFileName, bool bAddExtension, const OUString& rHtmlData )
1149 ErrCode nErr = ERRCODE_NONE;
1151 OUString aFileName( rFileName );
1152 if( bAddExtension )
1153 aFileName += gaHTMLExtension;
1155 meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, rFileName );
1156 EasyFile aFile;
1157 SvStream* pStr;
1158 OUString aFull(maExportPath + aFileName);
1159 nErr = aFile.createStream(aFull , pStr);
1160 if(nErr == ERRCODE_NONE)
1162 OString aStr(OUStringToOString(rHtmlData,
1163 RTL_TEXTENCODING_UTF8));
1164 pStr->WriteCharPtr( aStr.getStr() );
1165 aFile.close();
1168 if( nErr != ERRCODE_NONE )
1169 ErrorHandler::HandleError(nErr);
1171 return nErr == ERRCODE_NONE;
1174 /** creates a outliner text for the title objects of a page
1176 OUString HtmlExport::CreateTextForTitle( SdrOutliner* pOutliner, SdPage* pPage, const Color& rBackgroundColor )
1178 SdrTextObj* pTO = static_cast<SdrTextObj*>(pPage->GetPresObj(PRESOBJ_TITLE));
1179 if(!pTO)
1180 pTO = GetLayoutTextObject(pPage);
1182 if (pTO && !pTO->IsEmptyPresObj())
1184 OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1185 if(pOPO && pOutliner->GetParagraphCount() != 0)
1187 pOutliner->Clear();
1188 pOutliner->SetText(*pOPO);
1189 return ParagraphToHTMLString(pOutliner,0, rBackgroundColor);
1193 return OUString();
1196 // creates a outliner text for a page
1197 OUString HtmlExport::CreateTextForPage(SdrOutliner* pOutliner, SdPage const * pPage,
1198 bool bHeadLine, const Color& rBackgroundColor)
1200 OUStringBuffer aStr;
1202 for (size_t i = 0; i <pPage->GetObjCount(); ++i )
1204 SdrObject* pObject = pPage->GetObj(i);
1205 PresObjKind eKind = pPage->GetPresObjKind(pObject);
1207 switch (eKind)
1209 case PRESOBJ_NONE:
1211 if (pObject->GetObjIdentifier() == OBJ_GRUP)
1213 SdrObjGroup* pObjectGroup = static_cast<SdrObjGroup*>(pObject);
1214 WriteObjectGroup(aStr, pObjectGroup, pOutliner, rBackgroundColor, false);
1216 else if (pObject->GetObjIdentifier() == OBJ_TABLE)
1218 SdrTableObj* pTableObject = static_cast<SdrTableObj*>(pObject);
1219 WriteTable(aStr, pTableObject, pOutliner, rBackgroundColor);
1221 else
1223 if (pObject->GetOutlinerParaObject())
1225 WriteOutlinerParagraph(aStr, pOutliner, pObject->GetOutlinerParaObject(), rBackgroundColor, false);
1229 break;
1231 case PRESOBJ_TABLE:
1233 SdrTableObj* pTableObject = static_cast<SdrTableObj*>(pObject);
1234 WriteTable(aStr, pTableObject, pOutliner, rBackgroundColor);
1236 break;
1238 case PRESOBJ_TEXT:
1239 case PRESOBJ_OUTLINE:
1241 SdrTextObj* pTextObject = static_cast<SdrTextObj*>(pObject);
1242 if (pTextObject->IsEmptyPresObj())
1243 continue;
1244 WriteOutlinerParagraph(aStr, pOutliner, pTextObject->GetOutlinerParaObject(), rBackgroundColor, bHeadLine);
1246 break;
1248 default:
1249 break;
1252 return aStr.makeStringAndClear();
1255 void HtmlExport::WriteTable(OUStringBuffer& aStr, SdrTableObj const * pTableObject, SdrOutliner* pOutliner, const Color& rBackgroundColor)
1257 CellPos aStart, aEnd;
1259 aStart = SdrTableObj::getFirstCell();
1260 aEnd = pTableObject->getLastCell();
1262 sal_Int32 nColCount = pTableObject->getColumnCount();
1263 aStr.append("<table>\r\n");
1264 for (sal_Int32 nRow = aStart.mnRow; nRow <= aEnd.mnRow; nRow++)
1266 aStr.append(" <tr>\r\n");
1267 for (sal_Int32 nCol = aStart.mnCol; nCol <= aEnd.mnCol; nCol++)
1269 aStr.append(" <td>\r\n");
1270 sal_Int32 nCellIndex = nRow * nColCount + nCol;
1271 SdrText* pText = pTableObject->getText(nCellIndex);
1273 if (pText == nullptr)
1274 continue;
1275 WriteOutlinerParagraph(aStr, pOutliner, pText->GetOutlinerParaObject(), rBackgroundColor, false);
1276 aStr.append(" </td>\r\n");
1278 aStr.append(" </tr>\r\n");
1280 aStr.append("</table>\r\n");
1283 void HtmlExport::WriteObjectGroup(OUStringBuffer& aStr, SdrObjGroup const * pObjectGroup, SdrOutliner* pOutliner,
1284 const Color& rBackgroundColor, bool bHeadLine)
1286 SdrObjListIter aGroupIterator(pObjectGroup->GetSubList(), SdrIterMode::DeepNoGroups);
1287 while (aGroupIterator.IsMore())
1289 SdrObject* pCurrentObject = aGroupIterator.Next();
1290 if (pCurrentObject->GetObjIdentifier() == OBJ_GRUP)
1292 SdrObjGroup* pCurrentGroupObject = static_cast<SdrObjGroup*>(pCurrentObject);
1293 WriteObjectGroup(aStr, pCurrentGroupObject, pOutliner, rBackgroundColor, bHeadLine);
1295 else
1297 OutlinerParaObject* pOutlinerParagraphObject = pCurrentObject->GetOutlinerParaObject();
1298 if (pOutlinerParagraphObject != nullptr)
1300 WriteOutlinerParagraph(aStr, pOutliner, pOutlinerParagraphObject, rBackgroundColor, bHeadLine);
1306 void HtmlExport::WriteOutlinerParagraph(OUStringBuffer& aStr, SdrOutliner* pOutliner,
1307 OutlinerParaObject const * pOutlinerParagraphObject,
1308 const Color& rBackgroundColor, bool bHeadLine)
1310 if (pOutlinerParagraphObject == nullptr)
1311 return;
1313 pOutliner->SetText(*pOutlinerParagraphObject);
1315 sal_Int32 nCount = pOutliner->GetParagraphCount();
1318 sal_Int16 nCurrentDepth = -1;
1320 for (sal_Int32 nIndex = 0; nIndex < nCount; nIndex++)
1322 Paragraph* pParagraph = pOutliner->GetParagraph(nIndex);
1323 if(pParagraph == nullptr)
1324 continue;
1326 const sal_Int16 nDepth = static_cast<sal_uInt16>(pOutliner->GetDepth(nIndex));
1327 OUString aParaText = ParagraphToHTMLString(pOutliner, nIndex, rBackgroundColor);
1329 if (aParaText.isEmpty())
1330 continue;
1332 if (nDepth < 0)
1334 OUString aTag = bHeadLine ? OUString("h2") : OUString("p");
1335 lclAppendStyle(aStr, aTag, getParagraphStyle(pOutliner, nIndex));
1337 aStr.append(aParaText);
1338 aStr.append("</").append(aTag).append(">\r\n");
1340 else
1342 while(nCurrentDepth < nDepth)
1344 aStr.append("<ul>\r\n");
1345 nCurrentDepth++;
1347 while(nCurrentDepth > nDepth)
1349 aStr.append("</ul>\r\n");
1350 nCurrentDepth--;
1352 lclAppendStyle(aStr, "li", getParagraphStyle(pOutliner, nIndex));
1353 aStr.append(aParaText);
1354 aStr.append("</li>\r\n");
1357 while(nCurrentDepth >= 0)
1359 aStr.append("</ul>\r\n");
1360 nCurrentDepth--;
1362 pOutliner->Clear();
1365 // creates a outliner text for a note page
1366 OUString HtmlExport::CreateTextForNotesPage( SdrOutliner* pOutliner,
1367 SdPage* pPage,
1368 const Color& rBackgroundColor )
1370 OUStringBuffer aStr;
1372 SdrTextObj* pTO = static_cast<SdrTextObj*>(pPage->GetPresObj(PRESOBJ_NOTES));
1374 if (pTO && !pTO->IsEmptyPresObj())
1376 OutlinerParaObject* pOPO = pTO->GetOutlinerParaObject();
1377 if (pOPO)
1379 pOutliner->Clear();
1380 pOutliner->SetText( *pOPO );
1382 sal_Int32 nCount = pOutliner->GetParagraphCount();
1383 for (sal_Int32 nPara = 0; nPara < nCount; nPara++)
1385 lclAppendStyle(aStr, "p", getParagraphStyle(pOutliner, nPara));
1386 aStr.append(ParagraphToHTMLString(pOutliner, nPara, rBackgroundColor));
1387 aStr.append("</p>\r\n");
1392 return aStr.makeStringAndClear();
1395 // converts a paragraph of the outliner to html
1396 OUString HtmlExport::ParagraphToHTMLString( SdrOutliner const * pOutliner, sal_Int32 nPara, const Color& rBackgroundColor )
1398 OUStringBuffer aStr;
1400 if(nullptr == pOutliner)
1401 return OUString();
1403 // TODO: MALTE!!!
1404 EditEngine& rEditEngine = *const_cast<EditEngine*>(&pOutliner->GetEditEngine());
1405 bool bOldUpdateMode = rEditEngine.GetUpdateMode();
1406 rEditEngine.SetUpdateMode(true);
1408 Paragraph* pPara = pOutliner->GetParagraph(nPara);
1409 if(nullptr == pPara)
1410 return OUString();
1412 HtmlState aState( (mbUserAttr || mbDocColors) ? maTextColor : COL_BLACK );
1413 std::vector<sal_Int32> aPortionList;
1414 rEditEngine.GetPortions( nPara, aPortionList );
1416 sal_Int32 nPos1 = 0;
1417 for( sal_Int32 nPos2 : aPortionList )
1419 ESelection aSelection( nPara, nPos1, nPara, nPos2);
1421 SfxItemSet aSet( rEditEngine.GetAttribs( aSelection ) );
1423 OUString aPortion(StringToHTMLString(rEditEngine.GetText( aSelection )));
1425 aStr.append(TextAttribToHTMLString( &aSet, &aState, rBackgroundColor ));
1426 aStr.append(aPortion);
1428 nPos1 = nPos2;
1430 aStr.append(aState.Flush());
1431 rEditEngine.SetUpdateMode(bOldUpdateMode);
1433 return aStr.makeStringAndClear();
1436 // Depending on the attributes of the specified set and the specified
1437 // HtmlState, it creates the needed html tags in order to get the
1438 // attributes
1439 OUString HtmlExport::TextAttribToHTMLString( SfxItemSet const * pSet, HtmlState* pState, const Color& rBackgroundColor )
1441 OUStringBuffer aStr;
1443 if(nullptr == pSet)
1444 return OUString();
1446 OUString aLink, aTarget;
1447 if ( pSet->GetItemState( EE_FEATURE_FIELD ) == SfxItemState::SET )
1449 const SvxFieldItem* pItem = pSet->GetItem<SvxFieldItem>( EE_FEATURE_FIELD );
1450 if(pItem)
1452 const SvxURLField* pURL = dynamic_cast<const SvxURLField*>( pItem->GetField() );
1453 if(pURL)
1455 aLink = pURL->GetURL();
1456 aTarget = pURL->GetTargetFrame();
1461 bool bTemp;
1462 OUString aTemp;
1464 if ( pSet->GetItemState( EE_CHAR_WEIGHT ) == SfxItemState::SET )
1466 bTemp = pSet->Get( EE_CHAR_WEIGHT ).GetWeight() == WEIGHT_BOLD;
1467 aTemp = pState->SetWeight( bTemp );
1468 if( bTemp )
1469 aStr.insert(0, aTemp);
1470 else
1471 aStr.append(aTemp);
1474 if ( pSet->GetItemState( EE_CHAR_UNDERLINE ) == SfxItemState::SET )
1476 bTemp = pSet->Get( EE_CHAR_UNDERLINE ).GetLineStyle() != LINESTYLE_NONE;
1477 aTemp = pState->SetUnderline( bTemp );
1478 if( bTemp )
1479 aStr.insert(0, aTemp);
1480 else
1481 aStr.append(aTemp);
1484 if ( pSet->GetItemState( EE_CHAR_STRIKEOUT ) == SfxItemState::SET )
1486 bTemp = pSet->Get( EE_CHAR_STRIKEOUT ).GetStrikeout() != STRIKEOUT_NONE;
1487 aTemp = pState->SetStrikeout( bTemp );
1488 if( bTemp )
1489 aStr.insert(0, aTemp);
1490 else
1491 aStr.append(aTemp);
1494 if ( pSet->GetItemState( EE_CHAR_ITALIC ) == SfxItemState::SET )
1496 bTemp = pSet->Get( EE_CHAR_ITALIC ).GetPosture() != ITALIC_NONE;
1497 aTemp = pState->SetItalic( bTemp );
1498 if( bTemp )
1499 aStr.insert(0, aTemp);
1500 else
1501 aStr.append(aTemp);
1504 if(mbDocColors)
1506 if ( pSet->GetItemState( EE_CHAR_COLOR ) == SfxItemState::SET )
1508 Color aTextColor = pSet->Get( EE_CHAR_COLOR ).GetValue();
1509 if( aTextColor == COL_AUTO )
1511 if( !rBackgroundColor.IsDark() )
1512 aTextColor = COL_BLACK;
1514 aStr.append(pState->SetColor( aTextColor ));
1518 if (!aLink.isEmpty())
1519 aStr.insert(0, pState->SetLink(aLink, aTarget));
1520 else
1521 aStr.append(pState->SetLink(aLink, aTarget));
1523 return aStr.makeStringAndClear();
1526 // create HTML wrapper for picture files
1527 bool HtmlExport::CreateHtmlForPresPages()
1529 bool bOk = true;
1531 std::vector<SdrObject*> aClickableObjects;
1533 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount && bOk; nSdPage++)
1535 // find clickable objects (also on the master page) and put it in the
1536 // list. This in reverse order character order since in html the first
1537 // area is taken in the case they overlap.
1538 SdPage* pPage = maPages[ nSdPage ];
1540 if( mbDocColors )
1542 SetDocColors( pPage );
1545 bool bMasterDone = false;
1547 while (!bMasterDone)
1549 // sal_True = backwards
1550 SdrObjListIter aIter(pPage, SdrIterMode::DeepWithGroups, true);
1552 SdrObject* pObject = aIter.Next();
1553 while (pObject)
1555 SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObject);
1556 SdIMapInfo* pIMapInfo = SdDrawDocument::GetIMapInfo(pObject);
1558 if ((pInfo &&
1559 (pInfo->meClickAction == presentation::ClickAction_BOOKMARK ||
1560 pInfo->meClickAction == presentation::ClickAction_DOCUMENT ||
1561 pInfo->meClickAction == presentation::ClickAction_PREVPAGE ||
1562 pInfo->meClickAction == presentation::ClickAction_NEXTPAGE ||
1563 pInfo->meClickAction == presentation::ClickAction_FIRSTPAGE ||
1564 pInfo->meClickAction == presentation::ClickAction_LASTPAGE)) ||
1565 pIMapInfo)
1567 aClickableObjects.push_back(pObject);
1570 pObject = aIter.Next();
1572 // now to the master page or finishing
1573 if (!pPage->IsMasterPage())
1574 pPage = static_cast<SdPage*>(&(pPage->TRG_GetMasterPage()));
1575 else
1576 bMasterDone = true;
1579 // HTML Head
1580 OUStringBuffer aStr(gaHTMLHeader);
1581 aStr.append(CreateMetaCharset());
1582 aStr.append(" <title>" ).append( StringToHTMLString(maPageNames[nSdPage]) ).append("</title>\r\n");
1584 // insert timing information
1585 pPage = maPages[ nSdPage ];
1586 if( meMode == PUBLISH_KIOSK )
1588 double fSecs = 0;
1589 bool bEndless = false;
1590 if( !mbAutoSlide )
1592 if( pPage->GetPresChange() != PRESCHANGE_MANUAL )
1594 fSecs = pPage->GetTime();
1595 bEndless = mpDoc->getPresentationSettings().mbEndless;
1598 else
1600 fSecs = mfSlideDuration;
1601 bEndless = mbEndless;
1604 if( fSecs != 0 )
1606 if( nSdPage < (mnSdPageCount-1) || bEndless )
1608 aStr.append("<meta http-equiv=\"refresh\" content=\"");
1609 aStr.append(OUString::number(fSecs));
1610 aStr.append("; URL=");
1612 int nPage = nSdPage + 1;
1613 if( nPage == mnSdPageCount )
1614 nPage = 0;
1616 aStr.append(maHTMLFiles[nPage]);
1618 aStr.append("\">\r\n");
1623 aStr.append("</head>\r\n");
1625 // HTML Body
1626 aStr.append(CreateBodyTag());
1628 if( mbSlideSound && pPage->IsSoundOn() )
1629 aStr.append(InsertSound(pPage->GetSoundFile()));
1631 // navigation bar
1632 if(!mbFrames )
1633 aStr.append(CreateNavBar(nSdPage, false));
1634 // Image
1635 aStr.append("<center>");
1636 aStr.append("<img src=\"");
1637 aStr.append(maImageFiles[nSdPage]);
1638 aStr.append("\" alt=\"\"");
1640 if (!aClickableObjects.empty())
1641 aStr.append(" USEMAP=\"#map0\"");
1643 aStr.append("></center>\r\n");
1645 // notes
1646 if(mbNotes && !mbFrames)
1648 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
1649 SdPage* pNotesPage = maNotesPages[ nSdPage ];
1650 OUString aNotesStr( CreateTextForNotesPage( pOutliner, pNotesPage, maBackColor) );
1651 pOutliner->Clear();
1653 if (!aNotesStr.isEmpty())
1655 aStr.append("<h3>");
1656 aStr.append(RESTOHTML(STR_HTMLEXP_NOTES));
1657 aStr.append(":</h3><br>\r\n\r\n<p>");
1659 aStr.append(aNotesStr);
1660 aStr.append("\r\n</p>\r\n");
1664 // create Imagemap if necessary
1665 if (!aClickableObjects.empty())
1667 aStr.append("<map name=\"map0\">\r\n");
1669 for (SdrObject* pObject : aClickableObjects)
1671 SdAnimationInfo* pInfo = SdDrawDocument::GetAnimationInfo(pObject);
1672 SdIMapInfo* pIMapInfo = SdDrawDocument::GetIMapInfo(pObject);
1674 ::tools::Rectangle aRect(pObject->GetCurrentBoundRect());
1675 Point aLogPos(aRect.TopLeft());
1676 bool bIsSquare = aRect.GetWidth() == aRect.GetHeight();
1678 sal_uLong nPageWidth = pPage->GetSize().Width() - pPage->GetLeftBorder() -
1679 pPage->GetRightBorder();
1681 // BoundRect is relative to the physical page origin, not the
1682 // origin of ordinates
1683 aRect.Move(-pPage->GetLeftBorder(), -pPage->GetUpperBorder());
1685 double fLogicToPixel = static_cast<double>(mnWidthPixel) / nPageWidth;
1686 aRect.SetLeft( static_cast<long>(aRect.Left() * fLogicToPixel) );
1687 aRect.SetTop( static_cast<long>(aRect.Top() * fLogicToPixel) );
1688 aRect.SetRight( static_cast<long>(aRect.Right() * fLogicToPixel) );
1689 aRect.SetBottom( static_cast<long>(aRect.Bottom() * fLogicToPixel) );
1690 long nRadius = aRect.GetWidth() / 2;
1693 insert areas into Imagemap of the object, if the object has
1694 such a Imagemap
1696 if (pIMapInfo)
1698 const ImageMap& rIMap = pIMapInfo->GetImageMap();
1699 sal_uInt16 nAreaCount = rIMap.GetIMapObjectCount();
1700 for (sal_uInt16 nArea = 0; nArea < nAreaCount; nArea++)
1702 IMapObject* pArea = rIMap.GetIMapObject(nArea);
1703 sal_uInt16 nType = pArea->GetType();
1704 OUString aURL( pArea->GetURL() );
1706 // if necessary, convert page and object names into the
1707 // corresponding names of the html file
1708 bool bIsMasterPage;
1709 sal_uInt16 nPgNum = mpDoc->GetPageByName( aURL, bIsMasterPage );
1710 SdrObject* pObj = nullptr;
1712 if (nPgNum == SDRPAGE_NOTFOUND)
1714 // is the bookmark a object?
1715 pObj = mpDoc->GetObj( aURL );
1716 if (pObj)
1717 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1719 if (nPgNum != SDRPAGE_NOTFOUND)
1721 nPgNum = (nPgNum - 1) / 2; // SdrPageNum --> SdPageNum
1722 aURL = CreatePageURL(nPgNum);
1725 switch(nType)
1727 case IMAP_OBJ_RECTANGLE:
1729 ::tools::Rectangle aArea(static_cast<IMapRectangleObject*>(pArea)->
1730 GetRectangle(false));
1732 // conversion into pixel coordinates
1733 aArea.Move(aLogPos.X() - pPage->GetLeftBorder(),
1734 aLogPos.Y() - pPage->GetUpperBorder());
1735 aArea.SetLeft( static_cast<long>(aArea.Left() * fLogicToPixel) );
1736 aArea.SetTop( static_cast<long>(aArea.Top() * fLogicToPixel) );
1737 aArea.SetRight( static_cast<long>(aArea.Right() * fLogicToPixel) );
1738 aArea.SetBottom( static_cast<long>(aArea.Bottom() * fLogicToPixel) );
1740 aStr.append(CreateHTMLRectArea(aArea, aURL));
1742 break;
1744 case IMAP_OBJ_CIRCLE:
1746 Point aCenter(static_cast<IMapCircleObject*>(pArea)->
1747 GetCenter(false));
1748 aCenter += Point(aLogPos.X() - pPage->GetLeftBorder(),
1749 aLogPos.Y() - pPage->GetUpperBorder());
1750 aCenter.setX( static_cast<long>(aCenter.X() * fLogicToPixel) );
1751 aCenter.setY( static_cast<long>(aCenter.Y() * fLogicToPixel) );
1753 sal_uLong nCircleRadius = static_cast<IMapCircleObject*>(pArea)->
1754 GetRadius(false);
1755 nCircleRadius = static_cast<sal_uLong>(nCircleRadius * fLogicToPixel);
1756 aStr.append(CreateHTMLCircleArea(nCircleRadius,
1757 aCenter.X(), aCenter.Y(),
1758 aURL));
1760 break;
1762 case IMAP_OBJ_POLYGON:
1764 tools::Polygon aArea(static_cast<IMapPolygonObject*>(pArea)->GetPolygon(false));
1765 aStr.append(CreateHTMLPolygonArea(::basegfx::B2DPolyPolygon(aArea.getB2DPolygon()),
1766 Size(aLogPos.X() - pPage->GetLeftBorder(),
1767 aLogPos.Y() - pPage->GetUpperBorder()),
1768 fLogicToPixel, aURL));
1770 break;
1772 default:
1774 SAL_INFO("sd", "unknown IMAP_OBJ_type");
1776 break;
1782 if there is a presentation::ClickAction, determine bookmark
1783 and create area for the whole object
1785 if( pInfo )
1787 OUString aHRef;
1788 presentation::ClickAction eClickAction = pInfo->meClickAction;
1790 switch( eClickAction )
1792 case presentation::ClickAction_BOOKMARK:
1794 bool bIsMasterPage;
1795 sal_uInt16 nPgNum = mpDoc->GetPageByName( pInfo->GetBookmark(), bIsMasterPage );
1796 SdrObject* pObj = nullptr;
1798 if( nPgNum == SDRPAGE_NOTFOUND )
1800 // is the bookmark a object?
1801 pObj = mpDoc->GetObj(pInfo->GetBookmark());
1802 if (pObj)
1803 nPgNum = pObj->getSdrPageFromSdrObject()->GetPageNum();
1806 if( SDRPAGE_NOTFOUND != nPgNum )
1807 aHRef = CreatePageURL(( nPgNum - 1 ) / 2 );
1809 break;
1811 case presentation::ClickAction_DOCUMENT:
1812 aHRef = pInfo->GetBookmark();
1813 break;
1815 case presentation::ClickAction_PREVPAGE:
1817 sal_uLong nPage;
1819 if (nSdPage == 0)
1820 nPage = 0;
1821 else
1822 nPage = nSdPage - 1;
1824 aHRef = CreatePageURL( static_cast<sal_uInt16>(nPage));
1826 break;
1828 case presentation::ClickAction_NEXTPAGE:
1830 sal_uLong nPage;
1831 if (nSdPage == mnSdPageCount - 1)
1832 nPage = mnSdPageCount - 1;
1833 else
1834 nPage = nSdPage + 1;
1836 aHRef = CreatePageURL( static_cast<sal_uInt16>(nPage));
1838 break;
1840 case presentation::ClickAction_FIRSTPAGE:
1841 aHRef = CreatePageURL(0);
1842 break;
1844 case presentation::ClickAction_LASTPAGE:
1845 aHRef = CreatePageURL(mnSdPageCount - 1);
1846 break;
1848 default:
1849 break;
1852 // and now the areas
1853 if (!aHRef.isEmpty())
1855 // a circle?
1856 if (pObject->GetObjInventor() == SdrInventor::Default &&
1857 pObject->GetObjIdentifier() == OBJ_CIRC &&
1858 bIsSquare )
1860 aStr.append(CreateHTMLCircleArea(aRect.GetWidth() / 2,
1861 aRect.Left() + nRadius,
1862 aRect.Top() + nRadius,
1863 aHRef));
1865 // a polygon?
1866 else if (pObject->GetObjInventor() == SdrInventor::Default &&
1867 (pObject->GetObjIdentifier() == OBJ_PATHLINE ||
1868 pObject->GetObjIdentifier() == OBJ_PLIN ||
1869 pObject->GetObjIdentifier() == OBJ_POLY))
1871 aStr.append(CreateHTMLPolygonArea(static_cast<SdrPathObj*>(pObject)->GetPathPoly(), Size(-pPage->GetLeftBorder(), -pPage->GetUpperBorder()), fLogicToPixel, aHRef));
1873 // something completely different: use the BoundRect
1874 else
1876 aStr.append(CreateHTMLRectArea(aRect, aHRef));
1883 aStr.append("</map>\r\n");
1885 aClickableObjects.clear();
1887 aStr.append("</body>\r\n</html>");
1889 bOk = WriteHtml(maHTMLFiles[nSdPage], false, aStr.makeStringAndClear());
1891 if (mpProgress)
1892 mpProgress->SetState(++mnPagesWritten);
1895 return bOk;
1898 // create overview pages
1899 bool HtmlExport::CreateContentPage()
1901 if( mbDocColors )
1902 SetDocColors();
1904 // html head
1905 OUStringBuffer aStr(gaHTMLHeader);
1906 aStr.append(CreateMetaCharset());
1907 aStr.append(" <title>");
1908 aStr.append(StringToHTMLString(maPageNames[0]));
1909 aStr.append("</title>\r\n</head>\r\n");
1910 aStr.append(CreateBodyTag());
1912 // page head
1913 aStr.append("<center>\r\n");
1915 if(mbHeader)
1917 aStr.append("<h1>");
1918 aStr.append(getDocumentTitle());
1919 aStr.append("</h1><br>\r\n");
1922 aStr.append("<h2>");
1924 // Solaris compiler bug workaround
1925 if( mbFrames )
1926 aStr.append(CreateLink(maFramePage,
1927 RESTOHTML(STR_HTMLEXP_CLICKSTART)));
1928 else
1929 aStr.append(CreateLink(StringToHTMLString(maHTMLFiles[0]),
1930 RESTOHTML(STR_HTMLEXP_CLICKSTART)));
1932 aStr.append("</h2>\r\n</center>\r\n");
1934 aStr.append("<center><table width=\"90%\"><tr>\r\n");
1936 // table of content
1937 aStr.append("<td valign=\"top\" align=\"left\" width=\"25%\">\r\n");
1938 aStr.append("<h3>");
1939 aStr.append(RESTOHTML(STR_HTMLEXP_CONTENTS));
1940 aStr.append("</h3>");
1942 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++)
1944 OUString aPageName = maPageNames[nSdPage];
1945 aStr.append("<div align=\"left\">");
1946 if(mbFrames)
1947 aStr.append(StringToHTMLString(aPageName));
1948 else
1949 aStr.append(CreateLink(maHTMLFiles[nSdPage], aPageName));
1950 aStr.append("</div>\r\n");
1952 aStr.append("</td>\r\n");
1954 // document information
1955 aStr.append("<td valign=\"top\" align=\"left\" width=\"75%\">\r\n");
1957 if (!maAuthor.isEmpty())
1959 aStr.append("<p><strong>");
1960 aStr.append(RESTOHTML(STR_HTMLEXP_AUTHOR));
1961 aStr.append(":</strong> ");
1962 aStr.append(StringToHTMLString(maAuthor));
1963 aStr.append("</p>\r\n");
1966 if (!maEMail.isEmpty())
1968 aStr.append("<p><strong>");
1969 aStr.append(RESTOHTML(STR_HTMLEXP_EMAIL));
1970 aStr.append(":</strong> <a href=\"mailto:");
1971 aStr.append(maEMail);
1972 aStr.append("\">");
1973 aStr.append(StringToHTMLString(maEMail));
1974 aStr.append("</a></p>\r\n");
1977 if (!maHomePage.isEmpty())
1979 aStr.append("<p><strong>");
1980 aStr.append(RESTOHTML(STR_HTMLEXP_HOMEPAGE));
1981 aStr.append(":</strong> <a href=\"");
1982 aStr.append(maHomePage);
1983 aStr.append("\">");
1984 aStr.append(StringToHTMLString(maHomePage));
1985 aStr.append("</a> </p>\r\n");
1988 if (!maInfo.isEmpty())
1990 aStr.append("<p><strong>");
1991 aStr.append(RESTOHTML(STR_HTMLEXP_INFO));
1992 aStr.append(":</strong><br>\r\n");
1993 aStr.append(StringToHTMLString(maInfo));
1994 aStr.append("</p>\r\n");
1997 if(mbDownload)
1999 aStr.append("<p><a href=\"");
2000 aStr.append(maDocFileName);
2001 aStr.append("\">");
2002 aStr.append(RESTOHTML(STR_HTMLEXP_DOWNLOAD));
2003 aStr.append("</a></p>\r\n");
2006 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++)
2008 OUString aText(
2009 "<img src=\"" +
2010 maThumbnailFiles[nSdPage] +
2011 "\" width=\"256\" height=\"192\" alt=\"" +
2012 StringToHTMLString(maPageNames[nSdPage]) +
2013 "\">");
2015 aStr.append(CreateLink(maHTMLFiles[nSdPage], aText));
2016 aStr.append("\r\n");
2019 aStr.append("</td></tr></table></center>\r\n");
2021 aStr.append("</body>\r\n</html>");
2023 bool bOk = WriteHtml(maIndex, false, aStr.makeStringAndClear());
2025 if (mpProgress)
2026 mpProgress->SetState(++mnPagesWritten);
2028 return bOk;
2031 // create note pages (for frames)
2033 bool HtmlExport::CreateNotesPages()
2035 bool bOk = true;
2037 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
2038 for( sal_uInt16 nSdPage = 0; bOk && nSdPage < mnSdPageCount; nSdPage++ )
2040 SdPage* pPage = maNotesPages[nSdPage];
2041 if( mbDocColors )
2042 SetDocColors( pPage );
2044 // Html head
2045 OUStringBuffer aStr(gaHTMLHeader);
2046 aStr.append(CreateMetaCharset());
2047 aStr.append(" <title>");
2048 aStr.append(StringToHTMLString(maPageNames[0]));
2049 aStr.append("</title>\r\n</head>\r\n");
2050 aStr.append(CreateBodyTag());
2052 if(pPage)
2053 aStr.append(CreateTextForNotesPage( pOutliner, pPage, maBackColor ));
2055 aStr.append("</body>\r\n</html>");
2057 OUString aFileName("note" + OUString::number(nSdPage));
2058 bOk = WriteHtml(aFileName, true, aStr.makeStringAndClear());
2060 if (mpProgress)
2061 mpProgress->SetState(++mnPagesWritten);
2064 pOutliner->Clear();
2066 return bOk;
2069 // create outline pages (for frames)
2071 bool HtmlExport::CreateOutlinePages()
2073 bool bOk = true;
2075 if( mbDocColors )
2077 SetDocColors();
2080 // page 0 will be the closed outline, page 1 the opened
2081 for (sal_Int32 nPage = 0; nPage < (mbImpress?2:1) && bOk; ++nPage)
2083 // Html head
2084 OUStringBuffer aStr(gaHTMLHeader);
2085 aStr.append(CreateMetaCharset());
2086 aStr.append(" <title>");
2087 aStr.append(StringToHTMLString(maPageNames[0]));
2088 aStr.append("</title>\r\n</head>\r\n");
2089 aStr.append(CreateBodyTag());
2091 SdrOutliner* pOutliner = mpDoc->GetInternalOutliner();
2092 for(sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++)
2094 SdPage* pPage = maPages[ nSdPage ];
2096 aStr.append("<div align=\"left\">");
2097 OUString aLink("JavaScript:parent.NavigateAbs(" +
2098 OUString::number(nSdPage) + ")");
2100 OUString aTitle = CreateTextForTitle(pOutliner, pPage, maBackColor);
2101 if (aTitle.isEmpty())
2102 aTitle = maPageNames[nSdPage];
2104 lclAppendStyle(aStr, "p", getParagraphStyle(pOutliner, 0));
2105 aStr.append(CreateLink(aLink, aTitle));
2106 aStr.append("</p>");
2108 if(nPage==1)
2110 aStr.append(CreateTextForPage( pOutliner, pPage, false, maBackColor ));
2112 aStr.append("</div>\r\n");
2114 pOutliner->Clear();
2116 aStr.append("</body>\r\n</html>");
2118 OUString aFileName("outline" + OUString::number(nPage));
2119 bOk = WriteHtml(aFileName, true, aStr.makeStringAndClear());
2121 if (mpProgress)
2122 mpProgress->SetState(++mnPagesWritten);
2125 return bOk;
2128 // set file name
2129 void HtmlExport::CreateFileNames()
2131 // create lists with new file names
2132 maHTMLFiles.resize(mnSdPageCount);
2133 maImageFiles.resize(mnSdPageCount);
2134 maThumbnailFiles.resize(mnSdPageCount);
2135 maPageNames.resize(mnSdPageCount);
2136 maTextFiles.resize(mnSdPageCount);
2138 mbHeader = false; // headline on overview page?
2140 for (sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++)
2142 OUString aHTMLFileName;
2143 if(nSdPage == 0 && !mbContentsPage && !mbFrames )
2144 aHTMLFileName = maIndex;
2145 else
2147 aHTMLFileName = "img" + OUString::number(nSdPage) + gaHTMLExtension;
2150 maHTMLFiles[nSdPage] = aHTMLFileName;
2152 OUString aImageFileName = "img" + OUString::number(nSdPage);
2153 if( meFormat==FORMAT_GIF )
2154 aImageFileName += ".gif";
2155 else if( meFormat==FORMAT_JPG )
2156 aImageFileName += ".jpg";
2157 else
2158 aImageFileName += ".png";
2160 maImageFiles[nSdPage] = aImageFileName;
2162 OUString aThumbnailFileName = "thumb" + OUString::number(nSdPage);
2163 if( meFormat!=FORMAT_JPG )
2164 aThumbnailFileName += ".png";
2165 else
2166 aThumbnailFileName += ".jpg";
2168 maThumbnailFiles[nSdPage] = aThumbnailFileName;
2170 maTextFiles[nSdPage] = "text" + OUString::number(nSdPage) + gaHTMLExtension;
2172 SdPage* pSdPage = maPages[ nSdPage ];
2174 // get slide title from page name
2175 maPageNames[nSdPage] = pSdPage->GetName();
2178 if(!mbContentsPage && mbFrames)
2179 maFramePage = maIndex;
2180 else
2182 maFramePage = "siframes" + gaHTMLExtension;
2186 OUString const & HtmlExport::getDocumentTitle()
2188 // check for a title object in this page, if it's the first
2189 // title it becomes this documents title for the content
2190 // page
2191 if( !mbHeader )
2193 if(mbImpress)
2195 // if there is a non-empty title object, use their first passage
2196 // as page title
2197 SdPage* pSdPage = mpDoc->GetSdPage(0, PageKind::Standard);
2198 SdrObject* pTitleObj = pSdPage->GetPresObj(PRESOBJ_TITLE);
2199 if (pTitleObj && !pTitleObj->IsEmptyPresObj())
2201 OutlinerParaObject* pParaObject = pTitleObj->GetOutlinerParaObject();
2202 if (pParaObject)
2204 const EditTextObject& rEditTextObject =
2205 pParaObject->GetTextObject();
2206 OUString aTest(rEditTextObject.GetText(0));
2207 if (!aTest.isEmpty())
2208 mDocTitle = aTest;
2212 mDocTitle = mDocTitle.replace(0xff, ' ');
2215 if (mDocTitle.isEmpty())
2217 mDocTitle = maDocFileName;
2218 sal_Int32 nDot = mDocTitle.indexOf('.');
2219 if (nDot > 0)
2220 mDocTitle = mDocTitle.copy(0, nDot);
2222 mbHeader = true;
2225 return mDocTitle;
2228 static const char JS_NavigateAbs[] =
2229 "function NavigateAbs( nPage )\r\n"
2230 "{\r\n"
2231 " frames[\"show\"].location.href = \"img\" + nPage + \".$EXT\";\r\n"
2232 " //frames[\"notes\"].location.href = \"note\" + nPage + \".$EXT\";\r\n"
2233 " nCurrentPage = nPage;\r\n"
2234 " if(nCurrentPage==0)\r\n"
2235 " {\r\n"
2236 " frames[\"navbar1\"].location.href = \"navbar0.$EXT\";\r\n"
2237 " }\r\n"
2238 " else if(nCurrentPage==nPageCount-1)\r\n"
2239 " {\r\n"
2240 " frames[\"navbar1\"].location.href = \"navbar2.$EXT\";\r\n"
2241 " }\r\n"
2242 " else\r\n"
2243 " {\r\n"
2244 " frames[\"navbar1\"].location.href = \"navbar1.$EXT\";\r\n"
2245 " }\r\n"
2246 "}\r\n\r\n";
2248 static const char JS_NavigateRel[] =
2249 "function NavigateRel( nDelta )\r\n"
2250 "{\r\n"
2251 " var nPage = parseInt(nCurrentPage) + parseInt(nDelta);\r\n"
2252 " if( (nPage >= 0) && (nPage < nPageCount) )\r\n"
2253 " {\r\n"
2254 " NavigateAbs( nPage );\r\n"
2255 " }\r\n"
2256 "}\r\n\r\n";
2258 static const char JS_ExpandOutline[] =
2259 "function ExpandOutline()\r\n"
2260 "{\r\n"
2261 " frames[\"navbar2\"].location.href = \"navbar4.$EXT\";\r\n"
2262 " frames[\"outline\"].location.href = \"outline1.$EXT\";\r\n"
2263 "}\r\n\r\n";
2265 static const char JS_CollapseOutline[] =
2266 "function CollapseOutline()\r\n"
2267 "{\r\n"
2268 " frames[\"navbar2\"].location.href = \"navbar3.$EXT\";\r\n"
2269 " frames[\"outline\"].location.href = \"outline0.$EXT\";\r\n"
2270 "}\r\n\r\n";
2272 // create page with the frames
2274 bool HtmlExport::CreateFrames()
2276 OUString aTmp;
2277 OUStringBuffer aStr(
2278 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\"\r\n"
2279 " \"http://www.w3.org/TR/html4/frameset.dtd\">\r\n"
2280 "<html>\r\n<head>\r\n");
2282 aStr.append(CreateMetaCharset());
2283 aStr.append(" <title>");
2284 aStr.append(StringToHTMLString(maPageNames[0]));
2285 aStr.append("</title>\r\n");
2287 aStr.append("<script type=\"text/javascript\">\r\n<!--\r\n");
2289 aStr.append("var nCurrentPage = 0;\r\nvar nPageCount = ");
2290 aStr.append(OUString::number(mnSdPageCount));
2291 aStr.append(";\r\n\r\n");
2293 OUString aFunction = JS_NavigateAbs;
2295 if(mbNotes)
2297 aFunction = aFunction.replaceAll("//", "");
2300 // substitute HTML file extension
2301 OUString aPlaceHolder(".$EXT");
2302 aFunction = aFunction.replaceAll(aPlaceHolder, gaHTMLExtension);
2303 aStr.append(aFunction);
2305 aTmp = JS_NavigateRel;
2306 aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension);
2307 aStr.append(aTmp);
2309 if(mbImpress)
2311 aTmp = JS_ExpandOutline;
2312 aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension);
2313 aStr.append(aTmp);
2315 aTmp = JS_CollapseOutline;
2316 aTmp = aTmp.replaceAll(aPlaceHolder, gaHTMLExtension);
2317 aStr.append(aTmp);
2319 aStr.append("// -->\r\n</script>\r\n");
2321 aStr.append("</head>\r\n");
2323 aStr.append("<frameset cols=\"*,");
2324 aStr.append(OUString::number((mnWidthPixel + 16)));
2325 aStr.append("\">\r\n");
2326 if(mbImpress)
2328 aStr.append(" <frameset rows=\"42,*\">\r\n");
2329 aStr.append(" <frame src=\"navbar3");
2330 aStr.append(gaHTMLExtension);
2331 aStr.append("\" name=\"navbar2\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n");
2333 aStr.append(" <frame src=\"outline0");
2334 aStr.append(gaHTMLExtension);
2335 aStr.append("\" name=\"outline\">\r\n");
2336 if(mbImpress)
2337 aStr.append(" </frameset>\r\n");
2339 if(mbNotes)
2341 aStr.append(" <frameset rows=\"42,");
2342 aStr.append(OUString::number(static_cast<int>(static_cast<double>(mnWidthPixel) * 0.75) + 16));
2343 aStr.append(",*\">\r\n");
2345 else
2346 aStr.append(" <frameset rows=\"42,*\">\r\n");
2348 aStr.append(" <frame src=\"navbar0");
2349 aStr.append(gaHTMLExtension);
2350 aStr.append("\" name=\"navbar1\" marginwidth=\"4\" marginheight=\"4\" scrolling=\"no\">\r\n");
2352 aStr.append(" <frame src=\"");
2353 aStr.append(maHTMLFiles[0]);
2354 aStr.append("\" name=\"show\" marginwidth=\"4\" marginheight=\"4\">\r\n");
2356 if(mbNotes)
2358 aStr.append(" <frame src=\"note0");
2359 aStr.append(gaHTMLExtension);
2360 aStr.append("\" name=\"notes\">\r\n");
2362 aStr.append(" </frameset>\r\n");
2364 aStr.append("<noframes>\r\n");
2365 aStr.append(CreateBodyTag());
2366 aStr.append(RESTOHTML(STR_HTMLEXP_NOFRAMES));
2367 aStr.append("\r\n</noframes>\r\n</frameset>\r\n</html>");
2369 bool bOk = WriteHtml(maFramePage, false, aStr.makeStringAndClear());
2371 if (mpProgress)
2372 mpProgress->SetState(++mnPagesWritten);
2374 return bOk;
2377 // create button bar for standard
2378 // we create the following html files
2379 // navbar0.htm navigation bar graphic for the first page
2380 // navbar1.htm navigation bar graphic for the second until second last page
2381 // navbar2.htm navigation bar graphic for the last page
2382 // navbar3.htm navigation outline closed
2383 // navbar4.htm navigation outline open
2384 bool HtmlExport::CreateNavBarFrames()
2386 bool bOk = true;
2387 OUString aButton;
2389 if( mbDocColors )
2391 SetDocColors();
2392 maBackColor = maFirstPageColor;
2395 for( int nFile = 0; nFile < 3 && bOk; nFile++ )
2397 OUStringBuffer aStr(gaHTMLHeader);
2398 aStr.append(CreateMetaCharset());
2399 aStr.append(" <title>");
2400 aStr.append(StringToHTMLString(maPageNames[0]));
2401 aStr.append("</title>\r\n</head>\r\n");
2402 aStr.append(CreateBodyTag());
2403 aStr.append("<center>\r\n");
2405 // first page
2406 aButton = SdResId(STR_HTMLEXP_FIRSTPAGE);
2407 if(mnButtonThema != -1)
2408 aButton = CreateImage(GetButtonName(nFile == 0 || mnSdPageCount == 1 ? BTN_FIRST_0 : BTN_FIRST_1),
2409 aButton);
2411 if(nFile != 0 && mnSdPageCount > 1)
2412 aButton = CreateLink("JavaScript:parent.NavigateAbs(0)", aButton);
2414 aStr.append(aButton);
2415 aStr.append("\r\n");
2417 // to the previous page
2418 aButton = SdResId(STR_PUBLISH_BACK);
2419 if(mnButtonThema != -1)
2420 aButton = CreateImage(GetButtonName(nFile == 0 || mnSdPageCount == 1?
2421 BTN_PREV_0:BTN_PREV_1),
2422 aButton);
2424 if(nFile != 0 && mnSdPageCount > 1)
2425 aButton = CreateLink("JavaScript:parent.NavigateRel(-1)", aButton);
2427 aStr.append(aButton);
2428 aStr.append("\r\n");
2430 // to the next page
2431 aButton = SdResId(STR_PUBLISH_NEXT);
2432 if(mnButtonThema != -1)
2433 aButton = CreateImage(GetButtonName(nFile ==2 || mnSdPageCount == 1?
2434 BTN_NEXT_0:BTN_NEXT_1),
2435 aButton);
2437 if(nFile != 2 && mnSdPageCount > 1)
2438 aButton = CreateLink("JavaScript:parent.NavigateRel(1)", aButton);
2440 aStr.append(aButton);
2441 aStr.append("\r\n");
2443 // to the last page
2444 aButton = SdResId(STR_HTMLEXP_LASTPAGE);
2445 if(mnButtonThema != -1)
2446 aButton = CreateImage(GetButtonName(nFile ==2 || mnSdPageCount == 1?
2447 BTN_LAST_0:BTN_LAST_1),
2448 aButton);
2450 if(nFile != 2 && mnSdPageCount > 1)
2452 OUString aLink("JavaScript:parent.NavigateAbs(" +
2453 OUString::number(mnSdPageCount-1) + ")");
2455 aButton = CreateLink(aLink, aButton);
2458 aStr.append(aButton);
2459 aStr.append("\r\n");
2461 // content
2462 if (mbContentsPage)
2464 aButton = SdResId(STR_PUBLISH_OUTLINE);
2465 if(mnButtonThema != -1)
2466 aButton = CreateImage(GetButtonName(BTN_INDEX), aButton);
2468 // to the overview
2469 aStr.append(CreateLink(maIndex, aButton, "_top"));
2470 aStr.append("\r\n");
2473 // text mode
2474 if(mbImpress)
2476 aButton = SdResId(STR_HTMLEXP_SETTEXT);
2477 if(mnButtonThema != -1)
2478 aButton = CreateImage(GetButtonName(BTN_TEXT), aButton);
2480 OUString aText0("text0" + gaHTMLExtension);
2481 aStr.append(CreateLink(aText0, aButton, "_top"));
2482 aStr.append("\r\n");
2485 // and finished...
2486 aStr.append("</center>\r\n");
2487 aStr.append("</body>\r\n</html>");
2489 OUString aFileName("navbar" + OUString::number(nFile));
2491 bOk = WriteHtml(aFileName, true, aStr.makeStringAndClear());
2493 if (mpProgress)
2494 mpProgress->SetState(++mnPagesWritten);
2497 // the navigation bar outliner closed...
2498 if(bOk)
2500 OUStringBuffer aStr(gaHTMLHeader);
2501 aStr.append(CreateMetaCharset());
2502 aStr.append(" <title>");
2503 aStr.append(StringToHTMLString(maPageNames[0]));
2504 aStr.append("</title>\r\n</head>\r\n");
2505 aStr.append(CreateBodyTag());
2507 aButton = SdResId(STR_HTMLEXP_OUTLINE);
2508 if(mnButtonThema != -1)
2509 aButton = CreateImage(GetButtonName(BTN_MORE), aButton);
2511 aStr.append(CreateLink("JavaScript:parent.ExpandOutline()", aButton));
2512 aStr.append("</body>\r\n</html>");
2514 bOk = WriteHtml("navbar3", true, aStr.makeStringAndClear());
2516 if (mpProgress)
2517 mpProgress->SetState(++mnPagesWritten);
2520 // ... and the outliner open
2521 if( bOk )
2523 OUStringBuffer aStr(gaHTMLHeader);
2524 aStr.append(CreateMetaCharset());
2525 aStr.append(" <title>");
2526 aStr.append(StringToHTMLString(maPageNames[0]));
2527 aStr.append("</title>\r\n</head>\r\n");
2528 aStr.append(CreateBodyTag());
2530 aButton = SdResId(STR_HTMLEXP_NOOUTLINE);
2531 if(mnButtonThema != -1)
2532 aButton = CreateImage(GetButtonName(BTN_LESS), aButton);
2534 aStr.append(CreateLink("JavaScript:parent.CollapseOutline()", aButton));
2535 aStr.append("</body>\r\n</html>");
2537 bOk = WriteHtml("navbar4", true, aStr.makeStringAndClear());
2539 if (mpProgress)
2540 mpProgress->SetState(++mnPagesWritten);
2544 return bOk;
2547 // create button bar for standard
2548 OUString HtmlExport::CreateNavBar( sal_uInt16 nSdPage, bool bIsText ) const
2550 // prepare button bar
2551 OUString aStrNavFirst(SdResId(STR_HTMLEXP_FIRSTPAGE));
2552 OUString aStrNavPrev(SdResId(STR_PUBLISH_BACK));
2553 OUString aStrNavNext(SdResId(STR_PUBLISH_NEXT));
2554 OUString aStrNavLast(SdResId(STR_HTMLEXP_LASTPAGE));
2555 OUString aStrNavContent(SdResId(STR_PUBLISH_OUTLINE));
2556 OUString aStrNavText;
2557 if( bIsText )
2559 aStrNavText = SdResId(STR_HTMLEXP_SETGRAPHIC);
2561 else
2563 aStrNavText = SdResId(STR_HTMLEXP_SETTEXT);
2566 if(!bIsText && mnButtonThema != -1)
2568 if(nSdPage<1 || mnSdPageCount == 1)
2570 aStrNavFirst = CreateImage(GetButtonName(BTN_FIRST_0), aStrNavFirst);
2571 aStrNavPrev = CreateImage(GetButtonName(BTN_PREV_0), aStrNavPrev);
2573 else
2575 aStrNavFirst = CreateImage(GetButtonName(BTN_FIRST_1), aStrNavFirst);
2576 aStrNavPrev = CreateImage(GetButtonName(BTN_PREV_1), aStrNavPrev);
2579 if(nSdPage == mnSdPageCount-1 || mnSdPageCount == 1)
2581 aStrNavNext = CreateImage(GetButtonName(BTN_NEXT_0), aStrNavNext);
2582 aStrNavLast = CreateImage(GetButtonName(BTN_LAST_0), aStrNavLast);
2584 else
2586 aStrNavNext = CreateImage(GetButtonName(BTN_NEXT_1), aStrNavNext);
2587 aStrNavLast = CreateImage(GetButtonName(BTN_LAST_1), aStrNavLast);
2590 aStrNavContent = CreateImage(GetButtonName(BTN_INDEX), aStrNavContent);
2591 aStrNavText = CreateImage(GetButtonName(BTN_TEXT), aStrNavText);
2594 OUStringBuffer aStr("<center>\r\n"); //<table><tr>\r\n");
2596 // first page
2597 if(nSdPage > 0)
2598 aStr.append(CreateLink( bIsText ? maTextFiles[0] : maHTMLFiles[0],aStrNavFirst));
2599 else
2600 aStr.append(aStrNavFirst);
2601 aStr.append(' ');
2603 // to Previous page
2604 if(nSdPage > 0)
2605 aStr.append(CreateLink( bIsText ? maTextFiles[nSdPage-1]
2606 : maHTMLFiles[nSdPage-1], aStrNavPrev));
2607 else
2608 aStr.append(aStrNavPrev);
2609 aStr.append(' ');
2611 // to Next page
2612 if(nSdPage < mnSdPageCount-1)
2613 aStr.append(CreateLink( bIsText ? maTextFiles[nSdPage+1]
2614 : maHTMLFiles[nSdPage+1], aStrNavNext));
2615 else
2616 aStr.append(aStrNavNext);
2617 aStr.append(' ');
2619 // to Last page
2620 if(nSdPage < mnSdPageCount-1)
2621 aStr.append(CreateLink( bIsText ? maTextFiles[mnSdPageCount-1]
2622 : maHTMLFiles[mnSdPageCount-1],
2623 aStrNavLast));
2624 else
2625 aStr.append(aStrNavLast);
2626 aStr.append(' ');
2628 // to Index page
2629 if (mbContentsPage)
2631 aStr.append(CreateLink(maIndex, aStrNavContent));
2632 aStr.append(' ');
2635 // Text/Graphics
2636 if(mbImpress)
2638 aStr.append(CreateLink( bIsText ? (mbFrames ? maFramePage : maHTMLFiles[nSdPage])
2639 : maTextFiles[nSdPage], aStrNavText));
2643 aStr.append("</center><br>\r\n");
2645 return aStr.makeStringAndClear();
2648 // export navigation graphics from button set
2649 void HtmlExport::CreateBitmaps()
2651 if(mnButtonThema == -1 || !mpButtonSet.get())
2652 return;
2654 for( int nButton = 0; nButton != SAL_N_ELEMENTS(pButtonNames); nButton++ )
2656 if(!mbFrames && (nButton == BTN_MORE || nButton == BTN_LESS))
2657 continue;
2659 if(!mbImpress && (nButton == BTN_TEXT || nButton == BTN_MORE || nButton == BTN_LESS ))
2660 continue;
2662 OUString aFull(maExportPath);
2663 aFull += GetButtonName(nButton);
2664 mpButtonSet->exportButton( mnButtonThema, aFull, GetButtonName(nButton) );
2668 // creates the <body> tag, including the specified color attributes
2669 OUString HtmlExport::CreateBodyTag() const
2671 OUStringBuffer aStr( "<body" );
2673 if( mbUserAttr || mbDocColors )
2675 Color aTextColor( maTextColor );
2676 if( (aTextColor == COL_AUTO) && (!maBackColor.IsDark()) )
2677 aTextColor = COL_BLACK;
2679 aStr.append(" text=\"");
2680 aStr.append(ColorToHTMLString( aTextColor ));
2681 aStr.append("\" bgcolor=\"");
2682 aStr.append(ColorToHTMLString( maBackColor ));
2683 aStr.append("\" link=\"");
2684 aStr.append(ColorToHTMLString( maLinkColor ));
2685 aStr.append("\" vlink=\"");
2686 aStr.append(ColorToHTMLString( maVLinkColor ));
2687 aStr.append("\" alink=\"");
2688 aStr.append(ColorToHTMLString( maALinkColor ));
2689 aStr.append("\"");
2692 aStr.append(">\r\n");
2694 return aStr.makeStringAndClear();
2697 // creates a hyperlink
2698 OUString HtmlExport::CreateLink( const OUString& aLink,
2699 const OUString& aText,
2700 const OUString& aTarget )
2702 OUStringBuffer aStr( "<a href=\"" );
2703 aStr.append(aLink);
2704 if (!aTarget.isEmpty())
2706 aStr.append("\" target=\"");
2707 aStr.append(aTarget);
2709 aStr.append("\">");
2710 aStr.append(aText);
2711 aStr.append("</a>");
2713 return aStr.makeStringAndClear();
2716 // creates a image tag
2717 OUString HtmlExport::CreateImage( const OUString& aImage, const OUString& aAltText )
2719 OUStringBuffer aStr( "<img src=\"");
2720 aStr.append(aImage);
2721 aStr.append("\" border=0");
2723 if (!aAltText.isEmpty())
2725 aStr.append(" alt=\"");
2726 aStr.append(aAltText);
2727 aStr.append('"');
2729 else
2731 // Agerskov: HTML 4.01 has to have an alt attribute even if it is an empty string
2732 aStr.append(" alt=\"\"");
2735 aStr.append('>');
2737 return aStr.makeStringAndClear();
2740 // create area for a circle; we expect pixel coordinates
2741 OUString HtmlExport::ColorToHTMLString( Color aColor )
2743 static const char hex[] = "0123456789ABCDEF";
2744 OUStringBuffer aStr( "#xxxxxx" );
2745 aStr[1] = hex[(aColor.GetRed() >> 4) & 0xf];
2746 aStr[2] = hex[aColor.GetRed() & 0xf];
2747 aStr[3] = hex[(aColor.GetGreen() >> 4) & 0xf];
2748 aStr[4] = hex[aColor.GetGreen() & 0xf];
2749 aStr[5] = hex[(aColor.GetBlue() >> 4) & 0xf];
2750 aStr[6] = hex[aColor.GetBlue() & 0xf];
2752 return aStr.makeStringAndClear();
2755 // create area for a circle; we expect pixel coordinates
2756 OUString HtmlExport::CreateHTMLCircleArea( sal_uLong nRadius,
2757 sal_uLong nCenterX,
2758 sal_uLong nCenterY,
2759 const OUString& rHRef )
2761 OUString aStr(
2762 "<area shape=\"circle\" alt=\"\" coords=\"" +
2763 OUString::number(nCenterX) + "," +
2764 OUString::number(nCenterY) + "," +
2765 OUString::number(nRadius) +
2766 "\" href=\"" + rHRef + "\">\n");
2768 return aStr;
2771 // create area for a polygon; we expect pixel coordinates
2772 OUString HtmlExport::CreateHTMLPolygonArea( const ::basegfx::B2DPolyPolygon& rPolyPolygon,
2773 Size aShift, double fFactor, const OUString& rHRef )
2775 OUStringBuffer aStr;
2776 const sal_uInt32 nNoOfPolygons(rPolyPolygon.count());
2778 for ( sal_uInt32 nXPoly = 0; nXPoly < nNoOfPolygons; nXPoly++ )
2780 const ::basegfx::B2DPolygon& aPolygon = rPolyPolygon.getB2DPolygon(nXPoly);
2781 const sal_uInt32 nNoOfPoints(aPolygon.count());
2783 aStr.append("<area shape=\"polygon\" alt=\"\" coords=\"");
2785 for ( sal_uInt32 nPoint = 0; nPoint < nNoOfPoints; nPoint++ )
2787 const ::basegfx::B2DPoint aB2DPoint(aPolygon.getB2DPoint(nPoint));
2788 Point aPnt(FRound(aB2DPoint.getX()), FRound(aB2DPoint.getY()));
2789 // coordinates are relative to the physical page origin, not the
2790 // origin of ordinates
2791 aPnt.Move(aShift.Width(), aShift.Height());
2793 aPnt.setX( static_cast<long>(aPnt.X() * fFactor) );
2794 aPnt.setY( static_cast<long>(aPnt.Y() * fFactor) );
2795 aStr.append(OUString::number(aPnt.X())).append(",").append(OUString::number(aPnt.Y()));
2797 if (nPoint < nNoOfPoints - 1)
2798 aStr.append(',');
2800 aStr.append("\" href=\"").append(rHRef).append("\">\n");
2803 return aStr.makeStringAndClear();
2806 // create area for a rectangle; we expect pixel coordinates
2807 OUString HtmlExport::CreateHTMLRectArea( const ::tools::Rectangle& rRect,
2808 const OUString& rHRef )
2810 OUString aStr(
2811 "<area shape=\"rect\" alt=\"\" coords=\"" +
2812 OUString::number(rRect.Left()) + "," +
2813 OUString::number(rRect.Top()) + "," +
2814 OUString::number(rRect.Right()) + "," +
2815 OUString::number(rRect.Bottom()) +
2816 "\" href=\"" + rHRef + "\">\n");
2818 return aStr;
2821 // escapes a string for html
2822 OUString HtmlExport::StringToHTMLString( const OUString& rString )
2824 SvMemoryStream aMemStm;
2825 HTMLOutFuncs::Out_String( aMemStm, rString, RTL_TEXTENCODING_UTF8 );
2826 aMemStm.WriteChar( char(0) );
2827 sal_Int32 nLength = strlen(static_cast<char const *>(aMemStm.GetData()));
2828 return OUString( static_cast<char const *>(aMemStm.GetData()), nLength, RTL_TEXTENCODING_UTF8 );
2831 // creates a url for a specific page
2832 OUString HtmlExport::CreatePageURL( sal_uInt16 nPgNum )
2834 if(mbFrames)
2836 return OUString("JavaScript:parent.NavigateAbs(" +
2837 OUString::number(nPgNum) + ")");
2839 else
2840 return maHTMLFiles[nPgNum];
2843 bool HtmlExport::CopyScript( const OUString& rPath, const OUString& rSource, const OUString& rDest, bool bUnix /* = false */ )
2845 INetURLObject aURL( SvtPathOptions().GetConfigPath() );
2846 OUStringBuffer aScriptBuf;
2848 aURL.Append( "webcast" );
2849 aURL.Append( rSource );
2851 meEC.SetContext( STR_HTMLEXP_ERROR_OPEN_FILE, rSource );
2853 ErrCode nErr = ERRCODE_NONE;
2854 std::unique_ptr<SvStream> pIStm = ::utl::UcbStreamHelper::CreateStream( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ );
2856 if( pIStm )
2858 OString aLine;
2860 while( pIStm->ReadLine( aLine ) )
2862 aScriptBuf.appendAscii( aLine.getStr() );
2863 if( bUnix )
2865 aScriptBuf.append("\n");
2867 else
2869 aScriptBuf.append("\r\n");
2873 nErr = pIStm->GetError();
2874 pIStm.reset();
2877 if( nErr != ERRCODE_NONE )
2879 ErrorHandler::HandleError( nErr );
2880 return static_cast<bool>(nErr);
2883 OUString aScript(aScriptBuf.makeStringAndClear());
2884 aScript = aScript.replaceAll("$$1", getDocumentTitle());
2885 aScript = aScript.replaceAll("$$2", RESTOHTML(STR_WEBVIEW_SAVE));
2886 aScript = aScript.replaceAll("$$3", maCGIPath);
2887 aScript = aScript.replaceAll("$$4", OUString::number(mnWidthPixel));
2888 aScript = aScript.replaceAll("$$5", OUString::number(mnHeightPixel));
2890 OUString aDest(rPath + rDest);
2892 meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, rDest );
2893 // write script file
2895 EasyFile aFile;
2896 SvStream* pStr;
2897 nErr = aFile.createStream(aDest, pStr);
2898 if(nErr == ERRCODE_NONE)
2900 OString aStr(OUStringToOString(aScript,
2901 RTL_TEXTENCODING_UTF8));
2902 pStr->WriteCharPtr( aStr.getStr() );
2903 aFile.close();
2907 if (mpProgress)
2908 mpProgress->SetState(++mnPagesWritten);
2910 if( nErr != ERRCODE_NONE )
2911 ErrorHandler::HandleError( nErr );
2913 return nErr == ERRCODE_NONE;
2916 static const char * ASP_Scripts[] = { "common.inc", "webcast.asp", "show.asp", "savepic.asp", "poll.asp", "editpic.asp" };
2918 /** creates and saves the ASP scripts for WebShow */
2919 bool HtmlExport::CreateASPScripts()
2921 for(const char * p : ASP_Scripts)
2923 OUString aScript = OUString::createFromAscii(p);
2925 if(!CopyScript(maExportPath, aScript, aScript))
2926 return false;
2929 return CopyScript(maExportPath, "edit.asp", maIndex);
2932 static const char *PERL_Scripts[] = { "webcast.pl", "common.pl", "editpic.pl", "poll.pl", "savepic.pl", "show.pl" };
2934 // creates and saves the PERL scripts for WebShow
2935 bool HtmlExport::CreatePERLScripts()
2937 for(const char * p : PERL_Scripts)
2939 OUString aScript = OUString::createFromAscii(p);
2941 if(!CopyScript(maExportPath, aScript, aScript, true))
2942 return false;
2945 if (!CopyScript(maExportPath, "edit.pl", maIndex, true))
2946 return false;
2948 if (!CopyScript(maExportPath, "index.pl", maIndexUrl, true))
2949 return false;
2951 return true;
2954 // creates a list with names of the saved images
2955 bool HtmlExport::CreateImageFileList()
2957 OUStringBuffer aStr;
2958 for( sal_uInt16 nSdPage = 0; nSdPage < mnSdPageCount; nSdPage++)
2960 aStr.append(OUString::number(nSdPage + 1));
2961 aStr.append(';');
2962 aStr.append(maURLPath);
2963 aStr.append(maImageFiles[nSdPage]);
2964 aStr.append("\r\n");
2967 bool bOk = WriteHtml("picture.txt", false, aStr.makeStringAndClear());
2969 if (mpProgress)
2970 mpProgress->SetState(++mnPagesWritten);
2972 return bOk;
2975 // creates a file with the actual page number
2976 bool HtmlExport::CreateImageNumberFile()
2978 OUString aFileName("currpic.txt");
2979 OUString aFull(maExportPath + aFileName);
2981 meEC.SetContext( STR_HTMLEXP_ERROR_CREATE_FILE, aFileName );
2982 EasyFile aFile;
2983 SvStream* pStr;
2984 ErrCode nErr = aFile.createStream(aFull, pStr);
2985 if(nErr == ERRCODE_NONE)
2987 pStr->WriteCharPtr( "1" );
2988 aFile.close();
2991 if (mpProgress)
2992 mpProgress->SetState(++mnPagesWritten);
2994 if( nErr != ERRCODE_NONE )
2995 ErrorHandler::HandleError( nErr );
2997 return nErr == ERRCODE_NONE;
3000 OUString HtmlExport::InsertSound( const OUString& rSoundFile )
3002 if (rSoundFile.isEmpty())
3003 return rSoundFile;
3005 INetURLObject aURL( rSoundFile );
3006 OUString aSoundFileName = aURL.getName();
3008 DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
3010 OUString aStr("<embed src=\"" + aSoundFileName +
3011 "\" hidden=\"true\" autostart=\"true\">");
3013 CopyFile(rSoundFile, maExportPath + aSoundFileName);
3015 return aStr;
3018 bool HtmlExport::CopyFile( const OUString& rSourceFile, const OUString& rDestFile )
3020 meEC.SetContext( STR_HTMLEXP_ERROR_COPY_FILE, rSourceFile, rDestFile );
3021 osl::FileBase::RC Error = osl::File::copy( rSourceFile, rDestFile );
3023 if( Error != osl::FileBase::E_None )
3025 ErrorHandler::HandleError(ErrCode(Error));
3026 return false;
3028 else
3030 return true;
3034 bool HtmlExport::checkFileExists( Reference< css::ucb::XSimpleFileAccess3 > const & xFileAccess, OUString const & aFileName )
3038 OUString url( maExportPath );
3039 url += aFileName;
3040 return xFileAccess->exists( url );
3042 catch( css::uno::Exception& )
3044 SAL_WARN( "sd", "sd::HtmlExport::checkFileExists(), exception caught: "
3045 << exceptionToString( cppu::getCaughtException() ) );
3048 return false;
3051 bool HtmlExport::checkForExistingFiles()
3053 bool bFound = false;
3057 Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
3058 uno::Reference<ucb::XSimpleFileAccess3> xFA(ucb::SimpleFileAccess::create(xContext));
3060 sal_uInt16 nSdPage;
3061 for( nSdPage = 0; !bFound && (nSdPage < mnSdPageCount); nSdPage++)
3063 if( checkFileExists( xFA, maImageFiles[nSdPage] ) ||
3064 checkFileExists( xFA, maHTMLFiles[nSdPage] ) ||
3065 checkFileExists( xFA, maThumbnailFiles[nSdPage] ) ||
3066 checkFileExists( xFA, maPageNames[nSdPage] ) ||
3067 checkFileExists( xFA, maTextFiles[nSdPage] ) )
3069 bFound = true;
3073 if( !bFound && mbDownload )
3074 bFound = checkFileExists( xFA, maDocFileName );
3076 if( !bFound && mbFrames )
3077 bFound = checkFileExists( xFA, maFramePage );
3079 if( bFound )
3081 OUString aSystemPath;
3082 osl::FileBase::getSystemPathFromFileURL( maExportPath, aSystemPath );
3083 OUString aMsg(SdResId(STR_OVERWRITE_WARNING));
3084 aMsg = aMsg.replaceFirst( "%FILENAME", aSystemPath );
3086 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(nullptr,
3087 VclMessageType::Warning, VclButtonsType::YesNo,
3088 aMsg));
3089 xWarn->set_default_response(RET_YES);
3090 bFound = (RET_NO == xWarn->run());
3093 catch( Exception& )
3095 SAL_WARN( "sd", "sd::HtmlExport::checkForExistingFiles(), exception caught: "
3096 << exceptionToString( cppu::getCaughtException() ) );
3097 bFound = false;
3100 return bFound;
3103 OUString HtmlExport::GetButtonName( int nButton )
3105 return OUString::createFromAscii(pButtonNames[nButton]);
3108 EasyFile::EasyFile()
3110 pOStm = nullptr;
3111 bOpen = false;
3114 EasyFile::~EasyFile()
3116 if( bOpen )
3117 close();
3120 ErrCode EasyFile::createStream( const OUString& rUrl, SvStream* &rpStr )
3122 if(bOpen)
3123 close();
3125 OUString aFileName;
3126 createFileName( rUrl, aFileName );
3128 ErrCode nErr = ERRCODE_NONE;
3129 pOStm = ::utl::UcbStreamHelper::CreateStream( aFileName, StreamMode::WRITE | StreamMode::TRUNC );
3130 if( pOStm )
3132 bOpen = true;
3133 nErr = pOStm->GetError();
3135 else
3137 nErr = ERRCODE_SFX_CANTCREATECONTENT;
3140 if( nErr != ERRCODE_NONE )
3142 bOpen = false;
3143 pOStm.reset();
3146 rpStr = pOStm.get();
3148 return nErr;
3151 void EasyFile::createFileName( const OUString& rURL, OUString& rFileName )
3153 if( bOpen )
3154 close();
3156 INetURLObject aURL( rURL );
3158 if( aURL.GetProtocol() == INetProtocol::NotValid )
3160 OUString aURLStr;
3161 osl::FileBase::getFileURLFromSystemPath( rURL, aURLStr );
3162 aURL = INetURLObject( aURLStr );
3164 DBG_ASSERT( aURL.GetProtocol() != INetProtocol::NotValid, "invalid URL" );
3165 rFileName = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
3168 void EasyFile::close()
3170 pOStm.reset();
3171 bOpen = false;
3174 // This class helps reporting errors during file i/o
3175 HtmlErrorContext::HtmlErrorContext()
3176 : ErrorContext(nullptr)
3177 , mpResId(nullptr)
3181 bool HtmlErrorContext::GetString( ErrCode, OUString& rCtxStr )
3183 DBG_ASSERT(mpResId, "No error context set");
3184 if (!mpResId)
3185 return false;
3187 rCtxStr = SdResId(mpResId);
3189 rCtxStr = rCtxStr.replaceAll( "$(URL1)", maURL1 );
3190 rCtxStr = rCtxStr.replaceAll( "$(URL2)", maURL2 );
3192 return true;
3195 void HtmlErrorContext::SetContext(const char* pResId, const OUString& rURL)
3197 mpResId = pResId;
3198 maURL1 = rURL;
3199 maURL2.clear();
3202 void HtmlErrorContext::SetContext(const char* pResId, const OUString& rURL1, const OUString& rURL2 )
3204 mpResId = pResId;
3205 maURL1 = rURL1;
3206 maURL2 = rURL2;
3209 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */