| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| |
| #include <stdlib.h> |
| #include <hintids.hxx> |
| #include <svl/urihelper.hxx> |
| #include <rtl/tencinfo.h> |
| #include <vcl/wrkwin.hxx> |
| #include <sfx2/linkmgr.hxx> |
| |
| #include <svtools/htmlcfg.hxx> |
| #include <vcl/svapp.hxx> |
| #include <i18npool/mslangid.hxx> |
| #include <sfx2/frmhtmlw.hxx> |
| #include <svx/xoutbmp.hxx> |
| #include <svx/htmlmode.hxx> |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/brshitem.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <editeng/scripttypeitem.hxx> |
| #include <editeng/langitem.hxx> |
| #include <svl/stritem.hxx> |
| #include <editeng/frmdiritem.hxx> |
| |
| #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> |
| #include <com/sun/star/document/XDocumentProperties.hpp> |
| #include <com/sun/star/form/XFormsSupplier.hpp> |
| #include <com/sun/star/form/XForm.hpp> |
| #include <com/sun/star/form/XImageProducerSupplier.hpp> |
| #include <com/sun/star/form/XFormController.hpp> |
| #include <com/sun/star/container/XContainer.hpp> |
| #include <com/sun/star/container/XIndexContainer.hpp> |
| #include <com/sun/star/container/XSet.hpp> |
| #include <fmthdft.hxx> |
| #include <fmtfld.hxx> |
| #include <fmtpdsc.hxx> |
| #include <txatbase.hxx> |
| #include <frmatr.hxx> |
| #include <charfmt.hxx> |
| #include <docary.hxx> |
| #include <pam.hxx> |
| #include <doc.hxx> |
| #include <ndtxt.hxx> |
| #include <mdiexp.hxx> // ...Percent() |
| #include <fltini.hxx> |
| #include <viewopt.hxx> |
| #include <IMark.hxx> // fuer SwBookmark ... |
| #include <poolfmt.hxx> |
| #include <pagedesc.hxx> |
| #include <section.hxx> |
| #include <swtable.hxx> |
| #include <fldbas.hxx> |
| #include <fmtclds.hxx> |
| #ifndef _DOCSH_HXX |
| #include <docsh.hxx> |
| #endif |
| #include <wrthtml.hxx> |
| #include <htmlnum.hxx> |
| #include <htmlfly.hxx> |
| #include <swmodule.hxx> |
| |
| #ifndef _STATSTR_HRC |
| #include <statstr.hrc> // ResId fuer Statusleiste |
| #endif |
| #include <swerror.h> |
| |
| #define MAX_INDENT_LEVEL 20 |
| |
| #if defined(UNX) |
| const sal_Char SwHTMLWriter::sNewLine = '\012'; |
| #else |
| const sal_Char __FAR_DATA SwHTMLWriter::sNewLine[] = "\015\012"; |
| #endif |
| |
| static sal_Char __FAR_DATA sIndentTabs[MAX_INDENT_LEVEL+2] = |
| "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; |
| |
| SwHTMLWriter::SwHTMLWriter( const String& rBaseURL ) |
| { |
| SetBaseURL( rBaseURL ); |
| bFirstLine = sal_True; |
| nBkmkTabPos = -1; |
| pDfltColor = 0; |
| nImgMapCnt = 1; |
| pStartNdIdx = 0; |
| pTemplate = 0; |
| pNumRuleInfo = new SwHTMLNumRuleInfo; |
| pNextNumRuleInfo = 0; |
| pFootEndNotes = 0; |
| pFmtFtn = 0; |
| eDestEnc = RTL_TEXTENCODING_MS_1252; |
| nDirection = FRMDIR_HORI_LEFT_TOP; |
| } |
| |
| |
| __EXPORT SwHTMLWriter::~SwHTMLWriter() |
| { |
| delete pNumRuleInfo; |
| } |
| |
| sal_uLong SwHTMLWriter::WriteStream() |
| { |
| // neue Konfiguration setzen |
| SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get(); |
| |
| // die Fontgroessen 1-7 |
| aFontHeights[0] = pHtmlOptions->GetFontSize( 0 ) * 20; |
| aFontHeights[1] = pHtmlOptions->GetFontSize( 1 ) * 20; |
| aFontHeights[2] = pHtmlOptions->GetFontSize( 2 ) * 20; |
| aFontHeights[3] = pHtmlOptions->GetFontSize( 3 ) * 20; |
| aFontHeights[4] = pHtmlOptions->GetFontSize( 4 ) * 20; |
| aFontHeights[5] = pHtmlOptions->GetFontSize( 5 ) * 20; |
| aFontHeights[6] = pHtmlOptions->GetFontSize( 6 ) * 20; |
| |
| // ueberhaupt Styles ausgeben |
| // (dann auch obere und untere Absatz-Abstaende) |
| nExportMode = pHtmlOptions->GetExportMode(); |
| nHTMLMode = GetHtmlMode(0); |
| if( HTML_CFG_WRITER==nExportMode || |
| HTML_CFG_NS40==nExportMode ) |
| nHTMLMode |= HTMLMODE_BLOCK_SPACER; |
| |
| if( HTML_CFG_WRITER==nExportMode || HTML_CFG_MSIE==nExportMode ) |
| nHTMLMode |= (HTMLMODE_FLOAT_FRAME | HTMLMODE_LSPACE_IN_NUMBUL); |
| |
| if( HTML_CFG_MSIE==nExportMode ) |
| nHTMLMode |= HTMLMODE_NBSP_IN_TABLES; |
| |
| if( HTML_CFG_WRITER==nExportMode || HTML_CFG_NS40==nExportMode || |
| HTML_CFG_MSIE==nExportMode ) |
| nHTMLMode |= HTMLMODE_ABS_POS_FLY|HTMLMODE_ABS_POS_DRAW; |
| |
| if( HTML_CFG_WRITER==nExportMode ) |
| // nHTMLMode |= HTMLMODE_FLY_MARGINS | HTMLMODE_FRSTLINE_IN_NUMBUL; |
| nHTMLMode |= HTMLMODE_FLY_MARGINS; |
| |
| if( HTML_CFG_NS40==nExportMode ) |
| nHTMLMode |= HTMLMODE_BORDER_NONE; |
| |
| if( HTML_CFG_HTML32!=nExportMode ) |
| nHTMLMode |= HTMLMODE_FONT_GENERIC; |
| |
| if( HTML_CFG_NS40==nExportMode ) |
| nHTMLMode |= HTMLMODE_NO_CONTROL_CENTERING; |
| |
| bCfgOutStyles = IsHTMLMode(HTMLMODE_SOME_STYLES | |
| HTMLMODE_FULL_STYLES); |
| bCfgNetscape4 = (HTML_CFG_NS40==nExportMode); |
| |
| if( IsHTMLMode(HTMLMODE_SOME_STYLES | HTMLMODE_FULL_STYLES) ) |
| nHTMLMode |= HTMLMODE_PRINT_EXT; |
| |
| const sal_Char *pHelpHack = getenv( "HelpEx" ); |
| if( pHelpHack ) |
| { |
| ByteString aTmp( pHelpHack ); |
| if( aTmp.EqualsIgnoreCaseAscii( "Hilfe" ) ) |
| nHTMLMode |= HTMLMODE_NO_BR_AT_PAREND; |
| } |
| |
| eCSS1Unit = (FieldUnit)SW_MOD()->GetMetric( pDoc->get(IDocumentSettingAccess::HTML_MODE) ); |
| |
| sal_Bool bWriteUTF8 = bWriteClipboardDoc; |
| eDestEnc = bWriteUTF8 ? RTL_TEXTENCODING_UTF8 |
| : pHtmlOptions->GetTextEncoding(); |
| const sal_Char *pCharSet = |
| rtl_getBestMimeCharsetFromTextEncoding( eDestEnc ); |
| eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet ); |
| |
| // fuer Netscape optimieren heisst Spacer- und Multicol ausgeben |
| // bCfgMultiCol = pHtmlOptions->IsNetscape3(); |
| // bCfgSpacer = pHtmlOptions->IsNetscape3(); |
| |
| // wenn Styles exportiert werden, wird ein Style einem HTML-Tag manchmal |
| // vorgezogen, wenn nicht fuer Netscape exportiert wird |
| // bCfgPreferStyles = bCfgOutStyles; // && !pHtmlOptions->IsNetscape3(); |
| |
| // Nur noch fuer den MS-IE ziehen wir den Export von Styles vor. |
| bCfgPreferStyles = HTML_CFG_MSIE==nExportMode; |
| |
| bCfgStarBasic = pHtmlOptions->IsStarBasic(); |
| |
| bCfgFormFeed = !IsHTMLMode(HTMLMODE_PRINT_EXT); |
| bCfgCpyLinkedGrfs = pHtmlOptions->IsSaveGraphicsLocal(); |
| |
| // die HTML-Vorlage holen |
| sal_Bool bOldHTMLMode = sal_False; |
| sal_uInt16 nOldTxtFmtCollCnt = 0, nOldCharFmtCnt = 0; |
| |
| ASSERT( !pTemplate, "Wo kommt denn die HTML-Vorlage hier her?" ); |
| pTemplate = ((HTMLReader*)ReadHTML)->GetTemplateDoc(); |
| if( pTemplate ) |
| { |
| pTemplate->acquire(); |
| bOldHTMLMode = pTemplate->get(IDocumentSettingAccess::HTML_MODE); |
| pTemplate->set(IDocumentSettingAccess::HTML_MODE, true); |
| |
| nOldTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->Count(); |
| nOldCharFmtCnt = pTemplate->GetCharFmts()->Count(); |
| } |
| |
| if( bShowProgress ) |
| ::StartProgress( STR_STATSTR_W4WWRITE, 0, pDoc->GetNodes().Count(), |
| pDoc->GetDocShell()); |
| |
| pDfltColor = 0; |
| pFootEndNotes = 0; |
| pFmtFtn = 0; |
| bOutTable = bOutHeader = bOutFooter = bOutFlyFrame = sal_False; |
| pxFormComps = 0; |
| nFormCntrlCnt = 0; |
| bPreserveForm = sal_False; |
| bClearLeft = bClearRight = sal_False; |
| bLFPossible = sal_False; |
| |
| nLeftMargin = nDfltLeftMargin = nDfltRightMargin = 0; |
| nDfltTopMargin = nDfltBottomMargin = 0; |
| nFirstLineIndent = nDfltFirstLineIndent = 0; |
| bPoolCollTextModified = sal_False; |
| bFirstCSS1Property = bFirstCSS1Rule = sal_False; |
| bCSS1IgnoreFirstPageDesc = sal_False; |
| nIndentLvl = 0; |
| nWhishLineLen = 70; |
| nLastLFPos = 0; |
| nDefListLvl = 0; |
| nDefListMargin = ((pTemplate && !bCfgOutStyles) ? pTemplate : pDoc) |
| ->GetTxtCollFromPool( RES_POOLCOLL_HTML_DD, false ) |
| ->GetLRSpace().GetTxtLeft(); |
| nHeaderFooterSpace = 0; |
| nTxtAttrsToIgnore = 0; |
| nCSS1OutMode = 0; |
| sal_uInt16 nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( |
| static_cast< LanguageType >( GetAppLanguage() ) ); |
| switch( nScript ) |
| { |
| case SCRIPTTYPE_ASIAN: |
| nCSS1Script = CSS1_OUTMODE_CJK; |
| break; |
| case SCRIPTTYPE_COMPLEX: |
| nCSS1Script = CSS1_OUTMODE_CTL; |
| break; |
| default: |
| nCSS1Script = CSS1_OUTMODE_WESTERN; |
| break; |
| } |
| eLang = ((const SvxLanguageItem&)pDoc |
| ->GetDefault(GetLangWhichIdFromScript(nCSS1Script))).GetLanguage(); |
| |
| nFootNote = nEndNote = 0; |
| |
| nWarn = 0; |
| GetNumInfo().Clear(); |
| pNextNumRuleInfo = 0; |
| |
| ByteString aStartTags; |
| |
| // Tabellen und Bereiche am Doc.-Anfang beachten |
| { |
| SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode(); |
| if( pTNd && bWriteAll ) |
| { |
| // mit dem Tabellen-Node anfangen !! |
| pCurPam->GetPoint()->nNode = *pTNd; |
| |
| if( bWriteOnlyFirstTable ) |
| pCurPam->GetMark()->nNode = *pTNd->EndOfSectionNode(); |
| } |
| |
| // erster Node (der einen Seitenumbruch enthalten darf) |
| pStartNdIdx = new SwNodeIndex( pCurPam->GetPoint()->nNode ); |
| |
| SwSectionNode * pSNd = pCurPam->GetNode()->FindSectionNode(); |
| while( pSNd ) |
| { |
| if( bWriteAll ) |
| { |
| // mit dem Section-Node anfangen !! |
| pCurPam->GetPoint()->nNode = *pSNd; |
| } |
| else |
| { |
| ASSERT( FILE_LINK_SECTION != pSNd->GetSection().GetType(), |
| "Export gelinkter Bereiche am Dok-Anfang ist nicht implemntiert" ); |
| |
| // nur das Tag fuer die Section merken |
| ByteString aName; |
| HTMLOutFuncs::ConvertStringToHTML( |
| pSNd->GetSection().GetSectionName(), |
| aName, eDestEnc, &aNonConvertableCharacters ); |
| |
| ByteString sOut( '<' ); |
| (((((((sOut += OOO_STRING_SVTOOLS_HTML_division) |
| += ' ') += OOO_STRING_SVTOOLS_HTML_O_id) += "=\"") |
| += aName) += '\"') |
| += '>') += aStartTags; |
| |
| aStartTags = sOut; |
| } |
| // FindSectionNode() an einem SectionNode liefert den selben! |
| pSNd = pSNd->StartOfSectionNode()->FindSectionNode(); |
| } |
| } |
| |
| |
| // Tabelle fuer die freifliegenden Rahmen erzeugen, aber nur wenn |
| // das gesamte Dokument geschrieben wird |
| pHTMLPosFlyFrms = 0; |
| CollectFlyFrms(); |
| nLastParaToken = 0; |
| GetControls(); |
| CollectLinkTargets(); |
| |
| sal_uInt16 nHeaderAttrs = 0; |
| pCurrPageDesc = MakeHeader( nHeaderAttrs ); |
| |
| bLFPossible = sal_True; |
| |
| // Formulare, die nur HiddenControls enthalten ausgeben. |
| OutHiddenForms(); |
| |
| if( aStartTags.Len() ) |
| Strm() << aStartTags.GetBuffer(); |
| |
| const SfxPoolItem *pItem; |
| const SfxItemSet& rPageItemSet = pCurrPageDesc->GetMaster().GetAttrSet(); |
| if( !bWriteClipboardDoc && pDoc->GetDocShell() && |
| (!pDoc->get(IDocumentSettingAccess::HTML_MODE) && |
| !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) && |
| SFX_ITEM_SET == rPageItemSet.GetItemState( RES_HEADER, sal_True, &pItem) ) |
| { |
| const SwFrmFmt *pHeaderFmt = |
| ((const SwFmtHeader *)pItem)->GetHeaderFmt(); |
| if( pHeaderFmt ) |
| OutHTML_HeaderFooter( *this, *pHeaderFmt, sal_True ); |
| } |
| |
| nTxtAttrsToIgnore = nHeaderAttrs; |
| Out_SwDoc( pOrigPam ); |
| nTxtAttrsToIgnore = 0; |
| |
| if( pxFormComps && pxFormComps->is() ) |
| OutForm( sal_False, *pxFormComps ); |
| |
| if( pFootEndNotes ) |
| OutFootEndNotes(); |
| |
| if( !bWriteClipboardDoc && pDoc->GetDocShell() && |
| (!pDoc->get(IDocumentSettingAccess::HTML_MODE) && !pDoc->get(IDocumentSettingAccess::BROWSE_MODE)) && |
| SFX_ITEM_SET == rPageItemSet.GetItemState( RES_FOOTER, sal_True, &pItem) ) |
| { |
| const SwFrmFmt *pFooterFmt = |
| ((const SwFmtFooter *)pItem)->GetFooterFmt(); |
| if( pFooterFmt ) |
| OutHTML_HeaderFooter( *this, *pFooterFmt, sal_False ); |
| } |
| |
| if( bLFPossible ) |
| OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body, sal_False ); |
| OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html, sal_False ); |
| |
| // loesche die Tabelle mit den freifliegenden Rahmen |
| sal_uInt16 i; |
| ASSERT( !pHTMLPosFlyFrms, "Wurden nicht alle Rahmen ausgegeben" ); |
| if( pHTMLPosFlyFrms ) |
| { |
| pHTMLPosFlyFrms->DeleteAndDestroy( 0, pHTMLPosFlyFrms->Count() ); |
| delete pHTMLPosFlyFrms; |
| pHTMLPosFlyFrms = 0; |
| } |
| |
| if( aHTMLControls.Count() ) |
| aHTMLControls.DeleteAndDestroy( sal_uInt16(0), aHTMLControls.Count() ); |
| |
| if( aChrFmtInfos.Count() ) |
| aChrFmtInfos.DeleteAndDestroy( sal_uInt16(0), aChrFmtInfos.Count() ); |
| |
| if( aTxtCollInfos.Count() ) |
| aTxtCollInfos.DeleteAndDestroy( sal_uInt16(0), aTxtCollInfos.Count() ); |
| |
| if( aImgMapNames.Count() ) |
| aImgMapNames.DeleteAndDestroy( sal_uInt16(0), aImgMapNames.Count() ); |
| |
| if( aImplicitMarks.Count() ) |
| aImplicitMarks.DeleteAndDestroy( sal_uInt16(0), aImplicitMarks.Count() ); |
| |
| if( aOutlineMarks.Count() ) |
| aOutlineMarks.DeleteAndDestroy( sal_uInt16(0), aOutlineMarks.Count() ); |
| |
| if( aOutlineMarkPoss.Count() ) |
| aOutlineMarkPoss.Remove( sal_uInt16(0), aOutlineMarkPoss.Count() ); |
| |
| if( aNumRuleNames.Count() ) |
| aNumRuleNames.DeleteAndDestroy( sal_uInt16(0), aNumRuleNames.Count() ); |
| |
| if( aScriptParaStyles.Count() ) |
| aScriptParaStyles.DeleteAndDestroy( sal_uInt16(0), aScriptParaStyles.Count() ); |
| if( aScriptTextStyles.Count() ) |
| aScriptTextStyles.DeleteAndDestroy( sal_uInt16(0), aScriptTextStyles.Count() ); |
| |
| delete pDfltColor; |
| pDfltColor = 0; |
| |
| delete pStartNdIdx; |
| pStartNdIdx = 0; |
| |
| delete pxFormComps; |
| pxFormComps = 0; |
| |
| ASSERT( !pFootEndNotes, |
| "SwHTMLWriter::Write: Ftns nicht durch OutFootEndNotes geloescht" ); |
| |
| pCurrPageDesc = 0; |
| |
| ClearNextNumInfo(); |
| |
| for( i=0; i<MAXLEVEL; i++ ) |
| aBulletGrfs[i].Erase(); |
| |
| aNonConvertableCharacters.Erase(); |
| |
| if( bShowProgress ) |
| ::EndProgress( pDoc->GetDocShell() ); |
| |
| if( pTemplate ) |
| { |
| // Waehrend des Exports angelegte Zeichen- und Abastzvorlagen |
| // loeschen |
| sal_uInt16 nTxtFmtCollCnt = pTemplate->GetTxtFmtColls()->Count(); |
| while( nTxtFmtCollCnt > nOldTxtFmtCollCnt ) |
| pTemplate->DelTxtFmtColl( --nTxtFmtCollCnt ); |
| ASSERT( pTemplate->GetTxtFmtColls()->Count() == nOldTxtFmtCollCnt, |
| "falsche Anzahl TxtFmtColls geloescht" ); |
| |
| sal_uInt16 nCharFmtCnt = pTemplate->GetCharFmts()->Count(); |
| while( nCharFmtCnt > nOldCharFmtCnt ) |
| pTemplate->DelCharFmt( --nCharFmtCnt ); |
| ASSERT( pTemplate->GetCharFmts()->Count() == nOldCharFmtCnt, |
| "falsche Anzahl CharFmts geloescht" ); |
| |
| // HTML-Modus wieder restaurieren |
| pTemplate->set(IDocumentSettingAccess::HTML_MODE, bOldHTMLMode); |
| |
| if( 0 == pTemplate->release() ) |
| delete pTemplate; |
| |
| pTemplate = 0; |
| } |
| |
| return nWarn; |
| } |
| |
| const SwFmtCol *lcl_html_GetFmtCol( const SwHTMLWriter& rHTMLWrt, |
| const SwSection& rSection, |
| const SwSectionFmt& rFmt ) |
| { |
| const SwFmtCol *pCol = 0; |
| |
| const SfxPoolItem* pItem; |
| if( rHTMLWrt.IsHTMLMode( HTMLMODE_FRM_COLUMNS ) && |
| FILE_LINK_SECTION != rSection.GetType() && |
| SFX_ITEM_SET == rFmt.GetAttrSet().GetItemState(RES_COL,sal_False,&pItem) && |
| ((const SwFmtCol *)pItem)->GetNumCols() > 1 ) |
| { |
| pCol = (const SwFmtCol *)pItem; |
| } |
| |
| return pCol; |
| } |
| |
| sal_Bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex ) |
| { |
| sal_Bool bRet = sal_False; |
| const SwSectionNode *pSectNd = |
| rHTMLWrt.pDoc->GetNodes()[nIndex]->GetSectionNode(); |
| if( pSectNd ) |
| { |
| const SwSection& rSection = pSectNd->GetSection(); |
| const SwSectionFmt *pFmt = rSection.GetFmt(); |
| if( pFmt && lcl_html_GetFmtCol( rHTMLWrt, rSection, *pFmt ) ) |
| bRet = sal_True; |
| } |
| |
| return bRet; |
| } |
| |
| sal_Bool lcl_html_IsMultiColEnd( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex ) |
| { |
| sal_Bool bRet = sal_False; |
| const SwEndNode *pEndNd = rHTMLWrt.pDoc->GetNodes()[nIndex]->GetEndNode(); |
| if( pEndNd ) |
| bRet = lcl_html_IsMultiColStart( rHTMLWrt, |
| pEndNd->StartOfSectionIndex() ); |
| |
| return bRet; |
| } |
| |
| |
| void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt, |
| const SwSection& rSection, |
| const SwSectionFmt& rFmt, |
| const SwFmtCol *pCol, |
| sal_Bool bContinued=sal_False ) |
| { |
| ASSERT( pCol || !bContinued, "Continuation of DIV" ); |
| |
| if( rHTMLWrt.bLFPossible ) |
| rHTMLWrt.OutNewLine(); |
| |
| const sal_Char *pTag = pCol ? OOO_STRING_SVTOOLS_HTML_multicol : OOO_STRING_SVTOOLS_HTML_division; |
| |
| ByteString sOut( '<' ); |
| sOut += pTag; |
| |
| const String& rName = rSection.GetSectionName(); |
| if( rName.Len() && !bContinued ) |
| { |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_id) += "=\""; |
| rHTMLWrt.Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), rName, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); |
| sOut = '\"'; |
| } |
| |
| sal_uInt16 nDir = rHTMLWrt.GetHTMLDirection( rFmt.GetAttrSet() ); |
| rHTMLWrt.Strm() << sOut.GetBuffer(); |
| sOut.Erase(); |
| rHTMLWrt.OutDirection( nDir ); |
| |
| if( FILE_LINK_SECTION == rSection.GetType() ) |
| { |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\""; |
| rHTMLWrt.Strm() << sOut.GetBuffer(); |
| |
| const String& aFName = rSection.GetLinkFileName(); |
| String aURL( aFName.GetToken(0,sfx2::cTokenSeperator) ); |
| String aFilter( aFName.GetToken(1,sfx2::cTokenSeperator) ); |
| String aSection( aFName.GetToken(2,sfx2::cTokenSeperator) ); |
| |
| String aEncURL( URIHelper::simpleNormalizedMakeRelative(rHTMLWrt.GetBaseURL(), aURL ) ); |
| sal_Unicode cDelim = 255U; |
| sal_Bool bURLContainsDelim = |
| (STRING_NOTFOUND != aEncURL.Search( cDelim ) ); |
| |
| HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aEncURL, |
| rHTMLWrt.eDestEnc, |
| &rHTMLWrt.aNonConvertableCharacters ); |
| const sal_Char *pDelim = "ÿ"; |
| if( aFilter.Len() || aSection.Len() || bURLContainsDelim ) |
| rHTMLWrt.Strm() << pDelim; |
| if( aFilter.Len() ) |
| HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aFilter, |
| rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); |
| if( aSection.Len() || bURLContainsDelim ) |
| rHTMLWrt.Strm() << pDelim; |
| if( aSection.Len() ) |
| { |
| xub_StrLen nPos = aSection.Search( '%' ); |
| while( STRING_NOTFOUND != nPos ) |
| { |
| aSection.Erase( nPos, 1 ); |
| aSection.InsertAscii( "%25", nPos ); |
| nPos = aSection.Search( '%', nPos+3 ); |
| } |
| nPos = aSection.Search( cDelim ); |
| while( STRING_NOTFOUND != nPos ) |
| { |
| aSection.Erase( nPos, 1 ); |
| aSection.InsertAscii( "%FF", nPos ); |
| nPos = aSection.Search( cDelim, nPos+3 ); |
| } |
| HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aSection, |
| rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); |
| } |
| sOut = '\"'; |
| } |
| else if( pCol ) |
| { |
| (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=') |
| += ByteString::CreateFromInt32( pCol->GetNumCols() ); |
| |
| // minumum gutter width |
| sal_uInt16 nGutter = pCol->GetGutterWidth( sal_True ); |
| if( nGutter!=USHRT_MAX ) |
| { |
| if( nGutter && Application::GetDefaultDevice() ) |
| { |
| nGutter = (sal_uInt16)Application::GetDefaultDevice() |
| ->LogicToPixel( Size(nGutter,0), |
| MapMode(MAP_TWIP) ).Width(); |
| } |
| (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_gutter) += '=') |
| += ByteString::CreateFromInt32( nGutter ); |
| } |
| } |
| |
| rHTMLWrt.Strm() << sOut.GetBuffer(); |
| if( rHTMLWrt.IsHTMLMode( rHTMLWrt.bCfgOutStyles ) ) |
| rHTMLWrt.OutCSS1_SectionFmtOptions( rFmt ); |
| |
| rHTMLWrt.Strm() << '>'; |
| |
| rHTMLWrt.bLFPossible = sal_True; |
| if( rName.Len() && !bContinued ) |
| rHTMLWrt.OutImplicitMark( rName, pMarkToRegion ); |
| |
| rHTMLWrt.IncIndentLevel(); |
| } |
| |
| void lcl_html_OutSectionEndTag( SwHTMLWriter& rHTMLWrt, |
| const SwFmtCol *pCol ) |
| { |
| const sal_Char *pTag = pCol ? OOO_STRING_SVTOOLS_HTML_multicol : OOO_STRING_SVTOOLS_HTML_division; |
| |
| rHTMLWrt.DecIndentLevel(); |
| if( rHTMLWrt.bLFPossible ) |
| rHTMLWrt.OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), pTag, sal_False ); |
| rHTMLWrt.bLFPossible = sal_True; |
| } |
| |
| static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| |
| // End <PRE> and any <DL>, because a definition list's level may |
| // change inside the section. |
| rHTMLWrt.ChangeParaToken( 0 ); |
| rHTMLWrt.OutAndSetDefList( 0 ); |
| |
| const SwSection& rSection = rSectNd.GetSection(); |
| const SwSectionFmt *pFmt = rSection.GetFmt(); |
| ASSERT( pFmt, "Section without a format?" ); |
| |
| sal_Bool bStartTag = sal_True; |
| sal_Bool bEndTag = sal_True; |
| const SwSectionFmt *pSurrFmt = 0; |
| const SwSectionNode *pSurrSectNd = 0; |
| const SwSection *pSurrSection = 0; |
| const SwFmtCol *pSurrCol = 0; |
| |
| sal_uInt32 nSectSttIdx = rSectNd.GetIndex(); |
| sal_uInt32 nSectEndIdx = rSectNd.EndOfSectionIndex(); |
| const SwFmtCol *pCol = lcl_html_GetFmtCol( rHTMLWrt, rSection, *pFmt ); |
| if( pCol ) |
| { |
| // If the next node is a columned section node, too, don't export |
| // an empty section. |
| if( lcl_html_IsMultiColStart( rHTMLWrt, nSectSttIdx+1 ) ) |
| bStartTag = sal_False; |
| |
| // The same applies if the section end with another columned section. |
| if( lcl_html_IsMultiColEnd( rHTMLWrt, nSectEndIdx-1 ) ) |
| bEndTag = sal_False; |
| |
| //.is there a columned section arround this one? |
| const SwStartNode *pSttNd = rSectNd.StartOfSectionNode(); |
| if( pSttNd ) |
| { |
| pSurrSectNd = pSttNd->FindSectionNode(); |
| if( pSurrSectNd ) |
| { |
| const SwStartNode *pBoxSttNd = pSttNd->FindTableBoxStartNode(); |
| if( !pBoxSttNd || |
| pBoxSttNd->GetIndex() < pSurrSectNd->GetIndex() ) |
| { |
| pSurrSection = &pSurrSectNd->GetSection(); |
| pSurrFmt = pSurrSection->GetFmt(); |
| if( pSurrFmt ) |
| pSurrCol = lcl_html_GetFmtCol( rHTMLWrt, *pSurrSection, |
| *pSurrFmt ); |
| } |
| } |
| } |
| } |
| |
| // The surrounding section must be closed before the current one is |
| // opended, except that it start immediatly before the current one or |
| // another end immediately before the current one |
| if( pSurrCol && nSectSttIdx - pSurrSectNd->GetIndex() > 1 && |
| !lcl_html_IsMultiColEnd( rHTMLWrt, nSectSttIdx-1 ) ) |
| lcl_html_OutSectionEndTag( rHTMLWrt, pSurrCol ); |
| |
| if( bStartTag ) |
| lcl_html_OutSectionStartTag( rHTMLWrt, rSection, *pFmt, pCol ); |
| |
| { |
| HTMLSaveData aSaveData( rHTMLWrt, |
| rHTMLWrt.pCurPam->GetPoint()->nNode.GetIndex()+1, |
| rSectNd.EndOfSectionIndex(), |
| sal_False, pFmt ); |
| rHTMLWrt.Out_SwDoc( rHTMLWrt.pCurPam ); |
| } |
| |
| rHTMLWrt.pCurPam->GetPoint()->nNode = *rSectNd.EndOfSectionNode(); |
| |
| if( bEndTag ) |
| lcl_html_OutSectionEndTag( rHTMLWrt, pCol ); |
| |
| // The surrounding section must be started again, except that it ends |
| // immeditaly behind the current one. |
| if( pSurrCol && |
| pSurrSectNd->EndOfSectionIndex() - nSectEndIdx > 1 && |
| !lcl_html_IsMultiColStart( rHTMLWrt, nSectEndIdx+1 ) ) |
| lcl_html_OutSectionStartTag( rHTMLWrt, *pSurrSection, *pSurrFmt, |
| pSurrCol, sal_True ); |
| |
| return rWrt; |
| } |
| |
| void SwHTMLWriter::Out_SwDoc( SwPaM* pPam ) |
| { |
| sal_Bool bSaveWriteAll = bWriteAll; // sichern |
| |
| // suche die naechste text::Bookmark-Position aus der text::Bookmark-Tabelle |
| nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1; |
| |
| // gebe alle Bereiche des Pams in das HTML-File aus. |
| do { |
| bWriteAll = bSaveWriteAll; |
| bFirstLine = sal_True; |
| |
| // suche den ersten am Pam-auszugebenen FlyFrame |
| // fehlt noch: |
| |
| while( pCurPam->GetPoint()->nNode.GetIndex() < pCurPam->GetMark()->nNode.GetIndex() || |
| (pCurPam->GetPoint()->nNode.GetIndex() == pCurPam->GetMark()->nNode.GetIndex() && |
| pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex()) ) |
| { |
| SwNode * pNd = pCurPam->GetNode(); |
| |
| ASSERT( !(pNd->IsGrfNode() || pNd->IsOLENode()), |
| "Grf- oder OLE-Node hier unerwartet" ); |
| if( pNd->IsTxtNode() ) |
| { |
| SwTxtNode* pTxtNd = pNd->GetTxtNode(); |
| |
| if( !bFirstLine ) |
| pCurPam->GetPoint()->nContent.Assign( pTxtNd, 0 ); |
| |
| OutHTML_SwTxtNode( *this, *pTxtNd ); |
| } |
| else if( pNd->IsTableNode() ) |
| { |
| OutHTML_SwTblNode( *this, *pNd->GetTableNode(), 0 ); |
| nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1; |
| } |
| else if( pNd->IsSectionNode() ) |
| { |
| OutHTML_Section( *this, *pNd->GetSectionNode() ); |
| nBkmkTabPos = bWriteAll ? FindPos_Bkmk( *pCurPam->GetPoint() ) : -1; |
| } |
| else if( pNd == &pDoc->GetNodes().GetEndOfContent() ) |
| break; |
| |
| pCurPam->GetPoint()->nNode++; // Bewegen |
| sal_uInt32 nPos = pCurPam->GetPoint()->nNode.GetIndex(); |
| |
| if( bShowProgress ) |
| ::SetProgressState( nPos, pDoc->GetDocShell() ); // Wie weit ? |
| |
| /* sollen nur die Selectierten Bereiche gesichert werden, so |
| * duerfen nur die vollstaendigen Nodes gespeichert werde, |
| * d.H. der 1. und n. Node teilweise, der 2. bis n-1. Node |
| * vollstaendig. (vollstaendig heisst mit allen Formaten! ) |
| */ |
| bWriteAll = bSaveWriteAll || |
| nPos != pCurPam->GetMark()->nNode.GetIndex(); |
| bFirstLine = sal_False; |
| bOutFooter = sal_False; // Nach einem Node keine Fusszeile mehr |
| } |
| |
| ChangeParaToken( 0 ); // MIB 8.7.97: Machen wir jetzt hier und nicht |
| // beim Aufrufer |
| OutAndSetDefList( 0 ); |
| |
| } while( CopyNextPam( &pPam ) ); // bis alle PaM's bearbeitet |
| |
| bWriteAll = bSaveWriteAll; // wieder auf alten Wert zurueck |
| } |
| |
| |
| // schreibe die StyleTabelle, algemeine Angaben,Header/Footer/Footnotes |
| static void OutBodyColor( const sal_Char *pTag, const SwFmt *pFmt, |
| SwHTMLWriter& rHWrt ) |
| { |
| const SwFmt *pRefFmt = 0; |
| |
| if( rHWrt.pTemplate ) |
| pRefFmt = SwHTMLWriter::GetTemplateFmt( pFmt->GetPoolFmtId(), |
| rHWrt.pTemplate ); |
| |
| const SvxColorItem *pColorItem = 0; |
| |
| const SfxItemSet& rItemSet = pFmt->GetAttrSet(); |
| const SfxPoolItem *pRefItem = 0, *pItem = 0; |
| sal_Bool bItemSet = SFX_ITEM_SET == rItemSet.GetItemState( RES_CHRATR_COLOR, |
| sal_True, &pItem); |
| sal_Bool bRefItemSet = pRefFmt && |
| SFX_ITEM_SET == pRefFmt->GetAttrSet().GetItemState( RES_CHRATR_COLOR, |
| sal_True, &pRefItem); |
| if( bItemSet ) |
| { |
| // wenn das Item nur in der Vorlage des aktuellen Doks gesetzt |
| // ist oder einen anderen Wert hat, als in der HTML-Vorlage, |
| // wird es gesetzt |
| const SvxColorItem *pCItem = (const SvxColorItem*)pItem; |
| |
| if( !bRefItemSet ) |
| { |
| pColorItem = pCItem; |
| } |
| else |
| { |
| Color aColor( pCItem->GetValue() ); |
| if( COL_AUTO == aColor.GetColor() ) |
| aColor.SetColor( COL_BLACK ); |
| |
| Color aRefColor( ((const SvxColorItem*)pRefItem)->GetValue() ); |
| if( COL_AUTO == aRefColor.GetColor() ) |
| aRefColor.SetColor( COL_BLACK ); |
| |
| if( !aColor.IsRGBEqual( aRefColor ) ) |
| pColorItem = pCItem; |
| } |
| } |
| else if( bRefItemSet ) |
| { |
| // Das Item war in der HTML-Vorlage noch gesetzt, also geben wir |
| // das Default aus |
| pColorItem = (const SvxColorItem*)&rItemSet.GetPool() |
| ->GetDefaultItem( RES_CHRATR_COLOR ); |
| } |
| |
| if( pColorItem ) |
| { |
| ByteString sOut( ' ' ); |
| (sOut += pTag) += '='; |
| rHWrt.Strm() << sOut.GetBuffer(); |
| Color aColor( pColorItem->GetValue() ); |
| if( COL_AUTO == aColor.GetColor() ) |
| aColor.SetColor( COL_BLACK ); |
| HTMLOutFuncs::Out_Color( rHWrt.Strm(), aColor, rHWrt.eDestEnc ); |
| if( RES_POOLCOLL_STANDARD==pFmt->GetPoolFmtId() ) |
| rHWrt.pDfltColor = new Color( aColor ); |
| } |
| } |
| |
| sal_uInt16 SwHTMLWriter::OutHeaderAttrs() |
| { |
| sal_uLong nIdx = pCurPam->GetPoint()->nNode.GetIndex(); |
| sal_uLong nEndIdx = pCurPam->GetMark()->nNode.GetIndex(); |
| |
| SwTxtNode *pTxtNd = 0; |
| while( nIdx<=nEndIdx && |
| 0==(pTxtNd=pDoc->GetNodes()[nIdx]->GetTxtNode()) ) |
| nIdx++; |
| |
| ASSERT( pTxtNd, "Kein Text-Node gefunden" ); |
| if( !pTxtNd || !pTxtNd->HasHints() ) |
| return 0; |
| |
| sal_uInt16 nAttrs = 0; |
| sal_uInt16 nCntAttr = pTxtNd->GetSwpHints().Count(); |
| xub_StrLen nOldPos = 0; |
| for( sal_uInt16 i=0; i<nCntAttr; i++ ) |
| { |
| const SwTxtAttr *pHt = pTxtNd->GetSwpHints()[i]; |
| if( !pHt->End() ) |
| { |
| xub_StrLen nPos = *pHt->GetStart(); |
| if( nPos-nOldPos > 1 |
| || ( pHt->Which() != RES_TXTATR_FIELD |
| && pHt->Which() != RES_TXTATR_ANNOTATION ) ) |
| break; |
| |
| const sal_uInt16 nFldWhich = |
| ((const SwFmtFld&)pHt->GetAttr()).GetField()->GetTyp()->Which(); |
| if( RES_POSTITFLD!=nFldWhich && |
| RES_SCRIPTFLD!=nFldWhich ) |
| break; |
| |
| OutNewLine(); |
| OutHTML_SwFmtFld( *this, pHt->GetAttr() ); |
| nOldPos = nPos; |
| nAttrs++; |
| } |
| } |
| |
| return nAttrs; |
| } |
| |
| const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs ) |
| { |
| ByteString sOut( OOO_STRING_SVTOOLS_HTML_doctype ); |
| (sOut += ' ') += |
| (HTML_CFG_HTML32==nExportMode ? OOO_STRING_SVTOOLS_HTML_doctype32 |
| : OOO_STRING_SVTOOLS_HTML_doctype40); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.GetBuffer() ); |
| |
| // baue den Vorspann |
| OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html ); |
| |
| OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head ); |
| |
| IncIndentLevel(); // Inhalt von <HEAD> einruecken |
| |
| // DokumentInfo |
| ByteString sIndent; |
| GetIndentString( sIndent ); |
| // OutNewLine(); |
| using namespace ::com::sun::star; |
| uno::Reference<document::XDocumentProperties> xDocProps; |
| SwDocShell *pDocShell(pDoc->GetDocShell()); |
| if (pDocShell) { |
| uno::Reference<document::XDocumentPropertiesSupplier> xDPS( |
| pDocShell->GetModel(), uno::UNO_QUERY_THROW); |
| xDocProps.set(xDPS->getDocumentProperties()); |
| } |
| |
| // xDocProps may be null here (when copying) |
| SfxFrameHTMLWriter::Out_DocInfo( Strm(), GetBaseURL(), xDocProps, |
| sIndent.GetBuffer(), eDestEnc, |
| &aNonConvertableCharacters ); |
| |
| // Kommentare und Meta-Tags des ersten Absatzes |
| rHeaderAttrs = OutHeaderAttrs(); |
| |
| OutFootEndNoteInfo(); |
| |
| const SwPageDesc *pPageDesc = 0; |
| //if( !pDoc->IsHTMLMode() ) |
| //{ |
| // In Nicht-HTML-Dokumenten wird die erste gesetzte Seitenvorlage |
| // exportiert und wenn keine gesetzt ist die Standard-Vorlage |
| sal_uLong nNodeIdx = pCurPam->GetPoint()->nNode.GetIndex(); |
| |
| while( nNodeIdx < pDoc->GetNodes().Count() ) |
| { |
| SwNode *pNd = pDoc->GetNodes()[ nNodeIdx ]; |
| if( pNd->IsCntntNode() ) |
| { |
| pPageDesc = ((const SwFmtPageDesc &)pNd->GetCntntNode() |
| ->GetAttr(RES_PAGEDESC)).GetPageDesc(); |
| break; |
| } |
| else if( pNd->IsTableNode() ) |
| { |
| pPageDesc = pNd->GetTableNode()->GetTable().GetFrmFmt() |
| ->GetPageDesc().GetPageDesc(); |
| break; |
| } |
| |
| nNodeIdx++; |
| } |
| |
| if( !pPageDesc ) |
| pPageDesc = &const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 ); |
| //} |
| //else |
| //{ |
| // In HTML-Dokumenten nehmen wir immer die HTML-Vorlage |
| // pPageDesc = pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML ); |
| //} |
| |
| // und nun ... das Style-Sheet!!! |
| if( bCfgOutStyles ) |
| { |
| OutStyleSheet( *pPageDesc ); |
| } |
| |
| // und nun ... das BASIC und JavaScript! |
| if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich |
| OutBasic(); |
| |
| DecIndentLevel(); // Inhalt von <HEAD> einruecken |
| OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head, sal_False ); |
| |
| // der Body wird nicht eingerueckt, weil sonst alles eingerueckt waere! |
| OutNewLine(); |
| sOut = '<'; |
| sOut += OOO_STRING_SVTOOLS_HTML_body; |
| Strm() << sOut.GetBuffer(); |
| sOut.Erase(); |
| |
| // language |
| OutLanguage( eLang ); |
| |
| // Textfarbe ausgeben, wenn sie an der Standard-Vorlage gesetzt ist |
| // und sich geaendert hat. |
| OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_text, |
| pDoc->GetTxtCollFromPool( RES_POOLCOLL_STANDARD, false ), |
| *this ); |
| |
| // Farben fuer (un)besuchte Links |
| OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_link, |
| pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL ), |
| *this ); |
| OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_vlink, |
| pDoc->GetCharFmtFromPool( RES_POOLCHR_INET_VISIT ), |
| *this ); |
| |
| const SfxItemSet& rItemSet = pPageDesc->GetMaster().GetAttrSet(); |
| |
| String aEmbGrfName; |
| OutBackground( rItemSet, aEmbGrfName, sal_True ); |
| |
| nDirection = GetHTMLDirection( rItemSet ); |
| OutDirection( nDirection ); |
| |
| if( bCfgOutStyles ) |
| OutCSS1_BodyTagStyleOpt( *this, rItemSet, aEmbGrfName ); |
| |
| // Events anhaengen |
| if( pDoc->GetDocShell() ) // nur mit DocShell ist Basic moeglich |
| OutBasicBodyEvents(); |
| |
| Strm() << '>'; |
| |
| return pPageDesc; |
| } |
| |
| void SwHTMLWriter::OutAnchor( const String& rName ) |
| { |
| ByteString sOut( '<' ); |
| (((sOut += OOO_STRING_SVTOOLS_HTML_anchor) += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\""; |
| Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_String( Strm(), rName, eDestEnc, &aNonConvertableCharacters ) << "\">"; |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_anchor, sal_False ); |
| } |
| |
| void SwHTMLWriter::OutBookmarks() |
| { |
| // hole das aktuelle Bookmark |
| const ::sw::mark::IMark* pBookmark = NULL; |
| IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); |
| if(nBkmkTabPos != -1) |
| pBookmark = (pMarkAccess->getAllMarksBegin() + nBkmkTabPos)->get(); |
| // Ausgabe aller Bookmarks in diesem Absatz. Die Content-Position |
| // wird vorerst nicht beruecksichtigt! |
| sal_uInt32 nNode = pCurPam->GetPoint()->nNode.GetIndex(); |
| while( nBkmkTabPos != -1 |
| && pBookmark->GetMarkPos().nNode.GetIndex() == nNode ) |
| { |
| // Der Bereich derBookmark wird erstam ignoriert, da er von uns |
| // auch nicht eingelesen wird. |
| |
| // erst die SWG spezifischen Daten: |
| if ( dynamic_cast< const ::sw::mark::IBookmark* >(pBookmark) != NULL |
| && pBookmark->GetName().getLength() ) |
| { |
| OutAnchor( pBookmark->GetName() ); |
| } |
| |
| if( ++nBkmkTabPos >= pMarkAccess->getAllMarksCount() ) |
| nBkmkTabPos = -1; |
| else |
| pBookmark = (pMarkAccess->getAllMarksBegin() + nBkmkTabPos)->get(); |
| } |
| |
| sal_uInt16 nPos; |
| for( nPos = 0; nPos < aOutlineMarkPoss.Count() && |
| aOutlineMarkPoss[nPos] < nNode; nPos++ ) |
| ; |
| |
| while( nPos < aOutlineMarkPoss.Count() && aOutlineMarkPoss[nPos] == nNode ) |
| { |
| String sMark( *aOutlineMarks[nPos] ); |
| sMark.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5 |
| OutAnchor( sMark ); |
| aOutlineMarkPoss.Remove( nPos, 1 ); |
| aOutlineMarks.DeleteAndDestroy( nPos, 1 ); |
| } |
| } |
| |
| void SwHTMLWriter::OutImplicitMark( const String& rMark, |
| const sal_Char *pMarkType ) |
| { |
| if( rMark.Len() && aImplicitMarks.Count() ) |
| { |
| String sMark( rMark ); |
| sMark.Append( cMarkSeperator ); |
| sMark.AppendAscii( pMarkType ); |
| sal_uInt16 nPos; |
| if( aImplicitMarks.Seek_Entry( &sMark, &nPos ) ) |
| { |
| sMark.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5 |
| OutAnchor( sMark ); |
| aImplicitMarks.DeleteAndDestroy( nPos, 1 ); |
| } |
| } |
| } |
| |
| void SwHTMLWriter::OutHyperlinkHRefValue( const String& rURL ) |
| { |
| String sURL( rURL ); |
| xub_StrLen nPos = sURL.SearchBackward( cMarkSeperator ); |
| if( STRING_NOTFOUND != nPos ) |
| { |
| String sCmp( sURL.Copy( nPos+1 ) ); |
| sCmp.EraseAllChars(); |
| if( sCmp.Len() ) |
| { |
| sCmp.ToLowerAscii(); |
| if( sCmp.EqualsAscii( pMarkToRegion ) || |
| sCmp.EqualsAscii( pMarkToFrame ) || |
| sCmp.EqualsAscii( pMarkToGraphic ) || |
| sCmp.EqualsAscii( pMarkToOLE ) || |
| sCmp.EqualsAscii( pMarkToTable ) || |
| sCmp.EqualsAscii( pMarkToOutline ) || |
| sCmp.EqualsAscii( pMarkToText ) ) |
| { |
| sURL.SearchAndReplaceAll( '?', '_' ); // '?' causes problems in IE/Netscape 5 |
| } |
| } |
| } |
| |
| sURL = URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), sURL); |
| HTMLOutFuncs::Out_String( Strm(), sURL, eDestEnc, |
| &aNonConvertableCharacters ); |
| } |
| |
| void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem, |
| String& rEmbGrfNm, sal_Bool bGraphic ) |
| { |
| const Color &rBackColor = pBrushItem->GetColor(); |
| /// OD 02.09.2002 #99657# |
| /// check, if background color is not "no fill"/"auto fill", instead of |
| /// only checking, if transparency is not set. |
| if( rBackColor.GetColor() != COL_TRANSPARENT ) |
| { |
| ByteString sOut( ' ' ); |
| (sOut += OOO_STRING_SVTOOLS_HTML_O_bgcolor) += '='; |
| Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_Color( Strm(), rBackColor, eDestEnc); |
| } |
| |
| if( !bGraphic ) |
| return; |
| |
| const String *pLink = pBrushItem->GetGraphicLink(); |
| |
| // embeddete Grafik -> WriteEmbedded schreiben |
| if( !pLink ) |
| { |
| const Graphic* pGrf = pBrushItem->GetGraphic(); |
| if( pGrf ) |
| { |
| // Grafik als (JPG-)File speichern |
| const String* pTempFileName = GetOrigFileName(); |
| if(pTempFileName) |
| rEmbGrfNm = *pTempFileName; |
| sal_uInt16 nErr = XOutBitmap::WriteGraphic( *pGrf, rEmbGrfNm, |
| String::CreateFromAscii( "JPG" ), |
| XOUTBMP_USE_NATIVE_IF_POSSIBLE ); |
| if( !nErr ) // fehlerhaft, da ist nichts auszugeben |
| { |
| rEmbGrfNm = URIHelper::SmartRel2Abs( |
| INetURLObject( GetBaseURL() ), rEmbGrfNm, |
| URIHelper::GetMaybeFileHdl() ); |
| pLink = &rEmbGrfNm; |
| } |
| else |
| { |
| nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE; |
| } |
| } |
| } |
| else |
| { |
| rEmbGrfNm = *pLink; |
| if( bCfgCpyLinkedGrfs ) |
| { |
| CopyLocalFileToINet( rEmbGrfNm ); |
| pLink = &rEmbGrfNm; |
| } |
| } |
| |
| if( pLink ) |
| { |
| ByteString sOut( ' ' ); |
| String s( URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), *pLink)); |
| (sOut += OOO_STRING_SVTOOLS_HTML_O_background) += "=\""; |
| Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_String( Strm(), s, eDestEnc, &aNonConvertableCharacters ) << '\"'; |
| } |
| } |
| |
| void SwHTMLWriter::OutBackground( const SfxItemSet& rItemSet, |
| String& rEmbGrfNm, sal_Bool bGraphic ) |
| { |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, |
| &pItem )) |
| { |
| OutBackground( ((const SvxBrushItem*)pItem), rEmbGrfNm, bGraphic ); |
| } |
| } |
| |
| sal_uInt16 SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript ) |
| { |
| sal_uInt16 nWhichId; |
| switch( nScript ) |
| { |
| case CSS1_OUTMODE_CJK: |
| nWhichId = RES_CHRATR_CJK_LANGUAGE; |
| break; |
| case CSS1_OUTMODE_CTL: |
| nWhichId = RES_CHRATR_CJK_LANGUAGE; |
| break; |
| default: |
| nWhichId = RES_CHRATR_LANGUAGE; |
| break; |
| } |
| return nWhichId; |
| } |
| |
| void SwHTMLWriter::OutLanguage( LanguageType nLang ) |
| { |
| if( LANGUAGE_DONTKNOW != nLang ) |
| { |
| ByteString sOut( ' ' ); |
| (sOut += OOO_STRING_SVTOOLS_HTML_O_lang) += "=\""; |
| Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_String( Strm(), MsLangId::convertLanguageToIsoString(nLang), |
| eDestEnc, &aNonConvertableCharacters ) << '"'; |
| } |
| } |
| |
| sal_uInt16 SwHTMLWriter::GetHTMLDirection( const SfxItemSet& rItemSet ) const |
| { |
| return GetHTMLDirection( |
| static_cast < const SvxFrameDirectionItem& >( rItemSet.Get( RES_FRAMEDIR ) ) |
| .GetValue() ); |
| } |
| |
| sal_uInt16 SwHTMLWriter::GetHTMLDirection( sal_uInt16 nDir ) const |
| { |
| switch( nDir ) |
| { |
| case FRMDIR_VERT_TOP_LEFT: |
| nDir = FRMDIR_HORI_LEFT_TOP; |
| break; |
| case FRMDIR_VERT_TOP_RIGHT: |
| nDir = FRMDIR_HORI_RIGHT_TOP; |
| break; |
| case FRMDIR_ENVIRONMENT: |
| nDir = nDirection; |
| } |
| |
| return nDir; |
| } |
| |
| void SwHTMLWriter::OutDirection( sal_uInt16 nDir ) |
| { |
| const sal_Char *pValue = 0; |
| switch( nDir ) |
| { |
| case FRMDIR_HORI_LEFT_TOP: |
| case FRMDIR_VERT_TOP_LEFT: |
| pValue = "LTR"; |
| break; |
| case FRMDIR_HORI_RIGHT_TOP: |
| case FRMDIR_VERT_TOP_RIGHT: |
| pValue = "RTL"; |
| break; |
| } |
| if( pValue != 0 ) |
| { |
| ByteString sOut( ' ' ); |
| (((sOut += OOO_STRING_SVTOOLS_HTML_O_dir) += "=\"") += pValue) += '\"'; |
| Strm() << sOut.GetBuffer(); |
| } |
| } |
| |
| void SwHTMLWriter::GetIndentString( ByteString& rStr, sal_uInt16 nIncLvl ) |
| { |
| // etwas umstaendlich, aber wir haben nur einen Indent-String! |
| sal_uInt16 nLevel = nIndentLvl + nIncLvl; |
| |
| if( nLevel && nLevel <= MAX_INDENT_LEVEL) |
| { |
| sIndentTabs[nLevel] = 0; |
| rStr = sIndentTabs; |
| sIndentTabs[nLevel] = '\t'; |
| } |
| } |
| |
| void SwHTMLWriter::OutNewLine( sal_Bool bCheck ) |
| { |
| if( !bCheck || (Strm().Tell()-nLastLFPos) > nIndentLvl ) |
| { |
| Strm() << sNewLine; |
| nLastLFPos = Strm().Tell(); |
| } |
| |
| if( nIndentLvl && nIndentLvl <= MAX_INDENT_LEVEL) |
| { |
| sIndentTabs[nIndentLvl] = 0; |
| Strm() << sIndentTabs; |
| sIndentTabs[nIndentLvl] = '\t'; |
| } |
| } |
| |
| sal_uInt16 SwHTMLWriter::GetHTMLFontSize( sal_uInt32 nHeight ) const |
| { |
| sal_uInt16 nSize = 1; |
| for( sal_uInt16 i=6; i>0; i-- ) |
| { |
| if( nHeight > (aFontHeights[i] + aFontHeights[i-1])/2 ) |
| { |
| nSize = i+1; |
| break; |
| } |
| } |
| |
| return nSize; |
| } |
| |
| // Struktur speichert die aktuellen Daten des Writers zwischen, um |
| // einen anderen Dokument-Teil auszugeben, wie z.B. Header/Footer |
| HTMLSaveData::HTMLSaveData( SwHTMLWriter& rWriter, sal_uLong nStt, |
| sal_uLong nEnd, sal_Bool bSaveNum, |
| const SwFrmFmt *pFrmFmt ) : |
| rWrt( rWriter ), |
| pOldPam( rWrt.pCurPam ), |
| pOldEnd( rWrt.GetEndPaM() ), |
| pOldNumRuleInfo( 0 ), |
| pOldNextNumRuleInfo( 0 ), |
| nOldDefListLvl( rWrt.nDefListLvl ), |
| nOldDirection( rWrt.nDirection ), |
| bOldOutHeader( rWrt.bOutHeader ), |
| bOldOutFooter( rWrt.bOutFooter ), |
| bOldOutFlyFrame( rWrt.bOutFlyFrame ) |
| { |
| bOldWriteAll = rWrt.bWriteAll; |
| |
| rWrt.pCurPam = rWrt.NewSwPaM( *rWrt.pDoc, nStt, nEnd ); |
| |
| // Tabelle in Sonderbereichen erkennen |
| if( nStt != rWrt.pCurPam->GetMark()->nNode.GetIndex() ) |
| { |
| const SwNode *pNd = rWrt.pDoc->GetNodes()[ nStt ]; |
| if( pNd->IsTableNode() || pNd->IsSectionNode() ) |
| rWrt.pCurPam->GetMark()->nNode = nStt; |
| } |
| |
| rWrt.SetEndPaM( rWrt.pCurPam ); |
| rWrt.pCurPam->Exchange( ); |
| rWrt.bWriteAll = sal_True; |
| rWrt.nDefListLvl = 0; |
| rWrt.bOutHeader = rWrt.bOutFooter = sal_False; |
| |
| // Ggf. die aktuelle Numerierungs-Info merken, damit sie wieder |
| // neu aufgenommen werden kann. Nur dann belibt auch die Numerierungs- |
| // Info des nachsten Absatz gueltig. |
| if( bSaveNum ) |
| { |
| pOldNumRuleInfo = new SwHTMLNumRuleInfo( rWrt.GetNumInfo() ); |
| pOldNextNumRuleInfo = rWrt.GetNextNumInfo(); |
| rWrt.SetNextNumInfo( 0 ); |
| } |
| else |
| { |
| rWrt.ClearNextNumInfo(); |
| } |
| |
| // Die Numerierung wird in jedem Fall unterbrochen. |
| rWrt.GetNumInfo().Clear(); |
| |
| if( pFrmFmt ) |
| rWrt.nDirection = rWrt.GetHTMLDirection( pFrmFmt->GetAttrSet() ); |
| } |
| |
| |
| HTMLSaveData::~HTMLSaveData() |
| { |
| delete rWrt.pCurPam; // Pam wieder loeschen |
| |
| rWrt.pCurPam = pOldPam; |
| rWrt.SetEndPaM( pOldEnd ); |
| rWrt.bWriteAll = bOldWriteAll; |
| rWrt.nBkmkTabPos = bOldWriteAll ? rWrt.FindPos_Bkmk( *pOldPam->GetPoint() ) : -1; |
| rWrt.nLastParaToken = 0; |
| rWrt.nDefListLvl = nOldDefListLvl; |
| rWrt.nDirection = nOldDirection; |
| rWrt.bOutHeader = bOldOutHeader; |
| rWrt.bOutFooter = bOldOutFooter; |
| rWrt.bOutFlyFrame = bOldOutFlyFrame; |
| |
| // Ggf. die Numerierung von vor der Section fortsetzen. Die Numerierung |
| // des naecshten Absatz wird in jedem Fall ungueltig. |
| if( pOldNumRuleInfo ) |
| { |
| rWrt.GetNumInfo().Set( *pOldNumRuleInfo ); |
| delete pOldNumRuleInfo; |
| rWrt.SetNextNumInfo( pOldNextNumRuleInfo ); |
| } |
| else |
| { |
| rWrt.GetNumInfo().Clear(); |
| rWrt.ClearNextNumInfo(); |
| } |
| } |
| |
| |
| void GetHTMLWriter( const String&, const String& rBaseURL, WriterRef& xRet ) |
| { |
| xRet = new SwHTMLWriter( rBaseURL ); |
| } |
| |
| |