| /************************************************************** |
| * |
| * 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 <hintids.hxx> |
| #include <com/sun/star/i18n/ScriptType.hpp> |
| #include <vcl/svapp.hxx> |
| #include <vcl/wrkwin.hxx> |
| #include <tools/urlobj.hxx> |
| #include <sfx2/sfx.hrc> |
| #if !defined _SVSTDARR_XUB_STRLEN_DECL || !defined _SVSTDARR_USHORTS_DECL |
| #define _SVSTDARR_XUB_STRLEN |
| #define _SVSTDARR_USHORTS |
| #include <svl/svstdarr.hxx> |
| #endif |
| #include <svtools/htmlout.hxx> |
| #include <svtools/htmlkywd.hxx> |
| #include <svtools/htmltokn.h> |
| #include <svl/whiter.hxx> |
| #include <svx/htmlmode.hxx> |
| #include <editeng/escpitem.hxx> |
| #include <editeng/brkitem.hxx> |
| #include <editeng/boxitem.hxx> |
| #include <editeng/ulspitem.hxx> |
| #include <editeng/udlnitem.hxx> |
| #include <editeng/crsditem.hxx> |
| #include <editeng/blnkitem.hxx> |
| #include <editeng/cmapitem.hxx> |
| #include <editeng/colritem.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <editeng/fhgtitem.hxx> |
| #include <editeng/postitem.hxx> |
| #include <editeng/kernitem.hxx> |
| #include <editeng/wghtitem.hxx> |
| #include <editeng/lspcitem.hxx> |
| #include <editeng/adjitem.hxx> |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/brshitem.hxx> |
| #include <editeng/langitem.hxx> |
| #include <editeng/frmdiritem.hxx> |
| #include <fchrfmt.hxx> |
| #include <fmtautofmt.hxx> |
| #include <fmtfsize.hxx> |
| #include <fmtclds.hxx> |
| #include <fmtpdsc.hxx> |
| #include <fmtflcnt.hxx> |
| #include <fmtinfmt.hxx> |
| #include <fmtftn.hxx> |
| #include <txatbase.hxx> |
| #include <frmatr.hxx> |
| #include <charfmt.hxx> |
| #include <fmtfld.hxx> |
| #include <doc.hxx> |
| #include <pam.hxx> |
| #include <ndtxt.hxx> |
| #include <paratr.hxx> |
| #include <poolfmt.hxx> |
| #include <pagedesc.hxx> |
| #include <swtable.hxx> |
| #include "fldbas.hxx" |
| #include <breakit.hxx> |
| #include <htmlnum.hxx> |
| #include <wrthtml.hxx> |
| #include <htmlfly.hxx> |
| #include <numrule.hxx> |
| |
| using namespace ::com::sun::star; |
| |
| /* |
| * um nicht immer wieder nach einem Update festzustellen, das irgendwelche |
| * Hint-Ids dazugekommen sind, wird hier definiert, die Groesse der Tabelle |
| * definiert und mit der akt. verglichen. Bei unterschieden wird der |
| * Compiler schon meckern. |
| * |
| * diese Section und die dazugeherigen Tabellen muessen in folgenden Files |
| * gepflegt werden: rtf\rtfatr.cxx, sw6\sw6atr.cxx, w4w\w4watr.cxx |
| */ |
| #if !defined(UNX) && !defined(MSC) && !defined(PPC) && !defined(CSET) && !defined(__MWERKS__) && !defined(WTC) && !defined(__MINGW32__) && !defined(OS2) |
| |
| #define ATTRFNTAB_SIZE 130 |
| #if ATTRFNTAB_SIZE != POOLATTR_END - POOLATTR_BEGIN |
| #error Attribut-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ?? |
| #endif |
| |
| #ifdef FORMAT_TABELLE |
| // da sie nicht benutzt wird! |
| #define FORMATTAB_SIZE 7 |
| #if FORMATTAB_SIZE != RES_FMT_END - RES_FMT_BEGIN |
| #error Format-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ?? |
| #endif |
| #endif |
| |
| #define NODETAB_SIZE 3 |
| #if NODETAB_SIZE != RES_NODE_END - RES_NODE_BEGIN |
| #error Node-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ?? |
| #endif |
| |
| #endif |
| |
| #define HTML_BULLETCHAR_DISC 34 |
| #define HTML_BULLETCHAR_CIRCLE 38 |
| #define HTML_BULLETCHAR_SQUARE 36 |
| |
| #define COLFUZZY 20 |
| |
| //----------------------------------------------------------------------- |
| |
| HTMLOutEvent __FAR_DATA aAnchorEventTable[] = |
| { |
| { OOO_STRING_SVTOOLS_HTML_O_SDonclick, OOO_STRING_SVTOOLS_HTML_O_onclick, SFX_EVENT_MOUSECLICK_OBJECT }, |
| { OOO_STRING_SVTOOLS_HTML_O_SDonmouseover, OOO_STRING_SVTOOLS_HTML_O_onmouseover, SFX_EVENT_MOUSEOVER_OBJECT }, |
| { OOO_STRING_SVTOOLS_HTML_O_SDonmouseout, OOO_STRING_SVTOOLS_HTML_O_onmouseout, SFX_EVENT_MOUSEOUT_OBJECT }, |
| { 0, 0, 0 } |
| }; |
| |
| static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt ); |
| |
| static Writer& OutHTML_HoriSpacer( Writer& rWrt, sal_Int16 nSize ) |
| { |
| ASSERT( nSize>0, "horizontaler SPACER mit negativem Wert?" ) |
| if( nSize <= 0 ) |
| return rWrt; |
| |
| if( Application::GetDefaultDevice() ) |
| { |
| nSize = (sal_Int16)Application::GetDefaultDevice() |
| ->LogicToPixel( Size(nSize,0), MapMode(MAP_TWIP) ).Width(); |
| } |
| |
| ByteString sOut( '<' ); |
| (((((((((sOut += OOO_STRING_SVTOOLS_HTML_spacer) |
| += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=') += OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal) |
| += ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=') |
| +=ByteString::CreateFromInt32(nSize)) += '>'; |
| |
| rWrt.Strm() << sOut.GetBuffer(); |
| |
| return rWrt; |
| } |
| |
| sal_uInt16 SwHTMLWriter::GetDefListLvl( const String& rNm, sal_uInt16 nPoolId ) |
| { |
| if( nPoolId == RES_POOLCOLL_HTML_DD ) |
| { |
| return 1 | HTML_DLCOLL_DD; |
| } |
| else if( nPoolId == RES_POOLCOLL_HTML_DT ) |
| { |
| return 1 | HTML_DLCOLL_DT; |
| } |
| |
| String sDTDD( String::CreateFromAscii(OOO_STRING_SVTOOLS_HTML_dt) ); |
| sDTDD += ' '; |
| if( COMPARE_EQUAL == sDTDD.CompareTo( rNm, sDTDD.Len() ) ) |
| // DefinitionList - term |
| return (sal_uInt16)rNm.Copy( sDTDD.Len() ).ToInt32() | HTML_DLCOLL_DT; |
| |
| sDTDD.AssignAscii( OOO_STRING_SVTOOLS_HTML_dd ); |
| sDTDD += ' '; |
| if( COMPARE_EQUAL == sDTDD.CompareTo( rNm, sDTDD.Len() ) ) |
| // DefinitionList - definition |
| return (sal_uInt16)rNm.Copy( sDTDD.Len() ).ToInt32() | HTML_DLCOLL_DD; |
| |
| return 0; |
| } |
| |
| void SwHTMLWriter::OutAndSetDefList( sal_uInt16 nNewLvl ) |
| { |
| // eventuell muss erst mal eine Liste aufgemacht werden |
| if( nDefListLvl < nNewLvl ) |
| { |
| // output </pre> for the previous(!) pararagraph, if required. |
| // Preferable, the <pre> is exported by OutHTML_SwFmtOff for the |
| // previous paragraph already, but that's not possible, because a very |
| // deep look at the next paragraph (this one) is required to figure |
| // out that a def list starts here. |
| |
| ChangeParaToken( 0 ); |
| |
| // entsprechend dem Level-Unterschied schreiben! |
| for( sal_uInt16 i=nDefListLvl; i<nNewLvl; i++ ) |
| { |
| if( bLFPossible ) |
| OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_deflist, sal_True ); |
| IncIndentLevel(); |
| bLFPossible = sal_True; |
| } |
| } |
| else if( nDefListLvl > nNewLvl ) |
| { |
| for( sal_uInt16 i=nNewLvl ; i < nDefListLvl; i++ ) |
| { |
| DecIndentLevel(); |
| if( bLFPossible ) |
| OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_deflist, sal_False ); |
| bLFPossible = sal_True; |
| } |
| } |
| |
| nDefListLvl = nNewLvl; |
| } |
| |
| |
| void SwHTMLWriter::ChangeParaToken( sal_uInt16 nNew ) |
| { |
| if( nNew != nLastParaToken && HTML_PREFORMTXT_ON == nLastParaToken ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_preformtxt, sal_False ); |
| bLFPossible = sal_True; |
| } |
| nLastParaToken = nNew; |
| } |
| |
| sal_uInt16 SwHTMLWriter::GetCSS1ScriptForScriptType( sal_uInt16 nScriptType ) |
| { |
| sal_uInt16 nRet = CSS1_OUTMODE_ANY_SCRIPT; |
| |
| switch( nScriptType ) |
| { |
| case i18n::ScriptType::LATIN: |
| nRet = CSS1_OUTMODE_WESTERN; |
| break; |
| case i18n::ScriptType::ASIAN: |
| nRet = CSS1_OUTMODE_CJK; |
| break; |
| case i18n::ScriptType::COMPLEX: |
| nRet = CSS1_OUTMODE_CTL; |
| break; |
| } |
| |
| return nRet; |
| } |
| |
| // fuer die Formate muesste eine einzige Ausgabe-Funktion genuegen ! |
| /* |
| * Formate wie folgt ausgeben: |
| * - fuer Formate, fuer die es entsprechende HTML-Tags gibt wird das |
| * Tag ausgegeben |
| * - fuer alle anderen wird ein Absatz-Tag <P> ausgegeben und bUserFmt |
| * gesetzt |
| * - Wenn eine Absatz-Ausrichtung am uebergebenen Item-Set des Nodes |
| * oder im Item-Set des Format gesetzt ist, wird ein ALIGN=xxx ausgegeben, |
| * sofern HTML es zulaesst |
| * - in jedem Fall wird harte Attributierung als STYLE-Option geschrieben. |
| * Wenn bUserFmt nicht gesetzt ist, wird nur der uebergebene Item-Set |
| * betrachtet. Sonst werden auch Attribute des Formats ausgegeben. |
| */ |
| |
| struct SwHTMLTxtCollOutputInfo |
| { |
| ByteString aToken; // auszugendens End-Token |
| SfxItemSet *pItemSet; // harte Attributierung |
| |
| sal_Bool bInNumBulList; // in einer Aufzaehlungs-Liste; |
| sal_Bool bParaPossible; // ein </P> darf zusaetzlich ausgegeben werden |
| sal_Bool bOutPara; // ein </P> soll ausgegeben werden |
| sal_Bool bOutDiv; // write a </DIV> |
| |
| SwHTMLTxtCollOutputInfo() : |
| pItemSet( 0 ), |
| bInNumBulList( sal_False ), |
| bParaPossible( sal_False ), |
| bOutPara( sal_False ), |
| bOutDiv( sal_False ) |
| {} |
| |
| ~SwHTMLTxtCollOutputInfo(); |
| |
| sal_Bool HasParaToken() const { return aToken.Len()==1 && aToken.GetChar(0)=='P'; } |
| sal_Bool ShouldOutputToken() const { return bOutPara || !HasParaToken(); } |
| }; |
| |
| SwHTMLTxtCollOutputInfo::~SwHTMLTxtCollOutputInfo() |
| { |
| delete pItemSet; |
| } |
| |
| struct SwHTMLFmtInfo |
| { |
| const SwFmt *pFmt; // das Format selbst |
| const SwFmt *pRefFmt; // das Vergleichs-Format |
| |
| ByteString aToken; // das auszugebende Token |
| String aClass; // die auszugebende Klasse |
| |
| SfxItemSet *pItemSet; // der auszugebende Attribut-Set |
| |
| sal_Int32 nLeftMargin; // ein par default-Werte fuer |
| sal_Int32 nRightMargin; // Absatz-Vorlagen |
| short nFirstLineIndent; |
| |
| sal_uInt16 nTopMargin; |
| sal_uInt16 nBottomMargin; |
| |
| sal_Bool bScriptDependent; |
| |
| // Konstruktor fuer einen Dummy zum Suchen |
| SwHTMLFmtInfo( const SwFmt *pF ) : |
| pFmt( pF ), pItemSet( 0 ) |
| {} |
| |
| |
| // Konstruktor zum Erstellen der Format-Info |
| SwHTMLFmtInfo( const SwFmt *pFmt, SwDoc *pDoc, SwDoc *pTemlate, |
| sal_Bool bOutStyles, LanguageType eDfltLang=LANGUAGE_DONTKNOW, |
| sal_uInt16 nScript=CSS1_OUTMODE_ANY_SCRIPT, |
| sal_Bool bHardDrop=sal_False ); |
| ~SwHTMLFmtInfo(); |
| |
| friend sal_Bool operator==( const SwHTMLFmtInfo& rInfo1, |
| const SwHTMLFmtInfo& rInfo2 ) |
| { |
| return (long)rInfo1.pFmt == (long)rInfo2.pFmt; |
| } |
| |
| friend sal_Bool operator<( const SwHTMLFmtInfo& rInfo1, |
| const SwHTMLFmtInfo& rInfo2 ) |
| { |
| return (long)rInfo1.pFmt < (long)rInfo2.pFmt; |
| } |
| |
| }; |
| |
| SV_IMPL_OP_PTRARR_SORT( SwHTMLFmtInfos, SwHTMLFmtInfo* ) |
| |
| SwHTMLFmtInfo::SwHTMLFmtInfo( const SwFmt *pF, SwDoc *pDoc, SwDoc *pTemplate, |
| sal_Bool bOutStyles, |
| LanguageType eDfltLang, |
| sal_uInt16 nCSS1Script, sal_Bool bHardDrop ) : |
| pFmt( pF ), pItemSet( 0 ), bScriptDependent( sal_False ) |
| { |
| sal_uInt16 nRefPoolId = 0; |
| // Den Selektor des Formats holen |
| sal_uInt16 nDeep = SwHTMLWriter::GetCSS1Selector( pFmt, aToken, aClass, |
| nRefPoolId ); |
| ASSERT( nDeep ? aToken.Len()>0 : aToken.Len()==0, |
| "Hier stimmt doch was mit dem Token nicht!" ); |
| ASSERT( nDeep ? nRefPoolId : !nRefPoolId, |
| "Hier stimmt doch was mit der Vergleichs-Vorlage nicht!" ); |
| |
| sal_Bool bTxtColl = pFmt->Which() == RES_TXTFMTCOLL || |
| pFmt->Which() == RES_CONDTXTFMTCOLL; |
| |
| const SwFmt *pReferenceFmt = 0; // Vergleichs-Format |
| sal_Bool bSetDefaults = sal_True, bClearSame = sal_True; |
| if( nDeep != 0 ) |
| { |
| // Es ist eine HTML-Tag-Vorlage oder die Vorlage ist von einer |
| // solchen abgeleitet |
| if( !bOutStyles ) |
| { |
| // wenn keine Styles exportiert werden, muss evtl. zusaetlich |
| // harte Attributierung geschrieben werden |
| switch( nDeep ) |
| { |
| case CSS1_FMT_ISTAG: |
| case CSS1_FMT_CMPREF: |
| // fuer HTML-Tag-Vorlagen die Unterscheide zum Original |
| // (sofern verfuegbar) |
| pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId, |
| pTemplate ); |
| break; |
| |
| default: |
| // sonst die zur HTML-Tag-Vorlage des Originals oder des |
| // aktuellen Doks, wenn die nicht verfuegbar ist |
| if( pTemplate ) |
| pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId, |
| pTemplate ); |
| else |
| pReferenceFmt = SwHTMLWriter::GetParentFmt( *pFmt, nDeep ); |
| break; |
| } |
| } |
| } |
| else if( bTxtColl ) |
| { |
| // Nicht von einer HTML-Tag-Vorlage abgeleitete Absatz-Vorlagen |
| // muessen als harte Attributierung relativ zur Textkoerper-Volage |
| // exportiert werden. Fuer Nicht-Styles-Export sollte die der |
| // HTML-Vorlage als Referenz dienen |
| if( !bOutStyles && pTemplate ) |
| pReferenceFmt = pTemplate->GetTxtCollFromPool( RES_POOLCOLL_TEXT, false ); |
| else |
| pReferenceFmt = pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT, false ); |
| } |
| |
| if( pReferenceFmt || nDeep==0 ) |
| { |
| pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(), |
| pFmt->GetAttrSet().GetRanges() ); |
| // wenn Unterschiede zu einer anderen Vorlage geschrieben werden |
| // sollen ist harte Attributierung noetig. Fuer Vorlagen, die |
| // nicht von HTML-Tag-Vorlagen abgeleitet sind, gilt das immer |
| |
| pItemSet->Set( pFmt->GetAttrSet(), sal_True ); |
| |
| if( pReferenceFmt ) |
| SwHTMLWriter::SubtractItemSet( *pItemSet, pReferenceFmt->GetAttrSet(), |
| bSetDefaults, bClearSame ); |
| |
| // einen leeren Item-Set gleich loeschen, das spart speater |
| // Arbeit |
| if( !pItemSet->Count() ) |
| { |
| delete pItemSet; |
| pItemSet = 0; |
| } |
| } |
| |
| if( bTxtColl ) |
| { |
| if( bOutStyles ) |
| { |
| // We have to add hard attributes for any script dependent |
| // item that is not accessed by the style |
| static sal_uInt16 aWhichIds[3][4] = |
| { |
| { RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, |
| RES_CHRATR_POSTURE, RES_CHRATR_WEIGHT }, |
| { RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE, |
| RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT }, |
| { RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE, |
| RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT } |
| }; |
| |
| sal_uInt16 nRef = 0; |
| sal_uInt16 aSets[2] = {0,0}; |
| switch( nCSS1Script ) |
| { |
| case CSS1_OUTMODE_WESTERN: |
| nRef = 0; |
| aSets[0] = 1; |
| aSets[1] = 2; |
| break; |
| case CSS1_OUTMODE_CJK: |
| nRef = 1; |
| aSets[0] = 0; |
| aSets[1] = 2; |
| break; |
| case CSS1_OUTMODE_CTL: |
| nRef = 2; |
| aSets[0] = 0; |
| aSets[1] = 1; |
| break; |
| } |
| for( sal_uInt16 i=0; i<4; i++ ) |
| { |
| const SfxPoolItem& rRef = pFmt->GetFmtAttr( aWhichIds[nRef][i] ); |
| for( sal_uInt16 j=0; j<2; j++ ) |
| { |
| const SfxPoolItem& rSet = pFmt->GetFmtAttr( aWhichIds[aSets[j]][i] ); |
| if( rSet != rRef ) |
| { |
| if( !pItemSet ) |
| pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(), |
| pFmt->GetAttrSet().GetRanges() ); |
| pItemSet->Put( rSet ); |
| } |
| } |
| } |
| } |
| |
| // Ggf. noch ein DropCap-Attribut uebernehmen |
| if( bOutStyles && bHardDrop && nDeep != 0 ) |
| { |
| const SfxPoolItem *pItem; |
| if( SFX_ITEM_SET==pFmt->GetAttrSet().GetItemState( |
| RES_PARATR_DROP, sal_True, &pItem ) ) |
| { |
| sal_Bool bPut = sal_True; |
| if( pTemplate ) |
| { |
| pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId, pTemplate ); |
| const SfxPoolItem *pRefItem; |
| sal_Bool bRefItemSet = |
| SFX_ITEM_SET==pReferenceFmt->GetAttrSet().GetItemState( |
| RES_PARATR_DROP, sal_True, &pRefItem ); |
| bPut = !bRefItemSet || *pItem!=*pRefItem; |
| } |
| if( bPut ) |
| { |
| if( !pItemSet ) |
| pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(), |
| pFmt->GetAttrSet().GetRanges() ); |
| pItemSet->Put( *pItem ); |
| } |
| } |
| } |
| |
| |
| // Die diversen default-Abstaende aus der Vorlage oder der |
| // Vergleischs-Vorlage merken |
| const SvxLRSpaceItem &rLRSpace = |
| (pReferenceFmt ? pReferenceFmt : pFmt)->GetLRSpace(); |
| nLeftMargin = rLRSpace.GetTxtLeft(); |
| nRightMargin = rLRSpace.GetRight(); |
| nFirstLineIndent = rLRSpace.GetTxtFirstLineOfst(); |
| |
| const SvxULSpaceItem &rULSpace = |
| (pReferenceFmt ? pReferenceFmt : pFmt)->GetULSpace(); |
| nTopMargin = rULSpace.GetUpper(); |
| nBottomMargin = rULSpace.GetLower(); |
| |
| // export language if it differs from the default language |
| sal_uInt16 nWhichId = |
| SwHTMLWriter::GetLangWhichIdFromScript( nCSS1Script ); |
| const SvxLanguageItem& rLang = |
| (const SvxLanguageItem&)pFmt->GetFmtAttr( nWhichId ); |
| LanguageType eLang = rLang.GetLanguage(); |
| if( eLang != eDfltLang ) |
| { |
| if( !pItemSet ) |
| pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(), |
| pFmt->GetAttrSet().GetRanges() ); |
| pItemSet->Put( rLang ); |
| } |
| |
| static sal_uInt16 aWhichIds[3] = |
| { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, |
| RES_CHRATR_CTL_LANGUAGE }; |
| for( sal_uInt16 i=0; i<3; i++ ) |
| { |
| if( aWhichIds[i] != nWhichId ) |
| { |
| const SvxLanguageItem& rTmpLang = |
| (const SvxLanguageItem&)pFmt->GetFmtAttr(aWhichIds[i]); |
| if( rTmpLang.GetLanguage() != eLang ) |
| { |
| if( !pItemSet ) |
| pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(), |
| pFmt->GetAttrSet().GetRanges() ); |
| pItemSet->Put( rTmpLang ); |
| } |
| } |
| } |
| } |
| } |
| |
| SwHTMLFmtInfo::~SwHTMLFmtInfo() |
| { |
| delete pItemSet; |
| } |
| |
| void OutHTML_SwFmt( Writer& rWrt, const SwFmt& rFmt, |
| const SfxItemSet *pNodeItemSet, |
| SwHTMLTxtCollOutputInfo& rInfo ) |
| { |
| ASSERT( RES_CONDTXTFMTCOLL==rFmt.Which() || RES_TXTFMTCOLL==rFmt.Which(), |
| "keine Absatz-Vorlage" ); |
| |
| SwHTMLWriter & rHWrt = (SwHTMLWriter&)rWrt; |
| |
| // Erstmal ein par Flags ... |
| sal_uInt16 nNewDefListLvl = 0; |
| sal_uInt16 nNumStart = USHRT_MAX; |
| sal_Bool bForceDL = sal_False; |
| sal_Bool bDT = sal_False; |
| rInfo.bInNumBulList = sal_False; // Wir sind in einer Liste? |
| sal_Bool bNumbered = sal_False; // Der aktuelle Absatz ist numeriert |
| sal_Bool bPara = sal_False; // das aktuelle Token ist <P> |
| rInfo.bParaPossible = sal_False; // ein <P> darf zusaetzlich ausgegeben werden |
| sal_Bool bNoEndTag = sal_False; // kein End-Tag ausgeben |
| |
| rHWrt.bNoAlign = sal_False; // kein ALIGN=... moeglich |
| sal_Bool bNoStyle = sal_False; // kein STYLE=... moeglich |
| sal_uInt8 nBulletGrfLvl = 255; // Die auszugebende Bullet-Grafik |
| |
| // Sind wir in einer Aufzaehlungs- oder Numerierungliste? |
| const SwTxtNode* pTxtNd = rWrt.pCurPam->GetNode()->GetTxtNode(); |
| |
| SwHTMLNumRuleInfo aNumInfo; |
| if( rHWrt.GetNextNumInfo() ) |
| { |
| aNumInfo = *rHWrt.GetNextNumInfo(); |
| rHWrt.ClearNextNumInfo(); |
| } |
| else |
| { |
| aNumInfo.Set( *pTxtNd ); |
| } |
| |
| if( aNumInfo.GetNumRule() ) |
| { |
| rInfo.bInNumBulList = sal_True; |
| nNewDefListLvl = 0; |
| |
| // ist der aktuelle Absatz numeriert? |
| bNumbered = aNumInfo.IsNumbered(); |
| sal_uInt8 nLvl = aNumInfo.GetLevel(); |
| |
| ASSERT( pTxtNd->GetActualListLevel() == nLvl, |
| "Gemerkter Num-Level ist falsch" ); |
| ASSERT( bNumbered == static_cast< sal_Bool >(pTxtNd->IsCountedInList()), |
| "Gemerkter Numerierungs-Zustand ist falsch" ); |
| |
| if( bNumbered ) |
| { |
| nBulletGrfLvl = nLvl; // nur veruebergehend!!! |
| // --> OD 2005-11-15 #i57919# |
| // correction of re-factoring done by cws swnumtree: |
| // - <nNumStart> has to contain the restart value, if the |
| // numbering is restarted at this text node. Value <USHRT_MAX> |
| // indicates, that no additional restart value has to be written. |
| if ( pTxtNd->IsListRestart() ) |
| { |
| nNumStart = static_cast< sal_uInt16 >(pTxtNd->GetActualListStartValue()); |
| } |
| // <-- |
| DBG_ASSERT( rHWrt.nLastParaToken == 0, |
| "<PRE> wurde nicht vor <LI> beendet." ); |
| } |
| } |
| |
| // Jetzt holen wir das Token und ggf. die Klasse |
| SwHTMLFmtInfo aFmtInfo( &rFmt ); |
| sal_uInt16 nArrayPos; |
| const SwHTMLFmtInfo *pFmtInfo; |
| if( rHWrt.aTxtCollInfos.Seek_Entry( &aFmtInfo, &nArrayPos ) ) |
| { |
| pFmtInfo = rHWrt.aTxtCollInfos[nArrayPos]; |
| } |
| else |
| { |
| pFmtInfo = new SwHTMLFmtInfo( &rFmt, rWrt.pDoc, rHWrt.pTemplate, |
| rHWrt.bCfgOutStyles, rHWrt.eLang, |
| rHWrt.nCSS1Script, |
| !rHWrt.IsHTMLMode(HTMLMODE_DROPCAPS) ); |
| rHWrt.aTxtCollInfos.C40_PTR_INSERT( SwHTMLFmtInfo, pFmtInfo ); |
| String aName( rFmt.GetName() ); |
| if( rHWrt.aScriptParaStyles.Seek_Entry( &aName ) ) |
| ((SwHTMLFmtInfo *)pFmtInfo)->bScriptDependent = sal_True; |
| } |
| |
| // Jetzt wird festgelegt, was aufgrund des Tokens so moeglich ist |
| sal_uInt16 nToken = 0; // Token fuer Tag-Wechsel |
| sal_Bool bOutNewLine = sal_False; // nur ein LF ausgeben? |
| if( pFmtInfo->aToken.Len() ) |
| { |
| // Es ist eine HTML-Tag-Vorlage oder die Vorlage ist von einer |
| // solchen abgeleitet |
| rInfo.aToken = pFmtInfo->aToken; |
| |
| // der erste Buchstabe reicht meistens |
| switch( rInfo.aToken.GetChar( 0 ) ) |
| { |
| case 'A': ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_address), |
| "Doch kein ADDRESS?" ); |
| rInfo.bParaPossible = sal_True; |
| rHWrt.bNoAlign = sal_True; |
| break; |
| |
| case 'B': ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_blockquote), |
| "Doch kein BLOCKQUOTE?" ); |
| rInfo.bParaPossible = sal_True; |
| rHWrt.bNoAlign = sal_True; |
| break; |
| |
| case 'P': if( rInfo.aToken.Len() == 1 ) |
| { |
| bPara = sal_True; |
| } |
| else |
| { |
| ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_preformtxt), |
| "Doch kein PRE?" ); |
| if( HTML_PREFORMTXT_ON == rHWrt.nLastParaToken ) |
| { |
| bOutNewLine = sal_True; |
| } |
| else |
| { |
| nToken = HTML_PREFORMTXT_ON; |
| rHWrt.bNoAlign = sal_True; |
| bNoEndTag = sal_True; |
| } |
| } |
| break; |
| |
| case 'D': ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dt) || |
| rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dd), |
| "Doch kein DD/DT?" ); |
| bDT = rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dt); |
| rInfo.bParaPossible = !bDT; |
| rHWrt.bNoAlign = sal_True; |
| bForceDL = sal_True; |
| break; |
| } |
| } |
| else |
| { |
| // alle Vorlagen, die nicht einem HTML-Tag entsprechen oder von |
| // diesem abgeleitet sind, werden als <P> exportiert |
| |
| rInfo.aToken = OOO_STRING_SVTOOLS_HTML_parabreak; |
| bPara = sal_True; |
| } |
| |
| // Falls noetig, die harte Attributierung der Vorlage uebernehmen |
| if( pFmtInfo->pItemSet ) |
| { |
| ASSERT( !rInfo.pItemSet, "Wo kommt der Item-Set her?" ); |
| rInfo.pItemSet = new SfxItemSet( *pFmtInfo->pItemSet ); |
| } |
| |
| // und noch die harte Attributierung des Absatzes dazunehmen |
| if( pNodeItemSet ) |
| { |
| if( rInfo.pItemSet ) |
| rInfo.pItemSet->Put( *pNodeItemSet ); |
| else |
| rInfo.pItemSet = new SfxItemSet( *pNodeItemSet ); |
| } |
| |
| // den unteren Absatz-Abstand brauchen wir noch |
| const SvxULSpaceItem& rULSpace = |
| pNodeItemSet ? ((const SvxULSpaceItem &)pNodeItemSet->Get(RES_UL_SPACE)) |
| : rFmt.GetULSpace(); |
| |
| |
| if( (rHWrt.bOutHeader && |
| rWrt.pCurPam->GetPoint()->nNode.GetIndex() == |
| rWrt.pCurPam->GetMark()->nNode.GetIndex()) || |
| rHWrt.bOutFooter ) |
| { |
| if( rHWrt.bCfgOutStyles ) |
| { |
| SvxULSpaceItem aULSpaceItem( rULSpace ); |
| if( rHWrt.bOutHeader ) |
| aULSpaceItem.SetLower( rHWrt.nHeaderFooterSpace ); |
| else |
| aULSpaceItem.SetUpper( rHWrt.nHeaderFooterSpace ); |
| |
| if( !rInfo.pItemSet ) |
| rInfo.pItemSet = new SfxItemSet( |
| *rFmt.GetAttrSet().GetPool(), |
| RES_UL_SPACE, RES_UL_SPACE ); |
| rInfo.pItemSet->Put( aULSpaceItem ); |
| } |
| rHWrt.bOutHeader = sal_False; |
| rHWrt.bOutFooter = sal_False; |
| } |
| |
| if( bOutNewLine ) |
| { |
| // nur einen Zeilen-Umbruch (ohne Einrueckung) am Absatz-Anfang |
| // ausgeben |
| rInfo.aToken.Erase(); // kein End-Tag ausgeben |
| rWrt.Strm() << SwHTMLWriter::sNewLine; |
| |
| return; |
| } |
| |
| |
| // soll ein ALIGN=... geschrieben werden? |
| const SfxPoolItem* pAdjItem = 0; |
| const SfxPoolItem* pItem; |
| |
| if( rInfo.pItemSet && |
| SFX_ITEM_SET == rInfo.pItemSet->GetItemState( RES_PARATR_ADJUST, |
| sal_False, &pItem ) ) |
| { |
| pAdjItem = pItem; |
| } |
| |
| // Unteren Absatz-Abstand beachten ? (nie im letzen Absatz von |
| // Tabellen) |
| sal_Bool bUseParSpace = !rHWrt.bOutTable || |
| (rWrt.pCurPam->GetPoint()->nNode.GetIndex() != |
| rWrt.pCurPam->GetMark()->nNode.GetIndex()); |
| // Wenn Styles exportiert werden, wird aus eingerueckten Absaetzen |
| // eine Definitions-Liste |
| const SvxLRSpaceItem& rLRSpace = |
| pNodeItemSet ? ((const SvxLRSpaceItem &)pNodeItemSet->Get(RES_LR_SPACE)) |
| : rFmt.GetLRSpace(); |
| if( (!rHWrt.bCfgOutStyles || bForceDL) && !rInfo.bInNumBulList ) |
| { |
| sal_Int32 nLeftMargin; |
| if( bForceDL ) |
| nLeftMargin = rLRSpace.GetTxtLeft(); |
| else |
| nLeftMargin = rLRSpace.GetTxtLeft() > pFmtInfo->nLeftMargin |
| ? rLRSpace.GetTxtLeft() - pFmtInfo->nLeftMargin |
| : 0; |
| |
| if( nLeftMargin > 0 && rHWrt.nDefListMargin > 0 ) |
| { |
| nNewDefListLvl = static_cast< sal_uInt16 >((nLeftMargin + (rHWrt.nDefListMargin/2)) / |
| rHWrt.nDefListMargin); |
| if( nNewDefListLvl == 0 && bForceDL && !bDT ) |
| nNewDefListLvl = 1; |
| } |
| else |
| { |
| // If the left margin is 0 or negative, emulating indent |
| // with <dd> does not work. We then set a def list only if |
| // the dd style is used. |
| nNewDefListLvl = (bForceDL&& !bDT) ? 1 : 0; |
| } |
| |
| sal_Bool bIsNextTxtNode = |
| rWrt.pDoc->GetNodes()[rWrt.pCurPam->GetPoint()->nNode.GetIndex()+1] |
| ->IsTxtNode(); |
| |
| if( bForceDL && bDT ) |
| { |
| // Statt eines DD muessen wir hier auch ein DT der Ebene |
| // darueber nehmen |
| nNewDefListLvl++; |
| } |
| else if( !nNewDefListLvl && !rHWrt.bCfgOutStyles && bPara && |
| rULSpace.GetLower()==0 && |
| ((bUseParSpace && bIsNextTxtNode) || rHWrt.nDefListLvl==1) && |
| (!pAdjItem || SVX_ADJUST_LEFT== |
| ((const SvxAdjustItem *)pAdjItem)->GetAdjust()) ) |
| { |
| // Absaetze ohne unteren Abstand als DT exportieren |
| nNewDefListLvl = 1; |
| bDT = sal_True; |
| rInfo.bParaPossible = sal_False; |
| rHWrt.bNoAlign = sal_True; |
| } |
| } |
| |
| if( nNewDefListLvl != rHWrt.nDefListLvl ) |
| rHWrt.OutAndSetDefList( nNewDefListLvl ); |
| |
| // ggf. eine Aufzaehlung- oder Numerierungsliste beginnen |
| if( rInfo.bInNumBulList ) |
| { |
| ASSERT( !rHWrt.nDefListLvl, "DL in OL geht nicht!" ); |
| OutHTML_NumBulListStart( rHWrt, aNumInfo ); |
| |
| if( bNumbered ) |
| { |
| if( rHWrt.aBulletGrfs[nBulletGrfLvl].Len() ) |
| bNumbered = sal_False; |
| else |
| nBulletGrfLvl = 255; |
| } |
| } |
| |
| // Die Defaults aus der Vorlage merken, denn sie muessen nicht |
| // exportiert werden |
| rHWrt.nDfltLeftMargin = pFmtInfo->nLeftMargin; |
| rHWrt.nDfltRightMargin = pFmtInfo->nRightMargin; |
| rHWrt.nDfltFirstLineIndent = pFmtInfo->nFirstLineIndent; |
| |
| if( rInfo.bInNumBulList ) |
| { |
| if( !rHWrt.IsHTMLMode( HTMLMODE_LSPACE_IN_NUMBUL ) ) |
| rHWrt.nDfltLeftMargin = rLRSpace.GetTxtLeft(); |
| |
| // In Numerierungs-Listen keinen Ertzeilen-Einzug ausgeben. |
| rHWrt.nFirstLineIndent = rLRSpace.GetTxtFirstLineOfst(); |
| } |
| |
| if( rInfo.bInNumBulList && bNumbered && bPara && !rHWrt.bCfgOutStyles ) |
| { |
| // ein einzelnes LI hat keinen Abstand |
| rHWrt.nDfltTopMargin = 0; |
| rHWrt.nDfltBottomMargin = 0; |
| } |
| else if( rHWrt.nDefListLvl && bPara ) |
| { |
| // ein einzelnes DD hat auch keinen Abstand |
| rHWrt.nDfltTopMargin = 0; |
| rHWrt.nDfltBottomMargin = 0; |
| } |
| else |
| { |
| rHWrt.nDfltTopMargin = pFmtInfo->nTopMargin; |
| // #60393#: Wenn im letzten Absatz einer Tabelle der |
| // untere Absatz-Abstand veraendert wird, vertut sich |
| // Netscape total. Deshalb exportieren wir hier erstmal |
| // nichts, indem wir den Abstand aus dem Absatz als Default |
| // setzen. |
| if( rHWrt.bCfgNetscape4 && !bUseParSpace ) |
| rHWrt.nDfltBottomMargin = rULSpace.GetLower(); |
| else |
| rHWrt.nDfltBottomMargin = pFmtInfo->nBottomMargin; |
| } |
| |
| if( rHWrt.nDefListLvl ) |
| { |
| rHWrt.nLeftMargin = |
| (rHWrt.nDefListLvl-1) * rHWrt.nDefListMargin; |
| } |
| |
| if( rHWrt.bLFPossible ) |
| rHWrt.OutNewLine(); // Absatz-Tag in neue Zeile |
| rInfo.bOutPara = sal_False; |
| |
| // das ist jetzt unser neues Token |
| rHWrt.ChangeParaToken( nToken ); |
| |
| sal_Bool bHasParSpace = bUseParSpace && rULSpace.GetLower() > 0; |
| |
| // ggf ein List-Item aufmachen |
| if( rInfo.bInNumBulList && bNumbered ) |
| { |
| ByteString sOut( '<' ); |
| sOut += OOO_STRING_SVTOOLS_HTML_li; |
| if( USHRT_MAX != nNumStart ) |
| (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_value) += '=') |
| += ByteString::CreateFromInt32(nNumStart); |
| sOut += '>'; |
| rWrt.Strm() << sOut.GetBuffer(); |
| } |
| |
| if( rHWrt.nDefListLvl > 0 && !bForceDL ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), bDT ? OOO_STRING_SVTOOLS_HTML_dt : OOO_STRING_SVTOOLS_HTML_dd ); |
| } |
| |
| if( pAdjItem && |
| rHWrt.IsHTMLMode( HTMLMODE_NO_CONTROL_CENTERING ) && |
| rHWrt.HasControls() ) |
| { |
| // #64687#: The align=... attribute does behave strange in netscape |
| // if there are controls in a paragraph, because the control and |
| // all text behind the control does not recognize this attribute. |
| ByteString sOut( '<' ); |
| sOut += OOO_STRING_SVTOOLS_HTML_division; |
| rWrt.Strm() << sOut.GetBuffer(); |
| |
| rHWrt.bTxtAttr = sal_False; |
| rHWrt.bOutOpts = sal_True; |
| OutHTML_SvxAdjust( rWrt, *pAdjItem ); |
| rWrt.Strm() << '>'; |
| pAdjItem = 0; |
| rHWrt.bNoAlign = sal_False; |
| rInfo.bOutDiv = sal_True; |
| rHWrt.IncIndentLevel(); |
| rHWrt.bLFPossible = sal_True; |
| rHWrt.OutNewLine(); |
| } |
| |
| // fuer BLOCKQUOTE, ADDRESS und DD wird noch ein Absatz-Token |
| // ausgegeben, wenn, |
| // - keine Styles geschrieben werden, und |
| // - ein untere Abstand oder eine Absatz-Ausrichtung existiert |
| ByteString aToken = rInfo.aToken; |
| if( !rHWrt.bCfgOutStyles && rInfo.bParaPossible && !bPara && |
| (bHasParSpace || pAdjItem) ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rInfo.aToken.GetBuffer() ); |
| aToken = OOO_STRING_SVTOOLS_HTML_parabreak; |
| bPara = sal_True; |
| rHWrt.bNoAlign = sal_False; |
| bNoStyle = sal_False; |
| } |
| |
| LanguageType eLang = rInfo.pItemSet |
| ? ((const SvxLanguageItem&)rInfo.pItemSet->Get(SwHTMLWriter::GetLangWhichIdFromScript(rHWrt.nCSS1Script))).GetLanguage() |
| : rHWrt.eLang; |
| |
| if( rInfo.pItemSet ) |
| { |
| static sal_uInt16 aWhichIds[3] = { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE }; |
| |
| for( sal_uInt16 i=0; i<3; i++ ) |
| { |
| // export language if it differs from the default language only. |
| const SfxPoolItem *pTmpItem; |
| if( SFX_ITEM_SET == rInfo.pItemSet->GetItemState( aWhichIds[i], |
| sal_True, &pTmpItem ) && |
| ((const SvxLanguageItem *)pTmpItem)->GetLanguage() == eLang ) |
| rInfo.pItemSet->ClearItem( aWhichIds[i] ); |
| } |
| } |
| |
| // and the text direction |
| sal_uInt16 nDir = rHWrt.GetHTMLDirection( |
| (pNodeItemSet ? static_cast < const SvxFrameDirectionItem& >( |
| pNodeItemSet->Get( RES_FRAMEDIR ) ) |
| : rFmt.GetFrmDir() ).GetValue() ); |
| |
| // Ein <P> wird nur geschrieben, wenn |
| // - wir in keiner OL/UL/DL sind, oder |
| // - der Absatz einer OL/UL nicht numeriert ist, oder |
| // - keine Styles exportiert werden und |
| // - ein unterer Abstand oder |
| // - eine Absatz-Ausrichtung existiert, ode |
| // - Styles exportiert werden und, |
| // - die Textkoerper-Vorlage geaendert wurde, oder |
| // - ein Benutzer-Format exportiert wird, oder |
| // - Absatz-Attribute existieren |
| if( !bPara || |
| (!rInfo.bInNumBulList && !rHWrt.nDefListLvl) || |
| (rInfo.bInNumBulList && !bNumbered) || |
| (!rHWrt.bCfgOutStyles && |
| (bHasParSpace || pAdjItem || |
| (eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.eLang))) || |
| nDir != rHWrt.nDirection || |
| rHWrt.bCfgOutStyles ) |
| { |
| // jetzt werden Optionen ausgegeben |
| rHWrt.bTxtAttr = sal_False; |
| rHWrt.bOutOpts = sal_True; |
| |
| ByteString sOut( '<' ); |
| sOut += aToken; |
| |
| if( eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.eLang ) |
| { |
| rWrt.Strm() << sOut.GetBuffer(); |
| rHWrt.OutLanguage( eLang ); |
| sOut.Erase(); |
| } |
| |
| if( nDir != rHWrt.nDirection ) |
| { |
| if( sOut.Len() ) |
| { |
| rWrt.Strm() << sOut.GetBuffer(); |
| sOut.Erase(); |
| } |
| rHWrt.OutDirection( nDir ); |
| } |
| |
| if( rHWrt.bCfgOutStyles && |
| (pFmtInfo->aClass.Len() || pFmtInfo->bScriptDependent) ) |
| { |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\""; |
| rWrt.Strm() << sOut.GetBuffer(); |
| String aClass( pFmtInfo->aClass ); |
| if( pFmtInfo->bScriptDependent ) |
| { |
| if( aClass.Len() ) |
| aClass += '-'; |
| switch( rHWrt.nCSS1Script ) |
| { |
| case CSS1_OUTMODE_WESTERN: |
| aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("western") ); |
| break; |
| case CSS1_OUTMODE_CJK: |
| aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("cjk") ); |
| break; |
| case CSS1_OUTMODE_CTL: |
| aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("ctl") ); |
| break; |
| } |
| } |
| HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, |
| rHWrt.eDestEnc, &rHWrt.aNonConvertableCharacters ); |
| sOut = '\"'; |
| } |
| rWrt.Strm() << sOut.GetBuffer(); |
| |
| // ggf. Ausrichtung ausgeben. |
| if( !rHWrt.bNoAlign && pAdjItem ) |
| OutHTML_SvxAdjust( rWrt, *pAdjItem ); |
| |
| // und nun ggf. noch die STYLE-Option |
| if( rHWrt.bCfgOutStyles && rInfo.pItemSet && !bNoStyle) |
| { |
| OutCSS1_ParaTagStyleOpt( rWrt, *rInfo.pItemSet ); |
| } |
| |
| rWrt.Strm() << '>'; |
| |
| // Soll ein </P> geschrieben wenrden |
| rInfo.bOutPara = |
| bPara && |
| ( rHWrt.bCfgOutStyles || |
| (!rHWrt.bCfgOutStyles && bHasParSpace) ); |
| |
| // wenn kein End-Tag geschrieben werden soll, es loeschen |
| if( bNoEndTag ) |
| rInfo.aToken.Erase(); |
| } |
| |
| // ??? Warum nicht ueber den Hint-Mechanismus ??? |
| if( rHWrt.IsHTMLMode(HTMLMODE_FIRSTLINE) ) |
| { |
| const SvxLRSpaceItem& rLRSpaceTmp = |
| pNodeItemSet ? ((const SvxLRSpaceItem &)pNodeItemSet->Get(RES_LR_SPACE)) |
| : rFmt.GetLRSpace(); |
| if( rLRSpaceTmp.GetTxtFirstLineOfst() > 0 ) |
| { |
| OutHTML_HoriSpacer( rWrt, rLRSpaceTmp.GetTxtFirstLineOfst() ); |
| } |
| } |
| |
| if( nBulletGrfLvl != 255 ) |
| { |
| ASSERT( aNumInfo.GetNumRule(), "Wo ist die Numerierung geblieben???" ); |
| ASSERT( nBulletGrfLvl < MAXLEVEL, "So viele Ebenen gibt's nicht" ); |
| const SwNumFmt& rNumFmt = aNumInfo.GetNumRule()->Get(nBulletGrfLvl); |
| |
| OutHTML_BulletImage( rWrt, OOO_STRING_SVTOOLS_HTML_image, 0, |
| rHWrt.aBulletGrfs[nBulletGrfLvl], |
| rNumFmt.GetGraphicSize(), rNumFmt.GetGraphicOrientation() ); |
| } |
| |
| rHWrt.GetNumInfo() = aNumInfo; |
| |
| // die Defaults zuruecksetzen |
| rHWrt.nDfltLeftMargin = 0; |
| rHWrt.nDfltRightMargin = 0; |
| rHWrt.nDfltFirstLineIndent = 0; |
| rHWrt.nDfltTopMargin = 0; |
| rHWrt.nDfltBottomMargin = 0; |
| rHWrt.nLeftMargin = 0; |
| rHWrt.nFirstLineIndent = 0; |
| } |
| |
| void OutHTML_SwFmtOff( Writer& rWrt, const SwHTMLTxtCollOutputInfo& rInfo ) |
| { |
| SwHTMLWriter & rHWrt = (SwHTMLWriter&)rWrt; |
| |
| // wenn es kein Token gibt haben wir auch nichts auszugeben |
| if( !rInfo.aToken.Len() ) |
| { |
| rHWrt.FillNextNumInfo(); |
| const SwHTMLNumRuleInfo& rNextInfo = *rHWrt.GetNextNumInfo(); |
| // Auch in PRE muss eine Bullet-Liste beendet werden |
| if( rInfo.bInNumBulList ) |
| { |
| |
| const SwHTMLNumRuleInfo& rNRInfo = rHWrt.GetNumInfo(); |
| if( rNextInfo.GetNumRule() != rNRInfo.GetNumRule() || |
| rNextInfo.GetDepth() != rNRInfo.GetDepth() || |
| rNextInfo.IsNumbered() || rNextInfo.IsRestart() ) |
| rHWrt.ChangeParaToken( 0 ); |
| OutHTML_NumBulListEnd( rHWrt, rNextInfo ); |
| } |
| else if( rNextInfo.GetNumRule() != 0 ) |
| rHWrt.ChangeParaToken( 0 ); |
| |
| return; |
| } |
| |
| if( rInfo.ShouldOutputToken() ) |
| { |
| if( rHWrt.bLFPossible ) |
| rHWrt.OutNewLine( sal_True ); |
| |
| // fuer BLOCKQUOTE, ADDRESS und DD wird ggf noch ein |
| // Absatz-Token ausgegeben, wenn |
| // - keine Styles geschrieben werden, und |
| // - ein untere Abstand existiert |
| if( rInfo.bParaPossible && rInfo.bOutPara ) |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_parabreak, sal_False ); |
| |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rInfo.aToken.GetBuffer(), |
| sal_False ); |
| rHWrt.bLFPossible = !rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_dt ) && |
| !rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_dd ) && |
| !rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_li ); |
| } |
| if( rInfo.bOutDiv ) |
| { |
| rHWrt.DecIndentLevel(); |
| if( rHWrt.bLFPossible ) |
| rHWrt.OutNewLine(); |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_division, sal_False ); |
| rHWrt.bLFPossible = sal_True; |
| } |
| |
| // ggf. eine Aufzaehlung- oder Numerierungsliste beenden |
| if( rInfo.bInNumBulList ) |
| { |
| rHWrt.FillNextNumInfo(); |
| OutHTML_NumBulListEnd( rHWrt, *rHWrt.GetNextNumInfo() ); |
| } |
| } |
| |
| |
| class HTMLSttEndPos |
| { |
| xub_StrLen nStart; |
| xub_StrLen nEnd; |
| SfxPoolItem* pItem; |
| |
| public: |
| |
| HTMLSttEndPos( const SfxPoolItem& rItem, xub_StrLen nStt, xub_StrLen nE ); |
| ~HTMLSttEndPos(); |
| |
| const SfxPoolItem *GetItem() const { return pItem; } |
| |
| void SetStart( xub_StrLen nStt ) { nStart = nStt; } |
| xub_StrLen GetStart() const { return nStart; } |
| |
| xub_StrLen GetEnd() const { return nEnd; } |
| void SetEnd( xub_StrLen nE ) { nEnd = nE; } |
| }; |
| |
| HTMLSttEndPos::HTMLSttEndPos( const SfxPoolItem& rItem, xub_StrLen nStt, |
| xub_StrLen nE ) : |
| nStart( nStt ), |
| nEnd( nE ), |
| pItem( rItem.Clone() ) |
| {} |
| |
| HTMLSttEndPos::~HTMLSttEndPos() |
| { |
| delete pItem; |
| } |
| |
| typedef HTMLSttEndPos *HTMLSttEndPosPtr; |
| SV_DECL_PTRARR( _HTMLEndLst, HTMLSttEndPosPtr, 5, 5 ) |
| |
| enum HTMLOnOffState { HTML_NOT_SUPPORTED, // nicht unterst. Attribut |
| HTML_REAL_VALUE, // Attribut mit Wert |
| HTML_ON_VALUE, // Attribut entspricht On-Tag |
| HTML_OFF_VALUE, // Attribut entspricht Off-Tag |
| HTML_CHRFMT_VALUE, // Attribut fuer Zeichenvorlage |
| HTML_COLOR_VALUE, // Attribut fuer Vordergrundfarbe |
| HTML_STYLE_VALUE, // Attribut muss als Style exp. |
| HTML_DROPCAP_VALUE, // DropCap-Attributs |
| HTML_AUTOFMT_VALUE }; // Attribute for automatic character styles |
| |
| |
| class HTMLEndPosLst |
| { |
| _HTMLEndLst aStartLst; // nach Anfangs-Psoitionen sortierte Liste |
| _HTMLEndLst aEndLst; // nach End-Psotionen sortierte Liste |
| SvXub_StrLens aScriptChgLst; // positions where script changes |
| // 0 is not contained in this list, |
| // but the text length |
| // the script that is valif up to the position |
| // contained in aScriptChgList at the same index |
| ::std::vector<sal_uInt16> aScriptLst; |
| |
| SwDoc *pDoc; // das aktuelle Dokument |
| SwDoc* pTemplate; // die HTML-Vorlage (oder 0) |
| const Color* pDfltColor;// die Default-Vordergrund-Farbe |
| SvStringsSortDtor& rScriptTxtStyles; // |
| |
| sal_uLong nHTMLMode; |
| sal_Bool bOutStyles : 1; // werden Styles exportiert |
| |
| |
| // die Position eines Items in der Start-/Ende-Liste suchen |
| sal_uInt16 _FindStartPos( const HTMLSttEndPos *pPos ) const; |
| sal_uInt16 _FindEndPos( const HTMLSttEndPos *pPos ) const; |
| |
| // Eine SttEndPos in die Start- und Ende-Listen eintragen bzw. aus |
| // ihnen loeschen, wobei die Ende-Position bekannt ist |
| void _InsertItem( HTMLSttEndPos *pPos, sal_uInt16 nEndPos ); |
| void _RemoveItem( sal_uInt16 nEndPos ); |
| |
| // die "Art" es Attributs ermitteln |
| HTMLOnOffState GetHTMLItemState( const SfxPoolItem& rItem ); |
| |
| // Existiert ein bestimmtes On-Tag-Item |
| sal_Bool ExistsOnTagItem( sal_uInt16 nWhich, xub_StrLen nPos ); |
| |
| // Existiert ein Item zum ausschalten eines Attributs, das genauso |
| // exportiert wird wie das uebergebene Item im gleichen Bereich? |
| sal_Bool ExistsOffTagItem( sal_uInt16 nWhich, xub_StrLen nStartPos, |
| xub_StrLen nEndPos ); |
| |
| |
| // das Ende eines gesplitteten Items anpassen |
| void FixSplittedItem( HTMLSttEndPos *pPos, sal_uInt16 nStartPos, |
| xub_StrLen nNewEnd ); |
| |
| // Ein Attribut in die Listen eintragen und ggf. aufteilen |
| void InsertItem( const SfxPoolItem& rItem, xub_StrLen nStart, |
| xub_StrLen nEnd ); |
| |
| // Ein bereits vorhandenes Attribut aufteilen |
| void SplitItem( const SfxPoolItem& rItem, xub_StrLen nStart, |
| xub_StrLen nEnd ); |
| |
| // Insert without taking care of script |
| void InsertNoScript( const SfxPoolItem& rItem, xub_StrLen nStart, |
| xub_StrLen nEnd, SwHTMLFmtInfos& rFmtInfos, |
| sal_Bool bParaAttrs=sal_False ); |
| |
| const SwHTMLFmtInfo *GetFmtInfo( const SwFmt& rFmt, |
| SwHTMLFmtInfos& rFmtInfos ); |
| |
| public: |
| |
| HTMLEndPosLst( SwDoc *pDoc, SwDoc* pTemplate, const Color* pDfltColor, |
| sal_Bool bOutStyles, sal_uLong nHTMLMode, |
| const String& rText, SvStringsSortDtor& rStyles ); |
| ~HTMLEndPosLst(); |
| |
| // Ein Attribut einfuegen |
| void Insert( const SfxPoolItem& rItem, xub_StrLen nStart, xub_StrLen nEnd, |
| SwHTMLFmtInfos& rFmtInfos, sal_Bool bParaAttrs=sal_False ); |
| void Insert( const SfxItemSet& rItemSet, xub_StrLen nStart, xub_StrLen nEnd, |
| SwHTMLFmtInfos& rFmtInfos, sal_Bool bDeep, |
| sal_Bool bParaAttrs=sal_False ); |
| void Insert( const SwDrawFrmFmt& rFmt, xub_StrLen nPos, |
| SwHTMLFmtInfos& rFmtInfos ); |
| |
| sal_uInt16 GetScriptAtPos( xub_StrLen nPos, |
| sal_uInt16 nWeak=CSS1_OUTMODE_ANY_SCRIPT ); |
| |
| void OutStartAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos, |
| HTMLOutContext *pContext = 0 ); |
| void OutEndAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos, |
| HTMLOutContext *pContext = 0 ); |
| |
| sal_uInt16 Count() const { return aEndLst.Count(); } |
| |
| sal_Bool IsHTMLMode( sal_uLong nMode ) const { return (nHTMLMode & nMode) != 0; } |
| }; |
| |
| |
| sal_uInt16 HTMLEndPosLst::_FindStartPos( const HTMLSttEndPos *pPos ) const |
| { |
| sal_uInt16 i; |
| for( i = 0; i < aStartLst.Count() && aStartLst[i] != pPos; i++ ) |
| ; |
| |
| ASSERT( i != aStartLst.Count(), "Item nicht in Start-Liste gefunden!" ); |
| |
| return i==aStartLst.Count() ? USHRT_MAX : i; |
| } |
| |
| sal_uInt16 HTMLEndPosLst::_FindEndPos( const HTMLSttEndPos *pPos ) const |
| { |
| sal_uInt16 i; |
| |
| for( i = 0; i < aEndLst.Count() && aEndLst[i] != pPos; i++ ) |
| ; |
| |
| ASSERT( i != aEndLst.Count(), "Item nicht in Ende-Liste gefunden" ); |
| |
| return i==aEndLst.Count() ? USHRT_MAX : i; |
| } |
| |
| |
| void HTMLEndPosLst::_InsertItem( HTMLSttEndPos *pPos, sal_uInt16 nEndPos ) |
| { |
| // In der Start-Liste das Attribut hinter allen vorher und an |
| // der gleichen Position gestarteten Attributen einfuegen |
| xub_StrLen nStart = pPos->GetStart(); |
| sal_uInt16 i; |
| |
| for( i = 0; i < aStartLst.Count() && |
| aStartLst[i]->GetStart() <= nStart; i++ ) |
| ; |
| aStartLst.Insert( pPos, i ); |
| |
| // die Position in der Ende-Liste wurde uebergeben |
| aEndLst.Insert( pPos, nEndPos ); |
| } |
| |
| void HTMLEndPosLst::_RemoveItem( sal_uInt16 nEndPos ) |
| { |
| HTMLSttEndPos *pPos = aEndLst[nEndPos]; |
| |
| // jetzt Suchen wir es in der Start-Liste |
| sal_uInt16 nStartPos = _FindStartPos( pPos ); |
| if( nStartPos != USHRT_MAX ) |
| aStartLst.Remove( nStartPos, 1 ); |
| |
| aEndLst.Remove( nEndPos, 1 ); |
| |
| delete pPos; |
| } |
| |
| HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem ) |
| { |
| HTMLOnOffState eState = HTML_NOT_SUPPORTED; |
| switch( rItem.Which() ) |
| { |
| case RES_CHRATR_POSTURE: |
| case RES_CHRATR_CJK_POSTURE: |
| case RES_CHRATR_CTL_POSTURE: |
| switch( ((const SvxPostureItem&)rItem).GetPosture() ) |
| { |
| case ITALIC_NORMAL: |
| eState = HTML_ON_VALUE; |
| break; |
| case ITALIC_NONE: |
| eState = HTML_OFF_VALUE; |
| break; |
| default: |
| if( IsHTMLMode(HTMLMODE_SOME_STYLES) ) |
| eState = HTML_STYLE_VALUE; |
| break; |
| } |
| break; |
| |
| case RES_CHRATR_CROSSEDOUT: |
| switch( ((const SvxCrossedOutItem&)rItem).GetStrikeout() ) |
| { |
| case STRIKEOUT_SINGLE: |
| case STRIKEOUT_DOUBLE: |
| eState = HTML_ON_VALUE; |
| break; |
| case STRIKEOUT_NONE: |
| eState = HTML_OFF_VALUE; |
| break; |
| default: |
| ; |
| } |
| break; |
| |
| case RES_CHRATR_ESCAPEMENT: |
| switch( (const SvxEscapement) |
| ((const SvxEscapementItem&)rItem).GetEnumValue() ) |
| { |
| case SVX_ESCAPEMENT_SUPERSCRIPT: |
| case SVX_ESCAPEMENT_SUBSCRIPT: |
| eState = HTML_ON_VALUE; |
| break; |
| case SVX_ESCAPEMENT_OFF: |
| eState = HTML_OFF_VALUE; |
| break; |
| default: |
| ; |
| } |
| break; |
| |
| case RES_CHRATR_UNDERLINE: |
| switch( ((const SvxUnderlineItem&)rItem).GetLineStyle() ) |
| { |
| case UNDERLINE_SINGLE: |
| eState = HTML_ON_VALUE; |
| break; |
| case UNDERLINE_NONE: |
| eState = HTML_OFF_VALUE; |
| break; |
| default: |
| if( IsHTMLMode(HTMLMODE_SOME_STYLES) ) |
| eState = HTML_STYLE_VALUE; |
| break; |
| } |
| break; |
| |
| case RES_CHRATR_OVERLINE: |
| if( IsHTMLMode(HTMLMODE_SOME_STYLES) ) |
| eState = HTML_STYLE_VALUE; |
| break; |
| |
| case RES_CHRATR_WEIGHT: |
| case RES_CHRATR_CJK_WEIGHT: |
| case RES_CHRATR_CTL_WEIGHT: |
| switch( ((const SvxWeightItem&)rItem).GetWeight() ) |
| { |
| case WEIGHT_BOLD: |
| eState = HTML_ON_VALUE; |
| break; |
| case WEIGHT_NORMAL: |
| eState = HTML_OFF_VALUE; |
| break; |
| default: |
| if( IsHTMLMode(HTMLMODE_SOME_STYLES) ) |
| eState = HTML_STYLE_VALUE; |
| break; |
| } |
| break; |
| |
| case RES_CHRATR_BLINK: |
| if( IsHTMLMode(HTMLMODE_BLINK) ) |
| eState = ((const SvxBlinkItem&)rItem).GetValue() ? HTML_ON_VALUE |
| : HTML_OFF_VALUE; |
| break; |
| |
| case RES_CHRATR_COLOR: |
| eState = HTML_COLOR_VALUE; |
| break; |
| |
| case RES_CHRATR_FONT: |
| case RES_CHRATR_FONTSIZE: |
| case RES_CHRATR_LANGUAGE: |
| case RES_CHRATR_CJK_FONT: |
| case RES_CHRATR_CJK_FONTSIZE: |
| case RES_CHRATR_CJK_LANGUAGE: |
| case RES_CHRATR_CTL_FONT: |
| case RES_CHRATR_CTL_FONTSIZE: |
| case RES_CHRATR_CTL_LANGUAGE: |
| case RES_TXTATR_INETFMT: |
| eState = HTML_REAL_VALUE; |
| break; |
| |
| case RES_TXTATR_CHARFMT: |
| eState = HTML_CHRFMT_VALUE; |
| break; |
| |
| case RES_TXTATR_AUTOFMT: |
| eState = HTML_AUTOFMT_VALUE; |
| break; |
| |
| case RES_CHRATR_CASEMAP: |
| if( IsHTMLMode(HTMLMODE_SMALL_CAPS) ) |
| eState = HTML_STYLE_VALUE; |
| |
| case RES_CHRATR_KERNING: |
| if( IsHTMLMode(HTMLMODE_FULL_STYLES) ) |
| eState = HTML_STYLE_VALUE; |
| break; |
| |
| case RES_CHRATR_BACKGROUND: |
| if( IsHTMLMode(HTMLMODE_SOME_STYLES) ) |
| eState = HTML_STYLE_VALUE; |
| break; |
| |
| case RES_PARATR_DROP: |
| eState = HTML_DROPCAP_VALUE; |
| break; |
| |
| // default: |
| // eState = HTML_NOT_SUPPORTED; |
| // break; |
| } |
| |
| return eState; |
| } |
| |
| sal_Bool HTMLEndPosLst::ExistsOnTagItem( sal_uInt16 nWhich, xub_StrLen nPos ) |
| { |
| for( sal_uInt16 i=0; i<aStartLst.Count(); i++ ) |
| { |
| HTMLSttEndPos *pTest = aStartLst[i]; |
| |
| if( pTest->GetStart() > nPos ) |
| { |
| // dieses uns alle folgenden Attribute beginnen spaeter |
| break; |
| } |
| else if( pTest->GetEnd() > nPos ) |
| { |
| // das Attribut beginnt vor oder an der aktuellen Position |
| // und endet hinter ihr |
| const SfxPoolItem *pItem = pTest->GetItem(); |
| if( pItem->Which() == nWhich && |
| HTML_ON_VALUE == GetHTMLItemState(*pItem) ) |
| { |
| // ein On-Tag-Attibut wurde gefunden |
| return sal_True; |
| } |
| } |
| } |
| |
| return sal_False; |
| } |
| |
| sal_Bool HTMLEndPosLst::ExistsOffTagItem( sal_uInt16 nWhich, xub_StrLen nStartPos, |
| xub_StrLen nEndPos ) |
| { |
| if( nWhich != RES_CHRATR_CROSSEDOUT && |
| nWhich != RES_CHRATR_UNDERLINE && |
| nWhich != RES_CHRATR_BLINK ) |
| { |
| return sal_False; |
| } |
| |
| for( sal_uInt16 i=0; i<aStartLst.Count(); i++ ) |
| { |
| HTMLSttEndPos *pTest = aStartLst[i]; |
| |
| if( pTest->GetStart() > nStartPos ) |
| { |
| // dieses uns alle folgenden Attribute beginnen spaeter |
| break; |
| } |
| else if( pTest->GetStart()==nStartPos && |
| pTest->GetEnd()==nEndPos ) |
| { |
| // das Attribut beginnt vor oder an der aktuellen Position |
| // und endet hinter ihr |
| const SfxPoolItem *pItem = pTest->GetItem(); |
| sal_uInt16 nTstWhich = pItem->Which() ; |
| if( (nTstWhich == RES_CHRATR_CROSSEDOUT || |
| nTstWhich == RES_CHRATR_UNDERLINE || |
| nTstWhich == RES_CHRATR_BLINK) && |
| HTML_OFF_VALUE == GetHTMLItemState(*pItem) ) |
| { |
| // Ein Off-Tag-Attibut wurde gefunden, das genauso |
| // exportiert wird, wie das aktuelle Item |
| return sal_True; |
| } |
| } |
| } |
| |
| return sal_False; |
| } |
| |
| void HTMLEndPosLst::FixSplittedItem( HTMLSttEndPos *pPos, xub_StrLen nNewEnd, |
| sal_uInt16 nStartPos ) |
| { |
| // die End-Position entsprechend fixen |
| pPos->SetEnd( nNewEnd ); |
| |
| // das Item aus der End-Liste entfernen |
| sal_uInt16 nEndPos = _FindEndPos( pPos ); |
| if( nEndPos != USHRT_MAX ) |
| aEndLst.Remove( nEndPos, 1 ); |
| |
| // es wird von nun an als letztes an der entsprechenden Position |
| // beendet |
| for( nEndPos=0; nEndPos < aEndLst.Count() && |
| aEndLst[nEndPos]->GetEnd() <= nNewEnd; nEndPos++ ) |
| ; |
| aEndLst.Insert( pPos, nEndPos ); |
| |
| // jetzt noch die spaeter gestarteten Attribute anpassen |
| for( sal_uInt16 i=nStartPos+1; i<aStartLst.Count(); i++ ) |
| { |
| HTMLSttEndPos *pTest = aStartLst[i]; |
| xub_StrLen nTestEnd = pTest->GetEnd(); |
| if( pTest->GetStart() >= nNewEnd ) |
| { |
| // das Test-Attribut und alle folgenden beginnen, nachdem das |
| // gesplittete Attribut endet |
| break; |
| } |
| else if( nTestEnd > nNewEnd ) |
| { |
| // das Test-Attribut beginnt, bevor das gesplittete Attribut |
| // endet und endet danach, muss also auch gesplittet werden |
| |
| // das neue Ende setzen |
| pTest->SetEnd( nNewEnd ); |
| |
| // das Attribut aus der End-Liste entfernen |
| sal_uInt16 nEPos = _FindEndPos( pTest ); |
| if( nEPos != USHRT_MAX ) |
| aEndLst.Remove( nEPos, 1 ); |
| |
| // es endet jetzt als erstes Attribut an der entsprechenden |
| // Position. Diese Position in der Ende-Liste kennen wir schon. |
| aEndLst.Insert(pTest, nEndPos ); |
| |
| // den "Rest" des Attributs neu einfuegen |
| InsertItem( *pTest->GetItem(), nNewEnd, nTestEnd ); |
| } |
| } |
| } |
| |
| |
| void HTMLEndPosLst::InsertItem( const SfxPoolItem& rItem, xub_StrLen nStart, |
| xub_StrLen nEnd ) |
| { |
| sal_uInt16 i; |
| for( i = 0; i < aEndLst.Count(); i++ ) |
| { |
| HTMLSttEndPos *pTest = aEndLst[i]; |
| xub_StrLen nTestEnd = pTest->GetEnd(); |
| if( nTestEnd <= nStart ) |
| { |
| // das Test-Attribut endet, bevor das neue beginnt |
| continue; |
| } |
| else if( nTestEnd < nEnd ) |
| { |
| // das Test-Attribut endet, bevor das neue endet. Das |
| // neue Attribut muss deshalb aufgesplittet werden |
| _InsertItem( new HTMLSttEndPos( rItem, nStart, nTestEnd ), i ); |
| nStart = nTestEnd; |
| } |
| else |
| { |
| // das Test-Attribut (und alle folgenden) endet, bevor das neue |
| // endet |
| break; |
| } |
| } |
| |
| // ein Attribut muss noch eingefuegt werden |
| _InsertItem( new HTMLSttEndPos( rItem, nStart, nEnd ), i ); |
| } |
| |
| |
| |
| void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, xub_StrLen nStart, |
| xub_StrLen nEnd ) |
| { |
| sal_uInt16 nWhich = rItem.Which(); |
| |
| // erstmal muessen wir die alten Items anhand der Startliste suchen |
| // und die neuen Item-Bereiche festlegen |
| |
| for( sal_uInt16 i=0; i<aStartLst.Count(); i++ ) |
| { |
| HTMLSttEndPos *pTest = aStartLst[i]; |
| xub_StrLen nTestStart = pTest->GetStart(); |
| xub_StrLen nTestEnd = pTest->GetEnd(); |
| |
| if( nTestStart >= nEnd ) |
| { |
| // dieses und alle nachfolgenden Attribute beginnen spaeter |
| break; |
| } |
| else if( nTestEnd > nStart ) |
| { |
| // das Test Attribut endet im zu loeschenenden Bereich |
| const SfxPoolItem *pItem = pTest->GetItem(); |
| |
| // nur entsprechende On-Tag Attribute muessen beruecksichtigt |
| // werden |
| if( pItem->Which() == nWhich && |
| HTML_ON_VALUE == GetHTMLItemState( *pItem ) ) |
| { |
| sal_Bool bDelete = sal_True; |
| |
| if( nTestStart < nStart ) |
| { |
| // der Start des neuen Attribut entspricht |
| // dem neuen Ende des Attribts |
| FixSplittedItem( pTest, nStart, i ); |
| bDelete = sal_False; |
| } |
| else |
| { |
| // das Test-Item beginnt erst hinter dem neuen |
| // Ende des Attribts und kann deshalb komplett |
| // geloescht werden |
| aStartLst.Remove( i, 1 ); |
| i--; |
| |
| sal_uInt16 nEndPos = _FindEndPos( pTest ); |
| if( nEndPos != USHRT_MAX ) |
| aEndLst.Remove( nEndPos, 1 ); |
| } |
| |
| // ggf den zweiten Teil des gesplitteten Attribts einfuegen |
| if( nTestEnd > nEnd ) |
| { |
| InsertItem( *pTest->GetItem(), nEnd, nTestEnd ); |
| } |
| |
| if( bDelete ) |
| delete pTest; |
| } |
| } |
| } |
| } |
| |
| const SwHTMLFmtInfo *HTMLEndPosLst::GetFmtInfo( const SwFmt& rFmt, |
| SwHTMLFmtInfos& rFmtInfos ) |
| { |
| const SwHTMLFmtInfo *pFmtInfo; |
| SwHTMLFmtInfo aFmtInfo( &rFmt ); |
| sal_uInt16 nPos; |
| if( rFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) ) |
| { |
| pFmtInfo = rFmtInfos[nPos]; |
| } |
| else |
| { |
| pFmtInfo = new SwHTMLFmtInfo( &rFmt, pDoc, pTemplate, |
| bOutStyles ); |
| rFmtInfos.C40_PTR_INSERT( SwHTMLFmtInfo, pFmtInfo ); |
| String aName( rFmt.GetName() ); |
| if( rScriptTxtStyles.Seek_Entry( &aName ) ) |
| ((SwHTMLFmtInfo *)pFmtInfo)->bScriptDependent = sal_True; |
| } |
| |
| return pFmtInfo; |
| } |
| |
| HTMLEndPosLst::HTMLEndPosLst( SwDoc *pD, SwDoc* pTempl, |
| const Color* pDfltCol, sal_Bool bStyles, |
| sal_uLong nMode, const String& rText, |
| SvStringsSortDtor& rStyles ): |
| pDoc( pD ), |
| pTemplate( pTempl ), |
| pDfltColor( pDfltCol ), |
| rScriptTxtStyles( rStyles ), |
| nHTMLMode( nMode ), |
| bOutStyles( bStyles ) |
| { |
| xub_StrLen nEndPos = rText.Len(); |
| xub_StrLen nPos = 0; |
| while( nPos < nEndPos ) |
| { |
| sal_uInt16 nScript = pBreakIt->GetBreakIter()->getScriptType( rText, nPos ); |
| nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rText, nPos, nScript ); |
| aScriptChgLst.push_back( nPos ); |
| aScriptLst.push_back( nScript ); |
| } |
| } |
| |
| HTMLEndPosLst::~HTMLEndPosLst() |
| { |
| ASSERT( !aStartLst.Count(), "Start-Liste im Destruktor nicht leer" ); |
| ASSERT( !aEndLst.Count(), "End-Liste im Destruktor nicht leer" ); |
| } |
| |
| |
| |
| void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, |
| xub_StrLen nStart, xub_StrLen nEnd, |
| SwHTMLFmtInfos& rFmtInfos, sal_Bool bParaAttrs ) |
| { |
| // kein Bereich ?? dann nicht aufnehmen, wird nie wirksam !! |
| if( nStart != nEnd ) |
| { |
| sal_Bool bSet = sal_False, bSplit = sal_False; |
| switch( GetHTMLItemState(rItem) ) |
| { |
| case HTML_ON_VALUE: |
| // das Attribut wird ausgegeben, wenn es nicht sowieso |
| // schon an ist |
| if( !ExistsOnTagItem( rItem.Which(), nStart ) ) |
| bSet = sal_True; |
| break; |
| |
| case HTML_OFF_VALUE: |
| // wenn das entsprechne Attribut an ist, wird es gesplittet, |
| // Zusaetlich wird es aber als Style ausgegeben, wenn es nicht |
| // am ganzen Absatz gesetzt ist, weil es dann ja schon mit dem |
| // ABsatz-Tag ausgegeben wurde. |
| if( ExistsOnTagItem( rItem.Which(), nStart ) ) |
| bSplit = sal_True; |
| bSet = bOutStyles && !bParaAttrs && |
| !ExistsOffTagItem( rItem.Which(), nStart, nEnd ); |
| break; |
| |
| case HTML_REAL_VALUE: |
| // das Attribut kann immer ausgegeben werden |
| bSet = sal_True; |
| break; |
| |
| case HTML_STYLE_VALUE: |
| // Das Attribut kann nur als CSS1 ausgegeben werden. Wenn |
| // es am Absatz gesetzt ist, wurde es schon mit dem |
| // Absatz-Tag ausgegeben. Einzige Ausnahme ist das |
| // Zeichen-Hintergrund-Attribut. Es muss immer wie ein |
| // Hint behandelt werden. |
| bSet = bOutStyles && |
| (!bParaAttrs |
| || rItem.Which()==RES_CHRATR_BACKGROUND |
| || rItem.Which()==RES_CHRATR_OVERLINE); |
| break; |
| |
| case HTML_CHRFMT_VALUE: |
| { |
| ASSERT( RES_TXTATR_CHARFMT == rItem.Which(), |
| "Doch keine Zeichen-Vorlage" ); |
| const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rItem; |
| const SwCharFmt* pFmt = rChrFmt.GetCharFmt(); |
| |
| const SwHTMLFmtInfo *pFmtInfo = GetFmtInfo( *pFmt, rFmtInfos ); |
| if( pFmtInfo->aToken.Len() ) |
| { |
| // das Zeichenvorlagen-Tag muss vor den harten |
| // Attributen ausgegeben werden |
| InsertItem( rItem, nStart, nEnd ); |
| } |
| if( pFmtInfo->pItemSet ) |
| { |
| Insert( *pFmtInfo->pItemSet, nStart, nEnd, |
| rFmtInfos, sal_True, bParaAttrs ); |
| } |
| } |
| break; |
| |
| case HTML_AUTOFMT_VALUE: |
| { |
| const SwFmtAutoFmt& rAutoFmt = (const SwFmtAutoFmt&)rItem; |
| const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle(); |
| if( pSet.get() ) |
| Insert( *pSet.get(), nStart, nEnd, rFmtInfos, sal_True, bParaAttrs ); |
| } |
| break; |
| |
| case HTML_COLOR_VALUE: |
| // Eine Vordergrund-Farbe als Absatz-Attribut wird nur |
| // exportiert, wenn sie nicht der Default-Farbe entspricht. |
| { |
| ASSERT( RES_CHRATR_COLOR == rItem.Which(), |
| "Doch keine Vordergrund-Farbe" ); |
| Color aColor( ((const SvxColorItem&)rItem).GetValue() ); |
| if( COL_AUTO == aColor.GetColor() ) |
| aColor.SetColor( COL_BLACK ); |
| bSet = !bParaAttrs || !pDfltColor || |
| !pDfltColor->IsRGBEqual( aColor ); |
| } |
| break; |
| |
| case HTML_DROPCAP_VALUE: |
| { |
| ASSERT( RES_PARATR_DROP == rItem.Which(), |
| "Doch kein Drop-Cap" ); |
| const SwFmtDrop& rDrop = (const SwFmtDrop&)rItem; |
| nEnd = nStart + rDrop.GetChars(); |
| if( !bOutStyles ) |
| { |
| // Zumindest die Attribute der Zeichenvorlage uebernehmen |
| const SwCharFmt *pCharFmt = rDrop.GetCharFmt(); |
| if( pCharFmt ) |
| { |
| Insert( pCharFmt->GetAttrSet(), nStart, nEnd, |
| rFmtInfos, sal_True, bParaAttrs ); |
| } |
| } |
| else |
| { |
| bSet = sal_True; |
| } |
| } |
| break; |
| default: |
| ; |
| } |
| |
| if( bSet ) |
| InsertItem( rItem, nStart, nEnd ); |
| if( bSplit ) |
| SplitItem( rItem, nStart, nEnd ); |
| } |
| } |
| |
| void HTMLEndPosLst::Insert( const SfxPoolItem& rItem, |
| xub_StrLen nStart, xub_StrLen nEnd, |
| SwHTMLFmtInfos& rFmtInfos, sal_Bool bParaAttrs ) |
| { |
| sal_Bool bDependsOnScript = sal_False, bDependsOnAnyScript = sal_False; |
| sal_uInt16 nScript = i18n::ScriptType::LATIN; |
| switch( rItem.Which() ) |
| { |
| case RES_CHRATR_FONT: |
| case RES_CHRATR_FONTSIZE: |
| case RES_CHRATR_LANGUAGE: |
| case RES_CHRATR_POSTURE: |
| case RES_CHRATR_WEIGHT: |
| bDependsOnScript = sal_True; |
| nScript = i18n::ScriptType::LATIN; |
| break; |
| |
| case RES_CHRATR_CJK_FONT: |
| case RES_CHRATR_CJK_FONTSIZE: |
| case RES_CHRATR_CJK_LANGUAGE: |
| case RES_CHRATR_CJK_POSTURE: |
| case RES_CHRATR_CJK_WEIGHT: |
| bDependsOnScript = sal_True; |
| nScript = i18n::ScriptType::ASIAN; |
| break; |
| |
| case RES_CHRATR_CTL_FONT: |
| case RES_CHRATR_CTL_FONTSIZE: |
| case RES_CHRATR_CTL_LANGUAGE: |
| case RES_CHRATR_CTL_POSTURE: |
| case RES_CHRATR_CTL_WEIGHT: |
| bDependsOnScript = sal_True; |
| nScript = i18n::ScriptType::COMPLEX; |
| break; |
| case RES_TXTATR_CHARFMT: |
| { |
| const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rItem; |
| const SwCharFmt* pFmt = rChrFmt.GetCharFmt(); |
| const SwHTMLFmtInfo *pFmtInfo = GetFmtInfo( *pFmt, rFmtInfos ); |
| if( pFmtInfo->bScriptDependent ) |
| { |
| bDependsOnScript = sal_True; |
| bDependsOnAnyScript = sal_True; |
| } |
| } |
| break; |
| case RES_TXTATR_INETFMT: |
| { |
| if( GetFmtInfo( *pDoc->GetCharFmtFromPool( |
| RES_POOLCHR_INET_NORMAL), rFmtInfos )->bScriptDependent || |
| GetFmtInfo( *pDoc->GetCharFmtFromPool( |
| RES_POOLCHR_INET_VISIT), rFmtInfos )->bScriptDependent ) |
| { |
| bDependsOnScript = sal_True; |
| bDependsOnAnyScript = sal_True; |
| } |
| } |
| break; |
| } |
| |
| if( bDependsOnScript ) |
| { |
| xub_StrLen nPos = nStart; |
| for( size_t i=0; i < aScriptChgLst.size(); i++ ) |
| { |
| xub_StrLen nChgPos = aScriptChgLst[i]; |
| if( nPos >= nChgPos ) |
| { |
| // the hint starts behind or at the next script change, |
| // so we may continue with this position. |
| continue; |
| } |
| if( nEnd <= nChgPos ) |
| { |
| // the (rest of) the hint ends before or at the next script |
| // change, so we can insert it, but only if it belongs |
| // to the current script. |
| if( bDependsOnAnyScript || nScript == aScriptLst[i] ) |
| InsertNoScript( rItem, nPos, nEnd, rFmtInfos, |
| bParaAttrs ); |
| break; |
| } |
| |
| // the hint starts before the next script change and ends behind |
| // it, so we can insert a hint up to the next script change and |
| // continue with the rest of the hint. |
| if( bDependsOnAnyScript || nScript == aScriptLst[i] ) |
| InsertNoScript( rItem, nPos, nChgPos, rFmtInfos, bParaAttrs ); |
| nPos = nChgPos; |
| } |
| } |
| else |
| { |
| InsertNoScript( rItem, nStart, nEnd, rFmtInfos, bParaAttrs ); |
| } |
| } |
| |
| void HTMLEndPosLst::Insert( const SfxItemSet& rItemSet, |
| xub_StrLen nStart, xub_StrLen nEnd, |
| SwHTMLFmtInfos& rFmtInfos, |
| sal_Bool bDeep, sal_Bool bParaAttrs ) |
| { |
| SfxWhichIter aIter( rItemSet ); |
| |
| sal_uInt16 nWhich = aIter.FirstWhich(); |
| while( nWhich ) |
| { |
| const SfxPoolItem *pItem; |
| if( SFX_ITEM_SET == rItemSet.GetItemState( nWhich, bDeep, &pItem ) ) |
| { |
| Insert( *pItem, nStart, nEnd, rFmtInfos, bParaAttrs ); |
| } |
| |
| nWhich = aIter.NextWhich(); |
| } |
| } |
| |
| void HTMLEndPosLst::Insert( const SwDrawFrmFmt& rFmt, xub_StrLen nPos, |
| SwHTMLFmtInfos& rFmtInfos ) |
| { |
| // der Type-Cast ist nur noetig, um nicht seinetwegen |
| // svdrwobt.hxx zu includem |
| const SdrObject* pTextObj = |
| (const SdrObject *)SwHTMLWriter::GetMarqueeTextObj( rFmt ); |
| |
| if( pTextObj ) |
| { |
| // die Edit-Engine-Attribute des Objekts als SW-Attribute holen |
| // und als Hints einsortieren. Wegen der Menge der Hints werden |
| // Styles hierbei nicht beruecksichtigt! |
| const SfxItemSet& rFmtItemSet = rFmt.GetAttrSet(); |
| SfxItemSet aItemSet( *rFmtItemSet.GetPool(), RES_CHRATR_BEGIN, |
| RES_CHRATR_END ); |
| SwHTMLWriter::GetEEAttrsFromDrwObj( aItemSet, pTextObj, sal_True ); |
| sal_Bool bOutStylesOld = bOutStyles; |
| bOutStyles = sal_False; |
| Insert( aItemSet, nPos, nPos+1, rFmtInfos, sal_False, sal_False ); |
| bOutStyles = bOutStylesOld; |
| } |
| } |
| |
| sal_uInt16 HTMLEndPosLst::GetScriptAtPos( xub_StrLen nPos , |
| sal_uInt16 nWeak ) |
| { |
| sal_uInt16 nRet = CSS1_OUTMODE_ANY_SCRIPT; |
| |
| size_t nScriptChgs = aScriptChgLst.size(); |
| size_t i=0; |
| while( i < nScriptChgs && nPos >= aScriptChgLst[i] ) |
| i++; |
| ASSERT( i < nScriptChgs, "script list is to short" ); |
| if( i < nScriptChgs ) |
| { |
| if( i18n::ScriptType::WEAK == aScriptLst[i] ) |
| nRet = nWeak; |
| else |
| nRet = SwHTMLWriter::GetCSS1ScriptForScriptType( aScriptLst[i] ); |
| } |
| |
| return nRet; |
| } |
| |
| void HTMLEndPosLst::OutStartAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos, |
| HTMLOutContext *pContext ) |
| { |
| rHWrt.bTagOn = sal_True; |
| |
| // die Attribute in der Start-Liste sind aufsteigend sortiert |
| for( sal_uInt16 i=0; i< aStartLst.Count(); i++ ) |
| { |
| HTMLSttEndPos *pPos = aStartLst[i]; |
| xub_StrLen nStart = pPos->GetStart(); |
| if( nStart > nPos ) |
| { |
| // dieses und alle folgenden Attribute werden erst noch geoeffnet |
| break; |
| } |
| else if( nStart == nPos ) |
| { |
| // das Attribut ausgeben |
| sal_uInt16 nCSS1Script = rHWrt.nCSS1Script; |
| sal_uInt16 nWhich = pPos->GetItem()->Which(); |
| if( RES_TXTATR_CHARFMT == nWhich || |
| RES_TXTATR_INETFMT == nWhich || |
| RES_PARATR_DROP == nWhich ) |
| { |
| rHWrt.nCSS1Script = GetScriptAtPos( nPos, nCSS1Script ); |
| } |
| if( pContext ) |
| { |
| HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext ); |
| pContext = 0; // one time ony |
| } |
| Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt ); |
| rHWrt.nCSS1Script = nCSS1Script; |
| } |
| } |
| } |
| |
| void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos, |
| HTMLOutContext *pContext ) |
| { |
| rHWrt.bTagOn = sal_False; |
| |
| // die Attribute in der End-Liste sind aufsteigend sortiert |
| sal_uInt16 i=0; |
| while( i < aEndLst.Count() ) |
| { |
| HTMLSttEndPos *pPos = aEndLst[i]; |
| xub_StrLen nEnd = pPos->GetEnd(); |
| |
| if( STRING_MAXLEN==nPos || nEnd == nPos ) |
| { |
| if( pContext ) |
| { |
| HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext ); |
| pContext = 0; // one time ony |
| } |
| Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt ); |
| _RemoveItem( i ); |
| } |
| else if( nEnd > nPos ) |
| { |
| // dieses und alle folgenden Attribute werden erst spaeter beendet |
| break; |
| } |
| else |
| { |
| // Das Attribut wird vor der aktuellen Position beendet. Das |
| // darf nicht sein, aber wie koennen trotzdem damit umgehen |
| ASSERT( nEnd >= nPos, |
| "Das Attribut sollte schon laengst beendet sein" ); |
| i++; |
| } |
| } |
| } |
| |
| |
| /* Ausgabe der Nodes */ |
| Writer& OutHTML_SwTxtNode( Writer& rWrt, const SwCntntNode& rNode ) |
| { |
| SwTxtNode * pNd = &((SwTxtNode&)rNode); |
| SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; |
| |
| const String& rStr = pNd->GetTxt(); |
| xub_StrLen nEnde = rStr.Len(); |
| |
| // Besonderheit: leere Node und HR-Vorlage (horizontaler Strich) |
| // nur ein <HR> ausgeben |
| sal_uInt16 nPoolId = pNd->GetAnyFmtColl().GetPoolFmtId(); |
| |
| if( !nEnde && (RES_POOLCOLL_HTML_HR==nPoolId || |
| pNd->GetAnyFmtColl().GetName().EqualsAscii( OOO_STRING_SVTOOLS_HTML_horzrule) ) ) |
| { |
| // dann die absatz-gebundenen Grafiken/OLE-Objekte im Absatz |
| // MIB 8.7.97: Ein <PRE> spannen wir um die Linie auf. Dann stimmen |
| // zwar die Abstaende nicht, aber sonst bekommen wir einen leeren |
| // Absatz hinter dem <HR> und das ist noch unschoener. |
| rHTMLWrt.ChangeParaToken( 0 ); |
| |
| // Alle an dem Node verankerten Rahmen ausgeben |
| rHTMLWrt.OutFlyFrm( rNode.GetIndex(), 0, HTML_POS_ANY ); |
| |
| if( rHTMLWrt.bLFPossible ) |
| rHTMLWrt.OutNewLine(); // Absatz-Tag in eine neue Zeile |
| |
| rHTMLWrt.bLFPossible = sal_True; |
| |
| ByteString sOut( '<' ); |
| sOut += OOO_STRING_SVTOOLS_HTML_horzrule; |
| |
| const SfxItemSet* pItemSet = pNd->GetpSwAttrSet(); |
| if( !pItemSet ) |
| { |
| rWrt.Strm() << sOut.GetBuffer() << '>'; |
| return rHTMLWrt; |
| } |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == pItemSet->GetItemState( RES_LR_SPACE, sal_False, &pItem )) |
| { |
| sal_Int32 nLeft = ((SvxLRSpaceItem*)pItem)->GetLeft(); |
| sal_Int32 nRight = ((SvxLRSpaceItem*)pItem)->GetRight(); |
| if( nLeft || nRight ) |
| { |
| const SwFrmFmt& rPgFmt = |
| rHTMLWrt.pDoc->GetPageDescFromPool |
| ( RES_POOLPAGE_HTML, false )->GetMaster(); |
| const SwFmtFrmSize& rSz = rPgFmt.GetFrmSize(); |
| const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace(); |
| const SwFmtCol& rCol = rPgFmt.GetCol(); |
| |
| long nPageWidth = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight(); |
| |
| if( 1 < rCol.GetNumCols() ) |
| nPageWidth /= rCol.GetNumCols(); |
| |
| const SwTableNode* pTblNd = pNd->FindTableNode(); |
| if( pTblNd ) |
| { |
| const SwTableBox* pBox = pTblNd->GetTable().GetTblBox( |
| pNd->StartOfSectionIndex() ); |
| if( pBox ) |
| nPageWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); |
| } |
| |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width) += '='; |
| rWrt.Strm() << sOut.GetBuffer(); |
| rWrt.OutULong( rHTMLWrt.ToPixel(nPageWidth-nLeft-nRight) ); |
| |
| ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '='; |
| if( !nLeft ) |
| sOut += OOO_STRING_SVTOOLS_HTML_AL_left; |
| else if( !nRight ) |
| sOut += OOO_STRING_SVTOOLS_HTML_AL_right; |
| else |
| sOut += OOO_STRING_SVTOOLS_HTML_AL_center; |
| } |
| } |
| rWrt.Strm() << sOut.GetBuffer(); |
| if( SFX_ITEM_SET == pItemSet->GetItemState( RES_BOX, sal_False, &pItem )) |
| { |
| const SvxBoxItem* pBoxItem = (const SvxBoxItem*)pItem; |
| const SvxBorderLine* pBorderLine = pBoxItem->GetBottom(); |
| if( pBorderLine ) |
| { |
| sal_uInt16 nWidth = pBorderLine->GetOutWidth() + |
| pBorderLine->GetInWidth() + |
| pBorderLine->GetDistance(); |
| ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '='; |
| rWrt.Strm() << sOut.GetBuffer(); |
| rWrt.OutULong( rHTMLWrt.ToPixel(nWidth) ); |
| |
| const Color& rBorderColor = pBorderLine->GetColor(); |
| if( !rBorderColor.IsRGBEqual( Color(COL_GRAY) ) ) |
| { |
| ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '='; |
| rWrt.Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_Color( rWrt.Strm(), rBorderColor, |
| rHTMLWrt.eDestEnc ); |
| } |
| |
| if( !pBorderLine->GetInWidth() ) |
| { |
| (sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_noshade; |
| rWrt.Strm() << sOut.GetBuffer(); |
| } |
| } |
| } |
| rWrt.Strm() << '>'; |
| return rHTMLWrt; |
| } |
| |
| // Die leeren Nodes mit 2pt Font-Hoehe und der Stand-Vorlage, die |
| // vor Tabellen und Bereichen eingefuegt werden, nicht exportieren, |
| // Bookmarks oder absatzgebundene Grafiken aber schon. |
| // MIB 21.7.97: Ausserdem auch keine leeren Tabellen-Zellen exportieren. |
| if( !nEnde && (nPoolId == RES_POOLCOLL_STANDARD || |
| nPoolId == RES_POOLCOLL_TABLE || |
| nPoolId == RES_POOLCOLL_TABLE_HDLN) ) |
| { |
| // Der aktuelle Node ist leer und enthaelt Standard-Vorlage ... |
| const SfxPoolItem* pItem; |
| const SfxItemSet *pItemSet = pNd->GetpSwAttrSet(); |
| if( pItemSet && pItemSet->Count() && |
| SFX_ITEM_SET == pItemSet->GetItemState( RES_CHRATR_FONTSIZE, sal_False, &pItem ) && |
| 40 == ((const SvxFontHeightItem *)pItem)->GetHeight() ) |
| { |
| // ... ausserdem ist die 2pt Schrift eingestellt ... |
| sal_uLong nNdPos = rWrt.pCurPam->GetPoint()->nNode.GetIndex(); |
| const SwNode *pNextNd = rWrt.pDoc->GetNodes()[nNdPos+1]; |
| const SwNode *pPrevNd = rWrt.pDoc->GetNodes()[nNdPos-1]; |
| sal_Bool bStdColl = nPoolId == RES_POOLCOLL_STANDARD; |
| if( ( bStdColl && (pNextNd->IsTableNode() || |
| pNextNd->IsSectionNode()) ) || |
| ( !bStdColl && pNextNd->IsEndNode() && |
| pPrevNd->IsStartNode() && |
| SwTableBoxStartNode== |
| pPrevNd->GetStartNode()->GetStartNodeType() ) ) |
| { |
| // ... und er steht vor einer Tabelle ohne einem Bereich |
| rHTMLWrt.OutBookmarks(); |
| rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken; |
| |
| // Alle an dem Node verankerten Rahmen ausgeben |
| rHTMLWrt.OutFlyFrm( rNode.GetIndex(), 0, HTML_POS_ANY ); |
| rHTMLWrt.bLFPossible = sal_False; |
| |
| return rWrt; |
| } |
| } |
| } |
| |
| // PagePreaks uns PagDescs abfangen |
| sal_Bool bPageBreakBehind = sal_False; |
| if( rHTMLWrt.bCfgFormFeed && |
| !(rHTMLWrt.bOutTable || rHTMLWrt.bOutFlyFrame) && |
| rHTMLWrt.pStartNdIdx->GetIndex() != |
| rHTMLWrt.pCurPam->GetPoint()->nNode.GetIndex() ) |
| { |
| sal_Bool bPageBreakBefore = sal_False; |
| const SfxPoolItem* pItem; |
| const SfxItemSet* pItemSet = pNd->GetpSwAttrSet(); |
| |
| if( pItemSet ) |
| { |
| if( SFX_ITEM_SET == |
| pItemSet->GetItemState( RES_PAGEDESC, sal_True, &pItem ) && |
| ((SwFmtPageDesc *)pItem)->GetPageDesc() ) |
| bPageBreakBefore = sal_True; |
| else if( SFX_ITEM_SET == |
| pItemSet->GetItemState( RES_BREAK, sal_True, &pItem ) ) |
| { |
| switch( ((SvxFmtBreakItem *)pItem)->GetBreak() ) |
| { |
| case SVX_BREAK_PAGE_BEFORE: |
| bPageBreakBefore = sal_True; |
| break; |
| case SVX_BREAK_PAGE_AFTER: |
| bPageBreakBehind = sal_True; |
| break; |
| case SVX_BREAK_PAGE_BOTH: |
| bPageBreakBefore = sal_True; |
| bPageBreakBehind = sal_True; |
| break; |
| default: |
| ; |
| } |
| } |
| } |
| |
| if( bPageBreakBefore ) |
| rWrt.Strm() << '\f'; |
| } |
| |
| // eventuell eine Form oeffnen |
| rHTMLWrt.OutForm(); |
| |
| // An dem Node "verankerte" Seitenegebunde Rahmen ausgeben |
| sal_Bool bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(), |
| 0, HTML_POS_PREFIX ); |
| // An dem Node verankerte Rahmen ausgeben, die vor dem |
| // Absatz-Tag geschrieben werden sollen. |
| if( bFlysLeft ) |
| bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(), |
| 0, HTML_POS_BEFORE ); |
| |
| if( rHTMLWrt.pCurPam->GetPoint()->nNode == rHTMLWrt.pCurPam->GetMark()->nNode ) |
| nEnde = rHTMLWrt.pCurPam->GetMark()->nContent.GetIndex(); |
| |
| // gibt es harte Attribute, die als Optionen geschrieben werden muessen? |
| rHTMLWrt.bTagOn = sal_True; |
| |
| // jetzt das Tag des Absatzes ausgeben |
| const SwFmt& rFmt = pNd->GetAnyFmtColl(); |
| SwHTMLTxtCollOutputInfo aFmtInfo; |
| sal_Bool bOldLFPossible = rHTMLWrt.bLFPossible; |
| OutHTML_SwFmt( rWrt, rFmt, pNd->GetpSwAttrSet(), aFmtInfo ); |
| |
| // Wenn vor dem Absatz-Tag keine neue Zeile aufgemacht wurde, dann |
| // tun wir das jetzt |
| rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken; |
| if( !bOldLFPossible && rHTMLWrt.bLFPossible ) |
| rHTMLWrt.OutNewLine(); |
| |
| |
| // dann die Bookmarks (inkl. End-Tag) |
| rHTMLWrt.bOutOpts = sal_False; |
| rHTMLWrt.OutBookmarks(); |
| |
| // jetzt ist noch mal eine gute Gelegenheit fuer ein LF, sofern es noch |
| // erlaubt ist |
| if( rHTMLWrt.bLFPossible && |
| rHTMLWrt.GetLineLen() >= rHTMLWrt.nWhishLineLen ) |
| { |
| rHTMLWrt.OutNewLine(); |
| } |
| rHTMLWrt.bLFPossible = sal_False; |
| |
| // Text, der aus einer Outline-Numerierung kommt ermitteln |
| xub_StrLen nOffset = 0; |
| String aOutlineTxt; |
| String aFullText; |
| // --> OD 2006-06-12 #b6435904# |
| // export numbering string as plain text only for the outline numbering, |
| // because the outline numbering isn't exported as a numbering - see <SwHTMLNumRuleInfo::Set(..)> |
| if ( pNd->IsOutline() && |
| pNd->GetNumRule() == pNd->GetDoc()->GetOutlineNumRule() ) |
| // <-- |
| { |
| aOutlineTxt = pNd->GetNumString(); |
| nOffset = nOffset + aOutlineTxt.Len(); |
| aFullText = aOutlineTxt; |
| } |
| String aFootEndNoteSym; |
| if( rHTMLWrt.pFmtFtn ) |
| { |
| aFootEndNoteSym = rHTMLWrt.GetFootEndNoteSym( *rHTMLWrt.pFmtFtn ); |
| nOffset = nOffset + aFootEndNoteSym.Len(); |
| aFullText += aFootEndNoteSym; |
| } |
| |
| // gibt es harte Attribute, die als Tags geschrieben werden muessen? |
| aFullText += rStr; |
| HTMLEndPosLst aEndPosLst( rWrt.pDoc, rHTMLWrt.pTemplate, |
| rHTMLWrt.pDfltColor, rHTMLWrt.bCfgOutStyles, |
| rHTMLWrt.GetHTMLMode(), aFullText, |
| rHTMLWrt.aScriptTextStyles ); |
| if( aFmtInfo.pItemSet ) |
| { |
| aEndPosLst.Insert( *aFmtInfo.pItemSet, 0, nEnde + nOffset, |
| rHTMLWrt.aChrFmtInfos, sal_False, sal_True ); |
| } |
| |
| |
| if( aOutlineTxt.Len() || rHTMLWrt.pFmtFtn ) |
| { |
| // Absatz-Attribute ausgeben, damit der Text die Attribute des |
| // Absatzes bekommt. |
| aEndPosLst.OutStartAttrs( rHTMLWrt, 0 ); |
| |
| // Theoretisch muesste man hier die Zeichen-Vorlage der Numerierung |
| // beachten. Da man die ueber die UI nicht setzen kann, ignorieren |
| // wir sie erstmal. |
| |
| if( aOutlineTxt.Len() ) |
| HTMLOutFuncs::Out_String( rWrt.Strm(), aOutlineTxt, |
| rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters); |
| |
| if( rHTMLWrt.pFmtFtn ) |
| { |
| rHTMLWrt.OutFootEndNoteSym( *rHTMLWrt.pFmtFtn, aFootEndNoteSym, |
| aEndPosLst.GetScriptAtPos( aOutlineTxt.Len(), rHTMLWrt.nCSS1Script ) ); |
| rHTMLWrt.pFmtFtn = 0; |
| } |
| } |
| |
| // erstmal den Start berichtigen. D.h. wird nur ein Teil vom Satz |
| // ausgegeben, so muessen auch da die Attribute stimmen!! |
| rHTMLWrt.bTxtAttr = sal_True; |
| |
| |
| sal_uInt16 nAttrPos = 0; |
| xub_StrLen nStrPos = rHTMLWrt.pCurPam->GetPoint()->nContent.GetIndex(); |
| const SwTxtAttr * pHt = 0; |
| sal_uInt16 nCntAttr = pNd->HasHints() ? pNd->GetSwpHints().Count() : 0; |
| if( nCntAttr && nStrPos > *( pHt = pNd->GetSwpHints()[ 0 ] )->GetStart() ) |
| { |
| // Ok, es gibt vorher Attribute, die ausgegeben werden muessen |
| do { |
| aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset ); |
| |
| nAttrPos++; |
| if( pHt->Which() == RES_TXTATR_FIELD |
| || pHt->Which() == RES_TXTATR_ANNOTATION ) |
| continue; |
| |
| if ( pHt->End() && !pHt->HasDummyChar() ) |
| { |
| const xub_StrLen nHtEnd = *pHt->End(), |
| nHtStt = *pHt->GetStart(); |
| if( !rHTMLWrt.bWriteAll && nHtEnd <= nStrPos ) |
| continue; |
| |
| // leere Hints am Anfang nicht beachten, oder ?? |
| if( nHtEnd == nHtStt ) |
| continue; |
| |
| // Attribut in die Liste aufnehemen |
| if( rHTMLWrt.bWriteAll ) |
| aEndPosLst.Insert( pHt->GetAttr(), nHtStt + nOffset, |
| nHtEnd + nOffset, |
| rHTMLWrt.aChrFmtInfos ); |
| else |
| { |
| xub_StrLen nTmpStt = nHtStt < nStrPos ? nStrPos : nHtStt; |
| xub_StrLen nTmpEnd = nHtEnd < nEnde ? nHtEnd : nEnde; |
| aEndPosLst.Insert( pHt->GetAttr(), nTmpStt + nOffset, |
| nTmpEnd + nOffset, |
| rHTMLWrt.aChrFmtInfos ); |
| } |
| continue; |
| // aber nicht ausgeben, das erfolgt spaeter !! |
| } |
| |
| } while( nAttrPos < nCntAttr && nStrPos > |
| *( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() ); |
| |
| // dann gebe mal alle gesammelten Attribute von der String-Pos aus |
| aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset ); |
| aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset ); |
| } |
| |
| sal_Bool bWriteBreak = (HTML_PREFORMTXT_ON != rHTMLWrt.nLastParaToken); |
| if( bWriteBreak && pNd->GetNumRule() ) |
| bWriteBreak = sal_False; |
| |
| { |
| HTMLOutContext aContext( rHTMLWrt.eDestEnc ); |
| |
| xub_StrLen nPreSplitPos = 0; |
| for( ; nStrPos < nEnde; nStrPos++ ) |
| { |
| aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext ); |
| |
| // Die an der aktuellen Position verankerten Rahmen ausgeben |
| if( bFlysLeft ) |
| bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(), |
| nStrPos, HTML_POS_INSIDE, |
| &aContext ); |
| |
| sal_Bool bOutChar = sal_True; |
| const SwTxtAttr * pTxtHt = 0; |
| if( nAttrPos < nCntAttr && *pHt->GetStart() == nStrPos |
| && nStrPos != nEnde ) |
| { |
| do { |
| if ( pHt->End() && !pHt->HasDummyChar() ) |
| { |
| if( RES_CHRATR_KERNING == pHt->Which() && |
| rHTMLWrt.IsHTMLMode(HTMLMODE_FIRSTLINE) && |
| *pHt->End() - nStrPos == 1 && |
| ' ' == rStr.GetChar(nStrPos) && |
| ((const SvxKerningItem&)pHt->GetAttr()).GetValue() > 0 ) |
| { |
| // Wenn erlaubt, wird das Ding als Spacer exportiert |
| |
| bOutChar = sal_False; // Space nicht ausgeben |
| bWriteBreak = sal_False; // der Absatz ist aber auch nicht leer |
| HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); |
| OutHTML_HoriSpacer( rWrt, |
| ((const SvxKerningItem&)pHt->GetAttr()).GetValue() ); |
| |
| // Der Hint braucht nun doch nicht weiter |
| // beruecksichtigt werden. |
| } |
| else if( *pHt->End() != nStrPos ) |
| { |
| // Hints mit Ende einsortieren, wenn sie keinen |
| // leeren Bereich aufspannen (Hints, die keinen |
| // Bereich aufspannen werden ignoriert |
| aEndPosLst.Insert( pHt->GetAttr(), nStrPos + nOffset, |
| *pHt->End() + nOffset, |
| rHTMLWrt.aChrFmtInfos ); |
| } |
| } |
| else |
| { |
| // Hints ohne-Ende werden als letztes ausgebeben |
| ASSERT( !pTxtHt, "Wieso gibt es da schon ein Attribut ohne Ende?" ); |
| if( rHTMLWrt.nTxtAttrsToIgnore>0 ) |
| { |
| rHTMLWrt.nTxtAttrsToIgnore--; |
| } |
| else |
| { |
| pTxtHt = pHt; |
| sal_uInt16 nFldWhich; |
| if( RES_TXTATR_FIELD != pHt->Which() |
| || ( RES_POSTITFLD != (nFldWhich = ((const SwFmtFld&)pHt->GetAttr()).GetField()->Which()) |
| && RES_SCRIPTFLD != nFldWhich ) ) |
| { |
| bWriteBreak = sal_False; |
| } |
| } |
| bOutChar = sal_False; // keine 255 ausgeben |
| } |
| } while( ++nAttrPos < nCntAttr && nStrPos == |
| *( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() ); |
| } |
| |
| // Manche Draw-Formate koennen auch noch Attribute mitbringen |
| if( pTxtHt && RES_TXTATR_FLYCNT == pTxtHt->Which() ) |
| { |
| const SwFrmFmt* pFrmFmt = |
| ((const SwFmtFlyCnt &)pTxtHt->GetAttr()).GetFrmFmt(); |
| |
| if( RES_DRAWFRMFMT == pFrmFmt->Which() ) |
| aEndPosLst.Insert( *((const SwDrawFrmFmt *)pFrmFmt), |
| nStrPos + nOffset, |
| rHTMLWrt.aChrFmtInfos ); |
| } |
| |
| aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext ); |
| aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset, &aContext ); |
| |
| if( pTxtHt ) |
| { |
| rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken && nStrPos > 0 && |
| rStr.GetChar(nStrPos-1) == ' '; |
| sal_uInt16 nCSS1Script = rHTMLWrt.nCSS1Script; |
| rHTMLWrt.nCSS1Script = aEndPosLst.GetScriptAtPos( |
| nStrPos + nOffset, nCSS1Script ); |
| HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); |
| Out( aHTMLAttrFnTab, pTxtHt->GetAttr(), rHTMLWrt ); |
| rHTMLWrt.nCSS1Script = nCSS1Script; |
| rHTMLWrt.bLFPossible = sal_False; |
| } |
| |
| if( bOutChar ) |
| { |
| // #i120442#: get the UTF-32 codepoint by converting an eventual UTF-16 unicode surrogate pair |
| sal_uInt64 c = rStr.GetChar( nStrPos ); |
| if( nStrPos < nEnde - 1 ) |
| { |
| const sal_Unicode d = rStr.GetChar( nStrPos + 1 ); |
| if( (c >= 0xd800 && c <= 0xdbff) && (d >= 0xdc00 && d <= 0xdfff) ) |
| { |
| sal_uInt64 templow = d&0x03ff; |
| sal_uInt64 temphi = ((c&0x03ff) + 0x0040)<<10; |
| c = temphi|templow; |
| nStrPos++; |
| } |
| } |
| |
| // try to split a line after about 255 characters |
| // at a space character unless in a PRE-context |
| if( ' '==c && !rHTMLWrt.nLastParaToken ) |
| { |
| xub_StrLen nLineLen; |
| if( rHTMLWrt.nLastParaToken ) |
| nLineLen = nStrPos - nPreSplitPos; |
| else |
| nLineLen = rHTMLWrt.GetLineLen(); |
| |
| xub_StrLen nWordLen = rStr.Search( ' ', nStrPos+1 ); |
| if( nWordLen == STRING_NOTFOUND ) |
| nWordLen = nEnde; |
| nWordLen -= nStrPos; |
| |
| if( nLineLen >= rHTMLWrt.nWhishLineLen || |
| (nLineLen+nWordLen) >= rHTMLWrt.nWhishLineLen ) |
| { |
| HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); |
| rHTMLWrt.OutNewLine(); |
| bOutChar = sal_False; |
| if( rHTMLWrt.nLastParaToken ) |
| nPreSplitPos = nStrPos+1; |
| } |
| } |
| |
| if( bOutChar ) |
| { |
| if( 0x0a == c ) |
| { |
| HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak ); |
| } |
| // #i120442#: if c is outside the unicode base plane output it as "&#******;" |
| else if( c > 0xffff) |
| { |
| ByteString sOut("&#"); |
| sOut += ByteString::CreateFromInt64( (sal_uInt64)c ); |
| sOut += ';'; |
| rWrt.Strm() << sOut.GetBuffer(); |
| } |
| else |
| HTMLOutFuncs::Out_Char( rWrt.Strm(), (sal_Unicode)c, aContext, &rHTMLWrt.aNonConvertableCharacters ); |
| |
| // if a paragraph's last character is a hard line break |
| // then we need to add an extra <br> |
| // because browsers like Mozilla wouldn't add a line for the next paragraph |
| bWriteBreak = (0x0a == c) && |
| (HTML_PREFORMTXT_ON != rHTMLWrt.nLastParaToken); |
| } |
| } |
| } |
| HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); |
| } |
| |
| aEndPosLst.OutEndAttrs( rHTMLWrt, STRING_MAXLEN ); |
| |
| // Die an der letzten Position verankerten Rahmen ausgeben |
| if( bFlysLeft ) |
| bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(), |
| nEnde, HTML_POS_INSIDE ); |
| ASSERT( !bFlysLeft, "Es wurden nicht alle Rahmen gespeichert!" ); |
| |
| rHTMLWrt.bTxtAttr = sal_False; |
| |
| if( bWriteBreak ) |
| { |
| sal_Bool bEndOfCell = rHTMLWrt.bOutTable && |
| rWrt.pCurPam->GetPoint()->nNode.GetIndex() == |
| rWrt.pCurPam->GetMark()->nNode.GetIndex(); |
| |
| if( bEndOfCell && !nEnde && |
| rHTMLWrt.IsHTMLMode(HTMLMODE_NBSP_IN_TABLES) ) |
| { |
| // Wenn der letzte Absatz einer Tabellezelle leer ist und |
| // wir fuer den MS-IE exportieren, schreiben wir statt eines |
| // <BR> ein |
| rWrt.Strm() << '&' << OOO_STRING_SVTOOLS_HTML_S_nbsp << ';'; |
| } |
| else |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak ); |
| const SvxULSpaceItem& rULSpace = |
| (const SvxULSpaceItem &)pNd->GetSwAttrSet().Get(RES_UL_SPACE); |
| if( rULSpace.GetLower() > 0 && !bEndOfCell && |
| !rHTMLWrt.IsHTMLMode(HTMLMODE_NO_BR_AT_PAREND) ) |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak ); |
| rHTMLWrt.bLFPossible = sal_True; |
| } |
| } |
| |
| if( rHTMLWrt.bClearLeft || rHTMLWrt.bClearRight ) |
| { |
| const sal_Char *pStr; |
| if( rHTMLWrt.bClearLeft ) |
| { |
| if( rHTMLWrt.bClearRight ) |
| pStr = OOO_STRING_SVTOOLS_HTML_AL_all; |
| else |
| pStr = OOO_STRING_SVTOOLS_HTML_AL_left; |
| } |
| else |
| pStr = OOO_STRING_SVTOOLS_HTML_AL_right; |
| |
| ByteString sOut( OOO_STRING_SVTOOLS_HTML_linebreak ); |
| (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_clear) += '=') += pStr; |
| |
| HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), sOut.GetBuffer() ); |
| rHTMLWrt.bClearLeft = sal_False; |
| rHTMLWrt.bClearRight = sal_False; |
| |
| rHTMLWrt.bLFPossible = sal_True; |
| } |
| |
| // wenn ein LF nicht schon erlaubt ist wird es erlaubt, wenn der |
| // Absatz mit einem ' ' endet |
| if( !rHTMLWrt.bLFPossible && !rHTMLWrt.nLastParaToken && |
| nEnde > 0 && ' ' == rStr.GetChar(nEnde-1) ) |
| rHTMLWrt.bLFPossible = sal_True; |
| |
| rHTMLWrt.bTagOn = sal_False; |
| OutHTML_SwFmtOff( rWrt, aFmtInfo ); |
| |
| // eventuell eine Form schliessen |
| rHTMLWrt.OutForm( sal_False ); |
| |
| if( bPageBreakBehind ) |
| rWrt.Strm() << '\f'; |
| |
| return rHTMLWrt; |
| } |
| |
| |
| sal_uInt32 SwHTMLWriter::ToPixel( sal_uInt32 nVal ) const |
| { |
| if( Application::GetDefaultDevice() && nVal ) |
| { |
| nVal = Application::GetDefaultDevice()->LogicToPixel( |
| Size( nVal, nVal ), MapMode( MAP_TWIP ) ).Width(); |
| if( !nVal ) // wo ein Twip ist sollte auch ein Pixel sein |
| nVal = 1; |
| } |
| return nVal; |
| } |
| |
| |
| static Writer& OutHTML_CSS1Attr( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| // wenn gerade Hints geschrieben werden versuchen wir den Hint als |
| // CSS1-Attribut zu schreiben |
| |
| if( ((SwHTMLWriter&)rWrt).bCfgOutStyles && ((SwHTMLWriter&)rWrt).bTxtAttr ) |
| OutCSS1_HintSpanTag( rWrt, rHt ); |
| |
| return rWrt; |
| } |
| |
| |
| /* File CHRATR.HXX: */ |
| |
| static Writer& OutHTML_SvxColor( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| // die Default-Farbe nur Schreiben, wenn sie als Hint vorkommt |
| //if( rHTMLWrt.bTagOn && !rHTMLWrt.bTxtAttr && rHTMLWrt.pDfltColor |
| // && rColor == *rHTMLWrt.pDfltColor ) |
| // return rWrt; |
| |
| if( !rHTMLWrt.bTxtAttr && rHTMLWrt.bCfgOutStyles && rHTMLWrt.bCfgPreferStyles ) |
| { |
| // Font-Farbe nicht als Tag schreiben, wenn Styles normalen Tags |
| // vorgezogen werden |
| return rWrt; |
| } |
| |
| if( rHTMLWrt.bTagOn ) |
| { |
| Color aColor( ((const SvxColorItem&)rHt).GetValue() ); |
| if( COL_AUTO == aColor.GetColor() ) |
| aColor.SetColor( COL_BLACK ); |
| |
| ByteString sOut( '<' ); |
| (((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '='; |
| rWrt.Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_Color( rWrt.Strm(), aColor, rHTMLWrt.eDestEnc ) << '>'; |
| } |
| else |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font, sal_False ); |
| |
| return rWrt; |
| } |
| |
| |
| static Writer& OutHTML_SwPosture( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| const FontItalic nPosture = ((const SvxPostureItem&)rHt).GetPosture(); |
| if( ITALIC_NORMAL == nPosture ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_italic, rHTMLWrt.bTagOn ); |
| } |
| else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr ) |
| { |
| // vielleicht als CSS1-Attribut ? |
| OutCSS1_HintSpanTag( rWrt, rHt ); |
| } |
| |
| return rWrt; |
| } |
| |
| static Writer& OutHTML_SvxFont( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| if( rHTMLWrt.bTagOn ) |
| { |
| String aNames; |
| SwHTMLWriter::PrepareFontList( ((const SvxFontItem&)rHt), aNames, 0, |
| rHTMLWrt.IsHTMLMode(HTMLMODE_FONT_GENERIC) ); |
| ByteString sOut( '<' ); |
| (((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_face) += "=\""; |
| rWrt.Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_String( rWrt.Strm(), aNames, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ) |
| << "\">"; |
| } |
| else |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font , sal_False ); |
| |
| return rWrt; |
| } |
| |
| static Writer& OutHTML_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| if( rHTMLWrt.bTagOn ) |
| { |
| ByteString sOut( '<' ); |
| sOut += OOO_STRING_SVTOOLS_HTML_font; |
| |
| sal_uInt32 nHeight = ((const SvxFontHeightItem&)rHt).GetHeight(); |
| sal_uInt16 nSize = rHTMLWrt.GetHTMLFontSize( nHeight ); |
| (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=') |
| += ByteString::CreateFromInt32( nSize ); |
| rWrt.Strm() << sOut.GetBuffer(); |
| |
| if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr && |
| rHTMLWrt.aFontHeights[nSize-1] != nHeight ) |
| { |
| // wenn die Groesse keiner HTML-Groesse entspricht, |
| // wird sie noch zusatzlich als Style-Option exportiert |
| OutCSS1_HintStyleOpt( rWrt, rHt ); |
| } |
| rWrt.Strm() << '>'; |
| } |
| else |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font, sal_False ); |
| } |
| |
| return rWrt; |
| } |
| |
| static Writer& OutHTML_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| LanguageType eLang = ((const SvxLanguageItem &)rHt).GetLanguage(); |
| if( LANGUAGE_DONTKNOW == eLang ) |
| return rWrt; |
| |
| if( rHTMLWrt.bTagOn ) |
| { |
| ByteString sOut( '<' ); |
| sOut += OOO_STRING_SVTOOLS_HTML_span; |
| rWrt.Strm() << sOut.GetBuffer(); |
| rHTMLWrt.OutLanguage( ((const SvxLanguageItem &)rHt).GetLanguage() ); |
| rWrt.Strm() << '>'; |
| } |
| else |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_span, sal_False ); |
| } |
| |
| return rWrt; |
| } |
| static Writer& OutHTML_SwWeight( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| const FontWeight nBold = ((const SvxWeightItem&)rHt).GetWeight(); |
| if( WEIGHT_BOLD == nBold ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_bold, rHTMLWrt.bTagOn ); |
| } |
| else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr ) |
| { |
| // vielleicht als CSS1-Attribut ? |
| OutCSS1_HintSpanTag( rWrt, rHt ); |
| } |
| |
| return rWrt; |
| } |
| |
| |
| static Writer& OutHTML_SwCrossedOut( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| // Wegen Netscape schrieben wir hier STRIKE und nicht S raus! |
| const FontStrikeout nStrike = ((const SvxCrossedOutItem&)rHt).GetStrikeout(); |
| if( STRIKEOUT_NONE != nStrike ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_strike, rHTMLWrt.bTagOn ); |
| } |
| else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr ) |
| { |
| // vielleicht als CSS1-Attribut ? |
| OutCSS1_HintSpanTag( rWrt, rHt ); |
| } |
| |
| return rWrt; |
| } |
| |
| |
| static Writer& OutHTML_SvxEscapement( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| const SvxEscapement eEscape = |
| (const SvxEscapement)((const SvxEscapementItem&)rHt).GetEnumValue(); |
| const sal_Char *pStr = 0; |
| switch( eEscape ) |
| { |
| case SVX_ESCAPEMENT_SUPERSCRIPT: pStr = OOO_STRING_SVTOOLS_HTML_superscript; break; |
| case SVX_ESCAPEMENT_SUBSCRIPT: pStr = OOO_STRING_SVTOOLS_HTML_subscript; break; |
| default: |
| ; |
| } |
| |
| if( pStr ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), pStr, rHTMLWrt.bTagOn ); |
| } |
| else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr ) |
| { |
| // vielleicht als CSS1-Attribut ? |
| OutCSS1_HintSpanTag( rWrt, rHt ); |
| } |
| |
| return rWrt; |
| } |
| |
| |
| |
| static Writer& OutHTML_SwUnderline( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| const FontUnderline eUnder = ((const SvxUnderlineItem&)rHt).GetLineStyle(); |
| if( UNDERLINE_NONE != eUnder ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_underline, rHTMLWrt.bTagOn ); |
| } |
| else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr ) |
| { |
| // vielleicht als CSS1-Attribut ? |
| OutCSS1_HintSpanTag( rWrt, rHt ); |
| } |
| |
| return rWrt; |
| } |
| |
| |
| static Writer& OutHTML_SwFlyCnt( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; |
| SwFmtFlyCnt& rFlyCnt = (SwFmtFlyCnt&)rHt; |
| |
| const SwFrmFmt& rFmt = *rFlyCnt.GetFrmFmt(); |
| const SdrObject *pSdrObj = 0; |
| |
| SwHTMLFrmType eType = |
| (SwHTMLFrmType)rHTMLWrt.GuessFrmType( rFmt, pSdrObj ); |
| sal_uInt8 nMode = aHTMLOutFrmAsCharTable[eType][rHTMLWrt.nExportMode]; |
| rHTMLWrt.OutFrmFmt( nMode, rFmt, pSdrObj ); |
| return rWrt; |
| } |
| |
| |
| // Das ist jetzt unser Blink-Item. Blinkend wird eingeschaltet, indem man |
| // das Item auf sal_True setzt! |
| static Writer& OutHTML_SwBlink( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts || !rHTMLWrt.IsHTMLMode(HTMLMODE_BLINK) ) |
| return rWrt; |
| |
| if( ((const SvxBlinkItem&)rHt).GetValue() ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_blink, rHTMLWrt.bTagOn ); |
| } |
| else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr ) |
| { |
| // vielleicht als CSS1-Attribut ? |
| OutCSS1_HintSpanTag( rWrt, rHt ); |
| } |
| |
| return rWrt; |
| } |
| |
| Writer& OutHTML_INetFmt( Writer& rWrt, const SwFmtINetFmt& rINetFmt, sal_Bool bOn ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| |
| String aURL( rINetFmt.GetValue() ); |
| const SvxMacroTableDtor *pMacTable = rINetFmt.GetMacroTbl(); |
| sal_Bool bEvents = pMacTable != 0 && pMacTable->Count() > 0; |
| |
| // Gibt es ueberhaupt etwas auszugeben? |
| if( !aURL.Len() && !bEvents && !rINetFmt.GetName().Len() ) |
| return rWrt; |
| |
| // Tag aus? Dann nur ein </A> ausgeben. |
| if( !bOn ) |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_anchor, sal_False ); |
| return rWrt; |
| } |
| |
| ByteString sOut( '<' ); |
| sOut += OOO_STRING_SVTOOLS_HTML_anchor; |
| |
| sal_Bool bScriptDependent = sal_False; |
| { |
| const SwCharFmt* pFmt = rWrt.pDoc->GetCharFmtFromPool( |
| RES_POOLCHR_INET_NORMAL ); |
| SwHTMLFmtInfo aFmtInfo( pFmt ); |
| sal_uInt16 nPos; |
| if( rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) ) |
| { |
| bScriptDependent = rHTMLWrt.aChrFmtInfos[nPos]->bScriptDependent; |
| } |
| } |
| if( !bScriptDependent ) |
| { |
| const SwCharFmt* pFmt = rWrt.pDoc->GetCharFmtFromPool( |
| RES_POOLCHR_INET_VISIT ); |
| SwHTMLFmtInfo aFmtInfo( pFmt ); |
| sal_uInt16 nPos; |
| if( rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) ) |
| { |
| bScriptDependent = rHTMLWrt.aChrFmtInfos[nPos]->bScriptDependent; |
| } |
| } |
| |
| if( bScriptDependent ) |
| { |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\""; |
| switch( rHTMLWrt.nCSS1Script ) |
| { |
| case CSS1_OUTMODE_WESTERN: |
| sOut += "western"; |
| break; |
| case CSS1_OUTMODE_CJK: |
| sOut += "cjk"; |
| break; |
| case CSS1_OUTMODE_CTL: |
| sOut += "ctl"; |
| break; |
| } |
| sOut += '\"'; |
| } |
| |
| rWrt.Strm() << sOut.GetBuffer(); |
| |
| #define REL_HACK |
| #ifdef REL_HACK |
| String sRel; |
| #endif |
| |
| if( aURL.Len() || bEvents ) |
| { |
| #ifdef REL_HACK |
| String sTmp( aURL ); |
| sTmp.ToUpperAscii(); |
| xub_StrLen nPos = sTmp.SearchAscii( "\" REL=" ); |
| if( nPos!=STRING_NOTFOUND ) |
| { |
| sRel = aURL.Copy( nPos+1 ); |
| aURL.Erase( nPos ); |
| } |
| #endif |
| aURL.EraseLeadingChars().EraseTrailingChars(); |
| |
| ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\""; |
| rWrt.Strm() << sOut.GetBuffer(); |
| rHTMLWrt.OutHyperlinkHRefValue( aURL ); |
| sOut = '\"'; |
| } |
| else |
| sOut.Erase(); |
| |
| if( rINetFmt.GetName().Len() ) |
| { |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\""; |
| rWrt.Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_String( rWrt.Strm(), rINetFmt.GetName(), |
| rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); |
| sOut = '\"'; |
| } |
| |
| const String& rTarget = rINetFmt.GetTargetFrame(); |
| if( rTarget.Len() ) |
| { |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_target) += "=\""; |
| rWrt.Strm() << sOut.GetBuffer(); |
| HTMLOutFuncs::Out_String( rWrt.Strm(), rTarget, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); |
| sOut = '\"'; |
| } |
| |
| #ifdef REL_HACK |
| if( sRel.Len() ) |
| sOut += ByteString( sRel, RTL_TEXTENCODING_ASCII_US ); |
| #endif |
| if( sOut.Len() ) |
| rWrt.Strm() << sOut.GetBuffer(); |
| |
| if( bEvents ) |
| HTMLOutFuncs::Out_Events( rWrt.Strm(), *pMacTable, aAnchorEventTable, |
| rHTMLWrt.bCfgStarBasic, rHTMLWrt.eDestEnc, |
| &rHTMLWrt.aNonConvertableCharacters ); |
| rWrt.Strm() << ">"; |
| |
| return rWrt; |
| } |
| |
| static Writer& OutHTML_SwFmtINetFmt( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| const SwFmtINetFmt& rINetFmt = (const SwFmtINetFmt&)rHt; |
| |
| if( rHTMLWrt.bTagOn ) |
| { |
| // ggf. ein noch offenes Attribut voruebergehend beenden |
| if( rHTMLWrt.aINetFmts.Count() ) |
| { |
| SwFmtINetFmt *pINetFmt = |
| rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ]; |
| OutHTML_INetFmt( rWrt, *pINetFmt, sal_False ); |
| } |
| |
| // jetzt das neue aufmachen |
| OutHTML_INetFmt( rWrt, rINetFmt, sal_True ); |
| |
| // und merken |
| const SwFmtINetFmt *pINetFmt = new SwFmtINetFmt( rINetFmt ); |
| rHTMLWrt.aINetFmts.C40_INSERT( SwFmtINetFmt, pINetFmt, |
| rHTMLWrt.aINetFmts.Count() ); |
| } |
| else |
| { |
| // das |
| OutHTML_INetFmt( rWrt, rINetFmt, sal_False ); |
| |
| ASSERT( rHTMLWrt.aINetFmts.Count(), "da fehlt doch ein URL-Attribut" ); |
| if( rHTMLWrt.aINetFmts.Count() ) |
| { |
| // das eigene Attribut vom Stack holen |
| SwFmtINetFmt *pINetFmt = |
| rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ]; |
| |
| rHTMLWrt.aINetFmts.Remove( rHTMLWrt.aINetFmts.Count()-1, 1 ); |
| delete pINetFmt; |
| } |
| |
| if( rHTMLWrt.aINetFmts.Count() ) |
| { |
| // es ist noch ein Attribut auf dem Stack, das wieder geoeffnet |
| // werden muss |
| SwFmtINetFmt *pINetFmt = |
| rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ]; |
| OutHTML_INetFmt( rWrt, *pINetFmt, sal_True ); |
| } |
| } |
| |
| return rWrt; |
| } |
| |
| static Writer& OutHTML_SwTxtCharFmt( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( rHTMLWrt.bOutOpts ) |
| return rWrt; |
| |
| const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rHt; |
| const SwCharFmt* pFmt = rChrFmt.GetCharFmt(); |
| |
| if( !pFmt ) |
| { |
| return rWrt; |
| } |
| |
| SwHTMLFmtInfo aFmtInfo( pFmt ); |
| sal_uInt16 nPos; |
| if( !rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) ) |
| return rWrt; |
| |
| const SwHTMLFmtInfo *pFmtInfo = rHTMLWrt.aChrFmtInfos[nPos]; |
| ASSERT( pFmtInfo, "Wieso gint es keine Infos ueber die Zeichenvorlage?" ); |
| |
| if( rHTMLWrt.bTagOn ) |
| { |
| ByteString sOut( '<' ); |
| if( pFmtInfo->aToken.Len() > 0 ) |
| sOut += pFmtInfo->aToken; |
| else |
| sOut += OOO_STRING_SVTOOLS_HTML_span; |
| if( rHTMLWrt.bCfgOutStyles && |
| (pFmtInfo->aClass.Len() || pFmtInfo->bScriptDependent) ) |
| { |
| ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\""; |
| rWrt.Strm() << sOut.GetBuffer(); |
| String aClass( pFmtInfo->aClass ); |
| if( pFmtInfo->bScriptDependent ) |
| { |
| if( aClass.Len() ) |
| aClass += '-'; |
| switch( rHTMLWrt.nCSS1Script ) |
| { |
| case CSS1_OUTMODE_WESTERN: |
| aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("western") ); |
| break; |
| case CSS1_OUTMODE_CJK: |
| aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("cjk") ); |
| break; |
| case CSS1_OUTMODE_CTL: |
| aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("ctl") ); |
| break; |
| } |
| } |
| HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, |
| rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ); |
| sOut = '\"'; |
| } |
| sOut += '>'; |
| rWrt.Strm() << sOut.GetBuffer(); |
| } |
| else |
| { |
| HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), |
| pFmtInfo->aToken.Len() ? pFmtInfo->aToken.GetBuffer() |
| : OOO_STRING_SVTOOLS_HTML_span, |
| sal_False ); |
| } |
| |
| return rWrt; |
| } |
| |
| static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt ) |
| { |
| SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt; |
| if( !rHTMLWrt.bOutOpts || !rHTMLWrt.bTagOn ) |
| return rWrt; |
| |
| SvxAdjustItem& rAdjust = (SvxAdjustItem&)rHt; |
| const sal_Char* pStr = 0; |
| switch( rAdjust.GetAdjust() ) |
| { |
| case SVX_ADJUST_CENTER: pStr = OOO_STRING_SVTOOLS_HTML_AL_center; break; |
| case SVX_ADJUST_LEFT: pStr = OOO_STRING_SVTOOLS_HTML_AL_left; break; |
| case SVX_ADJUST_RIGHT: pStr = OOO_STRING_SVTOOLS_HTML_AL_right; break; |
| case SVX_ADJUST_BLOCK: pStr = OOO_STRING_SVTOOLS_HTML_AL_justify; break; |
| default: |
| ; |
| } |
| if( pStr ) |
| { |
| ByteString sOut( ' ' ); |
| ((sOut += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += pStr; |
| rWrt.Strm() << sOut.GetBuffer(); |
| } |
| |
| return rWrt; |
| } |
| |
| /* |
| * lege hier die Tabellen fuer die HTML-Funktions-Pointer auf |
| * die Ausgabe-Funktionen an. |
| * Es sind lokale Strukturen, die nur innerhalb der HTML-DLL |
| * bekannt sein muessen. |
| */ |
| |
| |
| SwAttrFnTab aHTMLAttrFnTab = { |
| /* RES_CHRATR_CASEMAP */ OutHTML_CSS1Attr, |
| /* RES_CHRATR_CHARSETCOLOR */ 0, |
| /* RES_CHRATR_COLOR */ OutHTML_SvxColor, |
| /* RES_CHRATR_CONTOUR */ 0, |
| /* RES_CHRATR_CROSSEDOUT */ OutHTML_SwCrossedOut, |
| /* RES_CHRATR_ESCAPEMENT */ OutHTML_SvxEscapement, |
| /* RES_CHRATR_FONT */ OutHTML_SvxFont, |
| /* RES_CHRATR_FONTSIZE */ OutHTML_SvxFontHeight, |
| /* RES_CHRATR_KERNING */ OutHTML_CSS1Attr, |
| /* RES_CHRATR_LANGUAGE */ OutHTML_SvxLanguage, |
| /* RES_CHRATR_POSTURE */ OutHTML_SwPosture, |
| /* RES_CHRATR_PROPORTIONALFONTSIZE*/0, |
| /* RES_CHRATR_SHADOWED */ 0, |
| /* RES_CHRATR_UNDERLINE */ OutHTML_SwUnderline, |
| /* RES_CHRATR_WEIGHT */ OutHTML_SwWeight, |
| /* RES_CHRATR_WORDLINEMODE */ 0, |
| /* RES_CHRATR_AUTOKERN */ 0, |
| /* RES_CHRATR_BLINK */ OutHTML_SwBlink, |
| /* RES_CHRATR_NOHYPHEN */ 0, // Neu: nicht trennen |
| /* RES_CHRATR_NOLINEBREAK */ 0, // Neu: nicht umbrechen |
| /* RES_CHRATR_BACKGROUND */ OutHTML_CSS1Attr, // Neu: Zeichenhintergrund |
| /* RES_CHRATR_CJK_FONT */ OutHTML_SvxFont, |
| /* RES_CHRATR_CJK_FONTSIZE */ OutHTML_SvxFontHeight, |
| /* RES_CHRATR_CJK_LANGUAGE */ OutHTML_SvxLanguage, |
| /* RES_CHRATR_CJK_POSTURE */ OutHTML_SwPosture, |
| /* RES_CHRATR_CJK_WEIGHT */ OutHTML_SwWeight, |
| /* RES_CHRATR_CTL_FONT */ OutHTML_SvxFont, |
| /* RES_CHRATR_CTL_FONTSIZE */ OutHTML_SvxFontHeight, |
| /* RES_CHRATR_CTL_LANGUAGE */ OutHTML_SvxLanguage, |
| /* RES_CHRATR_CTL_POSTURE */ OutHTML_SwPosture, |
| /* RES_CHRATR_CTL_WEIGHT */ OutHTML_SwWeight, |
| /* RES_CHRATR_ROTATE */ 0, |
| /* RES_CHRATR_EMPHASIS_MARK */ 0, |
| /* RES_CHRATR_TWO_LINES */ 0, |
| /* RES_CHRATR_SCALEW */ 0, |
| /* RES_CHRATR_RELIEF */ 0, |
| /* RES_CHRATR_HIDDEN */ 0, |
| /* RES_CHRATR_OVERLINE */ OutHTML_CSS1Attr, |
| /* RES_CHRATR_DUMMY1 */ 0, |
| /* RES_CHRATR_DUMMY2 */ 0, |
| //For i120935, Insert blank entry for RES_CHRATR_BIDITRL and RES_CHRATR_IDCTHINT, for keep the identical res order |
| /*RES_CHRATR_BIDIRTL*/ 0, |
| /*RES_CHRATR_IDCTHINT*/ 0, |
| /* RES_TXTATR_REFMARK */ 0, |
| /* RES_TXTATR_TOXMARK */ 0, |
| /* RES_TXTATR_META */ 0, |
| /* RES_TXTATR_METAFIELD */ 0, |
| /* RES_TXTATR_AUTOFMT */ 0, |
| /* RES_TXTATR_INETFMT */ OutHTML_SwFmtINetFmt, |
| /* RES_TXTATR_CHARFMT */ OutHTML_SwTxtCharFmt, |
| /* RES_TXTATR_CJK_RUBY */ 0, |
| /* RES_TXTATR_UNKNOWN_CONTAINER */ 0, |
| /* RES_TXTATR_INPUTFIELD */ OutHTML_SwFmtFld, |
| |
| /* RES_TXTATR_FIELD */ OutHTML_SwFmtFld, |
| /* RES_TXTATR_FLYCNT */ OutHTML_SwFlyCnt, |
| /* RES_TXTATR_FTN */ OutHTML_SwFmtFtn, |
| /* RES_TXTATR_ANNOTATION */ OutHTML_SwFmtFld, |
| /* RES_TXTATR_DUMMY3 */ 0, |
| /* RES_TXTATR_DUMMY1 */ 0, // Dummy: |
| /* RES_TXTATR_DUMMY2 */ 0, // Dummy: |
| |
| /* RES_PARATR_LINESPACING */ 0, |
| /* RES_PARATR_ADJUST */ OutHTML_SvxAdjust, |
| /* RES_PARATR_SPLIT */ 0, |
| /* RES_PARATR_WIDOWS */ 0, |
| /* RES_PARATR_ORPHANS */ 0, |
| /* RES_PARATR_TABSTOP */ 0, |
| /* RES_PARATR_HYPHENZONE*/ 0, |
| /* RES_PARATR_DROP */ OutHTML_CSS1Attr, |
| /* RES_PARATR_REGISTER */ 0, // neu: Registerhaltigkeit |
| /* RES_PARATR_NUMRULE */ 0, // Dummy: |
| /* RES_PARATR_SCRIPTSPACE */ 0, // Dummy: |
| /* RES_PARATR_HANGINGPUNCTUATION */ 0, // Dummy: |
| /* RES_PARATR_FORBIDDEN_RULES */ 0, // new |
| /* RES_PARATR_VERTALIGN */ 0, // new |
| /* RES_PARATR_SNAPTOGRID*/ 0, // new |
| /* RES_PARATR_CONNECT_TO_BORDER */ 0, // new |
| |
| /* RES_PARATR_LIST_ID */ 0, // new |
| /* RES_PARATR_LIST_LEVEL */ 0, // new |
| /* RES_PARATR_LIST_ISRESTART */ 0, // new |
| /* RES_PARATR_LIST_RESTARTVALUE */ 0, // new |
| /* RES_PARATR_LIST_ISCOUNTED */ 0, // new |
| |
| /* RES_FILL_ORDER */ 0, |
| /* RES_FRM_SIZE */ 0, |
| /* RES_PAPER_BIN */ 0, |
| /* RES_LR_SPACE */ 0, |
| /* RES_UL_SPACE */ 0, |
| /* RES_PAGEDESC */ 0, |
| /* RES_BREAK */ 0, |
| /* RES_CNTNT */ 0, |
| /* RES_HEADER */ 0, |
| /* RES_FOOTER */ 0, |
| /* RES_PRINT */ 0, |
| /* RES_OPAQUE */ 0, |
| /* RES_PROTECT */ 0, |
| /* RES_SURROUND */ 0, |
| /* RES_VERT_ORIENT */ 0, |
| /* RES_HORI_ORIENT */ 0, |
| /* RES_ANCHOR */ 0, |
| /* RES_BACKGROUND */ 0, |
| /* RES_BOX */ 0, |
| /* RES_SHADOW */ 0, |
| /* RES_FRMMACRO */ 0, |
| /* RES_COL */ 0, |
| /* RES_KEEP */ 0, |
| /* RES_URL */ 0, |
| /* RES_EDIT_IN_READONLY */ 0, |
| /* RES_LAYOUT_SPLIT */ 0, |
| /* RES_FRMATR_DUMMY1 */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY2 */ 0, // Dummy: |
| /* RES_AUTO_STYLE */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY4 */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY5 */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY6 */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY7 */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY8 */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY9 */ 0, // Dummy: |
| /* RES_FOLLOW_TEXT_FLOW */ 0, |
| /* RES_WRAP_INFLUENCE_ON_OBJPOS */ 0, |
| /* RES_FRMATR_DUMMY2 */ 0, // Dummy: |
| /* RES_AUTO_STYLE */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY4 */ 0, // Dummy: |
| /* RES_FRMATR_DUMMY5 */ 0, // Dummy: |
| |
| /* RES_GRFATR_MIRRORGRF */ 0, |
| /* RES_GRFATR_CROPGRF */ 0, |
| /* RES_GRFATR_ROTATION */ 0, |
| /* RES_GRFATR_LUMINANCE */ 0, |
| /* RES_GRFATR_CONTRAST */ 0, |
| /* RES_GRFATR_CHANNELR */ 0, |
| /* RES_GRFATR_CHANNELG */ 0, |
| /* RES_GRFATR_CHANNELB */ 0, |
| /* RES_GRFATR_GAMMA */ 0, |
| /* RES_GRFATR_INVERT */ 0, |
| /* RES_GRFATR_TRANSPARENCY */ 0, |
| /* RES_GRFATR_DRWAMODE */ 0, |
| /* RES_GRFATR_DUMMY1 */ 0, |
| /* RES_GRFATR_DUMMY2 */ 0, |
| /* RES_GRFATR_DUMMY3 */ 0, |
| /* RES_GRFATR_DUMMY4 */ 0, |
| /* RES_GRFATR_DUMMY5 */ 0, |
| |
| /* RES_BOXATR_FORMAT */ 0, |
| /* RES_BOXATR_FORMULA */ 0, |
| /* RES_BOXATR_VALUE */ 0 |
| }; |