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