1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <comphelper/string.hxx>
22 #include <editeng/eeitem.hxx>
24 #include <rtl/tencinfo.h>
26 #include <vcl/svapp.hxx>
27 #include <svx/algitem.hxx>
28 #include <editeng/boxitem.hxx>
29 #include <editeng/brushitem.hxx>
30 #include <editeng/colritem.hxx>
31 #include <editeng/fhgtitem.hxx>
32 #include <editeng/fontitem.hxx>
33 #include <editeng/postitem.hxx>
34 #include <editeng/udlnitem.hxx>
35 #include <editeng/wghtitem.hxx>
36 #include <editeng/justifyitem.hxx>
37 #include <svx/xoutbmp.hxx>
38 #include <editeng/editeng.hxx>
39 #include <svtools/htmlcfg.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <sfx2/frmhtmlw.hxx>
42 #include <sfx2/objsh.hxx>
43 #include <svl/stritem.hxx>
44 #include <svl/urihelper.hxx>
45 #include <svl/zforlist.hxx>
46 #include <svtools/htmlkywd.hxx>
47 #include <svtools/htmlout.hxx>
48 #include <svtools/parhtml.hxx>
49 #include <vcl/outdev.hxx>
52 #include "htmlexp.hxx"
56 #include "document.hxx"
58 #include "patattr.hxx"
59 #include "stlpool.hxx"
60 #include "scresid.hxx"
61 #include "formulacell.hxx"
62 #include "cellform.hxx"
63 #include "docoptio.hxx"
64 #include "editutil.hxx"
66 #include "cellvalue.hxx"
68 #include <editeng/flditem.hxx>
69 #include <editeng/borderline.hxx>
70 #include <unotools/syslocale.hxx>
72 // Without sc.hrc: error C2679: binary '=' : no operator defined which takes a
73 // right-hand operand of type 'const class String (__stdcall *)(class ScResId)'
75 // const String aStrTable( ScResId( SCSTR_TABLE ) ); aStrOut = aStrTable;
78 #include "globstr.hrc"
80 #include <com/sun/star/uno/Reference.h>
81 #include <com/sun/star/document/XDocumentProperties.hpp>
82 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
83 #include <rtl/strbuf.hxx>
85 using ::editeng::SvxBorderLine
;
86 using namespace ::com::sun::star
;
88 const static sal_Char sMyBegComment
[] = "<!-- ";
89 const static sal_Char sMyEndComment
[] = " -->";
90 const static sal_Char sFontFamily
[] = "font-family:";
91 const static sal_Char sFontSize
[] = "font-size:";
92 const static sal_Char sDisplay
[] = "display:";
93 const static sal_Char sBorder
[] = "border:";
94 const static sal_Char sPadding
[] = "padding:";
95 const static sal_Char sPosition
[] = "position:";
96 const static sal_Char sBackground
[] = "background:";
97 const static sal_Char sWidth
[] = "width:";
98 const static sal_Char sHeight
[] = "height:";
100 const sal_uInt16
ScHTMLExport::nDefaultFontSize
[SC_HTML_FONTSIZES
] =
102 HTMLFONTSZ1_DFLT
, HTMLFONTSZ2_DFLT
, HTMLFONTSZ3_DFLT
, HTMLFONTSZ4_DFLT
,
103 HTMLFONTSZ5_DFLT
, HTMLFONTSZ6_DFLT
, HTMLFONTSZ7_DFLT
106 sal_uInt16
ScHTMLExport::nFontSize
[SC_HTML_FONTSIZES
] = { 0 };
108 const char* ScHTMLExport::pFontSizeCss
[SC_HTML_FONTSIZES
] =
110 "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"
113 const sal_uInt16
ScHTMLExport::nCellSpacing
= 0;
114 const sal_Char
ScHTMLExport::sIndentSource
[nIndentMax
+1] =
115 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
117 // Macros for HTML export
119 #define TAG_ON( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag )
120 #define TAG_OFF( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag, false )
121 #define OUT_STR( str ) HTMLOutFuncs::Out_String( rStrm, str, eDestEnc, &aNonConvertibleChars )
122 #define OUT_LF() rStrm.WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() )
123 #define TAG_ON_LF( tag ) (TAG_ON( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
124 #define TAG_OFF_LF( tag ) (TAG_OFF( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
125 #define OUT_HR() TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_horzrule )
126 #define OUT_COMMENT( comment ) (rStrm.WriteCharPtr( sMyBegComment ), OUT_STR( comment ) \
127 .WriteCharPtr( sMyEndComment ).WriteCharPtr( SAL_NEWLINE_STRING ) \
128 .WriteCharPtr( GetIndentStr() ))
130 #define OUT_SP_CSTR_ASS( s ) rStrm.WriteChar( ' ').WriteCharPtr( s ).WriteChar( '=' )
132 #define GLOBSTR(id) ScGlobal::GetRscString( id )
134 void ScFormatFilterPluginImpl::ScExportHTML( SvStream
& rStrm
, const OUString
& rBaseURL
, ScDocument
* pDoc
,
135 const ScRange
& rRange
, const rtl_TextEncoding
/*eNach*/, bool bAll
,
136 const OUString
& rStreamPath
, OUString
& rNonConvertibleChars
, const OUString
& rFilterOptions
)
138 ScHTMLExport
aEx( rStrm
, rBaseURL
, pDoc
, rRange
, bAll
, rStreamPath
, rFilterOptions
);
140 rNonConvertibleChars
= aEx
.GetNonConvertibleChars();
143 static OString
lcl_getColGroupString(sal_Int32 nSpan
, sal_Int32 nWidth
)
145 OStringBuffer
aByteStr(OOO_STRING_SVTOOLS_HTML_colgroup
);
146 aByteStr
.append(' ');
149 aByteStr
.append(OOO_STRING_SVTOOLS_HTML_O_span
);
150 aByteStr
.append("=\"");
151 aByteStr
.append(nSpan
);
152 aByteStr
.append("\" ");
154 aByteStr
.append(OOO_STRING_SVTOOLS_HTML_O_width
);
155 aByteStr
.append("=\"");
156 aByteStr
.append(nWidth
);
157 aByteStr
.append('"');
158 return aByteStr
.makeStringAndClear();
161 static void lcl_AddStamp( OUString
& rStr
, const OUString
& rName
,
162 const css::util::DateTime
& rDateTime
,
163 const LocaleDataWrapper
& rLoc
)
165 Date
aD(rDateTime
.Day
, rDateTime
.Month
, rDateTime
.Year
);
166 tools::Time
aT(rDateTime
.Hours
, rDateTime
.Minutes
, rDateTime
.Seconds
,
167 rDateTime
.NanoSeconds
);
168 DateTime
aDateTime(aD
,aT
);
170 OUString aStrDate
= rLoc
.getDate( aDateTime
);
171 OUString aStrTime
= rLoc
.getTime( aDateTime
);
173 rStr
+= GLOBSTR( STR_BY
) + " ";
174 if (!rName
.isEmpty())
178 rStr
+= " " + GLOBSTR( STR_ON
) + " ";
179 if (!aStrDate
.isEmpty())
184 if (!aStrTime
.isEmpty())
190 static OString
lcl_makeHTMLColorTriplet(const Color
& rColor
)
192 OStringBuffer
aStr( "\"#" );
193 // <font COLOR="#00FF40">hello</font>
196 p
+= sprintf( p
, "%02X", rColor
.GetRed() );
197 p
+= sprintf( p
, "%02X", rColor
.GetGreen() );
198 sprintf( p
, "%02X", rColor
.GetBlue() );
201 return aStr
.makeStringAndClear();
204 ScHTMLExport::ScHTMLExport( SvStream
& rStrmP
, const OUString
& rBaseURL
, ScDocument
* pDocP
,
205 const ScRange
& rRangeP
, bool bAllP
,
206 const OUString
& rStreamPathP
, const OUString
& rFilterOptions
) :
207 ScExportBase( rStrmP
, pDocP
, rRangeP
),
208 aBaseURL( rBaseURL
),
209 aStreamPath( rStreamPathP
),
210 pAppWin( Application::GetDefaultDevice() ),
214 bTabHasGraphics( false ),
215 bTabAlignedLeft( false ),
216 bCalcAsShown( pDocP
->GetDocOptions().IsCalcAsShown() ),
217 bTableDataWidth( true ),
218 bTableDataHeight( true ),
219 mbSkipImages ( false ),
220 mbSkipHeaderFooter( false )
222 strcpy( sIndent
, sIndentSource
);
225 // set HTML configuration
226 SvxHtmlOptions
& rHtmlOptions
= SvxHtmlOptions::Get();
227 eDestEnc
= (pDoc
->IsClipOrUndo() ? RTL_TEXTENCODING_UTF8
: rHtmlOptions
.GetTextEncoding());
228 bCopyLocalFileToINet
= rHtmlOptions
.IsSaveGraphicsLocal();
230 if (rFilterOptions
== "SkipImages")
234 else if (rFilterOptions
== "SkipHeaderFooter")
236 mbSkipHeaderFooter
= true;
239 for ( sal_uInt16 j
=0; j
< SC_HTML_FONTSIZES
; j
++ )
241 sal_uInt16 nSize
= rHtmlOptions
.GetFontSize( j
);
242 // remember in Twips, like our SvxFontHeightItem
244 nFontSize
[j
] = nSize
* 20;
246 nFontSize
[j
] = nDefaultFontSize
[j
] * 20;
249 const SCTAB nCount
= pDoc
->GetTableCount();
250 for ( SCTAB nTab
= 0; nTab
< nCount
; nTab
++ )
252 if ( !IsEmptyTable( nTab
) )
256 // Content-Id for Mail export?
257 SfxObjectShell
* pDocSh
= pDoc
->GetDocumentShell();
260 const SfxPoolItem
* pItem
= pDocSh
->GetItem( SID_ORIGURL
);
263 aCId
= static_cast<const SfxStringItem
*>(pItem
)->GetValue();
264 OSL_ENSURE( !aCId
.isEmpty(), "CID without length!" );
269 ScHTMLExport::~ScHTMLExport()
274 sal_uInt16
ScHTMLExport::GetFontSizeNumber( sal_uInt16 nHeight
)
276 sal_uInt16 nSize
= 1;
277 for ( sal_uInt16 j
=SC_HTML_FONTSIZES
-1; j
>0; j
-- )
279 if( nHeight
> (nFontSize
[j
] + nFontSize
[j
-1]) / 2 )
280 { // The one next to it
288 const char* ScHTMLExport::GetFontSizeCss( sal_uInt16 nHeight
)
290 sal_uInt16 nSize
= GetFontSizeNumber( nHeight
);
291 return pFontSizeCss
[ nSize
-1 ];
294 sal_uInt16
ScHTMLExport::ToPixel( sal_uInt16 nVal
)
298 nVal
= (sal_uInt16
)pAppWin
->LogicToPixel(
299 Size( nVal
, nVal
), MapMode( MAP_TWIP
) ).Width();
300 if( !nVal
) // If there's a Twip there should also be a Pixel
306 Size
ScHTMLExport::MMToPixel( const Size
& rSize
)
309 aSize
= pAppWin
->LogicToPixel( rSize
, MapMode( MAP_100TH_MM
) );
310 // If there's something there should also be a Pixel
311 if ( !aSize
.Width() && rSize
.Width() )
313 if ( !aSize
.Height() && rSize
.Height() )
318 void ScHTMLExport::Write()
320 if (!mbSkipHeaderFooter
)
322 rStrm
.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype
).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype40
).WriteChar( '>' )
323 .WriteCharPtr( SAL_NEWLINE_STRING
).WriteCharPtr( SAL_NEWLINE_STRING
);
324 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_html
);
330 if (!mbSkipHeaderFooter
)
331 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_html
);
334 void ScHTMLExport::WriteHeader()
336 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_head
);
338 if ( pDoc
->IsClipOrUndo() )
339 { // no real DocInfo available, but some META information like charset needed
340 SfxFrameHTMLWriter::Out_DocInfo( rStrm
, aBaseURL
, nullptr, sIndent
, eDestEnc
, &aNonConvertibleChars
);
344 using namespace ::com::sun::star
;
345 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
346 pDoc
->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW
);
347 uno::Reference
<document::XDocumentProperties
> xDocProps
348 = xDPS
->getDocumentProperties();
349 SfxFrameHTMLWriter::Out_DocInfo( rStrm
, aBaseURL
, xDocProps
,
350 sIndent
, eDestEnc
, &aNonConvertibleChars
);
353 if (!xDocProps
->getPrintedBy().isEmpty())
355 OUT_COMMENT( GLOBSTR( STR_DOC_INFO
) );
356 OUString aStrOut
= ( GLOBSTR( STR_DOC_PRINTED
) ) + ": ";
357 lcl_AddStamp( aStrOut
, xDocProps
->getPrintedBy(),
358 xDocProps
->getPrintDate(), *ScGlobal::pLocaleData
);
359 OUT_COMMENT( aStrOut
);
366 PageDefaults( bAll
? 0 : aRange
.aStart
.Tab() );
368 rStrm
.WriteCharPtr( "<" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_style
).WriteCharPtr( " " ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_type
).WriteCharPtr( "=\"text/css\">" );
371 rStrm
.WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body
).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_division
).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_table
).WriteCharPtr( "," )
372 .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_thead
).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tbody
).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tfoot
).WriteCharPtr( "," )
373 .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tablerow
).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tableheader
).WriteCharPtr( "," )
374 .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tabledata
).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_parabreak
).WriteCharPtr( " { " ).WriteCharPtr( sFontFamily
);
375 sal_Int32 nFonts
= comphelper::string::getTokenCount(aHTMLStyle
.aFontFamilyName
, ';');
378 rStrm
.WriteChar( '\"' );
379 OUT_STR( aHTMLStyle
.aFontFamilyName
);
380 rStrm
.WriteChar( '\"' );
383 { // Fontlist, VCL: Semicolon as separator
384 // CSS1: Comma as separator and every single font name quoted
385 const OUString
& rList
= aHTMLStyle
.aFontFamilyName
;
386 for ( sal_Int32 j
= 0, nPos
= 0; j
< (sal_Int32
) nFonts
; j
++ )
388 rStrm
.WriteChar( '\"' );
389 OUT_STR( rList
.getToken( 0, ';', nPos
) );
390 rStrm
.WriteChar( '\"' );
392 rStrm
.WriteCharPtr( ", " );
395 rStrm
.WriteCharPtr( "; " ).WriteCharPtr( sFontSize
)
396 .WriteCharPtr( GetFontSizeCss( ( sal_uInt16
) aHTMLStyle
.nFontHeight
) ).WriteCharPtr( " }" );
400 // write the style for the comments to make them stand out from normal cell content
401 // this is done through only showing the cell contents when the custom indicator is hovered
402 rStrm
.WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor
).WriteCharPtr(".comment-indicator:hover")
403 .WriteCharPtr(" + ").WriteCharPtr( OOO_STRING_SVTOOLS_HTML_comment2
).WriteCharPtr(" { ")
404 .WriteCharPtr(sBackground
).WriteCharPtr("#ffd").WriteCharPtr("; ")
405 .WriteCharPtr(sPosition
).WriteCharPtr("absolute").WriteCharPtr("; ")
406 .WriteCharPtr(sDisplay
).WriteCharPtr("block").WriteCharPtr("; ")
407 .WriteCharPtr(sBorder
).WriteCharPtr("1px solid black").WriteCharPtr("; ")
408 .WriteCharPtr(sPadding
).WriteCharPtr("0.5em").WriteCharPtr("; ")
409 .WriteCharPtr(" } ");
413 rStrm
.WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor
).WriteCharPtr(".comment-indicator")
415 .WriteCharPtr(sBackground
).WriteCharPtr("red").WriteCharPtr("; ")
416 .WriteCharPtr(sDisplay
).WriteCharPtr("inline-block").WriteCharPtr("; ")
417 .WriteCharPtr(sBorder
).WriteCharPtr("1px solid black").WriteCharPtr("; ")
418 .WriteCharPtr(sWidth
).WriteCharPtr("0.5em").WriteCharPtr("; ")
419 .WriteCharPtr(sHeight
).WriteCharPtr("0.5em").WriteCharPtr("; ")
420 .WriteCharPtr(" } ");
424 rStrm
.WriteCharPtr( OOO_STRING_SVTOOLS_HTML_comment2
).WriteCharPtr(" { ")
425 .WriteCharPtr(sDisplay
).WriteCharPtr("none").WriteCharPtr("; ")
426 .WriteCharPtr(" } ");
429 IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_style
);
431 IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head
);
434 void ScHTMLExport::WriteOverview()
436 if ( nUsedTables
> 1 )
440 IncIndent(1); TAG_ON( OOO_STRING_SVTOOLS_HTML_parabreak
); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_center
);
441 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1
);
442 OUT_STR( ScGlobal::GetRscString( STR_OVERVIEW
) );
443 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head1
);
447 const SCTAB nCount
= pDoc
->GetTableCount();
448 for ( SCTAB nTab
= 0; nTab
< nCount
; nTab
++ )
450 if ( !IsEmptyTable( nTab
) )
452 pDoc
->GetName( nTab
, aStr
);
453 rStrm
.WriteCharPtr( "<A HREF=\"#table" )
454 .WriteCharPtr( OString::number(nTab
).getStr() )
455 .WriteCharPtr( "\">" );
457 rStrm
.WriteCharPtr( "</A>" );
458 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_linebreak
);
462 IncIndent(-1); OUT_LF();
463 IncIndent(-1); TAG_OFF( OOO_STRING_SVTOOLS_HTML_center
); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_parabreak
);
467 const SfxItemSet
& ScHTMLExport::PageDefaults( SCTAB nTab
)
469 SfxStyleSheetBasePool
* pStylePool
= pDoc
->GetStyleSheetPool();
470 SfxStyleSheetBase
* pStyleSheet
= nullptr;
471 OSL_ENSURE( pStylePool
, "StylePool not found! :-(" );
473 // remember defaults for compare in WriteCell
474 if ( !aHTMLStyle
.bInitialized
)
476 pStylePool
->SetSearchMask( SfxStyleFamily::Para
);
477 pStyleSheet
= pStylePool
->Find(
478 ScGlobal::GetRscString(STR_STYLENAME_STANDARD
),
479 SfxStyleFamily::Para
);
480 OSL_ENSURE( pStyleSheet
, "ParaStyle not found! :-(" );
482 pStyleSheet
= pStylePool
->First();
483 const SfxItemSet
& rSetPara
= pStyleSheet
->GetItemSet();
485 aHTMLStyle
.nDefaultScriptType
= ScGlobal::GetDefaultScriptType();
486 aHTMLStyle
.aFontFamilyName
= static_cast<const SvxFontItem
&>((rSetPara
.Get(
487 ScGlobal::GetScriptedWhichID(
488 aHTMLStyle
.nDefaultScriptType
, ATTR_FONT
489 )))).GetFamilyName();
490 aHTMLStyle
.nFontHeight
= static_cast<const SvxFontHeightItem
&>((rSetPara
.Get(
491 ScGlobal::GetScriptedWhichID(
492 aHTMLStyle
.nDefaultScriptType
, ATTR_FONT_HEIGHT
494 aHTMLStyle
.nFontSizeNumber
= GetFontSizeNumber( static_cast< sal_uInt16
>( aHTMLStyle
.nFontHeight
) );
497 // Page style sheet printer settings, e.g. for background graphics.
498 // There's only one background graphic in HTML!
499 pStylePool
->SetSearchMask( SfxStyleFamily::Page
);
500 pStyleSheet
= pStylePool
->Find( pDoc
->GetPageStyle( nTab
), SfxStyleFamily::Page
);
501 OSL_ENSURE( pStyleSheet
, "PageStyle not found! :-(" );
503 pStyleSheet
= pStylePool
->First();
504 const SfxItemSet
& rSet
= pStyleSheet
->GetItemSet();
505 if ( !aHTMLStyle
.bInitialized
)
507 const SvxBrushItem
* pBrushItem
= static_cast<const SvxBrushItem
*>(&rSet
.Get( ATTR_BACKGROUND
));
508 aHTMLStyle
.aBackgroundColor
= pBrushItem
->GetColor();
509 aHTMLStyle
.bInitialized
= true;
514 OString
ScHTMLExport::BorderToStyle(const char* pBorderName
,
515 const SvxBorderLine
* pLine
, bool& bInsertSemicolon
)
521 if ( bInsertSemicolon
)
525 aOut
.append("border-").append(pBorderName
).append(": ");
528 int nWidth
= pLine
->GetWidth();
529 int nPxWidth
= (nWidth
> 0) ?
530 std::max(int(nWidth
/ TWIPS_PER_PIXEL
), 1) : 0;
531 aOut
.append(static_cast<sal_Int32
>(nPxWidth
)).
533 switch (pLine
->GetBorderLineStyle())
535 case table::BorderLineStyle::SOLID
:
536 aOut
.append("solid");
538 case table::BorderLineStyle::DOTTED
:
539 aOut
.append("dotted");
541 case table::BorderLineStyle::DASHED
:
542 case table::BorderLineStyle::DASH_DOT
:
543 case table::BorderLineStyle::DASH_DOT_DOT
:
544 aOut
.append("dashed");
546 case table::BorderLineStyle::DOUBLE
:
547 case table::BorderLineStyle::DOUBLE_THIN
:
548 case table::BorderLineStyle::THINTHICK_SMALLGAP
:
549 case table::BorderLineStyle::THINTHICK_MEDIUMGAP
:
550 case table::BorderLineStyle::THINTHICK_LARGEGAP
:
551 case table::BorderLineStyle::THICKTHIN_SMALLGAP
:
552 case table::BorderLineStyle::THICKTHIN_MEDIUMGAP
:
553 case table::BorderLineStyle::THICKTHIN_LARGEGAP
:
554 aOut
.append("double");
556 case table::BorderLineStyle::EMBOSSED
:
557 aOut
.append("ridge");
559 case table::BorderLineStyle::ENGRAVED
:
560 aOut
.append("groove");
562 case table::BorderLineStyle::OUTSET
:
563 aOut
.append("outset");
565 case table::BorderLineStyle::INSET
:
566 aOut
.append("inset");
569 aOut
.append("hidden");
575 snprintf( hex
, 7, "%06x", static_cast< unsigned int >( pLine
->GetColor().GetRGBColor() ) );
580 bInsertSemicolon
= true;
583 return aOut
.makeStringAndClear();
586 void ScHTMLExport::WriteBody()
588 const SfxItemSet
& rSet
= PageDefaults( bAll
? 0 : aRange
.aStart
.Tab() );
589 const SvxBrushItem
* pBrushItem
= static_cast<const SvxBrushItem
*>(&rSet
.Get( ATTR_BACKGROUND
));
591 // default text color black
592 if (!mbSkipHeaderFooter
)
594 rStrm
.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body
);
598 if ( bAll
&& GPOS_NONE
!= pBrushItem
->GetGraphicPos() )
600 OUString aLink
= pBrushItem
->GetGraphicLink();
603 // Embedded graphic -> write using WriteGraphic
604 if( aLink
.isEmpty() )
606 const Graphic
* pGrf
= pBrushItem
->GetGraphic();
609 // Save graphic as (JPG) file
610 aGrfNm
= aStreamPath
;
611 sal_uInt16 nErr
= XOutBitmap::WriteGraphic( *pGrf
, aGrfNm
,
612 "JPG", XOutFlags::UseNativeIfPossible
);
613 if( !nErr
) // Contains errors, as we have nothing to output
615 aGrfNm
= URIHelper::SmartRel2Abs(
616 INetURLObject(aBaseURL
),
617 aGrfNm
, URIHelper::GetMaybeFileHdl());
619 MakeCIdURL( aGrfNm
);
627 if( bCopyLocalFileToINet
|| HasCId() )
629 CopyLocalFileToINet( aGrfNm
, aStreamPath
);
631 MakeCIdURL( aGrfNm
);
634 aGrfNm
= URIHelper::SmartRel2Abs(
635 INetURLObject(aBaseURL
),
636 aGrfNm
, URIHelper::GetMaybeFileHdl());
639 if( !aLink
.isEmpty() )
641 rStrm
.WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_background
).WriteCharPtr( "=\"" );
642 OUT_STR( URIHelper::simpleNormalizedMakeRelative(
644 aLink
) ).WriteChar( '\"' );
648 if ( !aHTMLStyle
.aBackgroundColor
.GetTransparency() )
649 { // A transparent background color should always result in default
650 // background of the browser. Also, HTMLOutFuncs::Out_Color() writes
651 // black #000000 for COL_AUTO which is the same as white #ffffff with
652 // transparency set to 0xff, our default background.
653 OUT_SP_CSTR_ASS( OOO_STRING_SVTOOLS_HTML_O_bgcolor
);
654 HTMLOutFuncs::Out_Color( rStrm
, aHTMLStyle
.aBackgroundColor
);
657 rStrm
.WriteChar( '>' ); OUT_LF();
665 if (!mbSkipHeaderFooter
)
666 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_body
);
669 void ScHTMLExport::WriteTables()
671 const SCTAB nTabCount
= pDoc
->GetTableCount();
672 const OUString
aStrTable( ScResId( SCSTR_TABLE
) );
681 SCCOL nStartColFix
= 0;
682 SCROW nStartRowFix
= 0;
683 SCCOL nEndColFix
= 0;
684 SCROW nEndRowFix
= 0;
685 ScDrawLayer
* pDrawLayer
= pDoc
->GetDrawLayer();
689 nEndTab
= nTabCount
- 1;
693 nStartCol
= nStartColFix
= aRange
.aStart
.Col();
694 nStartRow
= nStartRowFix
= aRange
.aStart
.Row();
695 nStartTab
= aRange
.aStart
.Tab();
696 nEndCol
= nEndColFix
= aRange
.aEnd
.Col();
697 nEndRow
= nEndRowFix
= aRange
.aEnd
.Row();
698 nEndTab
= aRange
.aEnd
.Tab();
700 SCTAB nTableStrNum
= 1;
701 for ( SCTAB nTab
=nStartTab
; nTab
<=nEndTab
; nTab
++ )
703 if ( !pDoc
->IsVisible( nTab
) )
708 if ( !GetDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
711 if ( nUsedTables
> 1 )
713 aStrOut
= aStrTable
+ " " + OUString::number( nTableStrNum
++ ) + ": ";
718 rStrm
.WriteCharPtr( "<A NAME=\"table" )
719 .WriteCharPtr( OString::number(nTab
).getStr() )
720 .WriteCharPtr( "\">" );
721 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1
);
723 TAG_ON( OOO_STRING_SVTOOLS_HTML_emphasis
);
725 pDoc
->GetName( nTab
, aStr
);
728 TAG_OFF( OOO_STRING_SVTOOLS_HTML_emphasis
);
729 TAG_OFF( OOO_STRING_SVTOOLS_HTML_head1
);
730 rStrm
.WriteCharPtr( "</A>" ); OUT_LF();
735 nStartCol
= nStartColFix
;
736 nStartRow
= nStartRowFix
;
737 nEndCol
= nEndColFix
;
738 nEndRow
= nEndRowFix
;
739 if ( !TrimDataArea( nTab
, nStartCol
, nStartRow
, nEndCol
, nEndRow
) )
744 OStringBuffer
aByteStrOut(OOO_STRING_SVTOOLS_HTML_table
);
746 bTabHasGraphics
= bTabAlignedLeft
= false;
747 if ( bAll
&& pDrawLayer
)
748 PrepareGraphics( pDrawLayer
, nTab
, nStartCol
, nStartRow
,
752 if ( bTabAlignedLeft
)
754 aByteStrOut
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align
).
756 append(OOO_STRING_SVTOOLS_HTML_AL_left
).append('"');
758 // ALIGN=LEFT allow text and graphics to flow around
760 aByteStrOut
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_cellspacing
).
762 append(static_cast<sal_Int32
>(nCellSpacing
)).append('"');
764 // BORDER=0, we do the styling of the cells in <TD>
765 aByteStrOut
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_border
).
767 IncIndent(1); TAG_ON_LF( aByteStrOut
.makeStringAndClear().getStr() );
769 // --- <COLGROUP> ----
771 SCCOL nCol
= nStartCol
;
772 sal_Int32 nWidth
= 0;
774 while( nCol
<= nEndCol
)
776 if( pDoc
->ColHidden(nCol
, nTab
) )
782 if( nWidth
!= ToPixel( pDoc
->GetColWidth( nCol
, nTab
) ) )
786 TAG_ON(lcl_getColGroupString(nSpan
, nWidth
).getStr());
787 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup
);
789 nWidth
= ToPixel( pDoc
->GetColWidth( nCol
, nTab
) );
798 TAG_ON(lcl_getColGroupString(nSpan
, nWidth
).getStr());
799 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup
);
803 // <TBODY> // Re-enable only when THEAD and TFOOT are exported
804 // IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tbody );
805 // At least old (3.x, 4.x?) Netscape doesn't follow <TABLE COLS=n> and
806 // <COL WIDTH=x> specified, but needs a width at every column.
807 bTableDataWidth
= true; // widths in first row
808 bool bHasHiddenRows
= pDoc
->HasHiddenRows(nStartRow
, nEndRow
, nTab
);
809 for ( SCROW nRow
=nStartRow
; nRow
<=nEndRow
; nRow
++ )
811 if ( bHasHiddenRows
&& pDoc
->RowHidden(nRow
, nTab
) )
813 nRow
= pDoc
->FirstVisibleRow(nRow
+1, nEndRow
, nTab
);
818 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tablerow
);
819 bTableDataHeight
= true; // height at every first cell of each row
820 for ( SCCOL nCol2
=nStartCol
; nCol2
<=nEndCol
; nCol2
++ )
822 if ( pDoc
->ColHidden(nCol2
, nTab
) )
825 if ( nCol2
== nEndCol
)
827 WriteCell( nCol2
, nRow
, nTab
);
828 bTableDataHeight
= false;
830 bTableDataWidth
= false; // widths only in first row
832 if ( nRow
== nEndRow
)
834 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow
);
836 // TODO: Uncomment later
837 // IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tbody );
839 IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_table
);
841 if ( bTabHasGraphics
&& !mbSkipImages
)
843 // the rest that is not in a cell
844 size_t ListSize
= aGraphList
.size();
845 for ( size_t i
= 0; i
< ListSize
; ++i
)
847 ScHTMLGraphEntry
* pE
= &aGraphList
[ i
];
849 WriteGraphEntry( pE
);
852 if ( bTabAlignedLeft
)
854 // clear <TABLE ALIGN=LEFT> with <BR CLEAR=LEFT>
855 aByteStrOut
.append(OOO_STRING_SVTOOLS_HTML_linebreak
);
856 aByteStrOut
.append(' ').
857 append(OOO_STRING_SVTOOLS_HTML_O_clear
).append('=').
858 append(OOO_STRING_SVTOOLS_HTML_AL_left
);
859 TAG_ON_LF( aByteStrOut
.makeStringAndClear().getStr() );
864 OUT_COMMENT( "**************************************************************************" );
868 void ScHTMLExport::WriteCell( SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
870 const ScPatternAttr
* pAttr
= pDoc
->GetPattern( nCol
, nRow
, nTab
);
871 const SfxItemSet
* pCondItemSet
= pDoc
->GetCondResult( nCol
, nRow
, nTab
);
873 const ScMergeFlagAttr
& rMergeFlagAttr
= static_cast<const ScMergeFlagAttr
&>( pAttr
->GetItem( ATTR_MERGE_FLAG
, pCondItemSet
) );
874 if ( rMergeFlagAttr
.IsOverlapped() )
877 ScAddress
aPos( nCol
, nRow
, nTab
);
878 ScHTMLGraphEntry
* pGraphEntry
= nullptr;
879 if ( bTabHasGraphics
&& !mbSkipImages
)
881 size_t ListSize
= aGraphList
.size();
882 for ( size_t i
= 0; i
< ListSize
; ++i
)
884 ScHTMLGraphEntry
* pE
= &aGraphList
[ i
];
885 if ( pE
->bInCell
&& pE
->aRange
.In( aPos
) )
887 if ( pE
->aRange
.aStart
== aPos
)
893 return ; // Is a Col/RowSpan, Overlapped
898 ScRefCellValue
aCell(*pDoc
, aPos
);
900 sal_uLong nFormat
= pAttr
->GetNumberFormat( pFormatter
);
901 bool bValueData
= aCell
.hasNumeric();
902 SvtScriptType nScriptType
= SvtScriptType::NONE
;
903 if (!aCell
.isEmpty())
904 nScriptType
= pDoc
->GetScriptType(nCol
, nRow
, nTab
);
906 if ( nScriptType
== SvtScriptType::NONE
)
907 nScriptType
= aHTMLStyle
.nDefaultScriptType
;
909 OStringBuffer
aStrTD(OOO_STRING_SVTOOLS_HTML_tabledata
);
911 // border of the cells
912 const SvxBoxItem
* pBorder
= static_cast<const SvxBoxItem
*>( pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_BORDER
) );
913 if ( pBorder
&& (pBorder
->GetTop() || pBorder
->GetBottom() || pBorder
->GetLeft() || pBorder
->GetRight()) )
915 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_style
).
918 bool bInsertSemicolon
= false;
919 aStrTD
.append(BorderToStyle("top", pBorder
->GetTop(),
921 aStrTD
.append(BorderToStyle("bottom", pBorder
->GetBottom(),
923 aStrTD
.append(BorderToStyle("left", pBorder
->GetLeft(),
925 aStrTD
.append(BorderToStyle("right", pBorder
->GetRight(),
931 const sal_Char
* pChar
;
932 sal_uInt16 nHeightPixel
;
934 const ScMergeAttr
& rMergeAttr
= static_cast<const ScMergeAttr
&>( pAttr
->GetItem( ATTR_MERGE
, pCondItemSet
) );
935 if ( pGraphEntry
|| rMergeAttr
.IsMerged() )
941 nC
= std::max( SCCOL(pGraphEntry
->aRange
.aEnd
.Col() - nCol
+ 1),
942 SCCOL(rMergeAttr
.GetColMerge()) );
944 nC
= rMergeAttr
.GetColMerge();
947 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_colspan
).
948 append('=').append(static_cast<sal_Int32
>(nC
));
950 for ( jC
=nCol
, v
=0; jC
<nC
; jC
++ )
951 v
+= pDoc
->GetColWidth( jC
, nTab
);
955 nR
= std::max( SCROW(pGraphEntry
->aRange
.aEnd
.Row() - nRow
+ 1),
956 SCROW(rMergeAttr
.GetRowMerge()) );
958 nR
= rMergeAttr
.GetRowMerge();
961 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_rowspan
).
962 append('=').append(static_cast<sal_Int32
>(nR
));
964 v
= pDoc
->GetRowHeight( nRow
, nR
-1, nTab
);
965 nHeightPixel
= ToPixel( static_cast< sal_uInt16
>( v
) );
968 nHeightPixel
= ToPixel( pDoc
->GetRowHeight( nRow
, nTab
) );
971 nHeightPixel
= ToPixel( pDoc
->GetRowHeight( nRow
, nTab
) );
973 if ( bTableDataHeight
)
975 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_height
).
977 append(static_cast<sal_Int32
>(nHeightPixel
)).append('"');
980 const SvxFontItem
& rFontItem
= static_cast<const SvxFontItem
&>( pAttr
->GetItem(
981 ScGlobal::GetScriptedWhichID( nScriptType
, ATTR_FONT
),
984 const SvxFontHeightItem
& rFontHeightItem
= static_cast<const SvxFontHeightItem
&>(
985 pAttr
->GetItem( ScGlobal::GetScriptedWhichID( nScriptType
,
986 ATTR_FONT_HEIGHT
), pCondItemSet
) );
988 const SvxWeightItem
& rWeightItem
= static_cast<const SvxWeightItem
&>( pAttr
->GetItem(
989 ScGlobal::GetScriptedWhichID( nScriptType
, ATTR_FONT_WEIGHT
),
992 const SvxPostureItem
& rPostureItem
= static_cast<const SvxPostureItem
&>(
993 pAttr
->GetItem( ScGlobal::GetScriptedWhichID( nScriptType
,
994 ATTR_FONT_POSTURE
), pCondItemSet
) );
996 const SvxUnderlineItem
& rUnderlineItem
= static_cast<const SvxUnderlineItem
&>(
997 pAttr
->GetItem( ATTR_FONT_UNDERLINE
, pCondItemSet
) );
999 const SvxColorItem
& rColorItem
= static_cast<const SvxColorItem
&>( pAttr
->GetItem(
1000 ATTR_FONT_COLOR
, pCondItemSet
) );
1002 const SvxHorJustifyItem
& rHorJustifyItem
= static_cast<const SvxHorJustifyItem
&>(
1003 pAttr
->GetItem( ATTR_HOR_JUSTIFY
, pCondItemSet
) );
1005 const SvxVerJustifyItem
& rVerJustifyItem
= static_cast<const SvxVerJustifyItem
&>(
1006 pAttr
->GetItem( ATTR_VER_JUSTIFY
, pCondItemSet
) );
1008 const SvxBrushItem
& rBrushItem
= static_cast<const SvxBrushItem
&>( pAttr
->GetItem(
1009 ATTR_BACKGROUND
, pCondItemSet
) );
1012 if ( rBrushItem
.GetColor().GetTransparency() == 255 )
1013 aBgColor
= aHTMLStyle
.aBackgroundColor
; // No unwanted background color
1015 aBgColor
= rBrushItem
.GetColor();
1017 bool bBold
= ( WEIGHT_BOLD
<= rWeightItem
.GetWeight() );
1018 bool bItalic
= ( ITALIC_NONE
!= rPostureItem
.GetPosture() );
1019 bool bUnderline
= ( LINESTYLE_NONE
!= rUnderlineItem
.GetLineStyle() );
1020 bool bSetFontColor
= ( COL_AUTO
!= rColorItem
.GetValue().GetColor() ); // default is AUTO now
1021 bool bSetFontName
= ( aHTMLStyle
.aFontFamilyName
!= rFontItem
.GetFamilyName() );
1022 sal_uInt16 nSetFontSizeNumber
= 0;
1023 sal_uInt32 nFontHeight
= rFontHeightItem
.GetHeight();
1024 if ( nFontHeight
!= aHTMLStyle
.nFontHeight
)
1026 nSetFontSizeNumber
= GetFontSizeNumber( (sal_uInt16
) nFontHeight
);
1027 if ( nSetFontSizeNumber
== aHTMLStyle
.nFontSizeNumber
)
1028 nSetFontSizeNumber
= 0; // no difference, don't set
1031 bool bSetFont
= (bSetFontColor
|| bSetFontName
|| nSetFontSizeNumber
);
1033 //! TODO: we could entirely use CSS1 here instead, but that would exclude
1034 //! Netscape 3.0 and Netscape 4.x without JavaScript enabled.
1035 //! Do we want that?
1037 switch( rHorJustifyItem
.GetValue() )
1039 case SVX_HOR_JUSTIFY_STANDARD
:
1040 pChar
= (bValueData
? OOO_STRING_SVTOOLS_HTML_AL_right
: OOO_STRING_SVTOOLS_HTML_AL_left
);
1042 case SVX_HOR_JUSTIFY_CENTER
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_center
; break;
1043 case SVX_HOR_JUSTIFY_BLOCK
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_justify
; break;
1044 case SVX_HOR_JUSTIFY_RIGHT
: pChar
= OOO_STRING_SVTOOLS_HTML_AL_right
; break;
1045 case SVX_HOR_JUSTIFY_LEFT
:
1046 case SVX_HOR_JUSTIFY_REPEAT
:
1047 default: pChar
= OOO_STRING_SVTOOLS_HTML_AL_left
; break;
1050 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align
).
1051 append("=\"").append(pChar
).append('"');
1053 switch( rVerJustifyItem
.GetValue() )
1055 case SVX_VER_JUSTIFY_TOP
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_top
; break;
1056 case SVX_VER_JUSTIFY_CENTER
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_middle
; break;
1057 case SVX_VER_JUSTIFY_BOTTOM
: pChar
= OOO_STRING_SVTOOLS_HTML_VA_bottom
; break;
1058 case SVX_VER_JUSTIFY_STANDARD
:
1059 default: pChar
= nullptr;
1063 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_valign
).
1064 append('=').append(pChar
);
1067 if ( aHTMLStyle
.aBackgroundColor
!= aBgColor
)
1069 aStrTD
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor
).
1071 aStrTD
.append(lcl_makeHTMLColorTriplet(aBgColor
));
1077 switch (aCell
.meType
)
1079 case CELLTYPE_VALUE
:
1080 fVal
= aCell
.mfValue
;
1081 if ( bCalcAsShown
&& fVal
!= 0.0 )
1082 fVal
= pDoc
->RoundValueAsShown( fVal
, nFormat
);
1084 case CELLTYPE_FORMULA
:
1085 fVal
= aCell
.mpFormula
->GetValue();
1088 OSL_FAIL( "value data with unsupported cell type" );
1092 aStrTD
.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValueData
, fVal
,
1093 nFormat
, *pFormatter
, eDestEnc
, &aNonConvertibleChars
));
1095 TAG_ON(aStrTD
.makeStringAndClear().getStr());
1097 //write the note for this as the first thing in the tag
1098 if (pDoc
->HasNote(aPos
))
1100 ScPostIt
* pNote
= pDoc
->GetNote(aPos
);
1102 //create the comment indicator
1103 OStringBuffer
aStr(OOO_STRING_SVTOOLS_HTML_anchor
);
1104 aStr
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_class
)
1105 .append("=\"").append("comment-indicator").append("\"");
1106 TAG_ON(aStr
.makeStringAndClear().getStr());
1107 TAG_OFF(OOO_STRING_SVTOOLS_HTML_anchor
);
1110 //create the element holding the contents
1111 //this is a bit naive, since it doesn't separate
1112 //lines into html breaklines yet
1113 TAG_ON(OOO_STRING_SVTOOLS_HTML_comment2
);
1114 OUT_STR( pNote
->GetText() );
1115 TAG_OFF(OOO_STRING_SVTOOLS_HTML_comment2
);
1119 if ( bBold
) TAG_ON( OOO_STRING_SVTOOLS_HTML_bold
);
1120 if ( bItalic
) TAG_ON( OOO_STRING_SVTOOLS_HTML_italic
);
1121 if ( bUnderline
) TAG_ON( OOO_STRING_SVTOOLS_HTML_underline
);
1125 OStringBuffer
aStr(OOO_STRING_SVTOOLS_HTML_font
);
1128 aStr
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_face
).
1130 sal_Int32 nFonts
= comphelper::string::getTokenCount(rFontItem
.GetFamilyName(), ';');
1133 OString aTmpStr
= HTMLOutFuncs::ConvertStringToHTML(
1134 rFontItem
.GetFamilyName(), eDestEnc
, &aNonConvertibleChars
);
1135 aStr
.append(aTmpStr
);
1138 { // Font list, VCL: Semicolon as separator, HTML: Comma
1139 const OUString
& rList
= rFontItem
.GetFamilyName();
1140 for ( sal_Int32 j
= 0, nPos
= 0; j
< (sal_Int32
)nFonts
; j
++ )
1142 OString aTmpStr
= HTMLOutFuncs::ConvertStringToHTML(
1143 rList
.getToken( 0, ';', nPos
), eDestEnc
,
1144 &aNonConvertibleChars
);
1145 aStr
.append(aTmpStr
);
1152 if ( nSetFontSizeNumber
)
1154 aStr
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_size
).
1155 append('=').append(static_cast<sal_Int32
>(nSetFontSizeNumber
));
1157 if ( bSetFontColor
)
1159 Color aColor
= rColorItem
.GetValue();
1161 // always export automatic text color as black
1162 if ( aColor
.GetColor() == COL_AUTO
)
1163 aColor
.SetColor( COL_BLACK
);
1165 aStr
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_color
).
1166 append('=').append(lcl_makeHTMLColorTriplet(aColor
));
1168 TAG_ON(aStr
.makeStringAndClear().getStr());
1172 bool bFieldText
= false;
1175 switch (aCell
.meType
)
1177 case CELLTYPE_EDIT
:
1178 bFieldText
= WriteFieldText(aCell
.mpEditText
);
1183 ScCellFormat::GetString(aCell
, nFormat
, aStrOut
, &pColor
, *pFormatter
, pDoc
);
1188 if ( aStrOut
.isEmpty() )
1190 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
); // No completely empty line
1194 sal_Int32 nPos
= aStrOut
.indexOf( '\n' );
1201 sal_Int32 nStartPos
= 0;
1204 OUString aSingleLine
= aStrOut
.copy( nStartPos
, nPos
- nStartPos
);
1205 OUT_STR( aSingleLine
);
1206 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
);
1207 nStartPos
= nPos
+ 1;
1209 while( ( nPos
= aStrOut
.indexOf( '\n', nStartPos
) ) != -1 );
1210 OUString aSingleLine
= aStrOut
.copy( nStartPos
, aStrOut
.getLength() - nStartPos
);
1211 OUT_STR( aSingleLine
);
1216 WriteGraphEntry( pGraphEntry
);
1218 if ( bSetFont
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_font
);
1219 if ( bUnderline
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_underline
);
1220 if ( bItalic
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_italic
);
1221 if ( bBold
) TAG_OFF( OOO_STRING_SVTOOLS_HTML_bold
);
1223 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tabledata
);
1226 bool ScHTMLExport::WriteFieldText( const EditTextObject
* pData
)
1228 bool bFields
= false;
1229 // text and anchor of URL fields, Doc-Engine is a ScFieldEditEngine
1230 EditEngine
& rEngine
= pDoc
->GetEditEngine();
1231 rEngine
.SetText( *pData
);
1232 sal_Int32 nParas
= rEngine
.GetParagraphCount();
1235 ESelection
aSel( 0, 0, nParas
-1, rEngine
.GetTextLen( nParas
-1 ) );
1236 SfxItemSet
aSet( rEngine
.GetAttribs( aSel
) );
1237 SfxItemState eFieldState
= aSet
.GetItemState( EE_FEATURE_FIELD
, false );
1238 if ( eFieldState
== SfxItemState::DONTCARE
|| eFieldState
== SfxItemState::SET
)
1243 bool bOldUpdateMode
= rEngine
.GetUpdateMode();
1244 rEngine
.SetUpdateMode( true ); // no portions if not formatted
1245 for ( sal_Int32 nPar
=0; nPar
< nParas
; nPar
++ )
1248 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak
);
1249 std::vector
<sal_Int32
> aPortions
;
1250 rEngine
.GetPortions( nPar
, aPortions
);
1251 sal_Int32 nStart
= 0;
1252 for ( std::vector
<sal_Int32
>::const_iterator
it(aPortions
.begin()); it
!= aPortions
.end(); ++it
)
1254 sal_Int32 nEnd
= *it
;
1255 ESelection
aSel( nPar
, nStart
, nPar
, nEnd
);
1257 // fields are single characters
1258 if ( nEnd
== nStart
+1 )
1260 const SfxPoolItem
* pItem
;
1261 SfxItemSet aSet
= rEngine
.GetAttribs( aSel
);
1262 if ( aSet
.GetItemState( EE_FEATURE_FIELD
, false, &pItem
) == SfxItemState::SET
)
1264 const SvxFieldData
* pField
= static_cast<const SvxFieldItem
*>(pItem
)->GetField();
1265 if (const SvxURLField
* pURLField
= dynamic_cast<const SvxURLField
*>(pField
))
1268 rStrm
.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor
).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_href
).WriteCharPtr( "=\"" );
1269 OUT_STR( pURLField
->GetURL() );
1270 rStrm
.WriteCharPtr( "\">" );
1271 OUT_STR( pURLField
->GetRepresentation() );
1272 rStrm
.WriteCharPtr( "</" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor
).WriteChar( '>' );
1277 OUT_STR( rEngine
.GetText( aSel
) );
1281 rEngine
.SetUpdateMode( bOldUpdateMode
);
1286 void ScHTMLExport::CopyLocalFileToINet( OUString
& rFileNm
,
1287 const OUString
& rTargetNm
)
1289 INetURLObject aFileUrl
, aTargetUrl
;
1290 aFileUrl
.SetSmartURL( rFileNm
);
1291 aTargetUrl
.SetSmartURL( rTargetNm
);
1292 if( INetProtocol::File
== aFileUrl
.GetProtocol() &&
1293 ( INetProtocol::File
!= aTargetUrl
.GetProtocol() &&
1294 INetProtocol::Ftp
<= aTargetUrl
.GetProtocol() &&
1295 INetProtocol::Javascript
>= aTargetUrl
.GetProtocol()) )
1299 // Did we already move the file?
1300 std::map
<OUString
, OUString
>::iterator it
= pFileNameMap
->find( rFileNm
);
1301 if( it
!= pFileNameMap
->end() )
1303 rFileNm
= it
->second
;
1309 pFileNameMap
.reset( new std::map
<OUString
, OUString
>() );
1313 SvFileStream
aTmp( aFileUrl
.PathToFileName(), StreamMode::READ
);
1315 OUString aSrc
= rFileNm
;
1316 OUString aDest
= aTargetUrl
.GetPartBeforeLastName();
1317 aDest
+= aFileUrl
.GetName();
1319 SfxMedium
aMedium( aDest
, StreamMode::WRITE
| StreamMode::SHARE_DENYNONE
);
1322 SvFileStream
aCpy( aMedium
.GetPhysicalName(), StreamMode::WRITE
);
1323 aCpy
.WriteStream( aTmp
);
1330 bRet
= 0 == aMedium
.GetError();
1334 pFileNameMap
->insert( std::make_pair( aSrc
, aDest
) );
1340 void ScHTMLExport::MakeCIdURL( OUString
& rURL
)
1342 if( aCId
.isEmpty() )
1345 INetURLObject
aURLObj( rURL
);
1346 if( INetProtocol::File
!= aURLObj
.GetProtocol() )
1349 OUString
aLastName( aURLObj
.GetLastName().toAsciiLowerCase() );
1350 OSL_ENSURE( !aLastName
.isEmpty(), "filename without length!" );
1352 rURL
= "cid:" + aLastName
+ "." + aCId
;
1355 void ScHTMLExport::IncIndent( short nVal
)
1357 sIndent
[nIndent
] = '\t';
1358 nIndent
= nIndent
+ nVal
;
1361 else if ( nIndent
> nIndentMax
)
1362 nIndent
= nIndentMax
;
1363 sIndent
[nIndent
] = 0;
1366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */