Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include "scitems.hxx"
21 : #include <comphelper/string.hxx>
22 : #include <editeng/eeitem.hxx>
23 :
24 : #include <rtl/tencinfo.h>
25 :
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>
51 :
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"
66 :
67 : #include <editeng/flditem.hxx>
68 : #include <editeng/borderline.hxx>
69 : #include <unotools/syslocale.hxx>
70 :
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"
78 :
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>
83 :
84 : using ::editeng::SvxBorderLine;
85 : using namespace ::com::sun::star;
86 :
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:";
91 :
92 : const sal_uInt16 ScHTMLExport::nDefaultFontSize[SC_HTML_FONTSIZES] =
93 : {
94 : HTMLFONTSZ1_DFLT, HTMLFONTSZ2_DFLT, HTMLFONTSZ3_DFLT, HTMLFONTSZ4_DFLT,
95 : HTMLFONTSZ5_DFLT, HTMLFONTSZ6_DFLT, HTMLFONTSZ7_DFLT
96 : };
97 :
98 : sal_uInt16 ScHTMLExport::nFontSize[SC_HTML_FONTSIZES] = { 0 };
99 :
100 : const char* ScHTMLExport::pFontSizeCss[SC_HTML_FONTSIZES] =
101 : {
102 : "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"
103 : };
104 :
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";
108 :
109 : // Macros for HTML export
110 :
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() ))
121 :
122 : #define OUT_SP_CSTR_ASS( s ) rStrm.WriteChar( ' ').WriteCharPtr( s ).WriteChar( '=' )
123 :
124 : #define GLOBSTR(id) ScGlobal::GetRscString( id )
125 :
126 3 : 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 )
129 : {
130 3 : ScHTMLExport aEx( rStrm, rBaseURL, pDoc, rRange, bAll, rStreamPath, rFilterOptions );
131 3 : FltError nErr = aEx.Write();
132 3 : rNonConvertibleChars = aEx.GetNonConvertibleChars();
133 3 : return nErr;
134 : }
135 :
136 3 : static OString lcl_getColGroupString(sal_Int32 nSpan, sal_Int32 nWidth)
137 : {
138 3 : OStringBuffer aByteStr(OOO_STRING_SVTOOLS_HTML_colgroup);
139 3 : aByteStr.append(' ');
140 3 : if( nSpan > 1 )
141 : {
142 3 : aByteStr.append(OOO_STRING_SVTOOLS_HTML_O_span);
143 3 : aByteStr.append("=\"");
144 3 : aByteStr.append(nSpan);
145 3 : aByteStr.append("\" ");
146 : }
147 3 : aByteStr.append(OOO_STRING_SVTOOLS_HTML_O_width);
148 3 : aByteStr.append("=\"");
149 3 : aByteStr.append(nWidth);
150 3 : aByteStr.append('"');
151 3 : return aByteStr.makeStringAndClear();
152 : }
153 :
154 0 : static void lcl_AddStamp( OUString& rStr, const OUString& rName,
155 : const ::com::sun::star::util::DateTime& rDateTime,
156 : const LocaleDataWrapper& rLoc )
157 : {
158 0 : Date aD(rDateTime.Day, rDateTime.Month, rDateTime.Year);
159 : tools::Time aT(rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds,
160 0 : rDateTime.NanoSeconds);
161 0 : DateTime aDateTime(aD,aT);
162 :
163 0 : OUString aStrDate = rLoc.getDate( aDateTime );
164 0 : OUString aStrTime = rLoc.getTime( aDateTime );
165 :
166 0 : rStr += GLOBSTR( STR_BY ) + " ";
167 0 : if (!rName.isEmpty())
168 0 : rStr += rName;
169 : else
170 0 : rStr += "???";
171 0 : rStr += " " + GLOBSTR( STR_ON ) + " ";
172 0 : if (!aStrDate.isEmpty())
173 0 : rStr += aStrDate;
174 : else
175 0 : rStr += "???";
176 0 : rStr += ", ";
177 0 : if (!aStrTime.isEmpty())
178 0 : rStr += aStrTime;
179 : else
180 0 : rStr += "???";
181 0 : }
182 :
183 4 : static OString lcl_makeHTMLColorTriplet(const Color& rColor)
184 : {
185 4 : OStringBuffer aStr( "\"#" );
186 : // <font COLOR="#00FF40">hello</font>
187 : sal_Char buf[64];
188 4 : sal_Char* p = buf;
189 4 : p += sprintf( p, "%02X", rColor.GetRed() );
190 4 : p += sprintf( p, "%02X", rColor.GetGreen() );
191 4 : p += sprintf( p, "%02X", rColor.GetBlue() );
192 4 : aStr.append(buf);
193 4 : aStr.append('\"');
194 4 : return aStr.makeStringAndClear();
195 : }
196 :
197 3 : 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 3 : bCalcAsShown( pDocP->GetDocOptions().IsCalcAsShown() ),
211 : bTableDataWidth( true ),
212 : bTableDataHeight( true ),
213 : mbSkipImages ( false ),
214 6 : mbSkipHeaderFooter( false )
215 : {
216 3 : strcpy( sIndent, sIndentSource );
217 3 : sIndent[0] = 0;
218 :
219 : // set HTML configuration
220 3 : SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
221 3 : eDestEnc = (pDoc->IsClipOrUndo() ? RTL_TEXTENCODING_UTF8 : rHtmlOptions.GetTextEncoding());
222 3 : bCopyLocalFileToINet = rHtmlOptions.IsSaveGraphicsLocal();
223 :
224 3 : if (rFilterOptions == "SkipImages")
225 : {
226 1 : mbSkipImages = true;
227 : }
228 2 : else if (rFilterOptions == "SkipHeaderFooter")
229 : {
230 1 : mbSkipHeaderFooter = true;
231 : }
232 :
233 24 : for ( sal_uInt16 j=0; j < SC_HTML_FONTSIZES; j++ )
234 : {
235 21 : sal_uInt16 nSize = rHtmlOptions.GetFontSize( j );
236 : // remember in Twips, like our SvxFontHeightItem
237 21 : if ( nSize )
238 21 : nFontSize[j] = nSize * 20;
239 : else
240 0 : nFontSize[j] = nDefaultFontSize[j] * 20;
241 : }
242 :
243 3 : const SCTAB nCount = pDoc->GetTableCount();
244 6 : for ( SCTAB nTab = 0; nTab < nCount; nTab++ )
245 : {
246 3 : if ( !IsEmptyTable( nTab ) )
247 3 : nUsedTables++;
248 : }
249 :
250 : // Content-Id for Mail export?
251 3 : SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
252 3 : if ( pDocSh )
253 : {
254 3 : const SfxPoolItem* pItem = pDocSh->GetItem( SID_ORIGURL );
255 3 : if( pItem )
256 : {
257 0 : aCId = static_cast<const SfxStringItem *>(pItem)->GetValue();
258 : OSL_ENSURE( !aCId.isEmpty(), "CID without length!" );
259 : }
260 : }
261 3 : }
262 :
263 6 : ScHTMLExport::~ScHTMLExport()
264 : {
265 3 : aGraphList.clear();
266 3 : }
267 :
268 5 : sal_uInt16 ScHTMLExport::GetFontSizeNumber( sal_uInt16 nHeight )
269 : {
270 5 : sal_uInt16 nSize = 1;
271 30 : for ( sal_uInt16 j=SC_HTML_FONTSIZES-1; j>0; j-- )
272 : {
273 30 : if( nHeight > (nFontSize[j] + nFontSize[j-1]) / 2 )
274 : { // The one next to it
275 5 : nSize = j+1;
276 5 : break;
277 : }
278 : }
279 5 : return nSize;
280 : }
281 :
282 2 : const char* ScHTMLExport::GetFontSizeCss( sal_uInt16 nHeight )
283 : {
284 2 : sal_uInt16 nSize = GetFontSizeNumber( nHeight );
285 2 : return pFontSizeCss[ nSize-1 ];
286 : }
287 :
288 90 : sal_uInt16 ScHTMLExport::ToPixel( sal_uInt16 nVal )
289 : {
290 90 : if( nVal )
291 : {
292 : nVal = (sal_uInt16)pAppWin->LogicToPixel(
293 90 : Size( nVal, nVal ), MapMode( MAP_TWIP ) ).Width();
294 90 : if( !nVal ) // If there's a Twip there should also be a Pixel
295 0 : nVal = 1;
296 : }
297 90 : return nVal;
298 : }
299 :
300 4 : Size ScHTMLExport::MMToPixel( const Size& rSize )
301 : {
302 4 : Size aSize( rSize );
303 4 : aSize = pAppWin->LogicToPixel( rSize, MapMode( MAP_100TH_MM ) );
304 : // If there's something there should also be a Pixel
305 4 : if ( !aSize.Width() && rSize.Width() )
306 0 : aSize.Width() = 1;
307 4 : if ( !aSize.Height() && rSize.Height() )
308 0 : aSize.Height() = 1;
309 4 : return aSize;
310 : }
311 :
312 3 : sal_uLong ScHTMLExport::Write()
313 : {
314 3 : if (!mbSkipHeaderFooter)
315 : {
316 2 : rStrm.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_doctype40 ).WriteChar( '>' )
317 2 : .WriteCharPtr( SAL_NEWLINE_STRING ).WriteCharPtr( SAL_NEWLINE_STRING );
318 2 : TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_html );
319 2 : WriteHeader();
320 2 : OUT_LF();
321 : }
322 3 : WriteBody();
323 3 : OUT_LF();
324 3 : if (!mbSkipHeaderFooter)
325 2 : TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_html );
326 :
327 3 : return rStrm.GetError();
328 : }
329 :
330 2 : void ScHTMLExport::WriteHeader()
331 : {
332 2 : IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_head );
333 :
334 2 : if ( pDoc->IsClipOrUndo() )
335 : { // no real DocInfo available, but some META information like charset needed
336 0 : SfxFrameHTMLWriter::Out_DocInfo( rStrm, aBaseURL, NULL, sIndent, eDestEnc, &aNonConvertibleChars );
337 : }
338 : else
339 : {
340 : using namespace ::com::sun::star;
341 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
342 2 : pDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW);
343 : uno::Reference<document::XDocumentProperties> xDocProps
344 4 : = xDPS->getDocumentProperties();
345 : SfxFrameHTMLWriter::Out_DocInfo( rStrm, aBaseURL, xDocProps,
346 2 : sIndent, eDestEnc, &aNonConvertibleChars );
347 2 : OUT_LF();
348 :
349 2 : if (!xDocProps->getPrintedBy().isEmpty())
350 : {
351 0 : OUT_COMMENT( GLOBSTR( STR_DOC_INFO ) );
352 0 : OUString aStrOut = ( GLOBSTR( STR_DOC_PRINTED ) ) + ": ";
353 0 : lcl_AddStamp( aStrOut, xDocProps->getPrintedBy(),
354 0 : xDocProps->getPrintDate(), *ScGlobal::pLocaleData );
355 0 : OUT_COMMENT( aStrOut );
356 2 : }
357 :
358 : }
359 2 : OUT_LF();
360 :
361 : // CSS1 StyleSheet
362 2 : PageDefaults( bAll ? 0 : aRange.aStart.Tab() );
363 2 : IncIndent(1);
364 2 : rStrm.WriteCharPtr( "<" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_style ).WriteCharPtr( " " ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_type ).WriteCharPtr( "=\"text/css\">" );
365 :
366 2 : OUT_LF();
367 2 : rStrm.WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_division ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_table ).WriteCharPtr( "," )
368 2 : .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_thead ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tbody ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tfoot ).WriteCharPtr( "," )
369 2 : .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tablerow ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tableheader ).WriteCharPtr( "," )
370 2 : .WriteCharPtr( OOO_STRING_SVTOOLS_HTML_tabledata ).WriteCharPtr( "," ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_parabreak ).WriteCharPtr( " { " ).WriteCharPtr( sFontFamily );
371 2 : sal_Int32 nFonts = comphelper::string::getTokenCount(aHTMLStyle.aFontFamilyName, ';');
372 2 : if ( nFonts == 1 )
373 : {
374 2 : rStrm.WriteChar( '\"' );
375 2 : OUT_STR( aHTMLStyle.aFontFamilyName );
376 2 : rStrm.WriteChar( '\"' );
377 : }
378 : else
379 : { // Fontlist, VCL: Semicolon as separator
380 : // CSS1: Comma as separator and every single font name quoted
381 0 : const OUString& rList = aHTMLStyle.aFontFamilyName;
382 0 : for ( sal_Int32 j = 0, nPos = 0; j < (sal_Int32) nFonts; j++ )
383 : {
384 0 : rStrm.WriteChar( '\"' );
385 0 : OUT_STR( rList.getToken( 0, ';', nPos ) );
386 0 : rStrm.WriteChar( '\"' );
387 0 : if ( j < nFonts-1 )
388 0 : rStrm.WriteCharPtr( ", " );
389 : }
390 : }
391 2 : rStrm.WriteCharPtr( "; " ).WriteCharPtr( sFontSize )
392 4 : .WriteCharPtr( GetFontSizeCss( ( sal_uInt16 ) aHTMLStyle.nFontHeight ) ).WriteCharPtr( " }" );
393 2 : IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_style );
394 :
395 2 : IncIndent(-1); OUT_LF(); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head );
396 2 : }
397 :
398 3 : void ScHTMLExport::WriteOverview()
399 : {
400 3 : if ( nUsedTables > 1 )
401 : {
402 0 : IncIndent(1);
403 0 : OUT_HR();
404 0 : IncIndent(1); TAG_ON( OOO_STRING_SVTOOLS_HTML_parabreak ); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_center );
405 0 : TAG_ON( OOO_STRING_SVTOOLS_HTML_head1 );
406 0 : OUT_STR( ScGlobal::GetRscString( STR_OVERVIEW ) );
407 0 : TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_head1 );
408 :
409 0 : OUString aStr;
410 :
411 0 : const SCTAB nCount = pDoc->GetTableCount();
412 0 : for ( SCTAB nTab = 0; nTab < nCount; nTab++ )
413 : {
414 0 : if ( !IsEmptyTable( nTab ) )
415 : {
416 0 : pDoc->GetName( nTab, aStr );
417 0 : rStrm.WriteCharPtr( "<A HREF=\"#table" )
418 0 : .WriteCharPtr( OString::number(nTab).getStr() )
419 0 : .WriteCharPtr( "\">" );
420 0 : OUT_STR( aStr );
421 0 : rStrm.WriteCharPtr( "</A>" );
422 0 : TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_linebreak );
423 : }
424 : }
425 :
426 0 : IncIndent(-1); OUT_LF();
427 0 : IncIndent(-1); TAG_OFF( OOO_STRING_SVTOOLS_HTML_center ); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_parabreak );
428 : }
429 3 : }
430 :
431 5 : const SfxItemSet& ScHTMLExport::PageDefaults( SCTAB nTab )
432 : {
433 5 : SfxStyleSheetBasePool* pStylePool = pDoc->GetStyleSheetPool();
434 5 : SfxStyleSheetBase* pStyleSheet = NULL;
435 : OSL_ENSURE( pStylePool, "StylePool not found! :-(" );
436 :
437 : // remember defaults for compare in WriteCell
438 5 : if ( !aHTMLStyle.bInitialized )
439 : {
440 3 : pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_ALL );
441 : pStyleSheet = pStylePool->Find(
442 3 : ScGlobal::GetRscString(STR_STYLENAME_STANDARD),
443 6 : SFX_STYLE_FAMILY_PARA );
444 : OSL_ENSURE( pStyleSheet, "ParaStyle not found! :-(" );
445 3 : if (!pStyleSheet)
446 0 : pStyleSheet = pStylePool->First();
447 3 : const SfxItemSet& rSetPara = pStyleSheet->GetItemSet();
448 :
449 3 : aHTMLStyle.nDefaultScriptType = ScGlobal::GetDefaultScriptType();
450 3 : aHTMLStyle.aFontFamilyName = static_cast<const SvxFontItem&>((rSetPara.Get(
451 : ScGlobal::GetScriptedWhichID(
452 : aHTMLStyle.nDefaultScriptType, ATTR_FONT
453 6 : )))).GetFamilyName();
454 : aHTMLStyle.nFontHeight = static_cast<const SvxFontHeightItem&>((rSetPara.Get(
455 : ScGlobal::GetScriptedWhichID(
456 : aHTMLStyle.nDefaultScriptType, ATTR_FONT_HEIGHT
457 3 : )))).GetHeight();
458 3 : aHTMLStyle.nFontSizeNumber = GetFontSizeNumber( static_cast< sal_uInt16 >( aHTMLStyle.nFontHeight ) );
459 : }
460 :
461 : // Page style sheet printer settings, e.g. for background graphics.
462 : // There's only one background graphic in HTML!
463 5 : pStylePool->SetSearchMask( SFX_STYLE_FAMILY_PAGE, SFXSTYLEBIT_ALL );
464 5 : pStyleSheet = pStylePool->Find( pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE );
465 : OSL_ENSURE( pStyleSheet, "PageStyle not found! :-(" );
466 5 : if (!pStyleSheet)
467 0 : pStyleSheet = pStylePool->First();
468 5 : const SfxItemSet& rSet = pStyleSheet->GetItemSet();
469 5 : if ( !aHTMLStyle.bInitialized )
470 : {
471 3 : const SvxBrushItem* pBrushItem = static_cast<const SvxBrushItem*>(&rSet.Get( ATTR_BACKGROUND ));
472 3 : aHTMLStyle.aBackgroundColor = pBrushItem->GetColor();
473 3 : aHTMLStyle.bInitialized = true;
474 : }
475 5 : return rSet;
476 : }
477 :
478 0 : OString ScHTMLExport::BorderToStyle(const char* pBorderName,
479 : const SvxBorderLine* pLine, bool& bInsertSemicolon)
480 : {
481 0 : OStringBuffer aOut;
482 :
483 0 : if ( pLine )
484 : {
485 0 : if ( bInsertSemicolon )
486 0 : aOut.append("; ");
487 :
488 : // which border
489 0 : aOut.append("border-").append(pBorderName).append(": ");
490 :
491 : // thickness
492 0 : int nWidth = pLine->GetWidth();
493 : int nPxWidth = (nWidth > 0) ?
494 0 : std::max(int(nWidth / TWIPS_PER_PIXEL), 1) : 0;
495 0 : aOut.append(static_cast<sal_Int32>(nPxWidth)).
496 0 : append("px ");
497 0 : switch (pLine->GetBorderLineStyle())
498 : {
499 : case table::BorderLineStyle::SOLID:
500 0 : aOut.append("solid");
501 0 : break;
502 : case table::BorderLineStyle::DOTTED:
503 0 : aOut.append("dotted");
504 0 : break;
505 : case table::BorderLineStyle::DASHED:
506 : case table::BorderLineStyle::DASH_DOT:
507 : case table::BorderLineStyle::DASH_DOT_DOT:
508 0 : aOut.append("dashed");
509 0 : 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 0 : aOut.append("double");
519 0 : break;
520 : case table::BorderLineStyle::EMBOSSED:
521 0 : aOut.append("ridge");
522 0 : break;
523 : case table::BorderLineStyle::ENGRAVED:
524 0 : aOut.append("groove");
525 0 : break;
526 : case table::BorderLineStyle::OUTSET:
527 0 : aOut.append("outset");
528 0 : break;
529 : case table::BorderLineStyle::INSET:
530 0 : aOut.append("inset");
531 0 : break;
532 : default:
533 0 : aOut.append("hidden");
534 : }
535 0 : aOut.append(" #");
536 :
537 : // color
538 : char hex[7];
539 0 : snprintf( hex, 7, "%06x", static_cast< unsigned int >( pLine->GetColor().GetRGBColor() ) );
540 0 : hex[6] = 0;
541 :
542 0 : aOut.append(hex);
543 :
544 0 : bInsertSemicolon = true;
545 : }
546 :
547 0 : return aOut.makeStringAndClear();
548 : }
549 :
550 3 : void ScHTMLExport::WriteBody()
551 : {
552 3 : const SfxItemSet& rSet = PageDefaults( bAll ? 0 : aRange.aStart.Tab() );
553 3 : const SvxBrushItem* pBrushItem = static_cast<const SvxBrushItem*>(&rSet.Get( ATTR_BACKGROUND ));
554 :
555 : // default text color black
556 3 : if (!mbSkipHeaderFooter)
557 : {
558 2 : rStrm.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_body );
559 :
560 2 : if (!mbSkipImages)
561 : {
562 1 : if ( bAll && GPOS_NONE != pBrushItem->GetGraphicPos() )
563 : {
564 0 : OUString aLink = pBrushItem->GetGraphicLink();
565 0 : OUString aGrfNm;
566 :
567 : // Embedded graphic -> write using WriteGraphic
568 0 : if( aLink.isEmpty() )
569 : {
570 0 : const Graphic* pGrf = pBrushItem->GetGraphic();
571 0 : if( pGrf )
572 : {
573 : // Save graphic as (JPG) file
574 0 : aGrfNm = aStreamPath;
575 : sal_uInt16 nErr = XOutBitmap::WriteGraphic( *pGrf, aGrfNm,
576 0 : "JPG", XOUTBMP_USE_NATIVE_IF_POSSIBLE );
577 0 : if( !nErr ) // Contains errors, as we have nothing to output
578 : {
579 0 : aGrfNm = URIHelper::SmartRel2Abs(
580 : INetURLObject(aBaseURL),
581 0 : aGrfNm, URIHelper::GetMaybeFileHdl(), true, false);
582 0 : if ( HasCId() )
583 0 : MakeCIdURL( aGrfNm );
584 0 : aLink = aGrfNm;
585 : }
586 : }
587 : }
588 : else
589 : {
590 0 : aGrfNm = aLink;
591 0 : if( bCopyLocalFileToINet || HasCId() )
592 : {
593 0 : CopyLocalFileToINet( aGrfNm, aStreamPath );
594 0 : if ( HasCId() )
595 0 : MakeCIdURL( aGrfNm );
596 : }
597 : else
598 0 : aGrfNm = URIHelper::SmartRel2Abs(
599 : INetURLObject(aBaseURL),
600 0 : aGrfNm, URIHelper::GetMaybeFileHdl(), true, false);
601 0 : aLink = aGrfNm;
602 : }
603 0 : if( !aLink.isEmpty() )
604 : {
605 0 : rStrm.WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_background ).WriteCharPtr( "=\"" );
606 0 : OUT_STR( URIHelper::simpleNormalizedMakeRelative(
607 : aBaseURL,
608 0 : aLink ) ).WriteChar( '\"' );
609 0 : }
610 : }
611 : }
612 2 : 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 0 : OUT_SP_CSTR_ASS( OOO_STRING_SVTOOLS_HTML_O_bgcolor );
618 0 : HTMLOutFuncs::Out_Color( rStrm, aHTMLStyle.aBackgroundColor );
619 : }
620 :
621 2 : rStrm.WriteChar( '>' ); OUT_LF();
622 : }
623 :
624 3 : if ( bAll )
625 3 : WriteOverview();
626 :
627 3 : WriteTables();
628 :
629 3 : if (!mbSkipHeaderFooter)
630 2 : TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_body );
631 3 : }
632 :
633 3 : void ScHTMLExport::WriteTables()
634 : {
635 3 : const SCTAB nTabCount = pDoc->GetTableCount();
636 3 : const OUString aStrTable( ScResId( SCSTR_TABLE ) );
637 6 : OUString aStr;
638 6 : OUString aStrOut;
639 : SCCOL nStartCol;
640 : SCROW nStartRow;
641 : SCTAB nStartTab;
642 : SCCOL nEndCol;
643 : SCROW nEndRow;
644 : SCTAB nEndTab;
645 3 : SCCOL nStartColFix = 0;
646 3 : SCROW nStartRowFix = 0;
647 3 : SCCOL nEndColFix = 0;
648 3 : SCROW nEndRowFix = 0;
649 3 : ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
650 3 : if ( bAll )
651 : {
652 3 : nStartTab = 0;
653 3 : nEndTab = nTabCount - 1;
654 : }
655 : else
656 : {
657 0 : nStartCol = nStartColFix = aRange.aStart.Col();
658 0 : nStartRow = nStartRowFix = aRange.aStart.Row();
659 0 : nStartTab = aRange.aStart.Tab();
660 0 : nEndCol = nEndColFix = aRange.aEnd.Col();
661 0 : nEndRow = nEndRowFix = aRange.aEnd.Row();
662 0 : nEndTab = aRange.aEnd.Tab();
663 : }
664 3 : SCTAB nTableStrNum = 1;
665 6 : for ( SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++ )
666 : {
667 3 : if ( !pDoc->IsVisible( nTab ) )
668 0 : continue; // for
669 :
670 3 : if ( bAll )
671 : {
672 3 : if ( !GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow ) )
673 0 : continue; // for
674 :
675 3 : if ( nUsedTables > 1 )
676 : {
677 0 : aStrOut = aStrTable + " " + OUString::number( nTableStrNum++ ) + ": ";
678 :
679 0 : OUT_HR();
680 :
681 : // Write anchor
682 0 : rStrm.WriteCharPtr( "<A NAME=\"table" )
683 0 : .WriteCharPtr( OString::number(nTab).getStr() )
684 0 : .WriteCharPtr( "\">" );
685 0 : TAG_ON( OOO_STRING_SVTOOLS_HTML_head1 );
686 0 : OUT_STR( aStrOut );
687 0 : TAG_ON( OOO_STRING_SVTOOLS_HTML_emphasis );
688 :
689 0 : pDoc->GetName( nTab, aStr );
690 0 : OUT_STR( aStr );
691 :
692 0 : TAG_OFF( OOO_STRING_SVTOOLS_HTML_emphasis );
693 0 : TAG_OFF( OOO_STRING_SVTOOLS_HTML_head1 );
694 0 : rStrm.WriteCharPtr( "</A>" ); OUT_LF();
695 : }
696 : }
697 : else
698 : {
699 0 : nStartCol = nStartColFix;
700 0 : nStartRow = nStartRowFix;
701 0 : nEndCol = nEndColFix;
702 0 : nEndRow = nEndRowFix;
703 0 : if ( !TrimDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow ) )
704 0 : continue; // for
705 : }
706 :
707 : // <TABLE ...>
708 3 : OStringBuffer aByteStrOut(OOO_STRING_SVTOOLS_HTML_table);
709 :
710 3 : bTabHasGraphics = bTabAlignedLeft = false;
711 3 : if ( bAll && pDrawLayer )
712 : PrepareGraphics( pDrawLayer, nTab, nStartCol, nStartRow,
713 3 : nEndCol, nEndRow );
714 :
715 : // more <TABLE ...>
716 3 : if ( bTabAlignedLeft )
717 : {
718 0 : aByteStrOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align).
719 0 : append("=\"").
720 0 : append(OOO_STRING_SVTOOLS_HTML_AL_left).append('"');
721 : }
722 : // ALIGN=LEFT allow text and graphics to flow around
723 : // CELLSPACING
724 3 : aByteStrOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_cellspacing).
725 3 : append("=\"").
726 3 : append(static_cast<sal_Int32>(nCellSpacing)).append('"');
727 :
728 : // BORDER=0, we do the styling of the cells in <TD>
729 3 : aByteStrOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_border).
730 3 : append("=\"0\"");
731 3 : IncIndent(1); TAG_ON_LF( aByteStrOut.makeStringAndClear().getStr() );
732 :
733 : // --- <COLGROUP> ----
734 : {
735 3 : SCCOL nCol = nStartCol;
736 3 : sal_Int32 nWidth = 0;
737 3 : sal_Int32 nSpan = 0;
738 18 : while( nCol <= nEndCol )
739 : {
740 12 : if( pDoc->ColHidden(nCol, nTab) )
741 : {
742 0 : ++nCol;
743 0 : continue;
744 : }
745 :
746 12 : if( nWidth != ToPixel( pDoc->GetColWidth( nCol, nTab ) ) )
747 : {
748 3 : if( nSpan != 0 )
749 : {
750 0 : TAG_ON(lcl_getColGroupString(nSpan, nWidth).getStr());
751 0 : TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup );
752 : }
753 3 : nWidth = ToPixel( pDoc->GetColWidth( nCol, nTab ) );
754 3 : nSpan = 1;
755 : }
756 : else
757 9 : nSpan++;
758 12 : nCol++;
759 : }
760 3 : if( nSpan )
761 : {
762 3 : TAG_ON(lcl_getColGroupString(nSpan, nWidth).getStr());
763 3 : TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_colgroup );
764 : }
765 : }
766 :
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 3 : bTableDataWidth = true; // widths in first row
772 3 : bool bHasHiddenRows = pDoc->HasHiddenRows(nStartRow, nEndRow, nTab);
773 21 : for ( SCROW nRow=nStartRow; nRow<=nEndRow; nRow++ )
774 : {
775 18 : if ( bHasHiddenRows && pDoc->RowHidden(nRow, nTab) )
776 : {
777 0 : nRow = pDoc->FirstVisibleRow(nRow+1, nEndRow, nTab);
778 0 : --nRow;
779 0 : continue; // for
780 : }
781 :
782 18 : IncIndent(1); TAG_ON_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
783 18 : bTableDataHeight = true; // height at every first cell of each row
784 102 : for ( SCCOL nCol2=nStartCol; nCol2<=nEndCol; nCol2++ )
785 : {
786 84 : if ( pDoc->ColHidden(nCol2, nTab) )
787 0 : continue; // for
788 :
789 84 : if ( nCol2 == nEndCol )
790 18 : IncIndent(-1);
791 84 : WriteCell( nCol2, nRow, nTab );
792 84 : bTableDataHeight = false;
793 : }
794 18 : bTableDataWidth = false; // widths only in first row
795 :
796 18 : if ( nRow == nEndRow )
797 3 : IncIndent(-1);
798 18 : TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tablerow );
799 : }
800 : // TODO: Uncomment later
801 : // IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tbody );
802 :
803 3 : IncIndent(-1); TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_table );
804 :
805 3 : if ( bTabHasGraphics && !mbSkipImages )
806 : {
807 : // the rest that is not in a cell
808 1 : size_t ListSize = aGraphList.size();
809 2 : for ( size_t i = 0; i < ListSize; ++i )
810 : {
811 1 : ScHTMLGraphEntry* pE = &aGraphList[ i ];
812 1 : if ( !pE->bWritten )
813 0 : WriteGraphEntry( pE );
814 : }
815 1 : aGraphList.clear();
816 1 : if ( bTabAlignedLeft )
817 : {
818 : // clear <TABLE ALIGN=LEFT> with <BR CLEAR=LEFT>
819 0 : aByteStrOut.append(OOO_STRING_SVTOOLS_HTML_linebreak);
820 0 : aByteStrOut.append(' ').
821 0 : append(OOO_STRING_SVTOOLS_HTML_O_clear).append('=').
822 0 : append(OOO_STRING_SVTOOLS_HTML_AL_left);
823 0 : TAG_ON_LF( aByteStrOut.makeStringAndClear().getStr() );
824 : }
825 : }
826 :
827 3 : if ( bAll )
828 3 : OUT_COMMENT( OUString("**************************************************************************") );
829 6 : }
830 3 : }
831 :
832 84 : void ScHTMLExport::WriteCell( SCCOL nCol, SCROW nRow, SCTAB nTab )
833 : {
834 84 : const ScPatternAttr* pAttr = pDoc->GetPattern( nCol, nRow, nTab );
835 84 : const SfxItemSet* pCondItemSet = pDoc->GetCondResult( nCol, nRow, nTab );
836 :
837 84 : const ScMergeFlagAttr& rMergeFlagAttr = static_cast<const ScMergeFlagAttr&>( pAttr->GetItem( ATTR_MERGE_FLAG, pCondItemSet ) );
838 84 : if ( rMergeFlagAttr.IsOverlapped() )
839 9 : return ;
840 :
841 84 : ScAddress aPos( nCol, nRow, nTab );
842 84 : ScHTMLGraphEntry* pGraphEntry = NULL;
843 84 : if ( bTabHasGraphics && !mbSkipImages )
844 : {
845 40 : size_t ListSize = aGraphList.size();
846 70 : for ( size_t i = 0; i < ListSize; ++i )
847 : {
848 40 : ScHTMLGraphEntry* pE = &aGraphList[ i ];
849 40 : if ( pE->bInCell && pE->aRange.In( aPos ) )
850 : {
851 10 : if ( pE->aRange.aStart == aPos )
852 : {
853 1 : pGraphEntry = pE;
854 1 : break; // for
855 : }
856 : else
857 9 : return ; // Is a Col/RowSpan, Overlapped
858 : }
859 : }
860 : }
861 :
862 75 : ScRefCellValue aCell;
863 75 : aCell.assign(*pDoc, aPos);
864 :
865 75 : sal_uLong nFormat = pAttr->GetNumberFormat( pFormatter );
866 75 : bool bValueData = aCell.hasNumeric();
867 75 : SvtScriptType nScriptType = SvtScriptType::NONE;
868 75 : if (!aCell.isEmpty())
869 40 : nScriptType = pDoc->GetScriptType(nCol, nRow, nTab);
870 :
871 75 : if ( nScriptType == SvtScriptType::NONE )
872 35 : nScriptType = aHTMLStyle.nDefaultScriptType;
873 :
874 150 : OStringBuffer aStrTD(OOO_STRING_SVTOOLS_HTML_tabledata);
875 :
876 : // border of the cells
877 75 : const SvxBoxItem* pBorder = static_cast<const SvxBoxItem*>( pDoc->GetAttr( nCol, nRow, nTab, ATTR_BORDER ) );
878 75 : if ( pBorder && (pBorder->GetTop() || pBorder->GetBottom() || pBorder->GetLeft() || pBorder->GetRight()) )
879 : {
880 0 : aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_style).
881 0 : append("=\"");
882 :
883 0 : bool bInsertSemicolon = false;
884 : aStrTD.append(BorderToStyle("top", pBorder->GetTop(),
885 0 : bInsertSemicolon));
886 : aStrTD.append(BorderToStyle("bottom", pBorder->GetBottom(),
887 0 : bInsertSemicolon));
888 : aStrTD.append(BorderToStyle("left", pBorder->GetLeft(),
889 0 : bInsertSemicolon));
890 : aStrTD.append(BorderToStyle("right", pBorder->GetRight(),
891 0 : bInsertSemicolon));
892 :
893 0 : aStrTD.append('"');
894 : }
895 :
896 : const sal_Char* pChar;
897 : sal_uInt16 nHeightPixel;
898 :
899 75 : const ScMergeAttr& rMergeAttr = static_cast<const ScMergeAttr&>( pAttr->GetItem( ATTR_MERGE, pCondItemSet ) );
900 75 : if ( pGraphEntry || rMergeAttr.IsMerged() )
901 : {
902 : SCCOL nC, jC;
903 : SCROW nR;
904 : sal_uLong v;
905 1 : if ( pGraphEntry )
906 1 : nC = std::max( SCCOL(pGraphEntry->aRange.aEnd.Col() - nCol + 1),
907 2 : SCCOL(rMergeAttr.GetColMerge()) );
908 : else
909 0 : nC = rMergeAttr.GetColMerge();
910 1 : if ( nC > 1 )
911 : {
912 1 : aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_colspan).
913 2 : append('=').append(static_cast<sal_Int32>(nC));
914 1 : nC = nC + nCol;
915 3 : for ( jC=nCol, v=0; jC<nC; jC++ )
916 2 : v += pDoc->GetColWidth( jC, nTab );
917 : }
918 :
919 1 : if ( pGraphEntry )
920 1 : nR = std::max( SCROW(pGraphEntry->aRange.aEnd.Row() - nRow + 1),
921 2 : SCROW(rMergeAttr.GetRowMerge()) );
922 : else
923 0 : nR = rMergeAttr.GetRowMerge();
924 1 : if ( nR > 1 )
925 : {
926 1 : aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_rowspan).
927 1 : append('=').append(static_cast<sal_Int32>(nR));
928 1 : nR += nRow;
929 1 : v = pDoc->GetRowHeight( nRow, nR-1, nTab );
930 1 : nHeightPixel = ToPixel( static_cast< sal_uInt16 >( v ) );
931 : }
932 : else
933 0 : nHeightPixel = ToPixel( pDoc->GetRowHeight( nRow, nTab ) );
934 : }
935 : else
936 74 : nHeightPixel = ToPixel( pDoc->GetRowHeight( nRow, nTab ) );
937 :
938 75 : if ( bTableDataHeight )
939 : {
940 18 : aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_height).
941 18 : append("=\"").
942 36 : append(static_cast<sal_Int32>(nHeightPixel)).append('"');
943 : }
944 :
945 : const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>( pAttr->GetItem(
946 75 : ScGlobal::GetScriptedWhichID( nScriptType, ATTR_FONT),
947 75 : pCondItemSet) );
948 :
949 : const SvxFontHeightItem& rFontHeightItem = static_cast<const SvxFontHeightItem&>(
950 : pAttr->GetItem( ScGlobal::GetScriptedWhichID( nScriptType,
951 75 : ATTR_FONT_HEIGHT), pCondItemSet) );
952 :
953 : const SvxWeightItem& rWeightItem = static_cast<const SvxWeightItem&>( pAttr->GetItem(
954 75 : ScGlobal::GetScriptedWhichID( nScriptType, ATTR_FONT_WEIGHT),
955 75 : pCondItemSet) );
956 :
957 : const SvxPostureItem& rPostureItem = static_cast<const SvxPostureItem&>(
958 : pAttr->GetItem( ScGlobal::GetScriptedWhichID( nScriptType,
959 75 : ATTR_FONT_POSTURE), pCondItemSet) );
960 :
961 : const SvxUnderlineItem& rUnderlineItem = static_cast<const SvxUnderlineItem&>(
962 75 : pAttr->GetItem( ATTR_FONT_UNDERLINE, pCondItemSet ) );
963 :
964 : const SvxColorItem& rColorItem = static_cast<const SvxColorItem&>( pAttr->GetItem(
965 75 : ATTR_FONT_COLOR, pCondItemSet ) );
966 :
967 : const SvxHorJustifyItem& rHorJustifyItem = static_cast<const SvxHorJustifyItem&>(
968 75 : pAttr->GetItem( ATTR_HOR_JUSTIFY, pCondItemSet ) );
969 :
970 : const SvxVerJustifyItem& rVerJustifyItem = static_cast<const SvxVerJustifyItem&>(
971 75 : pAttr->GetItem( ATTR_VER_JUSTIFY, pCondItemSet ) );
972 :
973 : const SvxBrushItem& rBrushItem = static_cast<const SvxBrushItem&>( pAttr->GetItem(
974 75 : ATTR_BACKGROUND, pCondItemSet ) );
975 :
976 75 : Color aBgColor;
977 75 : if ( rBrushItem.GetColor().GetTransparency() == 255 )
978 75 : aBgColor = aHTMLStyle.aBackgroundColor; // No unwanted background color
979 : else
980 0 : aBgColor = rBrushItem.GetColor();
981 :
982 75 : bool bBold = ( WEIGHT_BOLD <= rWeightItem.GetWeight() );
983 75 : bool bItalic = ( ITALIC_NONE != rPostureItem.GetPosture() );
984 75 : bool bUnderline = ( UNDERLINE_NONE != rUnderlineItem.GetLineStyle() );
985 75 : bool bSetFontColor = ( COL_AUTO != rColorItem.GetValue().GetColor() ); // default is AUTO now
986 75 : bool bSetFontName = ( aHTMLStyle.aFontFamilyName != rFontItem.GetFamilyName() );
987 75 : sal_uInt16 nSetFontSizeNumber = 0;
988 75 : sal_uInt32 nFontHeight = rFontHeightItem.GetHeight();
989 75 : if ( nFontHeight != aHTMLStyle.nFontHeight )
990 : {
991 0 : nSetFontSizeNumber = GetFontSizeNumber( (sal_uInt16) nFontHeight );
992 0 : if ( nSetFontSizeNumber == aHTMLStyle.nFontSizeNumber )
993 0 : nSetFontSizeNumber = 0; // no difference, don't set
994 : }
995 :
996 75 : bool bSetFont = (bSetFontColor || bSetFontName || nSetFontSizeNumber);
997 :
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?
1001 :
1002 75 : switch( rHorJustifyItem.GetValue() )
1003 : {
1004 : case SVX_HOR_JUSTIFY_STANDARD:
1005 75 : pChar = (bValueData ? OOO_STRING_SVTOOLS_HTML_AL_right : OOO_STRING_SVTOOLS_HTML_AL_left);
1006 75 : break;
1007 0 : case SVX_HOR_JUSTIFY_CENTER: pChar = OOO_STRING_SVTOOLS_HTML_AL_center; break;
1008 0 : case SVX_HOR_JUSTIFY_BLOCK: pChar = OOO_STRING_SVTOOLS_HTML_AL_justify; break;
1009 0 : 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 0 : default: pChar = OOO_STRING_SVTOOLS_HTML_AL_left; break;
1013 : }
1014 :
1015 75 : aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align).
1016 75 : append("=\"").append(pChar).append('"');
1017 :
1018 75 : switch( rVerJustifyItem.GetValue() )
1019 : {
1020 0 : case SVX_VER_JUSTIFY_TOP: pChar = OOO_STRING_SVTOOLS_HTML_VA_top; break;
1021 0 : case SVX_VER_JUSTIFY_CENTER: pChar = OOO_STRING_SVTOOLS_HTML_VA_middle; break;
1022 0 : case SVX_VER_JUSTIFY_BOTTOM: pChar = OOO_STRING_SVTOOLS_HTML_VA_bottom; break;
1023 : case SVX_VER_JUSTIFY_STANDARD:
1024 75 : default: pChar = NULL;
1025 : }
1026 75 : if ( pChar )
1027 : {
1028 0 : aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_valign).
1029 0 : append('=').append(pChar);
1030 : }
1031 :
1032 75 : if ( aHTMLStyle.aBackgroundColor != aBgColor )
1033 : {
1034 0 : aStrTD.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor).
1035 0 : append('=');
1036 0 : aStrTD.append(lcl_makeHTMLColorTriplet(aBgColor));
1037 : }
1038 :
1039 75 : double fVal = 0.0;
1040 75 : if ( bValueData )
1041 : {
1042 10 : switch (aCell.meType)
1043 : {
1044 : case CELLTYPE_VALUE:
1045 10 : fVal = aCell.mfValue;
1046 10 : if ( bCalcAsShown && fVal != 0.0 )
1047 0 : fVal = pDoc->RoundValueAsShown( fVal, nFormat );
1048 10 : break;
1049 : case CELLTYPE_FORMULA:
1050 0 : fVal = aCell.mpFormula->GetValue();
1051 0 : break;
1052 : default:
1053 : OSL_FAIL( "value data with unsupported cell type" );
1054 : }
1055 : }
1056 :
1057 : aStrTD.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValueData, fVal,
1058 75 : nFormat, *pFormatter, eDestEnc, &aNonConvertibleChars));
1059 :
1060 75 : TAG_ON(aStrTD.makeStringAndClear().getStr());
1061 :
1062 75 : if ( bBold ) TAG_ON( OOO_STRING_SVTOOLS_HTML_bold );
1063 75 : if ( bItalic ) TAG_ON( OOO_STRING_SVTOOLS_HTML_italic );
1064 75 : if ( bUnderline ) TAG_ON( OOO_STRING_SVTOOLS_HTML_underline );
1065 :
1066 75 : if ( bSetFont )
1067 : {
1068 4 : OStringBuffer aStr(OOO_STRING_SVTOOLS_HTML_font);
1069 4 : if ( bSetFontName )
1070 : {
1071 0 : aStr.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_face).
1072 0 : append("=\"");
1073 0 : sal_Int32 nFonts = comphelper::string::getTokenCount(rFontItem.GetFamilyName(), ';');
1074 0 : if ( nFonts == 1 )
1075 : {
1076 : OString aTmpStr = HTMLOutFuncs::ConvertStringToHTML(
1077 0 : rFontItem.GetFamilyName(), eDestEnc, &aNonConvertibleChars);
1078 0 : aStr.append(aTmpStr);
1079 : }
1080 : else
1081 : { // Font list, VCL: Semicolon as separator, HTML: Comma
1082 0 : const OUString& rList = rFontItem.GetFamilyName();
1083 0 : for ( sal_Int32 j = 0, nPos = 0; j < (sal_Int32)nFonts; j++ )
1084 : {
1085 : OString aTmpStr = HTMLOutFuncs::ConvertStringToHTML(
1086 : rList.getToken( 0, ';', nPos ), eDestEnc,
1087 0 : &aNonConvertibleChars);
1088 0 : aStr.append(aTmpStr);
1089 0 : if ( j < nFonts-1 )
1090 0 : aStr.append(',');
1091 0 : }
1092 : }
1093 0 : aStr.append('\"');
1094 : }
1095 4 : if ( nSetFontSizeNumber )
1096 : {
1097 0 : aStr.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_size).
1098 0 : append('=').append(static_cast<sal_Int32>(nSetFontSizeNumber));
1099 : }
1100 4 : if ( bSetFontColor )
1101 : {
1102 4 : Color aColor = rColorItem.GetValue();
1103 :
1104 : // always export automatic text color as black
1105 4 : if ( aColor.GetColor() == COL_AUTO )
1106 0 : aColor.SetColor( COL_BLACK );
1107 :
1108 4 : aStr.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_color).
1109 8 : append('=').append(lcl_makeHTMLColorTriplet(aColor));
1110 : }
1111 4 : TAG_ON(aStr.makeStringAndClear().getStr());
1112 : }
1113 :
1114 75 : OUString aStrOut;
1115 75 : bool bFieldText = false;
1116 :
1117 : Color* pColor;
1118 75 : switch (aCell.meType)
1119 : {
1120 : case CELLTYPE_EDIT :
1121 0 : bFieldText = WriteFieldText(aCell.mpEditText);
1122 0 : if ( bFieldText )
1123 0 : break;
1124 : //! else: fallthru
1125 : default:
1126 75 : ScCellFormat::GetString(aCell, nFormat, aStrOut, &pColor, *pFormatter, pDoc);
1127 : }
1128 :
1129 75 : if ( !bFieldText )
1130 : {
1131 75 : if ( aStrOut.isEmpty() )
1132 : {
1133 35 : TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak ); // No completely empty line
1134 : }
1135 : else
1136 : {
1137 40 : OUString aStr = aStrOut;
1138 40 : sal_Int32 nPos = aStr.indexOf( '\n' );
1139 40 : if ( nPos == -1 )
1140 : {
1141 40 : OUT_STR( aStrOut );
1142 : }
1143 : else
1144 : {
1145 0 : sal_Int32 nStartPos = 0;
1146 0 : do
1147 : {
1148 0 : OUString aSingleLine = aStr.copy( nStartPos, nPos - nStartPos );
1149 0 : OUT_STR( aSingleLine );
1150 0 : TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak );
1151 0 : nStartPos = nPos + 1;
1152 : }
1153 : while( ( nPos = aStr.indexOf( '\n', nStartPos ) ) != -1 );
1154 0 : OUString aSingleLine = aStr.copy( nStartPos, aStr.getLength() - nStartPos );
1155 0 : OUT_STR( aSingleLine );
1156 40 : }
1157 : }
1158 : }
1159 75 : if ( pGraphEntry )
1160 1 : WriteGraphEntry( pGraphEntry );
1161 :
1162 75 : if ( bSetFont ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_font );
1163 75 : if ( bUnderline ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_underline );
1164 75 : if ( bItalic ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_italic );
1165 75 : if ( bBold ) TAG_OFF( OOO_STRING_SVTOOLS_HTML_bold );
1166 :
1167 150 : TAG_OFF_LF( OOO_STRING_SVTOOLS_HTML_tabledata );
1168 : }
1169 :
1170 0 : bool ScHTMLExport::WriteFieldText( const EditTextObject* pData )
1171 : {
1172 0 : bool bFields = false;
1173 : // text and anchor of URL fields, Doc-Engine is a ScFieldEditEngine
1174 0 : EditEngine& rEngine = pDoc->GetEditEngine();
1175 0 : rEngine.SetText( *pData );
1176 0 : sal_Int32 nParas = rEngine.GetParagraphCount();
1177 0 : if ( nParas )
1178 : {
1179 0 : ESelection aSel( 0, 0, nParas-1, rEngine.GetTextLen( nParas-1 ) );
1180 0 : SfxItemSet aSet( rEngine.GetAttribs( aSel ) );
1181 0 : SfxItemState eFieldState = aSet.GetItemState( EE_FEATURE_FIELD, false );
1182 0 : if ( eFieldState == SfxItemState::DONTCARE || eFieldState == SfxItemState::SET )
1183 0 : bFields = true;
1184 : }
1185 0 : if ( bFields )
1186 : {
1187 0 : bool bOldUpdateMode = rEngine.GetUpdateMode();
1188 0 : rEngine.SetUpdateMode( true ); // no portions if not formatted
1189 0 : for ( sal_Int32 nPar=0; nPar < nParas; nPar++ )
1190 : {
1191 0 : if ( nPar > 0 )
1192 0 : TAG_ON( OOO_STRING_SVTOOLS_HTML_linebreak );
1193 0 : std::vector<sal_Int32> aPortions;
1194 0 : rEngine.GetPortions( nPar, aPortions );
1195 0 : sal_Int32 nStart = 0;
1196 0 : for ( std::vector<sal_Int32>::const_iterator it(aPortions.begin()); it != aPortions.end(); ++it )
1197 : {
1198 0 : sal_Int32 nEnd = *it;
1199 0 : ESelection aSel( nPar, nStart, nPar, nEnd );
1200 0 : bool bUrl = false;
1201 : // fields are single characters
1202 0 : if ( nEnd == nStart+1 )
1203 : {
1204 : const SfxPoolItem* pItem;
1205 0 : SfxItemSet aSet = rEngine.GetAttribs( aSel );
1206 0 : if ( aSet.GetItemState( EE_FEATURE_FIELD, false, &pItem ) == SfxItemState::SET )
1207 : {
1208 0 : const SvxFieldData* pField = static_cast<const SvxFieldItem*>(pItem)->GetField();
1209 0 : if ( pField && pField->ISA(SvxURLField) )
1210 : {
1211 0 : bUrl = true;
1212 0 : const SvxURLField* pURLField = static_cast<const SvxURLField*>(pField);
1213 : // String aFieldText = rEngine.GetText( aSel );
1214 0 : rStrm.WriteChar( '<' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor ).WriteChar( ' ' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_href ).WriteCharPtr( "=\"" );
1215 0 : OUT_STR( pURLField->GetURL() );
1216 0 : rStrm.WriteCharPtr( "\">" );
1217 0 : OUT_STR( pURLField->GetRepresentation() );
1218 0 : rStrm.WriteCharPtr( "</" ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_anchor ).WriteChar( '>' );
1219 : }
1220 0 : }
1221 : }
1222 0 : if ( !bUrl )
1223 0 : OUT_STR( rEngine.GetText( aSel ) );
1224 0 : nStart = nEnd;
1225 : }
1226 0 : }
1227 0 : rEngine.SetUpdateMode( bOldUpdateMode );
1228 : }
1229 0 : return bFields;
1230 : }
1231 :
1232 0 : bool ScHTMLExport::CopyLocalFileToINet( OUString& rFileNm,
1233 : const OUString& rTargetNm, bool bFileToFile )
1234 : {
1235 0 : bool bRet = false;
1236 0 : INetURLObject aFileUrl, aTargetUrl;
1237 0 : aFileUrl.SetSmartURL( rFileNm );
1238 0 : aTargetUrl.SetSmartURL( rTargetNm );
1239 0 : if( INetProtocol::File == aFileUrl.GetProtocol() &&
1240 0 : ( (bFileToFile && INetProtocol::File == aTargetUrl.GetProtocol()) ||
1241 0 : (!bFileToFile && INetProtocol::File != aTargetUrl.GetProtocol() &&
1242 0 : INetProtocol::Ftp <= aTargetUrl.GetProtocol() &&
1243 0 : INetProtocol::Javascript >= aTargetUrl.GetProtocol()) ) )
1244 : {
1245 0 : if( pFileNameMap )
1246 : {
1247 : // Did we already move the file?
1248 0 : std::map<OUString, OUString>::iterator it = pFileNameMap->find( rFileNm );
1249 0 : if( it != pFileNameMap->end() )
1250 : {
1251 0 : rFileNm = it->second;
1252 0 : return true;
1253 : }
1254 : }
1255 : else
1256 : {
1257 0 : pFileNameMap.reset( new std::map<OUString, OUString>() );
1258 : }
1259 :
1260 0 : SvFileStream aTmp( aFileUrl.PathToFileName(), StreamMode::READ );
1261 :
1262 0 : OUString aSrc = rFileNm;
1263 0 : OUString aDest = aTargetUrl.GetPartBeforeLastName();
1264 0 : aDest += aFileUrl.GetName();
1265 :
1266 0 : if( bFileToFile )
1267 : {
1268 0 : INetURLObject aCpyURL( aDest );
1269 0 : SvFileStream aCpy( aCpyURL.PathToFileName(), StreamMode::WRITE );
1270 0 : aCpy.WriteStream( aTmp );
1271 :
1272 0 : aCpy.Close();
1273 0 : bRet = SVSTREAM_OK == aCpy.GetError();
1274 : }
1275 : else
1276 : {
1277 0 : SfxMedium aMedium( aDest, StreamMode::WRITE | StreamMode::SHARE_DENYNONE );
1278 :
1279 : {
1280 0 : SvFileStream aCpy( aMedium.GetPhysicalName(), StreamMode::WRITE );
1281 0 : aCpy.WriteStream( aTmp );
1282 : }
1283 :
1284 : // Take over
1285 0 : aMedium.Close();
1286 0 : aMedium.Commit();
1287 :
1288 0 : bRet = 0 == aMedium.GetError();
1289 : }
1290 :
1291 0 : if( bRet )
1292 : {
1293 0 : pFileNameMap->insert( std::make_pair( aSrc, aDest ) );
1294 0 : rFileNm = aDest;
1295 0 : }
1296 : }
1297 :
1298 0 : return bRet;
1299 : }
1300 :
1301 0 : void ScHTMLExport::MakeCIdURL( OUString& rURL )
1302 : {
1303 0 : if( aCId.isEmpty() )
1304 0 : return;
1305 :
1306 0 : INetURLObject aURLObj( rURL );
1307 0 : if( INetProtocol::File != aURLObj.GetProtocol() )
1308 0 : return;
1309 :
1310 0 : OUString aLastName( aURLObj.GetLastName().toAsciiLowerCase() );
1311 : OSL_ENSURE( !aLastName.isEmpty(), "filename without length!" );
1312 :
1313 0 : rURL = "cid:" + aLastName + "." + aCId;
1314 : }
1315 :
1316 53 : void ScHTMLExport::IncIndent( short nVal )
1317 : {
1318 53 : sIndent[nIndent] = '\t';
1319 53 : nIndent = nIndent + nVal;
1320 53 : if ( nIndent < 0 )
1321 3 : nIndent = 0;
1322 50 : else if ( nIndent > nIndentMax )
1323 0 : nIndent = nIndentMax;
1324 53 : sIndent[nIndent] = 0;
1325 83 : }
1326 :
1327 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|