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