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