1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrthtml.cxx,v $
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"
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>
68 #include <fmtpdsc.hxx>
69 #include <txatbase.hxx>
71 #include <charfmt.hxx>
76 #include <mdiexp.hxx> // ...Percent()
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>
85 #include <fmtclds.hxx>
89 #include <wrthtml.hxx>
90 #include <htmlnum.hxx>
91 #include <htmlfly.hxx>
92 #include <swmodule.hxx>
95 #include <statstr.hrc> // ResId fuer Statusleiste
99 #define MAX_INDENT_LEVEL 20
102 const sal_Char
SwHTMLWriter::sNewLine
= '\012';
104 const sal_Char __FAR_DATA
SwHTMLWriter::sNewLine
[] = "\015\012";
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
;
119 pNumRuleInfo
= new SwHTMLNumRuleInfo
;
120 pNextNumRuleInfo
= 0;
123 eDestEnc
= RTL_TEXTENCODING_MS_1252
;
124 nDirection
= FRMDIR_HORI_LEFT_TOP
;
128 __EXPORT
SwHTMLWriter::~SwHTMLWriter()
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" );
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();
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();
235 ::StartProgress( STR_STATSTR_W4WWRITE
, 0, pDoc
->GetNodes().Count(),
236 pDoc
->GetDocShell());
241 bOutTable
= bOutHeader
= bOutFooter
= bOutFlyFrame
= sal_False
;
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
;
258 nDefListMargin
= ((pTemplate
&& !bCfgOutStyles
) ? pTemplate
: pDoc
)
259 ->GetTxtCollFromPool( RES_POOLCOLL_HTML_DD
, false )
260 ->GetLRSpace().GetTxtLeft();
261 nHeaderFooterSpace
= 0;
262 nTxtAttrsToIgnore
= 0;
264 sal_uInt16 nScript
= SvtLanguageOptions::GetScriptTypeOfLanguage(
265 static_cast< LanguageType
>( GetAppLanguage() ) );
268 case SCRIPTTYPE_ASIAN
:
269 nCSS1Script
= CSS1_OUTMODE_CJK
;
271 case SCRIPTTYPE_COMPLEX
:
272 nCSS1Script
= CSS1_OUTMODE_CTL
;
275 nCSS1Script
= CSS1_OUTMODE_WESTERN
;
278 eLang
= ((const SvxLanguageItem
&)pDoc
279 ->GetDefault(GetLangWhichIdFromScript(nCSS1Script
))).GetLanguage();
281 nFootNote
= nEndNote
= 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();
309 // mit dem Section-Node anfangen !!
310 pCurPam
->GetPoint()->nNode
= *pSNd
;
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
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
) += "=\"")
326 += '>') += aStartTags
;
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
342 CollectLinkTargets();
344 sal_uInt16 nHeaderAttrs
= 0;
345 pCurrPageDesc
= MakeHeader( nHeaderAttrs
);
347 bLFPossible
= sal_True
;
349 // Formulare, die nur HiddenControls enthalten ausgeben.
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();
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
);
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();
385 OutHTML_HeaderFooter( *this, *pFooterFmt
, sal_False
);
390 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body
, sal_False
);
392 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html
, sal_False
);
394 // loesche die Tabelle mit den freifliegenden Rahmen
396 ASSERT( !pHTMLPosFlyFrms
, "Wurden nicht alle Rahmen ausgegeben" );
397 if( pHTMLPosFlyFrms
)
399 pHTMLPosFlyFrms
->DeleteAndDestroy( 0, pHTMLPosFlyFrms
->Count() );
400 delete pHTMLPosFlyFrms
;
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() );
442 ASSERT( !pFootEndNotes
,
443 "SwHTMLWriter::Write: Ftns nicht durch OutFootEndNotes geloescht" );
449 for( i
=0; i
<MAXLEVEL
; i
++ )
450 aBulletGrfs
[i
].Erase();
452 aNonConvertableCharacters
.Erase();
455 ::EndProgress( pDoc
->GetDocShell() );
459 // Waehrend des Exports angelegte Zeichen- und Abastzvorlagen
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() )
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
;
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();
510 const SwSection
& rSection
= pSectNd
->GetSection();
511 const SwSectionFmt
*pFmt
= rSection
.GetFmt();
512 if( pFmt
&& lcl_html_GetFmtCol( rHTMLWrt
, rSection
, *pFmt
) )
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();
524 bRet
= lcl_html_IsMultiColStart( rHTMLWrt
,
525 pEndNd
->StartOfSectionIndex() );
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( '<' );
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
);
556 sal_uInt16 nDir
= rHTMLWrt
.GetHTMLDirection( rFmt
.GetAttrSet() );
557 rHTMLWrt
.Strm() << sOut
.GetBuffer();
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
,
578 &rHTMLWrt
.aNonConvertableCharacters
);
579 const sal_Char
*pDelim
= "ÿ";
580 if( aFilter
.Len() || aSection
.Len() || bURLContainsDelim
)
581 rHTMLWrt
.Strm() << pDelim
;
583 HTMLOutFuncs::Out_String( rHTMLWrt
.Strm(), aFilter
,
584 rHTMLWrt
.eDestEnc
, &rHTMLWrt
.aNonConvertableCharacters
);
585 if( aSection
.Len() || bURLContainsDelim
)
586 rHTMLWrt
.Strm() << pDelim
;
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
);
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
);
678 // If the next node is a columned section node, too, don't export
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 ) )
687 //.is there a columned section arround this one?
688 const SwStartNode
*pSttNd
= rSectNd
.StartOfSectionNode();
691 pSurrSectNd
= pSttNd
->FindSectionNode();
694 const SwStartNode
*pBoxSttNd
= pSttNd
->FindTableBoxStartNode();
696 pBoxSttNd
->GetIndex() < pSurrSectNd
->GetIndex() )
698 pSurrSection
= &pSurrSectNd
->GetSection();
699 pSurrFmt
= pSurrSection
->GetFmt();
701 pSurrCol
= lcl_html_GetFmtCol( rHTMLWrt
, *pSurrSection
,
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
);
716 lcl_html_OutSectionStartTag( rHTMLWrt
, rSection
, *pFmt
, pCol
);
719 HTMLSaveData
aSaveData( rHTMLWrt
,
720 rHTMLWrt
.pCurPam
->GetPoint()->nNode
.GetIndex()+1,
721 rSectNd
.EndOfSectionIndex(),
723 rHTMLWrt
.Out_SwDoc( rHTMLWrt
.pCurPam
);
726 rHTMLWrt
.pCurPam
->GetPoint()->nNode
= *rSectNd
.EndOfSectionNode();
729 lcl_html_OutSectionEndTag( rHTMLWrt
, pCol
);
731 // The surrounding section must be started again, except that it ends
732 // immeditaly behind the current one.
734 pSurrSectNd
->EndOfSectionIndex() - nSectEndIdx
> 1 &&
735 !lcl_html_IsMultiColStart( rHTMLWrt
, nSectEndIdx
+1 ) )
736 lcl_html_OutSectionStartTag( rHTMLWrt
, *pSurrSection
, *pSurrFmt
,
737 pSurrCol
, sal_True
);
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.
751 bWriteAll
= bSaveWriteAll
;
752 bFirstLine
= sal_True
;
754 // suche den ersten am Pam-auszugebenen FlyFrame
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();
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() )
787 pCurPam
->GetPoint()->nNode
++; // Bewegen
788 sal_uInt32 nPos
= pCurPam
->GetPoint()->nNode
.GetIndex();
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
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(),
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
,
830 sal_Bool bRefItemSet
= pRefFmt
&&
831 SFX_ITEM_SET
== pRefFmt
->GetAttrSet().GetItemState( RES_CHRATR_COLOR
,
832 sal_True
, &pRefItem
);
835 // wenn das Item nur in der Vorlage des aktuellen Doks gesetzt
836 // ist oder einen anderen Wert hat, als in der HTML-Vorlage,
838 const SvxColorItem
*pCItem
= (const SvxColorItem
*)pItem
;
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
) )
858 else if( bRefItemSet
)
860 // Das Item war in der HTML-Vorlage noch gesetzt, also geben wir
862 pColorItem
= (const SvxColorItem
*)&rItemSet
.GetPool()
863 ->GetDefaultItem( RES_CHRATR_COLOR
);
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()) )
890 ASSERT( pTxtNd
, "Kein Text-Node gefunden" );
891 if( !pTxtNd
|| !pTxtNd
->HasHints() )
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
];
902 xub_StrLen nPos
= *pHt
->GetStart();
903 if( nPos
-nOldPos
> 1 || RES_TXTATR_FIELD
!= pHt
->Which() )
906 sal_uInt16 nFldWhich
= ((const SwFmtFld
&)pHt
->GetAttr()).GetFld()
908 if( RES_POSTITFLD
!=nFldWhich
&&
909 RES_SCRIPTFLD
!=nFldWhich
)
913 OutHTML_SwFmtFld( *this, pHt
->GetAttr() );
922 const SwPageDesc
*SwHTMLWriter::MakeHeader( sal_uInt16
&rHeaderAttrs
)
924 ByteString
sOut( OOO_STRING_SVTOOLS_HTML_doctype
);
926 (HTML_CFG_HTML32
==nExportMode
? OOO_STRING_SVTOOLS_HTML_doctype32
927 : OOO_STRING_SVTOOLS_HTML_doctype40
);
928 HTMLOutFuncs::Out_AsciiTag( Strm(), sOut
.GetBuffer() );
932 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html
);
935 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head
);
937 IncIndentLevel(); // Inhalt von <HEAD> einruecken
941 GetIndentString( sIndent
);
943 using namespace ::com::sun::star
;
944 uno::Reference
<document::XDocumentProperties
> xDocProps
;
945 SwDocShell
*pDocShell(pDoc
->GetDocShell());
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();
978 else if( pNd
->IsTableNode() )
980 pPageDesc
= pNd
->GetTableNode()->GetTable().GetFrmFmt()
981 ->GetPageDesc().GetPageDesc();
989 pPageDesc
= &const_cast<const SwDoc
*>(pDoc
)->GetPageDesc( 0 );
993 // In HTML-Dokumenten nehmen wir immer die HTML-Vorlage
994 // pPageDesc = pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML );
997 // und nun ... das Style-Sheet!!!
1000 OutStyleSheet( *pPageDesc
);
1003 // und nun ... das BASIC und JavaScript!
1004 if( pDoc
->GetDocShell() ) // nur mit DocShell ist Basic moeglich
1007 DecIndentLevel(); // Inhalt von <HEAD> einruecken
1009 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head
, sal_False
);
1011 // der Body wird nicht eingerueckt, weil sonst alles eingerueckt waere!
1014 sOut
+= OOO_STRING_SVTOOLS_HTML_body
;
1015 Strm() << sOut
.GetBuffer();
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 ),
1027 // Farben fuer (un)besuchte Links
1028 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_link
,
1029 pDoc
->GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL
),
1031 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_vlink
,
1032 pDoc
->GetCharFmtFromPool( RES_POOLCHR_INET_VISIT
),
1035 const SfxItemSet
& rItemSet
= pPageDesc
->GetMaster().GetAttrSet();
1038 OutBackground( rItemSet
, aEmbGrfName
, sal_True
);
1040 nDirection
= GetHTMLDirection( rItemSet
);
1041 OutDirection( nDirection
);
1044 OutCSS1_BodyTagStyleOpt( *this, rItemSet
, aEmbGrfName
);
1047 if( pDoc
->GetDocShell() ) // nur mit DocShell ist Basic moeglich
1048 OutBasicBodyEvents();
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() )
1087 pBookmark
= (pMarkAccess
->getMarksBegin() + nBkmkTabPos
)->get();
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
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
);
1114 if( aImplicitMarks
.Seek_Entry( &sMark
, &nPos
) )
1116 sMark
.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5
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();
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
);
1170 const String
*pLink
= pBrushItem
->GetGraphicLink();
1172 // embeddete Grafik -> WriteEmbedded schreiben
1175 const Graphic
* pGrf
= pBrushItem
->GetGraphic();
1178 // Grafik als (JPG-)File speichern
1179 const String
* pTempFileName
= GetOrigFileName();
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() );
1194 nWarn
= WARN_SWG_POOR_LOAD
| WARN_SW_WRITE_BASE
;
1201 if( bCfgCpyLinkedGrfs
)
1203 CopyLocalFileToINet( rEmbGrfNm
);
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
,
1225 OutBackground( ((const SvxBrushItem
*)pItem
), rEmbGrfNm
, bGraphic
);
1229 sal_uInt16
SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript
)
1231 sal_uInt16 nWhichId
;
1234 case CSS1_OUTMODE_CJK
:
1235 nWhichId
= RES_CHRATR_CJK_LANGUAGE
;
1237 case CSS1_OUTMODE_CTL
:
1238 nWhichId
= RES_CHRATR_CJK_LANGUAGE
;
1241 nWhichId
= RES_CHRATR_LANGUAGE
;
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
) )
1266 sal_uInt16
SwHTMLWriter::GetHTMLDirection( sal_uInt16 nDir
) const
1270 case FRMDIR_VERT_TOP_LEFT
:
1271 nDir
= FRMDIR_HORI_LEFT_TOP
;
1273 case FRMDIR_VERT_TOP_RIGHT
:
1274 nDir
= FRMDIR_HORI_RIGHT_TOP
;
1276 case FRMDIR_ENVIRONMENT
:
1283 void SwHTMLWriter::OutDirection( sal_uInt16 nDir
)
1285 const sal_Char
*pValue
= 0;
1288 case FRMDIR_HORI_LEFT_TOP
:
1289 case FRMDIR_VERT_TOP_LEFT
:
1292 case FRMDIR_HORI_RIGHT_TOP
:
1293 case FRMDIR_VERT_TOP_RIGHT
:
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;
1314 sIndentTabs
[nLevel
] = '\t';
1318 void SwHTMLWriter::OutNewLine( sal_Bool bCheck
)
1320 if( !bCheck
|| (Strm().Tell()-nLastLFPos
) > nIndentLvl
)
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 )
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
) :
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.
1388 pOldNumRuleInfo
= new SwHTMLNumRuleInfo( rWrt
.GetNumInfo() );
1389 pOldNextNumRuleInfo
= rWrt
.GetNextNumInfo();
1390 rWrt
.SetNextNumInfo( 0 );
1394 rWrt
.ClearNextNumInfo();
1397 // Die Numerierung wird in jedem Fall unterbrochen.
1398 rWrt
.GetNumInfo().Clear();
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
);
1430 rWrt
.GetNumInfo().Clear();
1431 rWrt
.ClearNextNumInfo();
1436 void GetHTMLWriter( const String
&, const String
& rBaseURL
, WriterRef
& xRet
)
1438 xRet
= new SwHTMLWriter( rBaseURL
);