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