Update ooo320-m1
[ooovba.git] / sw / source / filter / html / wrthtml.cxx
blob26e150ad1a0a9e6e5afaec99f082cd65466b674b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrthtml.cxx,v $
10 * $Revision: 1.40 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <stdlib.h>
36 #include <hintids.hxx>
37 #include <svtools/urihelper.hxx>
38 #include <rtl/tencinfo.h>
39 #include <vcl/wrkwin.hxx>
40 #include <sfx2/linkmgr.hxx>
42 #include <svx/htmlcfg.hxx>
43 #include <vcl/svapp.hxx>
44 #include <i18npool/mslangid.hxx>
45 #include <sfx2/frmhtmlw.hxx>
46 #include <svx/xoutbmp.hxx>
47 #include <svx/htmlmode.hxx>
48 #include <svx/lrspitem.hxx>
49 #include <svx/colritem.hxx>
50 #include <svx/brshitem.hxx>
51 #include <svx/fontitem.hxx>
52 #include <svx/scripttypeitem.hxx>
53 #include <svx/langitem.hxx>
54 #include <svtools/stritem.hxx>
55 #include <svx/frmdiritem.hxx>
57 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
58 #include <com/sun/star/document/XDocumentProperties.hpp>
59 #include <com/sun/star/form/XFormsSupplier.hpp>
60 #include <com/sun/star/form/XForm.hpp>
61 #include <com/sun/star/form/XImageProducerSupplier.hpp>
62 #include <com/sun/star/form/XFormController.hpp>
63 #include <com/sun/star/container/XContainer.hpp>
64 #include <com/sun/star/container/XIndexContainer.hpp>
65 #include <com/sun/star/container/XSet.hpp>
66 #include <fmthdft.hxx>
67 #include <fmtfld.hxx>
68 #include <fmtpdsc.hxx>
69 #include <txatbase.hxx>
70 #include <frmatr.hxx>
71 #include <charfmt.hxx>
72 #include <docary.hxx>
73 #include <pam.hxx>
74 #include <doc.hxx>
75 #include <ndtxt.hxx>
76 #include <mdiexp.hxx> // ...Percent()
77 #include <fltini.hxx>
78 #include <viewopt.hxx>
79 #include <IMark.hxx> // fuer SwBookmark ...
80 #include <poolfmt.hxx>
81 #include <pagedesc.hxx>
82 #include <section.hxx>
83 #include <swtable.hxx>
84 #include <fldbas.hxx>
85 #include <fmtclds.hxx>
86 #ifndef _DOCSH_HXX
87 #include <docsh.hxx>
88 #endif
89 #include <wrthtml.hxx>
90 #include <htmlnum.hxx>
91 #include <htmlfly.hxx>
92 #include <swmodule.hxx>
94 #ifndef _STATSTR_HRC
95 #include <statstr.hrc> // ResId fuer Statusleiste
96 #endif
97 #include <swerror.h>
99 #define MAX_INDENT_LEVEL 20
101 #if defined(UNX)
102 const sal_Char SwHTMLWriter::sNewLine = '\012';
103 #else
104 const sal_Char __FAR_DATA SwHTMLWriter::sNewLine[] = "\015\012";
105 #endif
107 static sal_Char __FAR_DATA sIndentTabs[MAX_INDENT_LEVEL+2] =
108 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
110 SwHTMLWriter::SwHTMLWriter( const String& rBaseURL )
112 SetBaseURL( rBaseURL );
113 bFirstLine = sal_True;
114 nBkmkTabPos = -1;
115 pDfltColor = 0;
116 nImgMapCnt = 1;
117 pStartNdIdx = 0;
118 pTemplate = 0;
119 pNumRuleInfo = new SwHTMLNumRuleInfo;
120 pNextNumRuleInfo = 0;
121 pFootEndNotes = 0;
122 pFmtFtn = 0;
123 eDestEnc = RTL_TEXTENCODING_MS_1252;
124 nDirection = FRMDIR_HORI_LEFT_TOP;
128 __EXPORT SwHTMLWriter::~SwHTMLWriter()
130 delete pNumRuleInfo;
133 ULONG SwHTMLWriter::WriteStream()
135 // neue Konfiguration setzen
136 SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get();
138 // die Fontgroessen 1-7
139 aFontHeights[0] = pHtmlOptions->GetFontSize( 0 ) * 20;
140 aFontHeights[1] = pHtmlOptions->GetFontSize( 1 ) * 20;
141 aFontHeights[2] = pHtmlOptions->GetFontSize( 2 ) * 20;
142 aFontHeights[3] = pHtmlOptions->GetFontSize( 3 ) * 20;
143 aFontHeights[4] = pHtmlOptions->GetFontSize( 4 ) * 20;
144 aFontHeights[5] = pHtmlOptions->GetFontSize( 5 ) * 20;
145 aFontHeights[6] = pHtmlOptions->GetFontSize( 6 ) * 20;
147 // ueberhaupt Styles ausgeben
148 // (dann auch obere und untere Absatz-Abstaende)
149 nExportMode = pHtmlOptions->GetExportMode();
150 nHTMLMode = GetHtmlMode(0);
151 if( HTML_CFG_WRITER==nExportMode ||
152 HTML_CFG_NS40==nExportMode )
153 nHTMLMode |= HTMLMODE_BLOCK_SPACER;
155 if( HTML_CFG_WRITER==nExportMode || HTML_CFG_MSIE==nExportMode )
156 nHTMLMode |= (HTMLMODE_FLOAT_FRAME | HTMLMODE_LSPACE_IN_NUMBUL);
158 if( HTML_CFG_MSIE==nExportMode )
159 nHTMLMode |= HTMLMODE_NBSP_IN_TABLES;
161 if( HTML_CFG_WRITER==nExportMode || HTML_CFG_NS40==nExportMode ||
162 HTML_CFG_MSIE==nExportMode )
163 nHTMLMode |= HTMLMODE_ABS_POS_FLY|HTMLMODE_ABS_POS_DRAW;
165 if( HTML_CFG_WRITER==nExportMode )
166 // nHTMLMode |= HTMLMODE_FLY_MARGINS | HTMLMODE_FRSTLINE_IN_NUMBUL;
167 nHTMLMode |= HTMLMODE_FLY_MARGINS;
169 if( HTML_CFG_NS40==nExportMode )
170 nHTMLMode |= HTMLMODE_BORDER_NONE;
172 if( HTML_CFG_HTML32!=nExportMode )
173 nHTMLMode |= HTMLMODE_FONT_GENERIC;
175 if( HTML_CFG_NS40==nExportMode )
176 nHTMLMode |= HTMLMODE_NO_CONTROL_CENTERING;
178 bCfgOutStyles = IsHTMLMode(HTMLMODE_SOME_STYLES |
179 HTMLMODE_FULL_STYLES);
180 bCfgNetscape4 = (HTML_CFG_NS40==nExportMode);
182 if( IsHTMLMode(HTMLMODE_SOME_STYLES | HTMLMODE_FULL_STYLES) )
183 nHTMLMode |= HTMLMODE_PRINT_EXT;
185 const sal_Char *pHelpHack = getenv( "HelpEx" );
186 if( pHelpHack )
188 ByteString aTmp( pHelpHack );
189 if( aTmp.EqualsIgnoreCaseAscii( "Hilfe" ) )
190 nHTMLMode |= HTMLMODE_NO_BR_AT_PAREND;
193 eCSS1Unit = (FieldUnit)SW_MOD()->GetMetric( pDoc->get(IDocumentSettingAccess::HTML_MODE) );
195 sal_Bool bWriteUTF8 = bWriteClipboardDoc;
196 eDestEnc = bWriteUTF8 ? RTL_TEXTENCODING_UTF8
197 : pHtmlOptions->GetTextEncoding();
198 const sal_Char *pCharSet =
199 rtl_getBestMimeCharsetFromTextEncoding( eDestEnc );
200 eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet );
202 // fuer Netscape optimieren heisst Spacer- und Multicol ausgeben
203 // bCfgMultiCol = pHtmlOptions->IsNetscape3();
204 // bCfgSpacer = pHtmlOptions->IsNetscape3();
206 // wenn Styles exportiert werden, wird ein Style einem HTML-Tag manchmal
207 // vorgezogen, wenn nicht fuer Netscape exportiert wird
208 // bCfgPreferStyles = bCfgOutStyles; // && !pHtmlOptions->IsNetscape3();
210 // Nur noch fuer den MS-IE ziehen wir den Export von Styles vor.
211 bCfgPreferStyles = HTML_CFG_MSIE==nExportMode;
213 bCfgStarBasic = pHtmlOptions->IsStarBasic();
215 bCfgFormFeed = !IsHTMLMode(HTMLMODE_PRINT_EXT);
216 bCfgCpyLinkedGrfs = pHtmlOptions->IsSaveGraphicsLocal();
218 // die HTML-Vorlage holen
219 sal_Bool bOldHTMLMode = sal_False;
220 sal_uInt16 nOldTxtFmtCollCnt = 0, nOldCharFmtCnt = 0;
222 ASSERT( !pTemplate, "Wo kommt denn die HTML-Vorlage hier her?" );
223 pTemplate = ((HTMLReader*)ReadHTML)->GetTemplateDoc();
224 if( pTemplate )
226 pTemplate->acquire();
227 bOldHTMLMode = pTemplate->get(IDocumentSettingAccess::HTML_MODE);
228 pTemplate->set(IDocumentSettingAccess::HTML_MODE, true);
230 nOldTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->Count();
231 nOldCharFmtCnt = pTemplate->GetCharFmts()->Count();
234 if( bShowProgress )
235 ::StartProgress( STR_STATSTR_W4WWRITE, 0, pDoc->GetNodes().Count(),
236 pDoc->GetDocShell());
238 pDfltColor = 0;
239 pFootEndNotes = 0;
240 pFmtFtn = 0;
241 bOutTable = bOutHeader = bOutFooter = bOutFlyFrame = sal_False;
242 pxFormComps = 0;
243 nFormCntrlCnt = 0;
244 bPreserveForm = sal_False;
245 bClearLeft = bClearRight = sal_False;
246 bLFPossible = sal_False;
248 nLeftMargin = nDfltLeftMargin = nDfltRightMargin = 0;
249 nDfltTopMargin = nDfltBottomMargin = 0;
250 nFirstLineIndent = nDfltFirstLineIndent = 0;
251 bPoolCollTextModified = sal_False;
252 bFirstCSS1Property = bFirstCSS1Rule = sal_False;
253 bCSS1IgnoreFirstPageDesc = sal_False;
254 nIndentLvl = 0;
255 nWhishLineLen = 70;
256 nLastLFPos = 0;
257 nDefListLvl = 0;
258 nDefListMargin = ((pTemplate && !bCfgOutStyles) ? pTemplate : pDoc)
259 ->GetTxtCollFromPool( RES_POOLCOLL_HTML_DD, false )
260 ->GetLRSpace().GetTxtLeft();
261 nHeaderFooterSpace = 0;
262 nTxtAttrsToIgnore = 0;
263 nCSS1OutMode = 0;
264 sal_uInt16 nScript = SvtLanguageOptions::GetScriptTypeOfLanguage(
265 static_cast< LanguageType >( GetAppLanguage() ) );
266 switch( nScript )
268 case SCRIPTTYPE_ASIAN:
269 nCSS1Script = CSS1_OUTMODE_CJK;
270 break;
271 case SCRIPTTYPE_COMPLEX:
272 nCSS1Script = CSS1_OUTMODE_CTL;
273 break;
274 default:
275 nCSS1Script = CSS1_OUTMODE_WESTERN;
276 break;
278 eLang = ((const SvxLanguageItem&)pDoc
279 ->GetDefault(GetLangWhichIdFromScript(nCSS1Script))).GetLanguage();
281 nFootNote = nEndNote = 0;
283 nWarn = 0;
284 GetNumInfo().Clear();
285 pNextNumRuleInfo = 0;
287 ByteString aStartTags;
289 // Tabellen und Bereiche am Doc.-Anfang beachten
291 SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode();
292 if( pTNd && bWriteAll )
294 // mit dem Tabellen-Node anfangen !!
295 pCurPam->GetPoint()->nNode = *pTNd;
297 if( bWriteOnlyFirstTable )
298 pCurPam->GetMark()->nNode = *pTNd->EndOfSectionNode();
301 // erster Node (der einen Seitenumbruch enthalten darf)
302 pStartNdIdx = new SwNodeIndex( pCurPam->GetPoint()->nNode );
304 SwSectionNode * pSNd = pCurPam->GetNode()->FindSectionNode();
305 while( pSNd )
307 if( bWriteAll )
309 // mit dem Section-Node anfangen !!
310 pCurPam->GetPoint()->nNode = *pSNd;
312 else
314 ASSERT( FILE_LINK_SECTION != pSNd->GetSection().GetType(),
315 "Export gelinkter Bereiche am Dok-Anfang ist nicht implemntiert" );
317 // nur das Tag fuer die Section merken
318 ByteString aName;
319 HTMLOutFuncs::ConvertStringToHTML( pSNd->GetSection().GetName(),
320 aName, eDestEnc, &aNonConvertableCharacters );
322 ByteString sOut( '<' );
323 (((((((sOut += OOO_STRING_SVTOOLS_HTML_division)
324 += ' ') += OOO_STRING_SVTOOLS_HTML_O_id) += "=\"")
325 += aName) += '\"')
326 += '>') += aStartTags;
328 aStartTags = sOut;
330 // FindSectionNode() an einem SectionNode liefert den selben!
331 pSNd = pSNd->StartOfSectionNode()->FindSectionNode();
336 // Tabelle fuer die freifliegenden Rahmen erzeugen, aber nur wenn
337 // das gesamte Dokument geschrieben wird
338 pHTMLPosFlyFrms = 0;
339 CollectFlyFrms();
340 nLastParaToken = 0;
341 GetControls();
342 CollectLinkTargets();
344 sal_uInt16 nHeaderAttrs = 0;
345 pCurrPageDesc = MakeHeader( nHeaderAttrs );
347 bLFPossible = sal_True;
349 // Formulare, die nur HiddenControls enthalten ausgeben.
350 OutHiddenForms();
352 if( aStartTags.Len() )
353 Strm() << aStartTags.GetBuffer();
355 const SfxPoolItem *pItem;
356 const SfxItemSet& rPageItemSet = pCurrPageDesc->GetMaster().GetAttrSet();
357 if( !bWriteClipboardDoc && pDoc->GetDocShell() &&
358 (!pDoc->get(IDocumentSettingAccess::HTML_MODE) &&
359 !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) &&
360 SFX_ITEM_SET == rPageItemSet.GetItemState( RES_HEADER, sal_True, &pItem) )
362 const SwFrmFmt *pHeaderFmt =
363 ((const SwFmtHeader *)pItem)->GetHeaderFmt();
364 if( pHeaderFmt )
365 OutHTML_HeaderFooter( *this, *pHeaderFmt, sal_True );
368 nTxtAttrsToIgnore = nHeaderAttrs;
369 Out_SwDoc( pOrigPam );
370 nTxtAttrsToIgnore = 0;
372 if( pxFormComps && pxFormComps->is() )
373 OutForm( sal_False, *pxFormComps );
375 if( pFootEndNotes )
376 OutFootEndNotes();
378 if( !bWriteClipboardDoc && pDoc->GetDocShell() &&
379 (!pDoc->get(IDocumentSettingAccess::HTML_MODE) && !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) &&
380 SFX_ITEM_SET == rPageItemSet.GetItemState( RES_FOOTER, sal_True, &pItem) )
382 const SwFrmFmt *pFooterFmt =
383 ((const SwFmtFooter *)pItem)->GetFooterFmt();
384 if( pFooterFmt )
385 OutHTML_HeaderFooter( *this, *pFooterFmt, sal_False );
388 if( bLFPossible )
389 OutNewLine();
390 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body, sal_False );
391 OutNewLine();
392 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html, sal_False );
394 // loesche die Tabelle mit den freifliegenden Rahmen
395 sal_uInt16 i;
396 ASSERT( !pHTMLPosFlyFrms, "Wurden nicht alle Rahmen ausgegeben" );
397 if( pHTMLPosFlyFrms )
399 pHTMLPosFlyFrms->DeleteAndDestroy( 0, pHTMLPosFlyFrms->Count() );
400 delete pHTMLPosFlyFrms;
401 pHTMLPosFlyFrms = 0;
404 if( aHTMLControls.Count() )
405 aHTMLControls.DeleteAndDestroy( sal_uInt16(0), aHTMLControls.Count() );
407 if( aChrFmtInfos.Count() )
408 aChrFmtInfos.DeleteAndDestroy( sal_uInt16(0), aChrFmtInfos.Count() );
410 if( aTxtCollInfos.Count() )
411 aTxtCollInfos.DeleteAndDestroy( sal_uInt16(0), aTxtCollInfos.Count() );
413 if( aImgMapNames.Count() )
414 aImgMapNames.DeleteAndDestroy( sal_uInt16(0), aImgMapNames.Count() );
416 if( aImplicitMarks.Count() )
417 aImplicitMarks.DeleteAndDestroy( sal_uInt16(0), aImplicitMarks.Count() );
419 if( aOutlineMarks.Count() )
420 aOutlineMarks.DeleteAndDestroy( sal_uInt16(0), aOutlineMarks.Count() );
422 if( aOutlineMarkPoss.Count() )
423 aOutlineMarkPoss.Remove( sal_uInt16(0), aOutlineMarkPoss.Count() );
425 if( aNumRuleNames.Count() )
426 aNumRuleNames.DeleteAndDestroy( sal_uInt16(0), aNumRuleNames.Count() );
428 if( aScriptParaStyles.Count() )
429 aScriptParaStyles.DeleteAndDestroy( sal_uInt16(0), aScriptParaStyles.Count() );
430 if( aScriptTextStyles.Count() )
431 aScriptTextStyles.DeleteAndDestroy( sal_uInt16(0), aScriptTextStyles.Count() );
433 delete pDfltColor;
434 pDfltColor = 0;
436 delete pStartNdIdx;
437 pStartNdIdx = 0;
439 delete pxFormComps;
440 pxFormComps = 0;
442 ASSERT( !pFootEndNotes,
443 "SwHTMLWriter::Write: Ftns nicht durch OutFootEndNotes geloescht" );
445 pCurrPageDesc = 0;
447 ClearNextNumInfo();
449 for( i=0; i<MAXLEVEL; i++ )
450 aBulletGrfs[i].Erase();
452 aNonConvertableCharacters.Erase();
454 if( bShowProgress )
455 ::EndProgress( pDoc->GetDocShell() );
457 if( pTemplate )
459 // Waehrend des Exports angelegte Zeichen- und Abastzvorlagen
460 // loeschen
461 sal_uInt16 nTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->Count();
462 while( nTxtFmtCollCnt > nOldTxtFmtCollCnt )
463 pTemplate->DelTxtFmtColl( --nTxtFmtCollCnt );
464 ASSERT( pTemplate->GetTxtFmtColls()->Count() == nOldTxtFmtCollCnt,
465 "falsche Anzahl TxtFmtColls geloescht" );
467 sal_uInt16 nCharFmtCnt = pTemplate->GetCharFmts()->Count();
468 while( nCharFmtCnt > nOldCharFmtCnt )
469 pTemplate->DelCharFmt( --nCharFmtCnt );
470 ASSERT( pTemplate->GetCharFmts()->Count() == nOldCharFmtCnt,
471 "falsche Anzahl CharFmts geloescht" );
473 // HTML-Modus wieder restaurieren
474 pTemplate->set(IDocumentSettingAccess::HTML_MODE, bOldHTMLMode);
476 if( 0 == pTemplate->release() )
477 delete pTemplate;
479 pTemplate = 0;
482 return nWarn;
485 const SwFmtCol *lcl_html_GetFmtCol( const SwHTMLWriter& rHTMLWrt,
486 const SwSection& rSection,
487 const SwSectionFmt& rFmt )
489 const SwFmtCol *pCol = 0;
491 const SfxPoolItem* pItem;
492 if( rHTMLWrt.IsHTMLMode( HTMLMODE_FRM_COLUMNS ) &&
493 FILE_LINK_SECTION != rSection.GetType() &&
494 SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState(RES_COL,sal_False,&pItem) &&
495 ((const SwFmtCol *)pItem)->GetNumCols() > 1 )
497 pCol = (const SwFmtCol *)pItem;
500 return pCol;
503 sal_Bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, ULONG nIndex )
505 sal_Bool bRet = sal_False;
506 const SwSectionNode *pSectNd =
507 rHTMLWrt.pDoc->GetNodes()[nIndex]->GetSectionNode();
508 if( pSectNd )
510 const SwSection& rSection = pSectNd->GetSection();
511 const SwSectionFmt *pFmt = rSection.GetFmt();
512 if( pFmt && lcl_html_GetFmtCol( rHTMLWrt, rSection, *pFmt ) )
513 bRet = sal_True;
516 return bRet;
519 sal_Bool lcl_html_IsMultiColEnd( const SwHTMLWriter& rHTMLWrt, ULONG nIndex )
521 sal_Bool bRet = sal_False;
522 const SwEndNode *pEndNd = rHTMLWrt.pDoc->GetNodes()[nIndex]->GetEndNode();
523 if( pEndNd )
524 bRet = lcl_html_IsMultiColStart( rHTMLWrt,
525 pEndNd->StartOfSectionIndex() );
527 return bRet;
531 void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt,
532 const SwSection& rSection,
533 const SwSectionFmt& rFmt,
534 const SwFmtCol *pCol,
535 sal_Bool bContinued=sal_False )
537 ASSERT( pCol || !bContinued, "Continuation of DIV" );
539 if( rHTMLWrt.bLFPossible )
540 rHTMLWrt.OutNewLine();
542 const sal_Char *pTag = pCol ? OOO_STRING_SVTOOLS_HTML_multicol : OOO_STRING_SVTOOLS_HTML_division;
544 ByteString sOut( '<' );
545 sOut += pTag;
547 const String& rName = rSection.GetName();
548 if( rName.Len() && !bContinued )
550 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_id) += "=\"";
551 rHTMLWrt.Strm() << sOut.GetBuffer();
552 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), rName, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
553 sOut = '\"';
556 sal_uInt16 nDir = rHTMLWrt.GetHTMLDirection( rFmt.GetAttrSet() );
557 rHTMLWrt.Strm() << sOut.GetBuffer();
558 sOut.Erase();
559 rHTMLWrt.OutDirection( nDir );
561 if( FILE_LINK_SECTION == rSection.GetType() )
563 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\"";
564 rHTMLWrt.Strm() << sOut.GetBuffer();
566 const String& aFName = rSection.GetLinkFileName();
567 String aURL( aFName.GetToken(0,sfx2::cTokenSeperator) );
568 String aFilter( aFName.GetToken(1,sfx2::cTokenSeperator) );
569 String aSection( aFName.GetToken(2,sfx2::cTokenSeperator) );
571 String aEncURL( URIHelper::simpleNormalizedMakeRelative(rHTMLWrt.GetBaseURL(), aURL ) );
572 sal_Unicode cDelim = 255U;
573 sal_Bool bURLContainsDelim =
574 (STRING_NOTFOUND != aEncURL.Search( cDelim ) );
576 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aEncURL,
577 rHTMLWrt.eDestEnc,
578 &rHTMLWrt.aNonConvertableCharacters );
579 const sal_Char *pDelim = "&#255;";
580 if( aFilter.Len() || aSection.Len() || bURLContainsDelim )
581 rHTMLWrt.Strm() << pDelim;
582 if( aFilter.Len() )
583 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aFilter,
584 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
585 if( aSection.Len() || bURLContainsDelim )
586 rHTMLWrt.Strm() << pDelim;
587 if( aSection.Len() )
589 xub_StrLen nPos = aSection.Search( '%' );
590 while( STRING_NOTFOUND != nPos )
592 aSection.Erase( nPos, 1 );
593 aSection.InsertAscii( "%25", nPos );
594 nPos = aSection.Search( '%', nPos+3 );
596 nPos = aSection.Search( cDelim );
597 while( STRING_NOTFOUND != nPos )
599 aSection.Erase( nPos, 1 );
600 aSection.InsertAscii( "%FF", nPos );
601 nPos = aSection.Search( cDelim, nPos+3 );
603 HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aSection,
604 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
606 sOut = '\"';
608 else if( pCol )
610 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=')
611 += ByteString::CreateFromInt32( pCol->GetNumCols() );
613 // minumum gutter width
614 sal_uInt16 nGutter = pCol->GetGutterWidth( sal_True );
615 if( nGutter!=USHRT_MAX )
617 if( nGutter && Application::GetDefaultDevice() )
619 nGutter = (sal_uInt16)Application::GetDefaultDevice()
620 ->LogicToPixel( Size(nGutter,0),
621 MapMode(MAP_TWIP) ).Width();
623 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_gutter) += '=')
624 += ByteString::CreateFromInt32( nGutter );
628 rHTMLWrt.Strm() << sOut.GetBuffer();
629 if( rHTMLWrt.IsHTMLMode( rHTMLWrt.bCfgOutStyles ) )
630 rHTMLWrt.OutCSS1_SectionFmtOptions( rFmt );
632 rHTMLWrt.Strm() << '>';
634 rHTMLWrt.bLFPossible = sal_True;
635 if( rName.Len() && !bContinued )
636 rHTMLWrt.OutImplicitMark( rName, pMarkToRegion );
638 rHTMLWrt.IncIndentLevel();
641 void lcl_html_OutSectionEndTag( SwHTMLWriter& rHTMLWrt,
642 const SwFmtCol *pCol )
644 const sal_Char *pTag = pCol ? OOO_STRING_SVTOOLS_HTML_multicol : OOO_STRING_SVTOOLS_HTML_division;
646 rHTMLWrt.DecIndentLevel();
647 if( rHTMLWrt.bLFPossible )
648 rHTMLWrt.OutNewLine();
649 HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), pTag, sal_False );
650 rHTMLWrt.bLFPossible = sal_True;
653 static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd )
655 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
657 // End <PRE> and any <DL>, because a definition list's level may
658 // change inside the section.
659 rHTMLWrt.ChangeParaToken( 0 );
660 rHTMLWrt.OutAndSetDefList( 0 );
662 const SwSection& rSection = rSectNd.GetSection();
663 const SwSectionFmt *pFmt = rSection.GetFmt();
664 ASSERT( pFmt, "Section without a format?" );
666 sal_Bool bStartTag = sal_True;
667 sal_Bool bEndTag = sal_True;
668 const SwSectionFmt *pSurrFmt = 0;
669 const SwSectionNode *pSurrSectNd = 0;
670 const SwSection *pSurrSection = 0;
671 const SwFmtCol *pSurrCol = 0;
673 sal_uInt32 nSectSttIdx = rSectNd.GetIndex();
674 sal_uInt32 nSectEndIdx = rSectNd.EndOfSectionIndex();
675 const SwFmtCol *pCol = lcl_html_GetFmtCol( rHTMLWrt, rSection, *pFmt );
676 if( pCol )
678 // If the next node is a columned section node, too, don't export
679 // an empty section.
680 if( lcl_html_IsMultiColStart( rHTMLWrt, nSectSttIdx+1 ) )
681 bStartTag = sal_False;
683 // The same applies if the section end with another columned section.
684 if( lcl_html_IsMultiColEnd( rHTMLWrt, nSectEndIdx-1 ) )
685 bEndTag = sal_False;
687 //.is there a columned section arround this one?
688 const SwStartNode *pSttNd = rSectNd.StartOfSectionNode();
689 if( pSttNd )
691 pSurrSectNd = pSttNd->FindSectionNode();
692 if( pSurrSectNd )
694 const SwStartNode *pBoxSttNd = pSttNd->FindTableBoxStartNode();
695 if( !pBoxSttNd ||
696 pBoxSttNd->GetIndex() < pSurrSectNd->GetIndex() )
698 pSurrSection = &pSurrSectNd->GetSection();
699 pSurrFmt = pSurrSection->GetFmt();
700 if( pSurrFmt )
701 pSurrCol = lcl_html_GetFmtCol( rHTMLWrt, *pSurrSection,
702 *pSurrFmt );
708 // The surrounding section must be closed before the current one is
709 // opended, except that it start immediatly before the current one or
710 // another end immediately before the current one
711 if( pSurrCol && nSectSttIdx - pSurrSectNd->GetIndex() > 1 &&
712 !lcl_html_IsMultiColEnd( rHTMLWrt, nSectSttIdx-1 ) )
713 lcl_html_OutSectionEndTag( rHTMLWrt, pSurrCol );
715 if( bStartTag )
716 lcl_html_OutSectionStartTag( rHTMLWrt, rSection, *pFmt, pCol );
719 HTMLSaveData aSaveData( rHTMLWrt,
720 rHTMLWrt.pCurPam->GetPoint()->nNode.GetIndex()+1,
721 rSectNd.EndOfSectionIndex(),
722 sal_False, pFmt );
723 rHTMLWrt.Out_SwDoc( rHTMLWrt.pCurPam );
726 rHTMLWrt.pCurPam->GetPoint()->nNode = *rSectNd.EndOfSectionNode();
728 if( bEndTag )
729 lcl_html_OutSectionEndTag( rHTMLWrt, pCol );
731 // The surrounding section must be started again, except that it ends
732 // immeditaly behind the current one.
733 if( pSurrCol &&
734 pSurrSectNd->EndOfSectionIndex() - nSectEndIdx > 1 &&
735 !lcl_html_IsMultiColStart( rHTMLWrt, nSectEndIdx+1 ) )
736 lcl_html_OutSectionStartTag( rHTMLWrt, *pSurrSection, *pSurrFmt,
737 pSurrCol, sal_True );
739 return rWrt;
742 void SwHTMLWriter::Out_SwDoc( SwPaM* pPam )
744 sal_Bool bSaveWriteAll = bWriteAll; // sichern
746 // suche die naechste text::Bookmark-Position aus der text::Bookmark-Tabelle
747 nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1;
749 // gebe alle Bereiche des Pams in das HTML-File aus.
750 do {
751 bWriteAll = bSaveWriteAll;
752 bFirstLine = sal_True;
754 // suche den ersten am Pam-auszugebenen FlyFrame
755 // fehlt noch:
757 while( pCurPam->GetPoint()->nNode.GetIndex() < pCurPam->GetMark()->nNode.GetIndex() ||
758 (pCurPam->GetPoint()->nNode.GetIndex() == pCurPam->GetMark()->nNode.GetIndex() &&
759 pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex()) )
761 SwNode * pNd = pCurPam->GetNode();
763 ASSERT( !(pNd->IsGrfNode() || pNd->IsOLENode()),
764 "Grf- oder OLE-Node hier unerwartet" );
765 if( pNd->IsTxtNode() )
767 SwTxtNode* pTxtNd = pNd->GetTxtNode();
769 if( !bFirstLine )
770 pCurPam->GetPoint()->nContent.Assign( pTxtNd, 0 );
772 OutHTML_SwTxtNode( *this, *pTxtNd );
774 else if( pNd->IsTableNode() )
776 OutHTML_SwTblNode( *this, *pNd->GetTableNode(), 0 );
777 nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1;
779 else if( pNd->IsSectionNode() )
781 OutHTML_Section( *this, *pNd->GetSectionNode() );
782 nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1;
784 else if( pNd == &pDoc->GetNodes().GetEndOfContent() )
785 break;
787 pCurPam->GetPoint()->nNode++; // Bewegen
788 sal_uInt32 nPos = pCurPam->GetPoint()->nNode.GetIndex();
790 if( bShowProgress )
791 ::SetProgressState( nPos, pDoc->GetDocShell() ); // Wie weit ?
793 /* sollen nur die Selectierten Bereiche gesichert werden, so
794 * duerfen nur die vollstaendigen Nodes gespeichert werde,
795 * d.H. der 1. und n. Node teilweise, der 2. bis n-1. Node
796 * vollstaendig. (vollstaendig heisst mit allen Formaten! )
798 bWriteAll = bSaveWriteAll ||
799 nPos != pCurPam->GetMark()->nNode.GetIndex();
800 bFirstLine = sal_False;
801 bOutFooter = sal_False; // Nach einem Node keine Fusszeile mehr
804 ChangeParaToken( 0 ); // MIB 8.7.97: Machen wir jetzt hier und nicht
805 // beim Aufrufer
806 OutAndSetDefList( 0 );
808 } while( CopyNextPam( &pPam ) ); // bis alle PaM's bearbeitet
810 bWriteAll = bSaveWriteAll; // wieder auf alten Wert zurueck
814 // schreibe die StyleTabelle, algemeine Angaben,Header/Footer/Footnotes
815 static void OutBodyColor( const sal_Char *pTag, const SwFmt *pFmt,
816 SwHTMLWriter& rHWrt )
818 const SwFmt *pRefFmt = 0;
820 if( rHWrt.pTemplate )
821 pRefFmt = SwHTMLWriter::GetTemplateFmt( pFmt->GetPoolFmtId(),
822 rHWrt.pTemplate );
824 const SvxColorItem *pColorItem = 0;
826 const SfxItemSet& rItemSet = pFmt->GetAttrSet();
827 const SfxPoolItem *pRefItem = 0, *pItem = 0;
828 sal_Bool bItemSet = SFX_ITEM_SET == rItemSet.GetItemState( RES_CHRATR_COLOR,
829 sal_True, &pItem);
830 sal_Bool bRefItemSet = pRefFmt &&
831 SFX_ITEM_SET == pRefFmt->GetAttrSet().GetItemState( RES_CHRATR_COLOR,
832 sal_True, &pRefItem);
833 if( bItemSet )
835 // wenn das Item nur in der Vorlage des aktuellen Doks gesetzt
836 // ist oder einen anderen Wert hat, als in der HTML-Vorlage,
837 // wird es gesetzt
838 const SvxColorItem *pCItem = (const SvxColorItem*)pItem;
840 if( !bRefItemSet )
842 pColorItem = pCItem;
844 else
846 Color aColor( pCItem->GetValue() );
847 if( COL_AUTO == aColor.GetColor() )
848 aColor.SetColor( COL_BLACK );
850 Color aRefColor( ((const SvxColorItem*)pRefItem)->GetValue() );
851 if( COL_AUTO == aRefColor.GetColor() )
852 aRefColor.SetColor( COL_BLACK );
854 if( !aColor.IsRGBEqual( aRefColor ) )
855 pColorItem = pCItem;
858 else if( bRefItemSet )
860 // Das Item war in der HTML-Vorlage noch gesetzt, also geben wir
861 // das Default aus
862 pColorItem = (const SvxColorItem*)&rItemSet.GetPool()
863 ->GetDefaultItem( RES_CHRATR_COLOR );
866 if( pColorItem )
868 ByteString sOut( ' ' );
869 (sOut += pTag) += '=';
870 rHWrt.Strm() << sOut.GetBuffer();
871 Color aColor( pColorItem->GetValue() );
872 if( COL_AUTO == aColor.GetColor() )
873 aColor.SetColor( COL_BLACK );
874 HTMLOutFuncs::Out_Color( rHWrt.Strm(), aColor, rHWrt.eDestEnc );
875 if( RES_POOLCOLL_STANDARD==pFmt->GetPoolFmtId() )
876 rHWrt.pDfltColor = new Color( aColor );
880 sal_uInt16 SwHTMLWriter::OutHeaderAttrs()
882 ULONG nIdx = pCurPam->GetPoint()->nNode.GetIndex();
883 ULONG nEndIdx = pCurPam->GetMark()->nNode.GetIndex();
885 SwTxtNode *pTxtNd = 0;
886 while( nIdx<=nEndIdx &&
887 0==(pTxtNd=pDoc->GetNodes()[nIdx]->GetTxtNode()) )
888 nIdx++;
890 ASSERT( pTxtNd, "Kein Text-Node gefunden" );
891 if( !pTxtNd || !pTxtNd->HasHints() )
892 return 0;
894 sal_uInt16 nAttrs = 0;
895 sal_uInt16 nCntAttr = pTxtNd->GetSwpHints().Count();
896 xub_StrLen nOldPos = 0;
897 for( sal_uInt16 i=0; i<nCntAttr; i++ )
899 const SwTxtAttr *pHt = pTxtNd->GetSwpHints()[i];
900 if( !pHt->GetEnd() )
902 xub_StrLen nPos = *pHt->GetStart();
903 if( nPos-nOldPos > 1 || RES_TXTATR_FIELD != pHt->Which() )
904 break;
906 sal_uInt16 nFldWhich = ((const SwFmtFld&)pHt->GetAttr()).GetFld()
907 ->GetTyp()->Which();
908 if( RES_POSTITFLD!=nFldWhich &&
909 RES_SCRIPTFLD!=nFldWhich )
910 break;
912 OutNewLine();
913 OutHTML_SwFmtFld( *this, pHt->GetAttr() );
914 nOldPos = nPos;
915 nAttrs++;
919 return nAttrs;
922 const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs )
924 ByteString sOut( OOO_STRING_SVTOOLS_HTML_doctype );
925 (sOut += ' ') +=
926 (HTML_CFG_HTML32==nExportMode ? OOO_STRING_SVTOOLS_HTML_doctype32
927 : OOO_STRING_SVTOOLS_HTML_doctype40);
928 HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.GetBuffer() );
930 // baue den Vorspann
931 OutNewLine();
932 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html );
934 OutNewLine();
935 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head );
937 IncIndentLevel(); // Inhalt von <HEAD> einruecken
939 // DokumentInfo
940 ByteString sIndent;
941 GetIndentString( sIndent );
942 // OutNewLine();
943 using namespace ::com::sun::star;
944 uno::Reference<document::XDocumentProperties> xDocProps;
945 SwDocShell *pDocShell(pDoc->GetDocShell());
946 if (pDocShell) {
947 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
948 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
949 xDocProps.set(xDPS->getDocumentProperties());
952 // xDocProps may be null here (when copying)
953 SfxFrameHTMLWriter::Out_DocInfo( Strm(), GetBaseURL(), xDocProps,
954 sIndent.GetBuffer(), eDestEnc,
955 &aNonConvertableCharacters );
957 // Kommentare und Meta-Tags des ersten Absatzes
958 rHeaderAttrs = OutHeaderAttrs();
960 OutFootEndNoteInfo();
962 const SwPageDesc *pPageDesc = 0;
963 //if( !pDoc->IsHTMLMode() )
965 // In Nicht-HTML-Dokumenten wird die erste gesetzte Seitenvorlage
966 // exportiert und wenn keine gesetzt ist die Standard-Vorlage
967 ULONG nNodeIdx = pCurPam->GetPoint()->nNode.GetIndex();
969 while( nNodeIdx < pDoc->GetNodes().Count() )
971 SwNode *pNd = pDoc->GetNodes()[ nNodeIdx ];
972 if( pNd->IsCntntNode() )
974 pPageDesc = ((const SwFmtPageDesc &)pNd->GetCntntNode()
975 ->GetAttr(RES_PAGEDESC)).GetPageDesc();
976 break;
978 else if( pNd->IsTableNode() )
980 pPageDesc = pNd->GetTableNode()->GetTable().GetFrmFmt()
981 ->GetPageDesc().GetPageDesc();
982 break;
985 nNodeIdx++;
988 if( !pPageDesc )
989 pPageDesc = &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
991 //else
993 // In HTML-Dokumenten nehmen wir immer die HTML-Vorlage
994 // pPageDesc = pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML );
997 // und nun ... das Style-Sheet!!!
998 if( bCfgOutStyles )
1000 OutStyleSheet( *pPageDesc );
1003 // und nun ... das BASIC und JavaScript!
1004 if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich
1005 OutBasic();
1007 DecIndentLevel(); // Inhalt von <HEAD> einruecken
1008 OutNewLine();
1009 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head, sal_False );
1011 // der Body wird nicht eingerueckt, weil sonst alles eingerueckt waere!
1012 OutNewLine();
1013 sOut = '<';
1014 sOut += OOO_STRING_SVTOOLS_HTML_body;
1015 Strm() << sOut.GetBuffer();
1016 sOut.Erase();
1018 // language
1019 OutLanguage( eLang );
1021 // Textfarbe ausgeben, wenn sie an der Standard-Vorlage gesetzt ist
1022 // und sich geaendert hat.
1023 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_text,
1024 pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ),
1025 *this );
1027 // Farben fuer (un)besuchte Links
1028 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_link,
1029 pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL ),
1030 *this );
1031 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_vlink,
1032 pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_VISIT ),
1033 *this );
1035 const SfxItemSet& rItemSet = pPageDesc->GetMaster().GetAttrSet();
1037 String aEmbGrfName;
1038 OutBackground( rItemSet, aEmbGrfName, sal_True );
1040 nDirection = GetHTMLDirection( rItemSet );
1041 OutDirection( nDirection );
1043 if( bCfgOutStyles )
1044 OutCSS1_BodyTagStyleOpt( *this, rItemSet, aEmbGrfName );
1046 // Events anhaengen
1047 if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich
1048 OutBasicBodyEvents();
1050 Strm() << '>';
1052 return pPageDesc;
1055 void SwHTMLWriter::OutAnchor( const String& rName )
1057 ByteString sOut( '<' );
1058 (((sOut += OOO_STRING_SVTOOLS_HTML_anchor) += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\"";
1059 Strm() << sOut.GetBuffer();
1060 HTMLOutFuncs::Out_String( Strm(), rName, eDestEnc, &aNonConvertableCharacters ) << "\">";
1061 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_anchor, sal_False );
1064 void SwHTMLWriter::OutBookmarks()
1066 // hole das aktuelle Bookmark
1067 const ::sw::mark::IMark* pBookmark = NULL;
1068 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1069 if(nBkmkTabPos != -1)
1070 pBookmark = (pMarkAccess->getMarksBegin() + nBkmkTabPos)->get();
1071 // Ausgabe aller Bookmarks in diesem Absatz. Die Content-Position
1072 // wird vorerst nicht beruecksichtigt!
1073 sal_uInt32 nNode = pCurPam->GetPoint()->nNode.GetIndex();
1074 while( nBkmkTabPos != -1 &&
1075 pBookmark->GetMarkPos().nNode.GetIndex() == nNode )
1077 // Der Bereich derBookmark wird erstam ignoriert, da er von uns
1078 // auch nicht eingelesen wird.
1080 // erst die SWG spezifischen Daten:
1081 if(dynamic_cast< const ::sw::mark::IBookmark* >(pBookmark) && pBookmark->GetName().getLength() )
1082 OutAnchor( pBookmark->GetName() );
1084 if( ++nBkmkTabPos >= pMarkAccess->getMarksCount() )
1085 nBkmkTabPos = -1;
1086 else
1087 pBookmark = (pMarkAccess->getMarksBegin() + nBkmkTabPos)->get();
1090 sal_uInt16 nPos;
1091 for( nPos = 0; nPos < aOutlineMarkPoss.Count() &&
1092 aOutlineMarkPoss[nPos] < nNode; nPos++ )
1095 while( nPos < aOutlineMarkPoss.Count() && aOutlineMarkPoss[nPos] == nNode )
1097 String sMark( *aOutlineMarks[nPos] );
1098 sMark.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5
1099 OutAnchor( sMark );
1100 aOutlineMarkPoss.Remove( nPos, 1 );
1101 aOutlineMarks.DeleteAndDestroy( nPos, 1 );
1105 void SwHTMLWriter::OutImplicitMark( const String& rMark,
1106 const sal_Char *pMarkType )
1108 if( rMark.Len() && aImplicitMarks.Count() )
1110 String sMark( rMark );
1111 sMark.Append( cMarkSeperator );
1112 sMark.AppendAscii( pMarkType );
1113 sal_uInt16 nPos;
1114 if( aImplicitMarks.Seek_Entry( &sMark, &nPos ) )
1116 sMark.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5
1117 OutAnchor( sMark );
1118 aImplicitMarks.DeleteAndDestroy( nPos, 1 );
1123 void SwHTMLWriter::OutHyperlinkHRefValue( const String& rURL )
1125 String sURL( rURL );
1126 xub_StrLen nPos = sURL.SearchBackward( cMarkSeperator );
1127 if( STRING_NOTFOUND != nPos )
1129 String sCmp( sURL.Copy( nPos+1 ) );
1130 sCmp.EraseAllChars();
1131 if( sCmp.Len() )
1133 sCmp.ToLowerAscii();
1134 if( sCmp.EqualsAscii( pMarkToRegion ) ||
1135 sCmp.EqualsAscii( pMarkToFrame ) ||
1136 sCmp.EqualsAscii( pMarkToGraphic ) ||
1137 sCmp.EqualsAscii( pMarkToOLE ) ||
1138 sCmp.EqualsAscii( pMarkToTable ) ||
1139 sCmp.EqualsAscii( pMarkToOutline ) ||
1140 sCmp.EqualsAscii( pMarkToText ) )
1142 sURL.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5
1147 sURL = URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), sURL);
1148 HTMLOutFuncs::Out_String( Strm(), sURL, eDestEnc,
1149 &aNonConvertableCharacters );
1152 void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem,
1153 String& rEmbGrfNm, sal_Bool bGraphic )
1155 const Color &rBackColor = pBrushItem->GetColor();
1156 /// OD 02.09.2002 #99657#
1157 /// check, if background color is not "no fill"/"auto fill", instead of
1158 /// only checking, if transparency is not set.
1159 if( rBackColor.GetColor() != COL_TRANSPARENT )
1161 ByteString sOut( ' ' );
1162 (sOut += OOO_STRING_SVTOOLS_HTML_O_bgcolor) += '=';
1163 Strm() << sOut.GetBuffer();
1164 HTMLOutFuncs::Out_Color( Strm(), rBackColor, eDestEnc);
1167 if( !bGraphic )
1168 return;
1170 const String *pLink = pBrushItem->GetGraphicLink();
1172 // embeddete Grafik -> WriteEmbedded schreiben
1173 if( !pLink )
1175 const Graphic* pGrf = pBrushItem->GetGraphic();
1176 if( pGrf )
1178 // Grafik als (JPG-)File speichern
1179 const String* pTempFileName = GetOrigFileName();
1180 if(pTempFileName)
1181 rEmbGrfNm = *pTempFileName;
1182 sal_uInt16 nErr = XOutBitmap::WriteGraphic( *pGrf, rEmbGrfNm,
1183 String::CreateFromAscii( "JPG" ),
1184 XOUTBMP_USE_NATIVE_IF_POSSIBLE );
1185 if( !nErr ) // fehlerhaft, da ist nichts auszugeben
1187 rEmbGrfNm = URIHelper::SmartRel2Abs(
1188 INetURLObject( GetBaseURL() ), rEmbGrfNm,
1189 URIHelper::GetMaybeFileHdl() );
1190 pLink = &rEmbGrfNm;
1192 else
1194 nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE;
1198 else
1200 rEmbGrfNm = *pLink;
1201 if( bCfgCpyLinkedGrfs )
1203 CopyLocalFileToINet( rEmbGrfNm );
1204 pLink = &rEmbGrfNm;
1208 if( pLink )
1210 ByteString sOut( ' ' );
1211 String s( URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), *pLink));
1212 (sOut += OOO_STRING_SVTOOLS_HTML_O_background) += "=\"";
1213 Strm() << sOut.GetBuffer();
1214 HTMLOutFuncs::Out_String( Strm(), s, eDestEnc, &aNonConvertableCharacters ) << '\"';
1218 void SwHTMLWriter::OutBackground( const SfxItemSet& rItemSet,
1219 String& rEmbGrfNm, sal_Bool bGraphic )
1221 const SfxPoolItem* pItem;
1222 if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
1223 &pItem ))
1225 OutBackground( ((const SvxBrushItem*)pItem), rEmbGrfNm, bGraphic );
1229 sal_uInt16 SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript )
1231 sal_uInt16 nWhichId;
1232 switch( nScript )
1234 case CSS1_OUTMODE_CJK:
1235 nWhichId = RES_CHRATR_CJK_LANGUAGE;
1236 break;
1237 case CSS1_OUTMODE_CTL:
1238 nWhichId = RES_CHRATR_CJK_LANGUAGE;
1239 break;
1240 default:
1241 nWhichId = RES_CHRATR_LANGUAGE;
1242 break;
1244 return nWhichId;
1247 void SwHTMLWriter::OutLanguage( LanguageType nLang )
1249 if( LANGUAGE_DONTKNOW != nLang )
1251 ByteString sOut( ' ' );
1252 (sOut += OOO_STRING_SVTOOLS_HTML_O_lang) += "=\"";
1253 Strm() << sOut.GetBuffer();
1254 HTMLOutFuncs::Out_String( Strm(), MsLangId::convertLanguageToIsoString(nLang),
1255 eDestEnc, &aNonConvertableCharacters ) << '"';
1259 sal_uInt16 SwHTMLWriter::GetHTMLDirection( const SfxItemSet& rItemSet ) const
1261 return GetHTMLDirection(
1262 static_cast < const SvxFrameDirectionItem& >( rItemSet.Get( RES_FRAMEDIR ) )
1263 .GetValue() );
1266 sal_uInt16 SwHTMLWriter::GetHTMLDirection( sal_uInt16 nDir ) const
1268 switch( nDir )
1270 case FRMDIR_VERT_TOP_LEFT:
1271 nDir = FRMDIR_HORI_LEFT_TOP;
1272 break;
1273 case FRMDIR_VERT_TOP_RIGHT:
1274 nDir = FRMDIR_HORI_RIGHT_TOP;
1275 break;
1276 case FRMDIR_ENVIRONMENT:
1277 nDir = nDirection;
1280 return nDir;
1283 void SwHTMLWriter::OutDirection( sal_uInt16 nDir )
1285 const sal_Char *pValue = 0;
1286 switch( nDir )
1288 case FRMDIR_HORI_LEFT_TOP:
1289 case FRMDIR_VERT_TOP_LEFT:
1290 pValue = "LTR";
1291 break;
1292 case FRMDIR_HORI_RIGHT_TOP:
1293 case FRMDIR_VERT_TOP_RIGHT:
1294 pValue = "RTL";
1295 break;
1297 if( pValue != 0 )
1299 ByteString sOut( ' ' );
1300 (((sOut += OOO_STRING_SVTOOLS_HTML_O_dir) += "=\"") += pValue) += '\"';
1301 Strm() << sOut.GetBuffer();
1305 void SwHTMLWriter::GetIndentString( ByteString& rStr, sal_uInt16 nIncLvl )
1307 // etwas umstaendlich, aber wir haben nur einen Indent-String!
1308 sal_uInt16 nLevel = nIndentLvl + nIncLvl;
1310 if( nLevel && nLevel <= MAX_INDENT_LEVEL)
1312 sIndentTabs[nLevel] = 0;
1313 rStr = sIndentTabs;
1314 sIndentTabs[nLevel] = '\t';
1318 void SwHTMLWriter::OutNewLine( sal_Bool bCheck )
1320 if( !bCheck || (Strm().Tell()-nLastLFPos) > nIndentLvl )
1322 Strm() << sNewLine;
1323 nLastLFPos = Strm().Tell();
1326 if( nIndentLvl && nIndentLvl <= MAX_INDENT_LEVEL)
1328 sIndentTabs[nIndentLvl] = 0;
1329 Strm() << sIndentTabs;
1330 sIndentTabs[nIndentLvl] = '\t';
1334 sal_uInt16 SwHTMLWriter::GetHTMLFontSize( sal_uInt32 nHeight ) const
1336 sal_uInt16 nSize = 1;
1337 for( sal_uInt16 i=6; i>0; i-- )
1339 if( nHeight > (aFontHeights[i] + aFontHeights[i-1])/2 )
1341 nSize = i+1;
1342 break;
1346 return nSize;
1349 // Struktur speichert die aktuellen Daten des Writers zwischen, um
1350 // einen anderen Dokument-Teil auszugeben, wie z.B. Header/Footer
1351 HTMLSaveData::HTMLSaveData( SwHTMLWriter& rWriter, ULONG nStt,
1352 ULONG nEnd, sal_Bool bSaveNum,
1353 const SwFrmFmt *pFrmFmt ) :
1354 rWrt( rWriter ),
1355 pOldPam( rWrt.pCurPam ),
1356 pOldEnd( rWrt.GetEndPaM() ),
1357 pOldNumRuleInfo( 0 ),
1358 pOldNextNumRuleInfo( 0 ),
1359 nOldDefListLvl( rWrt.nDefListLvl ),
1360 nOldDirection( rWrt.nDirection ),
1361 bOldOutHeader( rWrt.bOutHeader ),
1362 bOldOutFooter( rWrt.bOutFooter ),
1363 bOldOutFlyFrame( rWrt.bOutFlyFrame )
1365 bOldWriteAll = rWrt.bWriteAll;
1367 rWrt.pCurPam = rWrt.NewSwPaM( *rWrt.pDoc, nStt, nEnd );
1369 // Tabelle in Sonderbereichen erkennen
1370 if( nStt != rWrt.pCurPam->GetMark()->nNode.GetIndex() )
1372 const SwNode *pNd = rWrt.pDoc->GetNodes()[ nStt ];
1373 if( pNd->IsTableNode() || pNd->IsSectionNode() )
1374 rWrt.pCurPam->GetMark()->nNode = nStt;
1377 rWrt.SetEndPaM( rWrt.pCurPam );
1378 rWrt.pCurPam->Exchange( );
1379 rWrt.bWriteAll = sal_True;
1380 rWrt.nDefListLvl = 0;
1381 rWrt.bOutHeader = rWrt.bOutFooter = sal_False;
1383 // Ggf. die aktuelle Numerierungs-Info merken, damit sie wieder
1384 // neu aufgenommen werden kann. Nur dann belibt auch die Numerierungs-
1385 // Info des nachsten Absatz gueltig.
1386 if( bSaveNum )
1388 pOldNumRuleInfo = new SwHTMLNumRuleInfo( rWrt.GetNumInfo() );
1389 pOldNextNumRuleInfo = rWrt.GetNextNumInfo();
1390 rWrt.SetNextNumInfo( 0 );
1392 else
1394 rWrt.ClearNextNumInfo();
1397 // Die Numerierung wird in jedem Fall unterbrochen.
1398 rWrt.GetNumInfo().Clear();
1400 if( pFrmFmt )
1401 rWrt.nDirection = rWrt.GetHTMLDirection( pFrmFmt->GetAttrSet() );
1405 HTMLSaveData::~HTMLSaveData()
1407 delete rWrt.pCurPam; // Pam wieder loeschen
1409 rWrt.pCurPam = pOldPam;
1410 rWrt.SetEndPaM( pOldEnd );
1411 rWrt.bWriteAll = bOldWriteAll;
1412 rWrt.nBkmkTabPos = bOldWriteAll ? rWrt.FindPos_Bkmk( *pOldPam->GetPoint() ) : -1;
1413 rWrt.nLastParaToken = 0;
1414 rWrt.nDefListLvl = nOldDefListLvl;
1415 rWrt.nDirection = nOldDirection;
1416 rWrt.bOutHeader = bOldOutHeader;
1417 rWrt.bOutFooter = bOldOutFooter;
1418 rWrt.bOutFlyFrame = bOldOutFlyFrame;
1420 // Ggf. die Numerierung von vor der Section fortsetzen. Die Numerierung
1421 // des naecshten Absatz wird in jedem Fall ungueltig.
1422 if( pOldNumRuleInfo )
1424 rWrt.GetNumInfo().Set( *pOldNumRuleInfo );
1425 delete pOldNumRuleInfo;
1426 rWrt.SetNextNumInfo( pOldNextNumRuleInfo );
1428 else
1430 rWrt.GetNumInfo().Clear();
1431 rWrt.ClearNextNumInfo();
1436 void GetHTMLWriter( const String&, const String& rBaseURL, WriterRef& xRet )
1438 xRet = new SwHTMLWriter( rBaseURL );