Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdlib.h>
21 : #include <hintids.hxx>
22 : #include <comphelper/string.hxx>
23 : #include <svl/urihelper.hxx>
24 : #include <rtl/tencinfo.h>
25 : #include <vcl/wrkwin.hxx>
26 : #include <sfx2/linkmgr.hxx>
27 :
28 : #include <svtools/htmlcfg.hxx>
29 : #include <vcl/svapp.hxx>
30 : #include <i18nlangtag/languagetag.hxx>
31 : #include <sfx2/frmhtmlw.hxx>
32 : #include <svx/xoutbmp.hxx>
33 : #include <sfx2/htmlmode.hxx>
34 : #include <editeng/lrspitem.hxx>
35 : #include <editeng/colritem.hxx>
36 : #include <editeng/brushitem.hxx>
37 : #include <editeng/fontitem.hxx>
38 : #include <editeng/scripttypeitem.hxx>
39 : #include <editeng/langitem.hxx>
40 : #include <svl/stritem.hxx>
41 : #include <editeng/frmdiritem.hxx>
42 :
43 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
44 : #include <com/sun/star/document/XDocumentProperties.hpp>
45 : #include <com/sun/star/form/XFormsSupplier.hpp>
46 : #include <com/sun/star/form/XForm.hpp>
47 : #include <com/sun/star/form/XImageProducerSupplier.hpp>
48 : #include <com/sun/star/form/XFormController.hpp>
49 : #include <com/sun/star/container/XContainer.hpp>
50 : #include <com/sun/star/container/XIndexContainer.hpp>
51 : #include <com/sun/star/container/XSet.hpp>
52 : #include <fmthdft.hxx>
53 : #include <fmtfld.hxx>
54 : #include <fmtpdsc.hxx>
55 : #include <txatbase.hxx>
56 : #include <frmatr.hxx>
57 : #include <charfmt.hxx>
58 : #include <docary.hxx>
59 : #include <pam.hxx>
60 : #include <doc.hxx>
61 : #include <ndtxt.hxx>
62 : #include <mdiexp.hxx>
63 : #include <fltini.hxx>
64 : #include <viewopt.hxx>
65 : #include <IMark.hxx>
66 : #include <poolfmt.hxx>
67 : #include <pagedesc.hxx>
68 : #include <section.hxx>
69 : #include <swtable.hxx>
70 : #include <fldbas.hxx>
71 : #include <fmtclds.hxx>
72 : #include <docsh.hxx>
73 : #include <wrthtml.hxx>
74 : #include <htmlnum.hxx>
75 : #include <htmlfly.hxx>
76 : #include <swmodule.hxx>
77 : #include <statstr.hrc>
78 : #include <swerror.h>
79 : #include <rtl/strbuf.hxx>
80 :
81 : #define MAX_INDENT_LEVEL 20
82 :
83 : using namespace css;
84 :
85 : static sal_Char sIndentTabs[MAX_INDENT_LEVEL+2] =
86 : "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
87 :
88 5 : SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL )
89 : : bCfgOutStyles( sal_False )
90 : , bCfgPreferStyles( sal_False )
91 : , bCfgFormFeed( sal_False )
92 : , bCfgStarBasic( sal_False )
93 : , bCfgCpyLinkedGrfs( sal_False )
94 : , bFirstLine( sal_False )
95 : , bTagOn( sal_False )
96 : , bTxtAttr( sal_False )
97 : , bOutOpts( sal_False )
98 : , bOutTable( sal_False )
99 : , bOutHeader( sal_False )
100 : , bOutFooter( sal_False )
101 : , bOutFlyFrame( sal_False )
102 : , bFirstCSS1Rule( sal_False )
103 : , bFirstCSS1Property( sal_False )
104 : , bPoolCollTextModified( sal_False )
105 : , bCSS1IgnoreFirstPageDesc( sal_False )
106 : , bNoAlign( sal_False )
107 : , bClearLeft( sal_False )
108 : , bClearRight( sal_False )
109 : , bLFPossible( sal_False )
110 : , bPreserveForm( sal_False )
111 : , bCfgNetscape4( sal_False )
112 5 : , mbSkipImages(false)
113 :
114 : {
115 5 : SetBaseURL( rBaseURL );
116 5 : bFirstLine = sal_True;
117 5 : nBkmkTabPos = -1;
118 5 : pDfltColor = 0;
119 5 : nImgMapCnt = 1;
120 5 : pStartNdIdx = 0;
121 5 : pTemplate = 0;
122 5 : pNumRuleInfo = new SwHTMLNumRuleInfo;
123 5 : pNextNumRuleInfo = 0;
124 5 : pFootEndNotes = 0;
125 5 : pFmtFtn = 0;
126 5 : eDestEnc = RTL_TEXTENCODING_MS_1252;
127 5 : nDirection = FRMDIR_HORI_LEFT_TOP;
128 5 : }
129 :
130 15 : SwHTMLWriter::~SwHTMLWriter()
131 : {
132 5 : delete pNumRuleInfo;
133 10 : }
134 :
135 5 : void SwHTMLWriter::SetupFilterOptions(SfxMedium& rMedium)
136 : {
137 5 : const SfxItemSet* pSet = rMedium.GetItemSet();
138 5 : if (pSet == NULL)
139 4 : return;
140 :
141 : const SfxPoolItem* pItem;
142 5 : if (pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) != SFX_ITEM_SET)
143 4 : return;
144 :
145 :
146 1 : OUString sFilterOptions = ((const SfxStringItem*)pItem)->GetValue();
147 1 : if (sFilterOptions == "SkipImages")
148 : {
149 1 : mbSkipImages = true;
150 1 : }
151 : }
152 :
153 5 : sal_uLong SwHTMLWriter::WriteStream()
154 : {
155 5 : SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get();
156 :
157 : // font heights 1-7
158 5 : aFontHeights[0] = rHtmlOptions.GetFontSize( 0 ) * 20;
159 5 : aFontHeights[1] = rHtmlOptions.GetFontSize( 1 ) * 20;
160 5 : aFontHeights[2] = rHtmlOptions.GetFontSize( 2 ) * 20;
161 5 : aFontHeights[3] = rHtmlOptions.GetFontSize( 3 ) * 20;
162 5 : aFontHeights[4] = rHtmlOptions.GetFontSize( 4 ) * 20;
163 5 : aFontHeights[5] = rHtmlOptions.GetFontSize( 5 ) * 20;
164 5 : aFontHeights[6] = rHtmlOptions.GetFontSize( 6 ) * 20;
165 :
166 : // ueberhaupt Styles ausgeben
167 : // (dann auch obere und untere Absatz-Abstaende)
168 5 : nExportMode = rHtmlOptions.GetExportMode();
169 5 : nHTMLMode = GetHtmlMode(0);
170 :
171 5 : if( HTML_CFG_WRITER == nExportMode || HTML_CFG_NS40 == nExportMode )
172 5 : nHTMLMode |= HTMLMODE_BLOCK_SPACER;
173 :
174 5 : if( HTML_CFG_WRITER == nExportMode || HTML_CFG_MSIE == nExportMode )
175 0 : nHTMLMode |= (HTMLMODE_FLOAT_FRAME | HTMLMODE_LSPACE_IN_NUMBUL);
176 :
177 5 : if( HTML_CFG_MSIE == nExportMode )
178 0 : nHTMLMode |= HTMLMODE_NBSP_IN_TABLES;
179 :
180 5 : if( HTML_CFG_WRITER == nExportMode || HTML_CFG_NS40 == nExportMode || HTML_CFG_MSIE == nExportMode )
181 5 : nHTMLMode |= HTMLMODE_ABS_POS_FLY | HTMLMODE_ABS_POS_DRAW;
182 :
183 5 : if( HTML_CFG_WRITER == nExportMode )
184 0 : nHTMLMode |= HTMLMODE_FLY_MARGINS;
185 :
186 5 : if( HTML_CFG_NS40 == nExportMode )
187 5 : nHTMLMode |= HTMLMODE_BORDER_NONE;
188 :
189 5 : nHTMLMode |= HTMLMODE_FONT_GENERIC;
190 :
191 5 : if( HTML_CFG_NS40==nExportMode )
192 5 : nHTMLMode |= HTMLMODE_NO_CONTROL_CENTERING;
193 :
194 5 : bCfgOutStyles = IsHTMLMode(HTMLMODE_SOME_STYLES | HTMLMODE_FULL_STYLES);
195 5 : bCfgNetscape4 = (HTML_CFG_NS40 == nExportMode);
196 :
197 5 : if( IsHTMLMode(HTMLMODE_SOME_STYLES | HTMLMODE_FULL_STYLES) )
198 5 : nHTMLMode |= HTMLMODE_PRINT_EXT;
199 :
200 5 : const sal_Char *pHelpHack = getenv( "HelpEx" );
201 5 : if( pHelpHack )
202 : {
203 0 : OString aTmp(pHelpHack);
204 0 : if (aTmp.equalsIgnoreAsciiCase("Hilfe"))
205 0 : nHTMLMode |= HTMLMODE_NO_BR_AT_PAREND;
206 : }
207 :
208 5 : eCSS1Unit = (FieldUnit)SW_MOD()->GetMetric( pDoc->get(IDocumentSettingAccess::HTML_MODE) );
209 :
210 5 : sal_Bool bWriteUTF8 = bWriteClipboardDoc;
211 5 : eDestEnc = bWriteUTF8 ? RTL_TEXTENCODING_UTF8 : rHtmlOptions.GetTextEncoding();
212 5 : const sal_Char *pCharSet = rtl_getBestMimeCharsetFromTextEncoding( eDestEnc );
213 5 : eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet );
214 :
215 : // Nur noch fuer den MS-IE ziehen wir den Export von Styles vor.
216 5 : bCfgPreferStyles = HTML_CFG_MSIE == nExportMode;
217 :
218 5 : bCfgStarBasic = rHtmlOptions.IsStarBasic();
219 :
220 5 : bCfgFormFeed = !IsHTMLMode(HTMLMODE_PRINT_EXT);
221 5 : bCfgCpyLinkedGrfs = rHtmlOptions.IsSaveGraphicsLocal();
222 :
223 : // die HTML-Vorlage holen
224 5 : sal_Bool bOldHTMLMode = sal_False;
225 5 : sal_uInt16 nOldTxtFmtCollCnt = 0, nOldCharFmtCnt = 0;
226 :
227 : OSL_ENSURE( !pTemplate, "Wo kommt denn die HTML-Vorlage hier her?" );
228 5 : pTemplate = ((HTMLReader*)ReadHTML)->GetTemplateDoc();
229 5 : if( pTemplate )
230 : {
231 5 : pTemplate->acquire();
232 5 : bOldHTMLMode = pTemplate->get(IDocumentSettingAccess::HTML_MODE);
233 5 : pTemplate->set(IDocumentSettingAccess::HTML_MODE, true);
234 :
235 5 : nOldTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->size();
236 5 : nOldCharFmtCnt = pTemplate->GetCharFmts()->size();
237 : }
238 :
239 5 : if( bShowProgress )
240 5 : ::StartProgress( STR_STATSTR_W4WWRITE, 0, pDoc->GetNodes().Count(),
241 10 : pDoc->GetDocShell());
242 :
243 5 : pDfltColor = 0;
244 5 : pFootEndNotes = 0;
245 5 : pFmtFtn = 0;
246 5 : bOutTable = bOutHeader = bOutFooter = bOutFlyFrame = sal_False;
247 5 : pxFormComps = 0;
248 5 : nFormCntrlCnt = 0;
249 5 : bPreserveForm = sal_False;
250 5 : bClearLeft = bClearRight = sal_False;
251 5 : bLFPossible = sal_False;
252 :
253 5 : nLeftMargin = nDfltLeftMargin = nDfltRightMargin = 0;
254 5 : nDfltTopMargin = nDfltBottomMargin = 0;
255 5 : nFirstLineIndent = nDfltFirstLineIndent = 0;
256 5 : bPoolCollTextModified = sal_False;
257 5 : bFirstCSS1Property = bFirstCSS1Rule = sal_False;
258 5 : bCSS1IgnoreFirstPageDesc = sal_False;
259 5 : nIndentLvl = 0;
260 5 : nWhishLineLen = 70;
261 5 : nLastLFPos = 0;
262 5 : nDefListLvl = 0;
263 15 : nDefListMargin = ((pTemplate && !bCfgOutStyles) ? pTemplate : pDoc)
264 5 : ->GetTxtCollFromPool( RES_POOLCOLL_HTML_DD, false )
265 5 : ->GetLRSpace().GetTxtLeft();
266 5 : nHeaderFooterSpace = 0;
267 5 : nTxtAttrsToIgnore = 0;
268 5 : nCSS1OutMode = 0;
269 5 : sal_uInt16 nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( GetAppLanguage() );
270 5 : switch( nScript )
271 : {
272 : case SCRIPTTYPE_ASIAN:
273 0 : nCSS1Script = CSS1_OUTMODE_CJK;
274 0 : break;
275 : case SCRIPTTYPE_COMPLEX:
276 0 : nCSS1Script = CSS1_OUTMODE_CTL;
277 0 : break;
278 : default:
279 5 : nCSS1Script = CSS1_OUTMODE_WESTERN;
280 5 : break;
281 : }
282 : eLang = ((const SvxLanguageItem&)pDoc
283 5 : ->GetDefault(GetLangWhichIdFromScript(nCSS1Script))).GetLanguage();
284 :
285 5 : nFootNote = nEndNote = 0;
286 :
287 5 : nWarn = 0;
288 5 : GetNumInfo().Clear();
289 5 : pNextNumRuleInfo = 0;
290 :
291 5 : OString aStartTags;
292 :
293 : // Tabellen und Bereiche am Doc.-Anfang beachten
294 : {
295 5 : SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode();
296 5 : if( pTNd && bWriteAll )
297 : {
298 : // mit dem Tabellen-Node anfangen !!
299 1 : pCurPam->GetPoint()->nNode = *pTNd;
300 :
301 1 : if( bWriteOnlyFirstTable )
302 0 : pCurPam->GetMark()->nNode = *pTNd->EndOfSectionNode();
303 : }
304 :
305 : // erster Node (der einen Seitenumbruch enthalten darf)
306 5 : pStartNdIdx = new SwNodeIndex( pCurPam->GetPoint()->nNode );
307 :
308 5 : SwSectionNode * pSNd = pCurPam->GetNode()->FindSectionNode();
309 10 : while( pSNd )
310 : {
311 0 : if( bWriteAll )
312 : {
313 : // mit dem Section-Node anfangen !!
314 0 : pCurPam->GetPoint()->nNode = *pSNd;
315 : }
316 : else
317 : {
318 : OSL_ENSURE( FILE_LINK_SECTION != pSNd->GetSection().GetType(),
319 : "Export gelinkter Bereiche am Dok-Anfang ist nicht implemntiert" );
320 :
321 : // nur das Tag fuer die Section merken
322 : OString aName = HTMLOutFuncs::ConvertStringToHTML(
323 0 : pSNd->GetSection().GetSectionName(), eDestEnc,
324 0 : &aNonConvertableCharacters );
325 :
326 0 : OStringBuffer sOut;
327 0 : sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_division)
328 0 : .append(' ').append(OOO_STRING_SVTOOLS_HTML_O_id)
329 0 : .append("=\"").append(aName).append('\"').append('>')
330 0 : .append(aStartTags);
331 0 : aStartTags = sOut.makeStringAndClear();
332 : }
333 : // FindSectionNode() an einem SectionNode liefert den selben!
334 0 : pSNd = pSNd->StartOfSectionNode()->FindSectionNode();
335 : }
336 : }
337 :
338 : // Tabelle fuer die freifliegenden Rahmen erzeugen, aber nur wenn
339 : // das gesamte Dokument geschrieben wird
340 5 : pHTMLPosFlyFrms = 0;
341 5 : CollectFlyFrms();
342 5 : nLastParaToken = 0;
343 5 : GetControls();
344 5 : CollectLinkTargets();
345 :
346 5 : sal_uInt16 nHeaderAttrs = 0;
347 5 : pCurrPageDesc = MakeHeader( nHeaderAttrs );
348 :
349 5 : bLFPossible = sal_True;
350 :
351 : // Formulare, die nur HiddenControls enthalten ausgeben.
352 5 : OutHiddenForms();
353 :
354 5 : if( !aStartTags.isEmpty() )
355 0 : Strm().WriteCharPtr( aStartTags.getStr() );
356 :
357 : const SfxPoolItem *pItem;
358 5 : const SfxItemSet& rPageItemSet = pCurrPageDesc->GetMaster().GetAttrSet();
359 20 : if( !bWriteClipboardDoc && pDoc->GetDocShell() &&
360 9 : (!pDoc->get(IDocumentSettingAccess::HTML_MODE) &&
361 13 : !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) &&
362 4 : SFX_ITEM_SET == rPageItemSet.GetItemState( RES_HEADER, true, &pItem) )
363 : {
364 : const SwFrmFmt *pHeaderFmt =
365 4 : ((const SwFmtHeader *)pItem)->GetHeaderFmt();
366 4 : if( pHeaderFmt )
367 0 : OutHTML_HeaderFooter( *this, *pHeaderFmt, sal_True );
368 : }
369 :
370 5 : nTxtAttrsToIgnore = nHeaderAttrs;
371 5 : Out_SwDoc( pOrigPam );
372 5 : nTxtAttrsToIgnore = 0;
373 :
374 5 : if( pxFormComps && pxFormComps->is() )
375 0 : OutForm( sal_False, *pxFormComps );
376 :
377 5 : if( pFootEndNotes )
378 0 : OutFootEndNotes();
379 :
380 20 : if( !bWriteClipboardDoc && pDoc->GetDocShell() &&
381 18 : (!pDoc->get(IDocumentSettingAccess::HTML_MODE) && !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) &&
382 4 : SFX_ITEM_SET == rPageItemSet.GetItemState( RES_FOOTER, true, &pItem) )
383 : {
384 : const SwFrmFmt *pFooterFmt =
385 4 : ((const SwFmtFooter *)pItem)->GetFooterFmt();
386 4 : if( pFooterFmt )
387 0 : OutHTML_HeaderFooter( *this, *pFooterFmt, sal_False );
388 : }
389 :
390 5 : if( bLFPossible )
391 5 : OutNewLine();
392 5 : HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body, false );
393 5 : OutNewLine();
394 5 : HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html, false );
395 :
396 : // loesche die Tabelle mit den freifliegenden Rahmen
397 : sal_uInt16 i;
398 : OSL_ENSURE( !pHTMLPosFlyFrms, "Wurden nicht alle Rahmen ausgegeben" );
399 5 : if( pHTMLPosFlyFrms )
400 : {
401 0 : pHTMLPosFlyFrms->DeleteAndDestroyAll();
402 0 : delete pHTMLPosFlyFrms;
403 0 : pHTMLPosFlyFrms = 0;
404 : }
405 :
406 5 : aHTMLControls.DeleteAndDestroyAll();
407 :
408 5 : if( !aChrFmtInfos.empty() )
409 0 : aChrFmtInfos.clear();
410 :
411 5 : if( !aTxtCollInfos.empty() )
412 5 : aTxtCollInfos.clear();
413 :
414 5 : if(!aImgMapNames.empty())
415 0 : aImgMapNames.clear();
416 :
417 5 : aImplicitMarks.clear();
418 :
419 5 : aOutlineMarks.clear();
420 :
421 5 : aOutlineMarkPoss.clear();
422 :
423 5 : aNumRuleNames.clear();
424 :
425 5 : aScriptParaStyles.clear();
426 5 : aScriptTextStyles.clear();
427 :
428 5 : delete pDfltColor;
429 5 : pDfltColor = 0;
430 :
431 5 : delete pStartNdIdx;
432 5 : pStartNdIdx = 0;
433 :
434 5 : delete pxFormComps;
435 5 : pxFormComps = 0;
436 :
437 : OSL_ENSURE( !pFootEndNotes,
438 : "SwHTMLWriter::Write: Ftns nicht durch OutFootEndNotes geloescht" );
439 :
440 5 : pCurrPageDesc = 0;
441 :
442 5 : ClearNextNumInfo();
443 :
444 55 : for( i=0; i<MAXLEVEL; i++ )
445 50 : aBulletGrfs[i] = "";
446 :
447 5 : aNonConvertableCharacters = "";
448 :
449 5 : if( bShowProgress )
450 5 : ::EndProgress( pDoc->GetDocShell() );
451 :
452 5 : if( pTemplate )
453 : {
454 : // Waehrend des Exports angelegte Zeichen- und Abastzvorlagen
455 : // loeschen
456 5 : sal_uInt16 nTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->size();
457 10 : while( nTxtFmtCollCnt > nOldTxtFmtCollCnt )
458 0 : pTemplate->DelTxtFmtColl( --nTxtFmtCollCnt );
459 : OSL_ENSURE( pTemplate->GetTxtFmtColls()->size() == nOldTxtFmtCollCnt,
460 : "falsche Anzahl TxtFmtColls geloescht" );
461 :
462 5 : sal_uInt16 nCharFmtCnt = pTemplate->GetCharFmts()->size();
463 27 : while( nCharFmtCnt > nOldCharFmtCnt )
464 17 : pTemplate->DelCharFmt( --nCharFmtCnt );
465 : OSL_ENSURE( pTemplate->GetCharFmts()->size() == nOldCharFmtCnt,
466 : "falsche Anzahl CharFmts geloescht" );
467 :
468 : // HTML-Modus wieder restaurieren
469 5 : pTemplate->set(IDocumentSettingAccess::HTML_MODE, bOldHTMLMode);
470 :
471 5 : if( 0 == pTemplate->release() )
472 0 : delete pTemplate;
473 :
474 5 : pTemplate = 0;
475 : }
476 :
477 5 : return nWarn;
478 : }
479 :
480 0 : static const SwFmtCol *lcl_html_GetFmtCol( const SwSection& rSection,
481 : const SwSectionFmt& rFmt )
482 : {
483 0 : const SwFmtCol *pCol = 0;
484 :
485 : const SfxPoolItem* pItem;
486 0 : if( FILE_LINK_SECTION != rSection.GetType() &&
487 0 : SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState(RES_COL,false,&pItem) &&
488 0 : ((const SwFmtCol *)pItem)->GetNumCols() > 1 )
489 : {
490 0 : pCol = (const SwFmtCol *)pItem;
491 : }
492 :
493 0 : return pCol;
494 : }
495 :
496 0 : static bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex )
497 : {
498 0 : bool bRet = false;
499 : const SwSectionNode *pSectNd =
500 0 : rHTMLWrt.pDoc->GetNodes()[nIndex]->GetSectionNode();
501 0 : if( pSectNd )
502 : {
503 0 : const SwSection& rSection = pSectNd->GetSection();
504 0 : const SwSectionFmt *pFmt = rSection.GetFmt();
505 0 : if( pFmt && lcl_html_GetFmtCol( rSection, *pFmt ) )
506 0 : bRet = true;
507 : }
508 :
509 0 : return bRet;
510 : }
511 :
512 0 : static bool lcl_html_IsMultiColEnd( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex )
513 : {
514 0 : bool bRet = false;
515 0 : const SwEndNode *pEndNd = rHTMLWrt.pDoc->GetNodes()[nIndex]->GetEndNode();
516 0 : if( pEndNd )
517 : bRet = lcl_html_IsMultiColStart( rHTMLWrt,
518 0 : pEndNd->StartOfSectionIndex() );
519 :
520 0 : return bRet;
521 : }
522 :
523 0 : static void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt,
524 : const SwSection& rSection,
525 : const SwSectionFmt& rFmt,
526 : const SwFmtCol *pCol,
527 : bool bContinued=false )
528 : {
529 : OSL_ENSURE( pCol || !bContinued, "Continuation of DIV" );
530 :
531 0 : if( rHTMLWrt.bLFPossible )
532 0 : rHTMLWrt.OutNewLine();
533 :
534 0 : OStringBuffer sOut;
535 0 : sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_division);
536 :
537 0 : const OUString& rName = rSection.GetSectionName();
538 0 : if( !rName.isEmpty() && !bContinued )
539 : {
540 0 : sOut.append(" " + OString(OOO_STRING_SVTOOLS_HTML_O_id) + "=\"");
541 0 : rHTMLWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
542 0 : HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), rName, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
543 0 : sOut.append('\"');
544 : }
545 :
546 0 : sal_uInt16 nDir = rHTMLWrt.GetHTMLDirection( rFmt.GetAttrSet() );
547 0 : rHTMLWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
548 0 : rHTMLWrt.OutDirection( nDir );
549 :
550 0 : if( FILE_LINK_SECTION == rSection.GetType() )
551 : {
552 0 : sOut.append(" " + OString(OOO_STRING_SVTOOLS_HTML_O_href) + "=\"");
553 0 : rHTMLWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
554 :
555 0 : const OUString& aFName = rSection.GetLinkFileName();
556 0 : OUString aURL( aFName.getToken(0,sfx2::cTokenSeparator) );
557 0 : OUString aFilter( aFName.getToken(1,sfx2::cTokenSeparator) );
558 0 : OUString aSection( aFName.getToken(2,sfx2::cTokenSeparator) );
559 :
560 0 : OUString aEncURL( URIHelper::simpleNormalizedMakeRelative(rHTMLWrt.GetBaseURL(), aURL ) );
561 0 : sal_Unicode cDelim = 255U;
562 0 : bool bURLContainsDelim = (-1 != aEncURL.indexOf( cDelim ) );
563 :
564 0 : HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aEncURL,
565 : rHTMLWrt.eDestEnc,
566 0 : &rHTMLWrt.aNonConvertableCharacters );
567 0 : const sal_Char* pDelim = "ÿ";
568 0 : if( !aFilter.isEmpty() || !aSection.isEmpty() || bURLContainsDelim )
569 0 : rHTMLWrt.Strm().WriteCharPtr( pDelim );
570 0 : if( !aFilter.isEmpty() )
571 0 : HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aFilter, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
572 0 : if( !aSection.isEmpty() || bURLContainsDelim )
573 0 : rHTMLWrt.Strm().WriteCharPtr( pDelim );
574 0 : if( !aSection.isEmpty() )
575 : {
576 0 : sal_Int32 nPos = aSection.indexOf( '%' );
577 0 : while( nPos != -1 )
578 : {
579 0 : aSection = aSection.replaceAt(nPos, 1, "%25");
580 0 : nPos = aSection.indexOf( '%', nPos+3 );
581 : }
582 0 : nPos = aSection.indexOf( cDelim );
583 0 : while( nPos != -1 )
584 : {
585 0 : aSection = aSection.replaceAt(nPos, 1, "%FF" );
586 0 : nPos = aSection.indexOf( cDelim, nPos+3 );
587 : }
588 0 : HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aSection,
589 0 : rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
590 : }
591 0 : sOut.append('\"');
592 : }
593 0 : else if( pCol )
594 : {
595 : // minumum gutter width
596 0 : sal_uInt16 nGutter = pCol->GetGutterWidth( sal_True );
597 0 : if( nGutter!=USHRT_MAX )
598 : {
599 0 : if( nGutter && Application::GetDefaultDevice() )
600 : {
601 : nGutter = (sal_uInt16)Application::GetDefaultDevice()
602 0 : ->LogicToPixel( Size(nGutter, 0), MapMode(MAP_TWIP) ).Width();
603 : }
604 0 : sOut.append(" " + OString(OOO_STRING_SVTOOLS_HTML_O_gutter) + "=\"" + OString::number(nGutter) + "\"");
605 : }
606 : }
607 :
608 0 : rHTMLWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
609 0 : if( rHTMLWrt.IsHTMLMode( rHTMLWrt.bCfgOutStyles ) )
610 0 : rHTMLWrt.OutCSS1_SectionFmtOptions( rFmt, pCol );
611 :
612 0 : rHTMLWrt.Strm().WriteChar( '>' );
613 :
614 0 : rHTMLWrt.bLFPossible = sal_True;
615 0 : if( !rName.isEmpty() && !bContinued )
616 0 : rHTMLWrt.OutImplicitMark( rName, "region" );
617 :
618 0 : rHTMLWrt.IncIndentLevel();
619 0 : }
620 :
621 0 : static void lcl_html_OutSectionEndTag( SwHTMLWriter& rHTMLWrt )
622 : {
623 0 : rHTMLWrt.DecIndentLevel();
624 0 : if( rHTMLWrt.bLFPossible )
625 0 : rHTMLWrt.OutNewLine();
626 0 : HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), OOO_STRING_SVTOOLS_HTML_division, false );
627 0 : rHTMLWrt.bLFPossible = sal_True;
628 0 : }
629 :
630 0 : static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd )
631 : {
632 0 : SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
633 :
634 : // End <PRE> and any <DL>, because a definition list's level may
635 : // change inside the section.
636 0 : rHTMLWrt.ChangeParaToken( 0 );
637 0 : rHTMLWrt.OutAndSetDefList( 0 );
638 :
639 0 : const SwSection& rSection = rSectNd.GetSection();
640 0 : const SwSectionFmt *pFmt = rSection.GetFmt();
641 : OSL_ENSURE( pFmt, "Section without a format?" );
642 :
643 0 : bool bStartTag = true;
644 0 : bool bEndTag = true;
645 0 : const SwSectionFmt *pSurrFmt = 0;
646 0 : const SwSectionNode *pSurrSectNd = 0;
647 0 : const SwSection *pSurrSection = 0;
648 0 : const SwFmtCol *pSurrCol = 0;
649 :
650 0 : sal_uInt32 nSectSttIdx = rSectNd.GetIndex();
651 0 : sal_uInt32 nSectEndIdx = rSectNd.EndOfSectionIndex();
652 0 : const SwFmtCol *pCol = lcl_html_GetFmtCol( rSection, *pFmt );
653 0 : if( pCol )
654 : {
655 : // If the next node is a columned section node, too, don't export
656 : // an empty section.
657 0 : if( lcl_html_IsMultiColStart( rHTMLWrt, nSectSttIdx+1 ) )
658 0 : bStartTag = false;
659 :
660 : // The same applies if the section end with another columned section.
661 0 : if( lcl_html_IsMultiColEnd( rHTMLWrt, nSectEndIdx-1 ) )
662 0 : bEndTag = false;
663 :
664 : //.is there a columned section arround this one?
665 0 : const SwStartNode *pSttNd = rSectNd.StartOfSectionNode();
666 0 : if( pSttNd )
667 : {
668 0 : pSurrSectNd = pSttNd->FindSectionNode();
669 0 : if( pSurrSectNd )
670 : {
671 0 : const SwStartNode *pBoxSttNd = pSttNd->FindTableBoxStartNode();
672 0 : if( !pBoxSttNd ||
673 0 : pBoxSttNd->GetIndex() < pSurrSectNd->GetIndex() )
674 : {
675 0 : pSurrSection = &pSurrSectNd->GetSection();
676 0 : pSurrFmt = pSurrSection->GetFmt();
677 0 : if( pSurrFmt )
678 : pSurrCol = lcl_html_GetFmtCol( *pSurrSection,
679 0 : *pSurrFmt );
680 : }
681 : }
682 : }
683 : }
684 :
685 : // The surrounding section must be closed before the current one is
686 : // opended, except that it start immediately before the current one or
687 : // another end immediately before the current one
688 0 : if( pSurrCol && nSectSttIdx - pSurrSectNd->GetIndex() > 1 &&
689 0 : !lcl_html_IsMultiColEnd( rHTMLWrt, nSectSttIdx-1 ) )
690 0 : lcl_html_OutSectionEndTag( rHTMLWrt );
691 :
692 0 : if( bStartTag )
693 0 : lcl_html_OutSectionStartTag( rHTMLWrt, rSection, *pFmt, pCol );
694 :
695 : {
696 : HTMLSaveData aSaveData( rHTMLWrt,
697 0 : rHTMLWrt.pCurPam->GetPoint()->nNode.GetIndex()+1,
698 : rSectNd.EndOfSectionIndex(),
699 0 : sal_False, pFmt );
700 0 : rHTMLWrt.Out_SwDoc( rHTMLWrt.pCurPam );
701 : }
702 :
703 0 : rHTMLWrt.pCurPam->GetPoint()->nNode = *rSectNd.EndOfSectionNode();
704 :
705 0 : if( bEndTag )
706 0 : lcl_html_OutSectionEndTag( rHTMLWrt );
707 :
708 : // The surrounding section must be started again, except that it ends
709 : // immeditaly behind the current one.
710 0 : if( pSurrCol &&
711 0 : pSurrSectNd->EndOfSectionIndex() - nSectEndIdx > 1 &&
712 0 : !lcl_html_IsMultiColStart( rHTMLWrt, nSectEndIdx+1 ) )
713 : lcl_html_OutSectionStartTag( rHTMLWrt, *pSurrSection, *pSurrFmt,
714 0 : pSurrCol, true );
715 :
716 0 : return rWrt;
717 : }
718 :
719 265 : void SwHTMLWriter::Out_SwDoc( SwPaM* pPam )
720 : {
721 265 : sal_Bool bSaveWriteAll = bWriteAll; // sichern
722 :
723 : // suche die naechste text::Bookmark-Position aus der text::Bookmark-Tabelle
724 265 : nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1;
725 :
726 : // gebe alle Bereiche des Pams in das HTML-File aus.
727 265 : do {
728 265 : bWriteAll = bSaveWriteAll;
729 265 : bFirstLine = sal_True;
730 :
731 : // suche den ersten am Pam-auszugebenen FlyFrame
732 : // fehlt noch:
733 :
734 1594 : while( pCurPam->GetPoint()->nNode.GetIndex() < pCurPam->GetMark()->nNode.GetIndex() ||
735 790 : (pCurPam->GetPoint()->nNode.GetIndex() == pCurPam->GetMark()->nNode.GetIndex() &&
736 265 : pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex()) )
737 : {
738 272 : SwNode * pNd = pCurPam->GetNode();
739 :
740 : OSL_ENSURE( !(pNd->IsGrfNode() || pNd->IsOLENode()),
741 : "Grf- oder OLE-Node hier unerwartet" );
742 272 : if( pNd->IsTxtNode() )
743 : {
744 266 : SwTxtNode* pTxtNd = pNd->GetTxtNode();
745 :
746 266 : if( !bFirstLine )
747 2 : pCurPam->GetPoint()->nContent.Assign( pTxtNd, 0 );
748 :
749 266 : OutHTML_SwTxtNode( *this, *pTxtNd );
750 : }
751 6 : else if( pNd->IsTableNode() )
752 : {
753 1 : OutHTML_SwTblNode( *this, *pNd->GetTableNode(), 0 );
754 1 : nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1;
755 : }
756 5 : else if( pNd->IsSectionNode() )
757 : {
758 0 : OutHTML_Section( *this, *pNd->GetSectionNode() );
759 0 : nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1;
760 : }
761 5 : else if( pNd == &pDoc->GetNodes().GetEndOfContent() )
762 5 : break;
763 :
764 267 : pCurPam->GetPoint()->nNode++; // Bewegen
765 267 : sal_uInt32 nPos = pCurPam->GetPoint()->nNode.GetIndex();
766 :
767 267 : if( bShowProgress )
768 267 : ::SetProgressState( nPos, pDoc->GetDocShell() ); // Wie weit ?
769 :
770 : /* sollen nur die Selectierten Bereiche gesichert werden, so
771 : * duerfen nur die vollstaendigen Nodes gespeichert werde,
772 : * d.H. der 1. und n. Node teilweise, der 2. bis n-1. Node
773 : * vollstaendig. (vollstaendig heisst mit allen Formaten! )
774 : */
775 267 : bWriteAll = bSaveWriteAll ||
776 267 : nPos != pCurPam->GetMark()->nNode.GetIndex();
777 267 : bFirstLine = sal_False;
778 267 : bOutFooter = sal_False; // Nach einem Node keine Fusszeile mehr
779 : }
780 :
781 265 : ChangeParaToken( 0 ); // MIB 8.7.97: Machen wir jetzt hier und nicht
782 : // beim Aufrufer
783 265 : OutAndSetDefList( 0 );
784 :
785 265 : } while( CopyNextPam( &pPam ) ); // bis alle PaM's bearbeitet
786 :
787 265 : bWriteAll = bSaveWriteAll; // wieder auf alten Wert zurueck
788 265 : }
789 :
790 : // schreibe die StyleTabelle, algemeine Angaben,Header/Footer/Footnotes
791 15 : static void OutBodyColor( const sal_Char* pTag, const SwFmt *pFmt,
792 : SwHTMLWriter& rHWrt )
793 : {
794 15 : const SwFmt *pRefFmt = 0;
795 :
796 15 : if( rHWrt.pTemplate )
797 15 : pRefFmt = SwHTMLWriter::GetTemplateFmt( pFmt->GetPoolFmtId(),
798 30 : rHWrt.pTemplate );
799 :
800 15 : const SvxColorItem *pColorItem = 0;
801 :
802 15 : const SfxItemSet& rItemSet = pFmt->GetAttrSet();
803 15 : const SfxPoolItem *pRefItem = 0, *pItem = 0;
804 : bool bItemSet = SFX_ITEM_SET == rItemSet.GetItemState( RES_CHRATR_COLOR,
805 15 : true, &pItem);
806 30 : bool bRefItemSet = pRefFmt &&
807 15 : SFX_ITEM_SET == pRefFmt->GetAttrSet().GetItemState( RES_CHRATR_COLOR,
808 30 : true, &pRefItem);
809 15 : if( bItemSet )
810 : {
811 : // wenn das Item nur in der Vorlage des aktuellen Doks gesetzt
812 : // ist oder einen anderen Wert hat, als in der HTML-Vorlage,
813 : // wird es gesetzt
814 12 : const SvxColorItem *pCItem = (const SvxColorItem*)pItem;
815 :
816 12 : if( !bRefItemSet )
817 : {
818 2 : pColorItem = pCItem;
819 : }
820 : else
821 : {
822 10 : Color aColor( pCItem->GetValue() );
823 10 : if( COL_AUTO == aColor.GetColor() )
824 0 : aColor.SetColor( COL_BLACK );
825 :
826 10 : Color aRefColor( ((const SvxColorItem*)pRefItem)->GetValue() );
827 10 : if( COL_AUTO == aRefColor.GetColor() )
828 0 : aRefColor.SetColor( COL_BLACK );
829 :
830 10 : if( !aColor.IsRGBEqual( aRefColor ) )
831 1 : pColorItem = pCItem;
832 : }
833 : }
834 3 : else if( bRefItemSet )
835 : {
836 : // Das Item war in der HTML-Vorlage noch gesetzt, also geben wir
837 : // das Default aus
838 0 : pColorItem = (const SvxColorItem*)&rItemSet.GetPool()
839 0 : ->GetDefaultItem( RES_CHRATR_COLOR );
840 : }
841 :
842 15 : if( pColorItem )
843 : {
844 3 : OStringBuffer sOut;
845 3 : sOut.append(" " + OString(pTag) + "=");
846 3 : rHWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
847 3 : Color aColor( pColorItem->GetValue() );
848 3 : if( COL_AUTO == aColor.GetColor() )
849 0 : aColor.SetColor( COL_BLACK );
850 3 : HTMLOutFuncs::Out_Color( rHWrt.Strm(), aColor, rHWrt.eDestEnc );
851 3 : if( RES_POOLCOLL_STANDARD==pFmt->GetPoolFmtId() )
852 2 : rHWrt.pDfltColor = new Color( aColor );
853 : }
854 15 : }
855 :
856 5 : sal_uInt16 SwHTMLWriter::OutHeaderAttrs()
857 : {
858 5 : sal_uLong nIdx = pCurPam->GetPoint()->nNode.GetIndex();
859 5 : sal_uLong nEndIdx = pCurPam->GetMark()->nNode.GetIndex();
860 :
861 5 : SwTxtNode *pTxtNd = 0;
862 19 : while( nIdx<=nEndIdx &&
863 7 : 0==(pTxtNd=pDoc->GetNodes()[nIdx]->GetTxtNode()) )
864 2 : nIdx++;
865 :
866 : OSL_ENSURE( pTxtNd, "Kein Text-Node gefunden" );
867 5 : if( !pTxtNd || !pTxtNd->HasHints() )
868 3 : return 0;
869 :
870 2 : sal_uInt16 nAttrs = 0;
871 2 : sal_uInt16 nCntAttr = pTxtNd->GetSwpHints().Count();
872 2 : sal_Int32 nOldPos = 0;
873 5 : for( sal_uInt16 i=0; i<nCntAttr; i++ )
874 : {
875 3 : const SwTxtAttr *pHt = pTxtNd->GetSwpHints()[i];
876 3 : if( !pHt->End() )
877 : {
878 0 : sal_Int32 nPos = *pHt->GetStart();
879 0 : if( nPos-nOldPos > 1
880 0 : || ( pHt->Which() != RES_TXTATR_FIELD
881 0 : && pHt->Which() != RES_TXTATR_ANNOTATION ) )
882 0 : break;
883 :
884 : const sal_uInt16 nFldWhich =
885 0 : ((const SwFmtFld&)pHt->GetAttr()).GetField()->GetTyp()->Which();
886 0 : if( RES_POSTITFLD!=nFldWhich &&
887 : RES_SCRIPTFLD!=nFldWhich )
888 0 : break;
889 :
890 0 : OutNewLine();
891 0 : OutHTML_SwFmtFld( *this, pHt->GetAttr() );
892 0 : nOldPos = nPos;
893 0 : nAttrs++;
894 : }
895 : }
896 :
897 2 : return nAttrs;
898 : }
899 :
900 5 : const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs )
901 : {
902 5 : OStringBuffer sOut;
903 5 : sOut.append(OString(OOO_STRING_SVTOOLS_HTML_doctype) + " " + OString(OOO_STRING_SVTOOLS_HTML_doctype40));
904 5 : HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.makeStringAndClear().getStr() );
905 :
906 : // baue den Vorspann
907 5 : OutNewLine();
908 5 : HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html );
909 :
910 5 : OutNewLine();
911 5 : HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head );
912 :
913 5 : IncIndentLevel(); // Inhalt von <HEAD> einruecken
914 :
915 : // DokumentInfo
916 10 : OString sIndent = GetIndentString();
917 :
918 10 : uno::Reference<document::XDocumentProperties> xDocProps;
919 5 : SwDocShell *pDocShell(pDoc->GetDocShell());
920 5 : if (pDocShell)
921 : {
922 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
923 5 : pDocShell->GetModel(), uno::UNO_QUERY_THROW);
924 5 : xDocProps.set(xDPS->getDocumentProperties());
925 : }
926 :
927 : // xDocProps may be null here (when copying)
928 5 : SfxFrameHTMLWriter::Out_DocInfo( Strm(), GetBaseURL(), xDocProps,
929 : sIndent.getStr(), eDestEnc,
930 10 : &aNonConvertableCharacters );
931 :
932 : // Kommentare und Meta-Tags des ersten Absatzes
933 5 : rHeaderAttrs = OutHeaderAttrs();
934 :
935 5 : OutFootEndNoteInfo();
936 :
937 5 : const SwPageDesc *pPageDesc = 0;
938 :
939 : // In Nicht-HTML-Dokumenten wird die erste gesetzte Seitenvorlage
940 : // exportiert und wenn keine gesetzt ist die Standard-Vorlage
941 5 : sal_uLong nNodeIdx = pCurPam->GetPoint()->nNode.GetIndex();
942 :
943 10 : while( nNodeIdx < pDoc->GetNodes().Count() )
944 : {
945 5 : SwNode *pNd = pDoc->GetNodes()[ nNodeIdx ];
946 5 : if( pNd->IsCntntNode() )
947 : {
948 : pPageDesc = ((const SwFmtPageDesc &)pNd->GetCntntNode()
949 4 : ->GetAttr(RES_PAGEDESC)).GetPageDesc();
950 4 : break;
951 : }
952 1 : else if( pNd->IsTableNode() )
953 : {
954 1 : pPageDesc = pNd->GetTableNode()->GetTable().GetFrmFmt()
955 1 : ->GetPageDesc().GetPageDesc();
956 1 : break;
957 : }
958 :
959 0 : nNodeIdx++;
960 : }
961 :
962 5 : if( !pPageDesc )
963 1 : pPageDesc = &pDoc->GetPageDesc( 0 );
964 :
965 : // und nun ... das Style-Sheet!!!
966 5 : if( bCfgOutStyles )
967 : {
968 5 : OutStyleSheet( *pPageDesc );
969 : }
970 :
971 : // und nun ... das BASIC und JavaScript!
972 5 : if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich
973 5 : OutBasic();
974 :
975 5 : DecIndentLevel(); // Inhalt von <HEAD> einruecken
976 5 : OutNewLine();
977 5 : HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head, false );
978 :
979 : // der Body wird nicht eingerueckt, weil sonst alles eingerueckt waere!
980 5 : OutNewLine();
981 5 : sOut.append("<" + OString(OOO_STRING_SVTOOLS_HTML_body));
982 5 : Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
983 :
984 : // language
985 5 : OutLanguage( eLang );
986 :
987 : // Textfarbe ausgeben, wenn sie an der Standard-Vorlage gesetzt ist
988 : // und sich geaendert hat.
989 : OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_text,
990 5 : pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ),
991 10 : *this );
992 :
993 : // Farben fuer (un)besuchte Links
994 : OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_link,
995 5 : pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL ),
996 10 : *this );
997 : OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_vlink,
998 5 : pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_VISIT ),
999 10 : *this );
1000 :
1001 5 : const SfxItemSet& rItemSet = pPageDesc->GetMaster().GetAttrSet();
1002 :
1003 5 : OutBackground( rItemSet, sal_True );
1004 :
1005 5 : nDirection = GetHTMLDirection( rItemSet );
1006 5 : OutDirection( nDirection );
1007 :
1008 5 : if( bCfgOutStyles )
1009 5 : OutCSS1_BodyTagStyleOpt( *this, rItemSet );
1010 :
1011 : // Events anhaengen
1012 5 : if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich
1013 5 : OutBasicBodyEvents();
1014 :
1015 5 : Strm().WriteChar( '>' );
1016 :
1017 10 : return pPageDesc;
1018 : }
1019 :
1020 0 : void SwHTMLWriter::OutAnchor( const OUString& rName )
1021 : {
1022 0 : OStringBuffer sOut;
1023 0 : sOut.append("<" + OString(OOO_STRING_SVTOOLS_HTML_anchor) + " " + OString(OOO_STRING_SVTOOLS_HTML_O_name) + "=\"");
1024 0 : Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
1025 0 : HTMLOutFuncs::Out_String( Strm(), rName, eDestEnc, &aNonConvertableCharacters ).WriteCharPtr( "\">" );
1026 0 : HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_anchor, false );
1027 0 : }
1028 :
1029 266 : void SwHTMLWriter::OutBookmarks()
1030 : {
1031 : // hole das aktuelle Bookmark
1032 266 : const ::sw::mark::IMark* pBookmark = NULL;
1033 266 : IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1034 266 : if(nBkmkTabPos != -1)
1035 0 : pBookmark = (pMarkAccess->getAllMarksBegin() + nBkmkTabPos)->get();
1036 : // Ausgabe aller Bookmarks in diesem Absatz. Die Content-Position
1037 : // wird vorerst nicht beruecksichtigt!
1038 266 : sal_uInt32 nNode = pCurPam->GetPoint()->nNode.GetIndex();
1039 798 : while( nBkmkTabPos != -1
1040 266 : && pBookmark->GetMarkPos().nNode.GetIndex() == nNode )
1041 : {
1042 : // Der Bereich derBookmark wird erstam ignoriert, da er von uns
1043 : // auch nicht eingelesen wird.
1044 :
1045 : // erst die SWG spezifischen Daten:
1046 0 : if ( dynamic_cast< const ::sw::mark::IBookmark* >(pBookmark) && !pBookmark->GetName().isEmpty() )
1047 : {
1048 0 : OutAnchor( pBookmark->GetName() );
1049 : }
1050 :
1051 0 : if( ++nBkmkTabPos >= pMarkAccess->getAllMarksCount() )
1052 0 : nBkmkTabPos = -1;
1053 : else
1054 0 : pBookmark = (pMarkAccess->getAllMarksBegin() + nBkmkTabPos)->get();
1055 : }
1056 :
1057 : sal_uInt32 nPos;
1058 266 : for( nPos = 0; nPos < aOutlineMarkPoss.size() &&
1059 0 : aOutlineMarkPoss[nPos] < nNode; nPos++ )
1060 : ;
1061 :
1062 532 : while( nPos < aOutlineMarkPoss.size() && aOutlineMarkPoss[nPos] == nNode )
1063 : {
1064 0 : OUString sMark( aOutlineMarks[nPos] );
1065 0 : OutAnchor( sMark.replace('?', '_') ); // '?' causes problems in IE/Netscape 5
1066 0 : aOutlineMarkPoss.erase( aOutlineMarkPoss.begin()+nPos );
1067 0 : aOutlineMarks.erase( aOutlineMarks.begin() + nPos );
1068 0 : }
1069 266 : }
1070 :
1071 2 : void SwHTMLWriter::OutImplicitMark( const OUString& rMark,
1072 : const sal_Char *pMarkType )
1073 : {
1074 2 : if( !rMark.isEmpty() && !aImplicitMarks.empty() )
1075 : {
1076 0 : OUString sMark( rMark );
1077 0 : sMark + OUString(cMarkSeparator) + OUString::createFromAscii(pMarkType);
1078 0 : if( 0 != aImplicitMarks.erase( sMark ) )
1079 : {
1080 0 : OutAnchor(sMark.replace('?', '_')); // '?' causes problems in IE/Netscape 5
1081 0 : }
1082 : }
1083 2 : }
1084 :
1085 0 : void SwHTMLWriter::OutHyperlinkHRefValue( const OUString& rURL )
1086 : {
1087 0 : OUString sURL( rURL );
1088 0 : sal_Int32 nPos = sURL.lastIndexOf( cMarkSeparator );
1089 0 : if( nPos != -1 )
1090 : {
1091 0 : OUString sCmp(comphelper::string::remove(sURL.copy(nPos+1), ' '));
1092 0 : if( !sCmp.isEmpty() )
1093 : {
1094 0 : sCmp = sCmp.toAsciiLowerCase();
1095 0 : if( sCmp == "region" ||
1096 0 : sCmp == "frame" ||
1097 0 : sCmp == "graphic" ||
1098 0 : sCmp == "ole" ||
1099 0 : sCmp == "table" ||
1100 0 : sCmp == "outline" ||
1101 0 : sCmp == "text" )
1102 : {
1103 0 : sURL = sURL.replace( '?', '_' ); // '?' causes problems in IE/Netscape 5
1104 : }
1105 0 : }
1106 : }
1107 :
1108 0 : sURL = URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), sURL);
1109 0 : HTMLOutFuncs::Out_String( Strm(), sURL, eDestEnc,
1110 0 : &aNonConvertableCharacters );
1111 0 : }
1112 :
1113 262 : void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem, sal_Bool bGraphic )
1114 : {
1115 262 : const Color &rBackColor = pBrushItem->GetColor();
1116 : /// check, if background color is not "no fill"/"auto fill", instead of
1117 : /// only checking, if transparency is not set.
1118 262 : if( rBackColor.GetColor() != COL_TRANSPARENT )
1119 : {
1120 261 : OStringBuffer sOut;
1121 261 : sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor).append('=');
1122 261 : Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
1123 261 : HTMLOutFuncs::Out_Color( Strm(), rBackColor, eDestEnc);
1124 : }
1125 :
1126 262 : if( !bGraphic )
1127 523 : return;
1128 :
1129 1 : OUString aGraphicInBase64;
1130 1 : const Graphic* pGrf = pBrushItem->GetGraphic();
1131 1 : if( pGrf )
1132 : {
1133 0 : sal_uLong nErr = XOutBitmap::GraphicToBase64(*pGrf, aGraphicInBase64);
1134 0 : if( nErr )
1135 : {
1136 0 : nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE;
1137 : }
1138 0 : Strm().WriteCharPtr( " " OOO_STRING_SVTOOLS_HTML_O_background "=\"" );
1139 0 : Strm().WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_data ":" );
1140 0 : HTMLOutFuncs::Out_String( Strm(), aGraphicInBase64, eDestEnc, &aNonConvertableCharacters ).WriteChar( '\"' );
1141 1 : }
1142 : }
1143 :
1144 6 : void SwHTMLWriter::OutBackground( const SfxItemSet& rItemSet, sal_Bool bGraphic )
1145 : {
1146 : const SfxPoolItem* pItem;
1147 6 : if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, false,
1148 6 : &pItem ))
1149 : {
1150 2 : OutBackground( ((const SvxBrushItem*)pItem), bGraphic );
1151 : }
1152 6 : }
1153 :
1154 277 : sal_uInt16 SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript )
1155 : {
1156 : sal_uInt16 nWhichId;
1157 277 : switch( nScript )
1158 : {
1159 : case CSS1_OUTMODE_CJK:
1160 0 : nWhichId = RES_CHRATR_CJK_LANGUAGE;
1161 0 : break;
1162 : case CSS1_OUTMODE_CTL:
1163 0 : nWhichId = RES_CHRATR_CJK_LANGUAGE;
1164 0 : break;
1165 : default:
1166 277 : nWhichId = RES_CHRATR_LANGUAGE;
1167 277 : break;
1168 : }
1169 277 : return nWhichId;
1170 : }
1171 :
1172 261 : void SwHTMLWriter::OutLanguage( LanguageType nLang )
1173 : {
1174 261 : if( LANGUAGE_DONTKNOW != nLang )
1175 : {
1176 261 : OStringBuffer sOut;
1177 261 : sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_lang)
1178 261 : .append("=\"");
1179 261 : Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
1180 261 : HTMLOutFuncs::Out_String( Strm(), LanguageTag::convertToBcp47(nLang),
1181 522 : eDestEnc, &aNonConvertableCharacters ).WriteChar( '"' );
1182 : }
1183 261 : }
1184 :
1185 6 : sal_uInt16 SwHTMLWriter::GetHTMLDirection( const SfxItemSet& rItemSet ) const
1186 : {
1187 : return GetHTMLDirection(
1188 6 : static_cast < const SvxFrameDirectionItem& >( rItemSet.Get( RES_FRAMEDIR ) )
1189 6 : .GetValue() );
1190 : }
1191 :
1192 272 : sal_uInt16 SwHTMLWriter::GetHTMLDirection( sal_uInt16 nDir ) const
1193 : {
1194 272 : switch( nDir )
1195 : {
1196 : case FRMDIR_VERT_TOP_LEFT:
1197 0 : nDir = FRMDIR_HORI_LEFT_TOP;
1198 0 : break;
1199 : case FRMDIR_VERT_TOP_RIGHT:
1200 0 : nDir = FRMDIR_HORI_RIGHT_TOP;
1201 0 : break;
1202 : case FRMDIR_ENVIRONMENT:
1203 2 : nDir = nDirection;
1204 : }
1205 :
1206 272 : return nDir;
1207 : }
1208 :
1209 5 : void SwHTMLWriter::OutDirection( sal_uInt16 nDir )
1210 : {
1211 5 : const sal_Char *pValue = 0;
1212 5 : switch( nDir )
1213 : {
1214 : case FRMDIR_HORI_LEFT_TOP:
1215 : case FRMDIR_VERT_TOP_LEFT:
1216 5 : pValue = "ltr";
1217 5 : break;
1218 : case FRMDIR_HORI_RIGHT_TOP:
1219 : case FRMDIR_VERT_TOP_RIGHT:
1220 0 : pValue = "rtl";
1221 0 : break;
1222 : }
1223 5 : if( pValue != 0 )
1224 : {
1225 5 : OStringBuffer sOut;
1226 5 : sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_dir)
1227 5 : .append("=\"").append(pValue).append('\"');
1228 5 : Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
1229 : }
1230 5 : }
1231 :
1232 5 : OString SwHTMLWriter::GetIndentString(sal_uInt16 nIncLvl)
1233 : {
1234 5 : OString sRet;
1235 :
1236 : // etwas umstaendlich, aber wir haben nur einen Indent-String!
1237 5 : sal_uInt16 nLevel = nIndentLvl + nIncLvl;
1238 :
1239 5 : if( nLevel && nLevel <= MAX_INDENT_LEVEL)
1240 : {
1241 5 : sIndentTabs[nLevel] = 0;
1242 5 : sRet = sIndentTabs;
1243 5 : sIndentTabs[nLevel] = '\t';
1244 : }
1245 :
1246 5 : return sRet;
1247 : }
1248 :
1249 1213 : void SwHTMLWriter::OutNewLine( sal_Bool bCheck )
1250 : {
1251 1213 : if( !bCheck || (Strm().Tell()-nLastLFPos) > nIndentLvl )
1252 : {
1253 1213 : Strm().WriteCharPtr( SAL_NEWLINE_STRING );
1254 1213 : nLastLFPos = Strm().Tell();
1255 : }
1256 :
1257 1213 : if( nIndentLvl && nIndentLvl <= MAX_INDENT_LEVEL)
1258 : {
1259 1173 : sIndentTabs[nIndentLvl] = 0;
1260 1173 : Strm().WriteCharPtr( sIndentTabs );
1261 1173 : sIndentTabs[nIndentLvl] = '\t';
1262 : }
1263 1213 : }
1264 :
1265 5 : sal_uInt16 SwHTMLWriter::GetHTMLFontSize( sal_uInt32 nHeight ) const
1266 : {
1267 5 : sal_uInt16 nSize = 1;
1268 20 : for( sal_uInt16 i=6; i>0; i-- )
1269 : {
1270 20 : if( nHeight > (aFontHeights[i] + aFontHeights[i-1])/2 )
1271 : {
1272 5 : nSize = i+1;
1273 5 : break;
1274 : }
1275 : }
1276 :
1277 5 : return nSize;
1278 : }
1279 :
1280 : // Struktur speichert die aktuellen Daten des Writers zwischen, um
1281 : // einen anderen Dokument-Teil auszugeben, wie z.B. Header/Footer
1282 260 : HTMLSaveData::HTMLSaveData(SwHTMLWriter& rWriter, sal_uLong nStt,
1283 : sal_uLong nEnd, sal_Bool bSaveNum,
1284 : const SwFrmFmt *pFrmFmt)
1285 : : rWrt(rWriter)
1286 : , pOldPam(rWrt.pCurPam)
1287 260 : , pOldEnd(rWrt.GetEndPaM())
1288 : , pOldNumRuleInfo(0)
1289 : , pOldNextNumRuleInfo(0)
1290 : , nOldDefListLvl(rWrt.nDefListLvl)
1291 : , nOldDirection(rWrt.nDirection)
1292 : , bOldOutHeader(rWrt.bOutHeader)
1293 : , bOldOutFooter(rWrt.bOutFooter)
1294 : , bOldOutFlyFrame(rWrt.bOutFlyFrame)
1295 520 : , pOldFlyFmt(NULL)
1296 : {
1297 260 : bOldWriteAll = rWrt.bWriteAll;
1298 :
1299 260 : rWrt.pCurPam = rWrt.NewSwPaM( *rWrt.pDoc, nStt, nEnd );
1300 :
1301 : // Tabelle in Sonderbereichen erkennen
1302 260 : if( nStt != rWrt.pCurPam->GetMark()->nNode.GetIndex() )
1303 : {
1304 0 : const SwNode *pNd = rWrt.pDoc->GetNodes()[ nStt ];
1305 0 : if( pNd->IsTableNode() || pNd->IsSectionNode() )
1306 0 : rWrt.pCurPam->GetMark()->nNode = nStt;
1307 : }
1308 :
1309 260 : rWrt.SetEndPaM( rWrt.pCurPam );
1310 260 : rWrt.pCurPam->Exchange( );
1311 260 : rWrt.bWriteAll = sal_True;
1312 260 : rWrt.nDefListLvl = 0;
1313 260 : rWrt.bOutHeader = rWrt.bOutFooter = sal_False;
1314 :
1315 : // Ggf. die aktuelle Numerierungs-Info merken, damit sie wieder
1316 : // neu aufgenommen werden kann. Nur dann belibt auch die Numerierungs-
1317 : // Info des nachsten Absatz gueltig.
1318 260 : if( bSaveNum )
1319 : {
1320 260 : pOldNumRuleInfo = new SwHTMLNumRuleInfo( rWrt.GetNumInfo() );
1321 260 : pOldNextNumRuleInfo = rWrt.GetNextNumInfo();
1322 260 : rWrt.SetNextNumInfo( 0 );
1323 : }
1324 : else
1325 : {
1326 0 : rWrt.ClearNextNumInfo();
1327 : }
1328 :
1329 : // Die Numerierung wird in jedem Fall unterbrochen.
1330 260 : rWrt.GetNumInfo().Clear();
1331 :
1332 260 : if( pFrmFmt )
1333 0 : rWrt.nDirection = rWrt.GetHTMLDirection( pFrmFmt->GetAttrSet() );
1334 260 : }
1335 :
1336 260 : HTMLSaveData::~HTMLSaveData()
1337 : {
1338 260 : delete rWrt.pCurPam; // Pam wieder loeschen
1339 :
1340 260 : rWrt.pCurPam = pOldPam;
1341 260 : rWrt.SetEndPaM( pOldEnd );
1342 260 : rWrt.bWriteAll = bOldWriteAll;
1343 260 : rWrt.nBkmkTabPos = bOldWriteAll ? rWrt.FindPos_Bkmk( *pOldPam->GetPoint() ) : -1;
1344 260 : rWrt.nLastParaToken = 0;
1345 260 : rWrt.nDefListLvl = nOldDefListLvl;
1346 260 : rWrt.nDirection = nOldDirection;
1347 260 : rWrt.bOutHeader = bOldOutHeader;
1348 260 : rWrt.bOutFooter = bOldOutFooter;
1349 260 : rWrt.bOutFlyFrame = bOldOutFlyFrame;
1350 :
1351 : // Ggf. die Numerierung von vor der Section fortsetzen. Die Numerierung
1352 : // des naecshten Absatz wird in jedem Fall ungueltig.
1353 260 : if( pOldNumRuleInfo )
1354 : {
1355 260 : rWrt.GetNumInfo().Set( *pOldNumRuleInfo );
1356 260 : delete pOldNumRuleInfo;
1357 260 : rWrt.SetNextNumInfo( pOldNextNumRuleInfo );
1358 : }
1359 : else
1360 : {
1361 0 : rWrt.GetNumInfo().Clear();
1362 0 : rWrt.ClearNextNumInfo();
1363 : }
1364 260 : }
1365 :
1366 5 : void GetHTMLWriter( const OUString&, const OUString& rBaseURL, WriterRef& xRet )
1367 : {
1368 5 : xRet = new SwHTMLWriter( rBaseURL );
1369 5 : }
1370 :
1371 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|