xref: /AOO41X/main/sw/source/filter/html/wrthtml.cxx (revision dec99bbd1eb6ae693d6ee672c1a69e3a32d917e7)
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 = "&#255;";
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