fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / html / htmlexp.cxx
blob94c1cc06940851968c1f2d8e0980dae1479ba469
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 "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>
50 #include <stdio.h>
52 #include "htmlexp.hxx"
53 #include "filter.hxx"
54 #include "global.hxx"
55 #include "document.hxx"
56 #include "attrib.hxx"
57 #include "patattr.hxx"
58 #include "stlpool.hxx"
59 #include "scresid.hxx"
60 #include "formulacell.hxx"
61 #include "cellform.hxx"
62 #include "docoptio.hxx"
63 #include "editutil.hxx"
64 #include "ftools.hxx"
65 #include "cellvalue.hxx"
67 #include <editeng/flditem.hxx>
68 #include <editeng/borderline.hxx>
69 #include <unotools/syslocale.hxx>
71 // Without sc.hrc: error C2679: binary '=' : no operator defined which takes a
72 // right-hand operand of type 'const class String (__stdcall *)(class ScResId)'
73 // at
74 // const String aStrTable( ScResId( SCSTR_TABLE ) ); aStrOut = aStrTable;
75 // ?!???
76 #include "sc.hrc"
77 #include "globstr.hrc"
79 #include <com/sun/star/uno/Reference.h>
80 #include <com/sun/star/document/XDocumentProperties.hpp>
81 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
82 #include <rtl/strbuf.hxx>
84 using ::editeng::SvxBorderLine;
85 using namespace ::com::sun::star;
87 const static sal_Char sMyBegComment[] = "<!-- ";
88 const static sal_Char sMyEndComment[] = " -->";
89 const static sal_Char sFontFamily[] = "font-family:";
90 const static sal_Char sFontSize[] = "font-size:";
92 const sal_uInt16 ScHTMLExport::nDefaultFontSize[SC_HTML_FONTSIZES] =
94 HTMLFONTSZ1_DFLT, HTMLFONTSZ2_DFLT, HTMLFONTSZ3_DFLT, HTMLFONTSZ4_DFLT,
95 HTMLFONTSZ5_DFLT, HTMLFONTSZ6_DFLT, HTMLFONTSZ7_DFLT
98 sal_uInt16 ScHTMLExport::nFontSize[SC_HTML_FONTSIZES] = { 0 };
100 const char* ScHTMLExport::pFontSizeCss[SC_HTML_FONTSIZES] =
102 "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"
105 const sal_uInt16 ScHTMLExport::nCellSpacing = 0;
106 const sal_Char ScHTMLExport::sIndentSource[nIndentMax+1] =
107 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
109 // Macros for HTML export
111 #define TAG_ON( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag )
112 #define TAG_OFF( tag ) HTMLOutFuncs::Out_AsciiTag( rStrm, tag, false )
113 #define OUT_STR( str ) HTMLOutFuncs::Out_String( rStrm, str, eDestEnc, &aNonConvertibleChars )
114 #define OUT_LF() rStrm.WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() )
115 #define TAG_ON_LF( tag ) (TAG_ON( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
116 #define TAG_OFF_LF( tag ) (TAG_OFF( tag ).WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( GetIndentStr() ))
117 #define OUT_HR() TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_horzrule )
118 #define OUT_COMMENT( comment ) (rStrm.WriteCharPtr( sMyBegComment ), OUT_STR( comment ) \
119 .WriteCharPtr( sMyEndComment ).WriteCharPtr( SAL_NEWLINE_STRING ) \
120 .WriteCharPtr( GetIndentStr() ))
122 #define OUT_SP_CSTR_ASS( s ) rStrm.WriteChar( ' ').WriteCharPtr( s ).WriteChar( '=' )
124 #define GLOBSTR(id) ScGlobal::GetRscString( id )
126 FltError ScFormatFilterPluginImpl::ScExportHTML( SvStream& rStrm, const OUString& rBaseURL, ScDocument* pDoc,
127 const ScRange& rRange, const rtl_TextEncoding /*eNach*/, bool bAll,
128 const OUString& rStreamPath, OUString& rNonConvertibleChars, const OUString& rFilterOptions )
130 ScHTMLExport aEx( rStrm, rBaseURL, pDoc, rRange, bAll, rStreamPath, rFilterOptions );
131 FltError nErr = aEx.Write();
132 rNonConvertibleChars = aEx.GetNonConvertibleChars();
133 return nErr;
136 static OString lcl_getColGroupString(sal_Int32 nSpan, sal_Int32 nWidth)
138 OStringBuffer aByteStr(OOO_STRING_SVTOOLS_HTML_colgroup);
139 aByteStr.append(' ');
140 if( nSpan > 1 )
142 aByteStr.append(OOO_STRING_SVTOOLS_HTML_O_span);
143 aByteStr.append("=\"");
144 aByteStr.append(nSpan);
145 aByteStr.append("\" ");
147 aByteStr.append(OOO_STRING_SVTOOLS_HTML_O_width);
148 aByteStr.append("=\"");
149 aByteStr.append(nWidth);
150 aByteStr.append('"');
151 return aByteStr.makeStringAndClear();
154 static void lcl_AddStamp( OUString& rStr, const OUString& rName,
155 const ::com::sun::star::util::DateTime& rDateTime,
156 const LocaleDataWrapper& rLoc )
158 Date aD(rDateTime.Day, rDateTime.Month, rDateTime.Year);
159 tools::Time aT(rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds,
160 rDateTime.NanoSeconds);
161 DateTime aDateTime(aD,aT);
163 OUString aStrDate = rLoc.getDate( aDateTime );
164 OUString aStrTime = rLoc.getTime( aDateTime );
166 rStr += GLOBSTR( STR_BY ) + " ";
167 if (!rName.isEmpty())
168 rStr += rName;
169 else
170 rStr += "???";
171 rStr += " " + GLOBSTR( STR_ON ) + " ";
172 if (!aStrDate.isEmpty())
173 rStr += aStrDate;
174 else
175 rStr += "???";
176 rStr += ", ";
177 if (!aStrTime.isEmpty())
178 rStr += aStrTime;
179 else
180 rStr += "???";
183 static OString lcl_makeHTMLColorTriplet(const Color& rColor)
185 OStringBuffer aStr( "\"#" );
186 // <font COLOR="#00FF40">hello</font>
187 sal_Char buf[64];
188 sal_Char* p = buf;
189 p += sprintf( p, "%02X", rColor.GetRed() );
190 p += sprintf( p, "%02X", rColor.GetGreen() );
191 p += sprintf( p, "%02X", rColor.GetBlue() );
192 aStr.append(buf);
193 aStr.append('\"');
194 return aStr.makeStringAndClear();
197 ScHTMLExport::ScHTMLExport( SvStream& rStrmP, const OUString& rBaseURL, ScDocument* pDocP,
198 const ScRange& rRangeP, bool bAllP,
199 const OUString& rStreamPathP, const OUString& rFilterOptions ) :
200 ScExportBase( rStrmP, pDocP, rRangeP ),
201 aBaseURL( rBaseURL ),
202 aStreamPath( rStreamPathP ),
203 aFilterOptions( rFilterOptions ),
204 pAppWin( Application::GetDefaultDevice() ),
205 nUsedTables( 0 ),
206 nIndent( 0 ),
207 bAll( bAllP ),
208 bTabHasGraphics( false ),
209 bTabAlignedLeft( false ),
210 bCalcAsShown( pDocP->GetDocOptions().IsCalcAsShown() ),
211 bTableDataWidth( true ),
212 bTableDataHeight( true ),
213 mbSkipImages ( false ),
214 mbSkipHeaderFooter( false )
216 strcpy( sIndent, sIndentSource );
217 sIndent[0] = 0;
219 // set HTML configuration
220 SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
221 eDestEnc = (pDoc->IsClipOrUndo() ? RTL_TEXTENCODING_UTF8 : rHtmlOptions.GetTextEncoding());
222 bCopyLocalFileToINet = rHtmlOptions.IsSaveGraphicsLocal();
224 if (rFilterOptions == "SkipImages")
226 mbSkipImages = true;
228 else if (rFilterOptions == "SkipHeaderFooter")
230 mbSkipHeaderFooter = true;
233 for ( sal_uInt16 j=0; j < SC_HTML_FONTSIZES; j++ )
235 sal_uInt16 nSize = rHtmlOptions.GetFontSize( j );
236 // remember in Twips, like our SvxFontHeightItem
237 if ( nSize )
238 nFontSize[j] = nSize * 20;
239 else
240 nFontSize[j] = nDefaultFontSize[j] * 20;
243 const SCTAB nCount = pDoc->GetTableCount();
244 for ( SCTAB nTab = 0; nTab < nCount; nTab++ )
246 if ( !IsEmptyTable( nTab ) )
247 nUsedTables++;
250 // Content-Id for Mail export?
251 SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
252 if ( pDocSh )
254 const SfxPoolItem* pItem = pDocSh->GetItem( SID_ORIGURL );
255 if( pItem )
257 aCId = static_cast<const SfxStringItem *>(pItem)->GetValue();
258 OSL_ENSURE( !aCId.isEmpty(), "CID without length!" );
263 ScHTMLExport::~ScHTMLExport()
265 aGraphList.clear();
268 sal_uInt16 ScHTMLExport::GetFontSizeNumber( sal_uInt16 nHeight )
270 sal_uInt16 nSize = 1;
271 for ( sal_uInt16 j=SC_HTML_FONTSIZES-1; j>0; j-- )
273 if( nHeight > (nFontSize[j] + nFontSize[j-1]) / 2 )
274 { // The one next to it
275 nSize = j+1;
276 break;
279 return nSize;
282 const char* ScHTMLExport::GetFontSizeCss( sal_uInt16 nHeight )
284 sal_uInt16 nSize = GetFontSizeNumber( nHeight );
285 return pFontSizeCss[ nSize-1 ];
288 sal_uInt16 ScHTMLExport::ToPixel( sal_uInt16 nVal )
290 if( nVal )
292 nVal = (sal_uInt16)pAppWin->LogicToPixel(
293 Size( nVal, nVal ), MapMode( MAP_TWIP ) ).Width();
294 if( !nVal ) // If there's a Twip there should also be a Pixel
295 nVal = 1;
297 return nVal;
300 Size ScHTMLExport::MMToPixel( const Size& rSize )
302 Size aSize( rSize );
303 aSize = pAppWin->LogicToPixel( rSize, MapMode( MAP_100TH_MM ) );
304 // If there's something there should also be a Pixel
305 if ( !aSize.Width() && rSize.Width() )
306 aSize.Width() = 1;
307 if ( !aSize.Height() && rSize.Height() )
308 aSize.Height() = 1;
309 return aSize;
312 sal_uLong ScHTMLExport::Write()
314 if (!mbSkipHeaderFooter)
316 rStrm.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype40 ).WriteChar( '>' )
317 .WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( SAL_NEWLINE_STRING );
318 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_html );
319 WriteHeader();
320 OUT_LF();
322 WriteBody();
323 OUT_LF();
324 if (!mbSkipHeaderFooter)
325 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_html );
327 return rStrm.GetError();
330 void ScHTMLExport::WriteHeader()
332 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_head );
334 if ( pDoc->IsClipOrUndo() )
335 { // no real DocInfo available, but some META information like charset needed
336 SfxFrameHTMLWriter::Out_DocInfo( rStrm, aBaseURL, NULL, sIndent, eDestEnc, &aNonConvertibleChars );
338 else
340 using namespace ::com::sun::star;
341 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
342 pDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
343 uno::Reference<document::XDocumentProperties> xDocProps
344 = xDPS->getDocumentProperties();
345 SfxFrameHTMLWriter::Out_DocInfo( rStrm, aBaseURL, xDocProps,
346 sIndent, eDestEnc, &aNonConvertibleChars );
347 OUT_LF();
349 if (!xDocProps->getPrintedBy().isEmpty())
351 OUT_COMMENT( GLOBSTR( STR_DOC_INFO ) );
352 OUString aStrOut = ( GLOBSTR( STR_DOC_PRINTED ) ) + ": ";
353 lcl_AddStamp( aStrOut, xDocProps->getPrintedBy(),
354 xDocProps->getPrintDate(), *ScGlobal::pLocaleData );
355 OUT_COMMENT( aStrOut );
359 OUT_LF();
361 // CSS1 StyleSheet
362 PageDefaults( bAll ? 0 : aRange.aStart.Tab() );
363 IncIndent(1);
364 rStrm.WriteCharPtr( "<" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_style ).WriteCharPtr( " " ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_type ).WriteCharPtr( "=\"text/css\">" );
366 OUT_LF();
367 rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_division ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_table ).WriteCharPtr( "," )
368 .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_thead ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tbody ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tfoot ).WriteCharPtr( "," )
369 .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tablerow ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tableheader ).WriteCharPtr( "," )
370 .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tabledata ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_parabreak ).WriteCharPtr( " { " ).WriteCharPtr( sFontFamily );
371 sal_Int32 nFonts = comphelper::string::getTokenCount(aHTMLStyle.aFontFamilyName, ';');
372 if ( nFonts == 1 )
374 rStrm.WriteChar( '\"' );
375 OUT_STR( aHTMLStyle.aFontFamilyName );
376 rStrm.WriteChar( '\"' );
378 else
379 { // Fontlist, VCL: Semicolon as separator
380 // CSS1: Comma as separator and every single font name quoted
381 const OUString& rList = aHTMLStyle.aFontFamilyName;
382 for ( sal_Int32 j = 0, nPos = 0; j < (sal_Int32) nFonts; j++ )
384 rStrm.WriteChar( '\"' );
385 OUT_STR( rList.getToken( 0, ';', nPos ) );
386 rStrm.WriteChar( '\"' );
387 if ( j < nFonts-1 )
388 rStrm.WriteCharPtr( ", " );
391 rStrm.WriteCharPtr( "; " ).WriteCharPtr( sFontSize )
392 .WriteCharPtr( GetFontSizeCss( ( sal_uInt16 ) aHTMLStyle.nFontHeight ) ).WriteCharPtr( " }" );
393 IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_style );
395 IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head );
398 void ScHTMLExport::WriteOverview()
400 if ( nUsedTables > 1 )
402 IncIndent(1);
403 OUT_HR();
404 IncIndent(1); TAG_ON( OOO_STRING_SVTOOLS_HTML_parabreak ); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_center );
405 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1 );
406 OUT_STR( ScGlobal::GetRscString( STR_OVERVIEW ) );
407 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head1 );
409 OUString aStr;
411 const SCTAB nCount = pDoc->GetTableCount();
412 for ( SCTAB nTab = 0; nTab < nCount; nTab++ )
414 if ( !IsEmptyTable( nTab ) )
416 pDoc->GetName( nTab, aStr );
417 rStrm.WriteCharPtr( "<A HREF=\"#table" )
418 .WriteCharPtr( OString::number(nTab).getStr() )
419 .WriteCharPtr( "\">" );
420 OUT_STR( aStr );
421 rStrm.WriteCharPtr( "</A>" );
422 TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_linebreak );
426 IncIndent(-1); OUT_LF();
427 IncIndent(-1); TAG_OFF( OOO_STRING_SVTOOLS_HTML_center ); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_parabreak );
431 const SfxItemSet& ScHTMLExport::PageDefaults( SCTAB nTab )
433 SfxStyleSheetBasePool* pStylePool = pDoc->GetStyleSheetPool();
434 SfxStyleSheetBase* pStyleSheet = NULL;
435 OSL_ENSURE( pStylePool, "StylePool not found! :-(" );
437 // remember defaults for compare in WriteCell
438 if ( !aHTMLStyle.bInitialized )
440 pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_ALL );
441 pStyleSheet = pStylePool->Find(
442 ScGlobal::GetRscString(STR_STYLENAME_STANDARD),
443 SFX_STYLE_FAMILY_PARA );
444 OSL_ENSURE( pStyleSheet, "ParaStyle not found! :-(" );
445 if (!pStyleSheet)
446 pStyleSheet = pStylePool->First();
447 const SfxItemSet& rSetPara = pStyleSheet->GetItemSet();
449 aHTMLStyle.nDefaultScriptType = ScGlobal::GetDefaultScriptType();
450 aHTMLStyle.aFontFamilyName = static_cast<const SvxFontItem&>((rSetPara.Get(
451 ScGlobal::GetScriptedWhichID(
452 aHTMLStyle.nDefaultScriptType, ATTR_FONT
453 )))).GetFamilyName();
454 aHTMLStyle.nFontHeight = static_cast<const SvxFontHeightItem&>((rSetPara.Get(
455 ScGlobal::GetScriptedWhichID(
456 aHTMLStyle.nDefaultScriptType, ATTR_FONT_HEIGHT
457 )))).GetHeight();
458 aHTMLStyle.nFontSizeNumber = GetFontSizeNumber( static_cast< sal_uInt16 >( aHTMLStyle.nFontHeight ) );
461 // Page style sheet printer settings, e.g. for background graphics.
462 // There's only one background graphic in HTML!
463 pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PAGE, SFXSTYLEBIT_ALL );
464 pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE );
465 OSL_ENSURE( pStyleSheet, "PageStyle not found! :-(" );
466 if (!pStyleSheet)
467 pStyleSheet = pStylePool->First();
468 const SfxItemSet& rSet = pStyleSheet->GetItemSet();
469 if ( !aHTMLStyle.bInitialized )
471 const SvxBrushItem* pBrushItem = static_cast<const SvxBrushItem*>(&rSet.Get( ATTR_BACKGROUND ));
472 aHTMLStyle.aBackgroundColor = pBrushItem->GetColor();
473 aHTMLStyle.bInitialized = true;
475 return rSet;
478 OString ScHTMLExport::BorderToStyle(const char* pBorderName,
479 const SvxBorderLine* pLine, bool& bInsertSemicolon)
481 OStringBuffer aOut;
483 if ( pLine )
485 if ( bInsertSemicolon )
486 aOut.append("; ");
488 // which border
489 aOut.append("border-").append(pBorderName).append(": ");
491 // thickness
492 int nWidth = pLine->GetWidth();
493 int nPxWidth = (nWidth > 0) ?
494 std::max(int(nWidth / TWIPS_PER_PIXEL), 1) : 0;
495 aOut.append(static_cast<sal_Int32>(nPxWidth)).
496 append("px ");
497 switch (pLine->GetBorderLineStyle())
499 case table::BorderLineStyle::SOLID:
500 aOut.append("solid");
501 break;
502 case table::BorderLineStyle::DOTTED:
503 aOut.append("dotted");
504 break;
505 case table::BorderLineStyle::DASHED:
506 case table::BorderLineStyle::DASH_DOT:
507 case table::BorderLineStyle::DASH_DOT_DOT:
508 aOut.append("dashed");
509 break;
510 case table::BorderLineStyle::DOUBLE:
511 case table::BorderLineStyle::DOUBLE_THIN:
512 case table::BorderLineStyle::THINTHICK_SMALLGAP:
513 case table::BorderLineStyle::THINTHICK_MEDIUMGAP:
514 case table::BorderLineStyle::THINTHICK_LARGEGAP:
515 case table::BorderLineStyle::THICKTHIN_SMALLGAP:
516 case table::BorderLineStyle::THICKTHIN_MEDIUMGAP:
517 case table::BorderLineStyle::THICKTHIN_LARGEGAP:
518 aOut.append("double");
519 break;
520 case table::BorderLineStyle::EMBOSSED:
521 aOut.append("ridge");
522 break;
523 case table::BorderLineStyle::ENGRAVED:
524 aOut.append("groove");
525 break;
526 case table::BorderLineStyle::OUTSET:
527 aOut.append("outset");
528 break;
529 case table::BorderLineStyle::INSET:
530 aOut.append("inset");
531 break;
532 default:
533 aOut.append("hidden");
535 aOut.append(" #");
537 // color
538 char hex[7];
539 snprintf( hex, 7, "%06x", static_cast< unsigned int >( pLine->GetColor().GetRGBColor() ) );
540 hex[6] = 0;
542 aOut.append(hex);
544 bInsertSemicolon = true;
547 return aOut.makeStringAndClear();
550 void ScHTMLExport::WriteBody()
552 const SfxItemSet& rSet = PageDefaults( bAll ? 0 : aRange.aStart.Tab() );
553 const SvxBrushItem* pBrushItem = static_cast<const SvxBrushItem*>(&rSet.Get( ATTR_BACKGROUND ));
555 // default text color black
556 if (!mbSkipHeaderFooter)
558 rStrm.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body );
560 if (!mbSkipImages)
562 if ( bAll && GPOS_NONE != pBrushItem->GetGraphicPos() )
564 OUString aLink = pBrushItem->GetGraphicLink();
565 OUString aGrfNm;
567 // Embedded graphic -> write using WriteGraphic
568 if( aLink.isEmpty() )
570 const Graphic* pGrf = pBrushItem->GetGraphic();
571 if( pGrf )
573 // Save graphic as (JPG) file
574 aGrfNm = aStreamPath;
575 sal_uInt16 nErr = XOutBitmap::WriteGraphic( *pGrf, aGrfNm,
576 "JPG", XOUTBMP_USE_NATIVE_IF_POSSIBLE );
577 if( !nErr ) // Contains errors, as we have nothing to output
579 aGrfNm = URIHelper::SmartRel2Abs(
580 INetURLObject(aBaseURL),
581 aGrfNm, URIHelper::GetMaybeFileHdl(), true, false);
582 if ( HasCId() )
583 MakeCIdURL( aGrfNm );
584 aLink = aGrfNm;
588 else
590 aGrfNm = aLink;
591 if( bCopyLocalFileToINet || HasCId() )
593 CopyLocalFileToINet( aGrfNm, aStreamPath );
594 if ( HasCId() )
595 MakeCIdURL( aGrfNm );
597 else
598 aGrfNm = URIHelper::SmartRel2Abs(
599 INetURLObject(aBaseURL),
600 aGrfNm, URIHelper::GetMaybeFileHdl(), true, false);
601 aLink = aGrfNm;
603 if( !aLink.isEmpty() )
605 rStrm.WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_background ).WriteCharPtr( "=\"" );
606 OUT_STR( URIHelper::simpleNormalizedMakeRelative(
607 aBaseURL,
608 aLink ) ).WriteChar( '\"' );
612 if ( !aHTMLStyle.aBackgroundColor.GetTransparency() )
613 { // A transparent background color should always result in default
614 // background of the browser. Also, HTMLOutFuncs::Out_Color() writes
615 // black #000000 for COL_AUTO which is the same as white #ffffff with
616 // transparency set to 0xff, our default background.
617 OUT_SP_CSTR_ASS( OOO_STRING_SVTOOLS_HTML_O_bgcolor );
618 HTMLOutFuncs::Out_Color( rStrm, aHTMLStyle.aBackgroundColor );
621 rStrm.WriteChar( '>' ); OUT_LF();
624 if ( bAll )
625 WriteOverview();
627 WriteTables();
629 if (!mbSkipHeaderFooter)
630 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_body );
633 void ScHTMLExport::WriteTables()
635 const SCTAB nTabCount = pDoc->GetTableCount();
636 const OUString aStrTable( ScResId( SCSTR_TABLE ) );
637 OUString aStr;
638 OUString aStrOut;
639 SCCOL nStartCol;
640 SCROW nStartRow;
641 SCTAB nStartTab;
642 SCCOL nEndCol;
643 SCROW nEndRow;
644 SCTAB nEndTab;
645 SCCOL nStartColFix = 0;
646 SCROW nStartRowFix = 0;
647 SCCOL nEndColFix = 0;
648 SCROW nEndRowFix = 0;
649 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
650 if ( bAll )
652 nStartTab = 0;
653 nEndTab = nTabCount - 1;
655 else
657 nStartCol = nStartColFix = aRange.aStart.Col();
658 nStartRow = nStartRowFix = aRange.aStart.Row();
659 nStartTab = aRange.aStart.Tab();
660 nEndCol = nEndColFix = aRange.aEnd.Col();
661 nEndRow = nEndRowFix = aRange.aEnd.Row();
662 nEndTab = aRange.aEnd.Tab();
664 SCTAB nTableStrNum = 1;
665 for ( SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++ )
667 if ( !pDoc->IsVisible( nTab ) )
668 continue; // for
670 if ( bAll )
672 if ( !GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow ) )
673 continue; // for
675 if ( nUsedTables > 1 )
677 aStrOut = aStrTable + " " + OUString::number( nTableStrNum++ ) + ": ";
679 OUT_HR();
681 // Write anchor
682 rStrm.WriteCharPtr( "<A NAME=\"table" )
683 .WriteCharPtr( OString::number(nTab).getStr() )
684 .WriteCharPtr( "\">" );
685 TAG_ON( OOO_STRING_SVTOOLS_HTML_head1 );
686 OUT_STR( aStrOut );
687 TAG_ON( OOO_STRING_SVTOOLS_HTML_emphasis );
689 pDoc->GetName( nTab, aStr );
690 OUT_STR( aStr );
692 TAG_OFF( OOO_STRING_SVTOOLS_HTML_emphasis );
693 TAG_OFF( OOO_STRING_SVTOOLS_HTML_head1 );
694 rStrm.WriteCharPtr( "</A>" ); OUT_LF();
697 else
699 nStartCol = nStartColFix;
700 nStartRow = nStartRowFix;
701 nEndCol = nEndColFix;
702 nEndRow = nEndRowFix;
703 if ( !TrimDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow ) )
704 continue; // for
707 // <TABLE ...>
708 OStringBuffer aByteStrOut(OOO_STRING_SVTOOLS_HTML_table);
710 bTabHasGraphics = bTabAlignedLeft = false;
711 if ( bAll && pDrawLayer )
712 PrepareGraphics( pDrawLayer, nTab, nStartCol, nStartRow,
713 nEndCol, nEndRow );
715 // more <TABLE ...>
716 if ( bTabAlignedLeft )
718 aByteStrOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align).
719 append("=\"").
720 append(OOO_STRING_SVTOOLS_HTML_AL_left).append('"');
722 // ALIGN=LEFT allow text and graphics to flow around
723 // CELLSPACING
724 aByteStrOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_cellspacing).
725 append("=\"").
726 append(static_cast<sal_Int32>(nCellSpacing)).append('"');
728 // BORDER=0, we do the styling of the cells in <TD>
729 aByteStrOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_border).
730 append("=\"0\"");
731 IncIndent(1); TAG_ON_LF( aByteStrOut.makeStringAndClear().getStr() );
733 // --- <COLGROUP> ----
735 SCCOL nCol = nStartCol;
736 sal_Int32 nWidth = 0;
737 sal_Int32 nSpan = 0;
738 while( nCol <= nEndCol )
740 if( pDoc->ColHidden(nCol, nTab) )
742 ++nCol;
743 continue;
746 if( nWidth != ToPixel( pDoc->GetColWidth( nCol, nTab ) ) )
748 if( nSpan != 0 )
750 TAG_ON(lcl_getColGroupString(nSpan, nWidth).getStr());
751 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup );
753 nWidth = ToPixel( pDoc->GetColWidth( nCol, nTab ) );
754 nSpan = 1;
756 else
757 nSpan++;
758 nCol++;
760 if( nSpan )
762 TAG_ON(lcl_getColGroupString(nSpan, nWidth).getStr());
763 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup );
767 // <TBODY> // Re-enable only when THEAD and TFOOT are exported
768 // IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tbody );
769 // At least old (3.x, 4.x?) Netscape doesn't follow <TABLE COLS=n> and
770 // <COL WIDTH=x> specified, but needs a width at every column.
771 bTableDataWidth = true; // widths in first row
772 bool bHasHiddenRows = pDoc->HasHiddenRows(nStartRow, nEndRow, nTab);
773 for ( SCROW nRow=nStartRow; nRow<=nEndRow; nRow++ )
775 if ( bHasHiddenRows && pDoc->RowHidden(nRow, nTab) )
777 nRow = pDoc->FirstVisibleRow(nRow+1, nEndRow, nTab);
778 --nRow;
779 continue; // for
782 IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
783 bTableDataHeight = true; // height at every first cell of each row
784 for ( SCCOL nCol2=nStartCol; nCol2<=nEndCol; nCol2++ )
786 if ( pDoc->ColHidden(nCol2, nTab) )
787 continue; // for
789 if ( nCol2 == nEndCol )
790 IncIndent(-1);
791 WriteCell( nCol2, nRow, nTab );
792 bTableDataHeight = false;
794 bTableDataWidth = false; // widths only in first row
796 if ( nRow == nEndRow )
797 IncIndent(-1);
798 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
800 // TODO: Uncomment later
801 // IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tbody );
803 IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_table );
805 if ( bTabHasGraphics && !mbSkipImages )
807 // the rest that is not in a cell
808 size_t ListSize = aGraphList.size();
809 for ( size_t i = 0; i < ListSize; ++i )
811 ScHTMLGraphEntry* pE = &aGraphList[ i ];
812 if ( !pE->bWritten )
813 WriteGraphEntry( pE );
815 aGraphList.clear();
816 if ( bTabAlignedLeft )
818 // clear <TABLE ALIGN=LEFT> with <BR CLEAR=LEFT>
819 aByteStrOut.append(OOO_STRING_SVTOOLS_HTML_linebreak);
820 aByteStrOut.append(' ').
821 append(OOO_STRING_SVTOOLS_HTML_O_clear).append('=').
822 append(OOO_STRING_SVTOOLS_HTML_AL_left);
823 TAG_ON_LF( aByteStrOut.makeStringAndClear().getStr() );
827 if ( bAll )
828 OUT_COMMENT( OUString("**************************************************************************") );
832 void ScHTMLExport::WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
834 const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab );
835 const SfxItemSet* pCondItemSet = pDoc->GetCondResult( nCol, nRow, nTab );
837 const ScMergeFlagAttr& rMergeFlagAttr = static_cast<const ScMergeFlagAttr&>( pAttr->GetItem( ATTR_MERGE_FLAG, pCondItemSet ) );
838 if ( rMergeFlagAttr.IsOverlapped() )
839 return ;
841 ScAddress aPos( nCol, nRow, nTab );
842 ScHTMLGraphEntry* pGraphEntry = NULL;
843 if ( bTabHasGraphics && !mbSkipImages )
845 size_t ListSize = aGraphList.size();
846 for ( size_t i = 0; i < ListSize; ++i )
848 ScHTMLGraphEntry* pE = &aGraphList[ i ];
849 if ( pE->bInCell && pE->aRange.In( aPos ) )
851 if ( pE->aRange.aStart == aPos )
853 pGraphEntry = pE;
854 break; // for
856 else
857 return ; // Is a Col/RowSpan, Overlapped
862 ScRefCellValue aCell;
863 aCell.assign(*pDoc, aPos);
865 sal_uLong nFormat = pAttr->GetNumberFormat( pFormatter );
866 bool bValueData = aCell.hasNumeric();
867 SvtScriptType nScriptType = SvtScriptType::NONE;
868 if (!aCell.isEmpty())
869 nScriptType = pDoc->GetScriptType(nCol, nRow, nTab);
871 if ( nScriptType == SvtScriptType::NONE )
872 nScriptType = aHTMLStyle.nDefaultScriptType;
874 OStringBuffer aStrTD(OOO_STRING_SVTOOLS_HTML_tabledata);
876 // border of the cells
877 const SvxBoxItem* pBorder = static_cast<const SvxBoxItem*>( pDoc->GetAttr( nCol, nRow, nTab, ATTR_BORDER ) );
878 if ( pBorder && (pBorder->GetTop() || pBorder->GetBottom() || pBorder->GetLeft() || pBorder->GetRight()) )
880 aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_style).
881 append("=\"");
883 bool bInsertSemicolon = false;
884 aStrTD.append(BorderToStyle("top", pBorder->GetTop(),
885 bInsertSemicolon));
886 aStrTD.append(BorderToStyle("bottom", pBorder->GetBottom(),
887 bInsertSemicolon));
888 aStrTD.append(BorderToStyle("left", pBorder->GetLeft(),
889 bInsertSemicolon));
890 aStrTD.append(BorderToStyle("right", pBorder->GetRight(),
891 bInsertSemicolon));
893 aStrTD.append('"');
896 const sal_Char* pChar;
897 sal_uInt16 nHeightPixel;
899 const ScMergeAttr& rMergeAttr = static_cast<const ScMergeAttr&>( pAttr->GetItem( ATTR_MERGE, pCondItemSet ) );
900 if ( pGraphEntry || rMergeAttr.IsMerged() )
902 SCCOL nC, jC;
903 SCROW nR;
904 sal_uLong v;
905 if ( pGraphEntry )
906 nC = std::max( SCCOL(pGraphEntry->aRange.aEnd.Col() - nCol + 1),
907 SCCOL(rMergeAttr.GetColMerge()) );
908 else
909 nC = rMergeAttr.GetColMerge();
910 if ( nC > 1 )
912 aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_colspan).
913 append('=').append(static_cast<sal_Int32>(nC));
914 nC = nC + nCol;
915 for ( jC=nCol, v=0; jC<nC; jC++ )
916 v += pDoc->GetColWidth( jC, nTab );
919 if ( pGraphEntry )
920 nR = std::max( SCROW(pGraphEntry->aRange.aEnd.Row() - nRow + 1),
921 SCROW(rMergeAttr.GetRowMerge()) );
922 else
923 nR = rMergeAttr.GetRowMerge();
924 if ( nR > 1 )
926 aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_rowspan).
927 append('=').append(static_cast<sal_Int32>(nR));
928 nR += nRow;
929 v = pDoc->GetRowHeight( nRow, nR-1, nTab );
930 nHeightPixel = ToPixel( static_cast< sal_uInt16 >( v ) );
932 else
933 nHeightPixel = ToPixel( pDoc->GetRowHeight( nRow, nTab ) );
935 else
936 nHeightPixel = ToPixel( pDoc->GetRowHeight( nRow, nTab ) );
938 if ( bTableDataHeight )
940 aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_height).
941 append("=\"").
942 append(static_cast<sal_Int32>(nHeightPixel)).append('"');
945 const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>( pAttr->GetItem(
946 ScGlobal::GetScriptedWhichID( nScriptType, ATTR_FONT),
947 pCondItemSet) );
949 const SvxFontHeightItem& rFontHeightItem = static_cast<const SvxFontHeightItem&>(
950 pAttr->GetItem( ScGlobal::GetScriptedWhichID( nScriptType,
951 ATTR_FONT_HEIGHT), pCondItemSet) );
953 const SvxWeightItem& rWeightItem = static_cast<const SvxWeightItem&>( pAttr->GetItem(
954 ScGlobal::GetScriptedWhichID( nScriptType, ATTR_FONT_WEIGHT),
955 pCondItemSet) );
957 const SvxPostureItem& rPostureItem = static_cast<const SvxPostureItem&>(
958 pAttr->GetItem( ScGlobal::GetScriptedWhichID( nScriptType,
959 ATTR_FONT_POSTURE), pCondItemSet) );
961 const SvxUnderlineItem& rUnderlineItem = static_cast<const SvxUnderlineItem&>(
962 pAttr->GetItem( ATTR_FONT_UNDERLINE, pCondItemSet ) );
964 const SvxColorItem& rColorItem = static_cast<const SvxColorItem&>( pAttr->GetItem(
965 ATTR_FONT_COLOR, pCondItemSet ) );
967 const SvxHorJustifyItem& rHorJustifyItem = static_cast<const SvxHorJustifyItem&>(
968 pAttr->GetItem( ATTR_HOR_JUSTIFY, pCondItemSet ) );
970 const SvxVerJustifyItem& rVerJustifyItem = static_cast<const SvxVerJustifyItem&>(
971 pAttr->GetItem( ATTR_VER_JUSTIFY, pCondItemSet ) );
973 const SvxBrushItem& rBrushItem = static_cast<const SvxBrushItem&>( pAttr->GetItem(
974 ATTR_BACKGROUND, pCondItemSet ) );
976 Color aBgColor;
977 if ( rBrushItem.GetColor().GetTransparency() == 255 )
978 aBgColor = aHTMLStyle.aBackgroundColor; // No unwanted background color
979 else
980 aBgColor = rBrushItem.GetColor();
982 bool bBold = ( WEIGHT_BOLD <= rWeightItem.GetWeight() );
983 bool bItalic = ( ITALIC_NONE != rPostureItem.GetPosture() );
984 bool bUnderline = ( UNDERLINE_NONE != rUnderlineItem.GetLineStyle() );
985 bool bSetFontColor = ( COL_AUTO != rColorItem.GetValue().GetColor() ); // default is AUTO now
986 bool bSetFontName = ( aHTMLStyle.aFontFamilyName != rFontItem.GetFamilyName() );
987 sal_uInt16 nSetFontSizeNumber = 0;
988 sal_uInt32 nFontHeight = rFontHeightItem.GetHeight();
989 if ( nFontHeight != aHTMLStyle.nFontHeight )
991 nSetFontSizeNumber = GetFontSizeNumber( (sal_uInt16) nFontHeight );
992 if ( nSetFontSizeNumber == aHTMLStyle.nFontSizeNumber )
993 nSetFontSizeNumber = 0; // no difference, don't set
996 bool bSetFont = (bSetFontColor || bSetFontName || nSetFontSizeNumber);
998 //! TODO: we could entirely use CSS1 here instead, but that would exclude
999 //! Netscape 3.0 and Netscape 4.x without JavaScript enabled.
1000 //! Do we want that?
1002 switch( rHorJustifyItem.GetValue() )
1004 case SVX_HOR_JUSTIFY_STANDARD:
1005 pChar = (bValueData ? OOO_STRING_SVTOOLS_HTML_AL_right : OOO_STRING_SVTOOLS_HTML_AL_left);
1006 break;
1007 case SVX_HOR_JUSTIFY_CENTER: pChar = OOO_STRING_SVTOOLS_HTML_AL_center; break;
1008 case SVX_HOR_JUSTIFY_BLOCK: pChar = OOO_STRING_SVTOOLS_HTML_AL_justify; break;
1009 case SVX_HOR_JUSTIFY_RIGHT: pChar = OOO_STRING_SVTOOLS_HTML_AL_right; break;
1010 case SVX_HOR_JUSTIFY_LEFT:
1011 case SVX_HOR_JUSTIFY_REPEAT:
1012 default: pChar = OOO_STRING_SVTOOLS_HTML_AL_left; break;
1015 aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align).
1016 append("=\"").append(pChar).append('"');
1018 switch( rVerJustifyItem.GetValue() )
1020 case SVX_VER_JUSTIFY_TOP: pChar = OOO_STRING_SVTOOLS_HTML_VA_top; break;
1021 case SVX_VER_JUSTIFY_CENTER: pChar = OOO_STRING_SVTOOLS_HTML_VA_middle; break;
1022 case SVX_VER_JUSTIFY_BOTTOM: pChar = OOO_STRING_SVTOOLS_HTML_VA_bottom; break;
1023 case SVX_VER_JUSTIFY_STANDARD:
1024 default: pChar = NULL;
1026 if ( pChar )
1028 aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_valign).
1029 append('=').append(pChar);
1032 if ( aHTMLStyle.aBackgroundColor != aBgColor )
1034 aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor).
1035 append('=');
1036 aStrTD.append(lcl_makeHTMLColorTriplet(aBgColor));
1039 double fVal = 0.0;
1040 if ( bValueData )
1042 switch (aCell.meType)
1044 case CELLTYPE_VALUE:
1045 fVal = aCell.mfValue;
1046 if ( bCalcAsShown && fVal != 0.0 )
1047 fVal = pDoc->RoundValueAsShown( fVal, nFormat );
1048 break;
1049 case CELLTYPE_FORMULA:
1050 fVal = aCell.mpFormula->GetValue();
1051 break;
1052 default:
1053 OSL_FAIL( "value data with unsupported cell type" );
1057 aStrTD.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValueData, fVal,
1058 nFormat, *pFormatter, eDestEnc, &aNonConvertibleChars));
1060 TAG_ON(aStrTD.makeStringAndClear().getStr());
1062 if ( bBold ) TAG_ON( OOO_STRING_SVTOOLS_HTML_bold );
1063 if ( bItalic ) TAG_ON( OOO_STRING_SVTOOLS_HTML_italic );
1064 if ( bUnderline ) TAG_ON( OOO_STRING_SVTOOLS_HTML_underline );
1066 if ( bSetFont )
1068 OStringBuffer aStr(OOO_STRING_SVTOOLS_HTML_font);
1069 if ( bSetFontName )
1071 aStr.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_face).
1072 append("=\"");
1073 sal_Int32 nFonts = comphelper::string::getTokenCount(rFontItem.GetFamilyName(), ';');
1074 if ( nFonts == 1 )
1076 OString aTmpStr = HTMLOutFuncs::ConvertStringToHTML(
1077 rFontItem.GetFamilyName(), eDestEnc, &aNonConvertibleChars);
1078 aStr.append(aTmpStr);
1080 else
1081 { // Font list, VCL: Semicolon as separator, HTML: Comma
1082 const OUString& rList = rFontItem.GetFamilyName();
1083 for ( sal_Int32 j = 0, nPos = 0; j < (sal_Int32)nFonts; j++ )
1085 OString aTmpStr = HTMLOutFuncs::ConvertStringToHTML(
1086 rList.getToken( 0, ';', nPos ), eDestEnc,
1087 &aNonConvertibleChars);
1088 aStr.append(aTmpStr);
1089 if ( j < nFonts-1 )
1090 aStr.append(',');
1093 aStr.append('\"');
1095 if ( nSetFontSizeNumber )
1097 aStr.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_size).
1098 append('=').append(static_cast<sal_Int32>(nSetFontSizeNumber));
1100 if ( bSetFontColor )
1102 Color aColor = rColorItem.GetValue();
1104 // always export automatic text color as black
1105 if ( aColor.GetColor() == COL_AUTO )
1106 aColor.SetColor( COL_BLACK );
1108 aStr.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_color).
1109 append('=').append(lcl_makeHTMLColorTriplet(aColor));
1111 TAG_ON(aStr.makeStringAndClear().getStr());
1114 OUString aStrOut;
1115 bool bFieldText = false;
1117 Color* pColor;
1118 switch (aCell.meType)
1120 case CELLTYPE_EDIT :
1121 bFieldText = WriteFieldText(aCell.mpEditText);
1122 if ( bFieldText )
1123 break;
1124 //! else: fallthru
1125 default:
1126 ScCellFormat::GetString(aCell, nFormat, aStrOut, &pColor, *pFormatter, pDoc);
1129 if ( !bFieldText )
1131 if ( aStrOut.isEmpty() )
1133 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak ); // No completely empty line
1135 else
1137 OUString aStr = aStrOut;
1138 sal_Int32 nPos = aStr.indexOf( '\n' );
1139 if ( nPos == -1 )
1141 OUT_STR( aStrOut );
1143 else
1145 sal_Int32 nStartPos = 0;
1148 OUString aSingleLine = aStr.copy( nStartPos, nPos - nStartPos );
1149 OUT_STR( aSingleLine );
1150 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak );
1151 nStartPos = nPos + 1;
1153 while( ( nPos = aStr.indexOf( '\n', nStartPos ) ) != -1 );
1154 OUString aSingleLine = aStr.copy( nStartPos, aStr.getLength() - nStartPos );
1155 OUT_STR( aSingleLine );
1159 if ( pGraphEntry )
1160 WriteGraphEntry( pGraphEntry );
1162 if ( bSetFont ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_font );
1163 if ( bUnderline ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_underline );
1164 if ( bItalic ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_italic );
1165 if ( bBold ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_bold );
1167 TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tabledata );
1170 bool ScHTMLExport::WriteFieldText( const EditTextObject* pData )
1172 bool bFields = false;
1173 // text and anchor of URL fields, Doc-Engine is a ScFieldEditEngine
1174 EditEngine& rEngine = pDoc->GetEditEngine();
1175 rEngine.SetText( *pData );
1176 sal_Int32 nParas = rEngine.GetParagraphCount();
1177 if ( nParas )
1179 ESelection aSel( 0, 0, nParas-1, rEngine.GetTextLen( nParas-1 ) );
1180 SfxItemSet aSet( rEngine.GetAttribs( aSel ) );
1181 SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, false );
1182 if ( eFieldState == SfxItemState::DONTCARE || eFieldState == SfxItemState::SET )
1183 bFields = true;
1185 if ( bFields )
1187 bool bOldUpdateMode = rEngine.GetUpdateMode();
1188 rEngine.SetUpdateMode( true ); // no portions if not formatted
1189 for ( sal_Int32 nPar=0; nPar < nParas; nPar++ )
1191 if ( nPar > 0 )
1192 TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak );
1193 std::vector<sal_Int32> aPortions;
1194 rEngine.GetPortions( nPar, aPortions );
1195 sal_Int32 nStart = 0;
1196 for ( std::vector<sal_Int32>::const_iterator it(aPortions.begin()); it != aPortions.end(); ++it )
1198 sal_Int32 nEnd = *it;
1199 ESelection aSel( nPar, nStart, nPar, nEnd );
1200 bool bUrl = false;
1201 // fields are single characters
1202 if ( nEnd == nStart+1 )
1204 const SfxPoolItem* pItem;
1205 SfxItemSet aSet = rEngine.GetAttribs( aSel );
1206 if ( aSet.GetItemState( EE_FEATURE_FIELD, false, &pItem ) == SfxItemState::SET )
1208 const SvxFieldData* pField = static_cast<const SvxFieldItem*>(pItem)->GetField();
1209 if ( pField && pField->ISA(SvxURLField) )
1211 bUrl = true;
1212 const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
1213 // String aFieldText = rEngine.GetText( aSel );
1214 rStrm.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_href ).WriteCharPtr( "=\"" );
1215 OUT_STR( pURLField->GetURL() );
1216 rStrm.WriteCharPtr( "\">" );
1217 OUT_STR( pURLField->GetRepresentation() );
1218 rStrm.WriteCharPtr( "</" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor ).WriteChar( '>' );
1222 if ( !bUrl )
1223 OUT_STR( rEngine.GetText( aSel ) );
1224 nStart = nEnd;
1227 rEngine.SetUpdateMode( bOldUpdateMode );
1229 return bFields;
1232 bool ScHTMLExport::CopyLocalFileToINet( OUString& rFileNm,
1233 const OUString& rTargetNm, bool bFileToFile )
1235 bool bRet = false;
1236 INetURLObject aFileUrl, aTargetUrl;
1237 aFileUrl.SetSmartURL( rFileNm );
1238 aTargetUrl.SetSmartURL( rTargetNm );
1239 if( INetProtocol::File == aFileUrl.GetProtocol() &&
1240 ( (bFileToFile && INetProtocol::File == aTargetUrl.GetProtocol()) ||
1241 (!bFileToFile && INetProtocol::File != aTargetUrl.GetProtocol() &&
1242 INetProtocol::Ftp <= aTargetUrl.GetProtocol() &&
1243 INetProtocol::Javascript >= aTargetUrl.GetProtocol()) ) )
1245 if( pFileNameMap )
1247 // Did we already move the file?
1248 std::map<OUString, OUString>::iterator it = pFileNameMap->find( rFileNm );
1249 if( it != pFileNameMap->end() )
1251 rFileNm = it->second;
1252 return true;
1255 else
1257 pFileNameMap.reset( new std::map<OUString, OUString>() );
1260 SvFileStream aTmp( aFileUrl.PathToFileName(), StreamMode::READ );
1262 OUString aSrc = rFileNm;
1263 OUString aDest = aTargetUrl.GetPartBeforeLastName();
1264 aDest += aFileUrl.GetName();
1266 if( bFileToFile )
1268 INetURLObject aCpyURL( aDest );
1269 SvFileStream aCpy( aCpyURL.PathToFileName(), StreamMode::WRITE );
1270 aCpy.WriteStream( aTmp );
1272 aCpy.Close();
1273 bRet = SVSTREAM_OK == aCpy.GetError();
1275 else
1277 SfxMedium aMedium( aDest, StreamMode::WRITE | StreamMode::SHARE_DENYNONE );
1280 SvFileStream aCpy( aMedium.GetPhysicalName(), StreamMode::WRITE );
1281 aCpy.WriteStream( aTmp );
1284 // Take over
1285 aMedium.Close();
1286 aMedium.Commit();
1288 bRet = 0 == aMedium.GetError();
1291 if( bRet )
1293 pFileNameMap->insert( std::make_pair( aSrc, aDest ) );
1294 rFileNm = aDest;
1298 return bRet;
1301 void ScHTMLExport::MakeCIdURL( OUString& rURL )
1303 if( aCId.isEmpty() )
1304 return;
1306 INetURLObject aURLObj( rURL );
1307 if( INetProtocol::File != aURLObj.GetProtocol() )
1308 return;
1310 OUString aLastName( aURLObj.GetLastName().toAsciiLowerCase() );
1311 OSL_ENSURE( !aLastName.isEmpty(), "filename without length!" );
1313 rURL = "cid:" + aLastName + "." + aCId;
1316 void ScHTMLExport::IncIndent( short nVal )
1318 sIndent[nIndent] = '\t';
1319 nIndent = nIndent + nVal;
1320 if ( nIndent < 0 )
1321 nIndent = 0;
1322 else if ( nIndent > nIndentMax )
1323 nIndent = nIndentMax;
1324 sIndent[nIndent] = 0;
1327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */