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