update dev300-m58
[ooovba.git] / sw / source / filter / html / htmlatr.cxx
blob52a15785dcd7314b0de27845c82c548b7f274db3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: htmlatr.cxx,v $
10 * $Revision: 1.41.140.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <com/sun/star/i18n/ScriptType.hpp>
37 #include <vcl/svapp.hxx>
38 #ifndef _WRKWIN_HXX //autogen
39 #include <vcl/wrkwin.hxx>
40 #endif
41 #include <tools/urlobj.hxx>
43 #if !defined _SVSTDARR_XUB_STRLEN_DECL || !defined _SVSTDARR_USHORTS_DECL
44 #define _SVSTDARR_XUB_STRLEN
45 #define _SVSTDARR_USHORTS
46 #include <svtools/svstdarr.hxx>
47 #endif
48 #include <svtools/htmlout.hxx>
49 #include <svtools/htmlkywd.hxx>
50 #include <svtools/htmltokn.h>
51 #include <svtools/whiter.hxx>
52 #include <svx/htmlmode.hxx>
53 #include <svx/escpitem.hxx>
54 #include <svx/brkitem.hxx>
55 #include <svx/boxitem.hxx>
56 #include <svx/ulspitem.hxx>
57 #include <svx/udlnitem.hxx>
58 #include <svx/crsditem.hxx>
59 #include <svx/blnkitem.hxx>
60 #include <svx/cmapitem.hxx>
61 #include <svx/colritem.hxx>
62 #include <svx/fontitem.hxx>
63 #include <svx/fhgtitem.hxx>
64 #include <svx/postitem.hxx>
65 #include <svx/kernitem.hxx>
66 #include <svx/wghtitem.hxx>
67 #include <svx/lspcitem.hxx>
68 #include <svx/adjitem.hxx>
69 #include <svx/lrspitem.hxx>
70 #include <svx/brshitem.hxx>
71 #include <svx/langitem.hxx>
72 #include <svx/frmdiritem.hxx>
73 #include <fchrfmt.hxx>
74 #include <fmtautofmt.hxx>
75 #include <fmtfsize.hxx>
76 #include <fmtclds.hxx>
77 #include <fmtpdsc.hxx>
78 #include <fmtflcnt.hxx>
79 #include <fmtinfmt.hxx>
80 #include <fmtftn.hxx>
81 #include <txatbase.hxx>
82 #include <frmatr.hxx>
83 #include <charfmt.hxx>
84 #include <fmthbsh.hxx>
85 #include <fmtfld.hxx>
86 #include <doc.hxx>
87 #include <pam.hxx>
88 #include <ndtxt.hxx>
89 #include <paratr.hxx>
90 #include <poolfmt.hxx>
91 #include <pagedesc.hxx>
92 #include <swtable.hxx>
93 #include "fldbas.hxx"
94 #include <breakit.hxx>
95 #include <htmlnum.hxx>
96 #include <wrthtml.hxx>
97 #include <htmlfly.hxx>
98 #include <numrule.hxx>
100 using namespace ::com::sun::star;
103 * um nicht immer wieder nach einem Update festzustellen, das irgendwelche
104 * Hint-Ids dazugekommen sind, wird hier definiert, die Groesse der Tabelle
105 * definiert und mit der akt. verglichen. Bei unterschieden wird der
106 * Compiler schon meckern.
108 * diese Section und die dazugeherigen Tabellen muessen in folgenden Files
109 * gepflegt werden: rtf\rtfatr.cxx, sw6\sw6atr.cxx, w4w\w4watr.cxx
111 #if !defined(UNX) && !defined(MSC) && !defined(PPC) && !defined(CSET) && !defined(__MWERKS__) && !defined(WTC) && !defined(__MINGW32__) && !defined(OS2)
113 #define ATTRFNTAB_SIZE 130
114 #if ATTRFNTAB_SIZE != POOLATTR_END - POOLATTR_BEGIN
115 #error Attribut-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
116 #endif
118 #ifdef FORMAT_TABELLE
119 // da sie nicht benutzt wird!
120 #define FORMATTAB_SIZE 7
121 #if FORMATTAB_SIZE != RES_FMT_END - RES_FMT_BEGIN
122 #error Format-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
123 #endif
124 #endif
126 #define NODETAB_SIZE 3
127 #if NODETAB_SIZE != RES_NODE_END - RES_NODE_BEGIN
128 #error Node-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
129 #endif
131 #endif
133 #define HTML_BULLETCHAR_DISC 34
134 #define HTML_BULLETCHAR_CIRCLE 38
135 #define HTML_BULLETCHAR_SQUARE 36
137 #define COLFUZZY 20
139 //-----------------------------------------------------------------------
141 HTMLOutEvent __FAR_DATA aAnchorEventTable[] =
143 { OOO_STRING_SVTOOLS_HTML_O_SDonclick, OOO_STRING_SVTOOLS_HTML_O_onclick, SFX_EVENT_MOUSECLICK_OBJECT },
144 { OOO_STRING_SVTOOLS_HTML_O_SDonmouseover, OOO_STRING_SVTOOLS_HTML_O_onmouseover, SFX_EVENT_MOUSEOVER_OBJECT },
145 { OOO_STRING_SVTOOLS_HTML_O_SDonmouseout, OOO_STRING_SVTOOLS_HTML_O_onmouseout, SFX_EVENT_MOUSEOUT_OBJECT },
146 { 0, 0, 0 }
149 static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt );
151 static Writer& OutHTML_HoriSpacer( Writer& rWrt, INT16 nSize )
153 ASSERT( nSize>0, "horizontaler SPACER mit negativem Wert?" )
154 if( nSize <= 0 )
155 return rWrt;
157 if( Application::GetDefaultDevice() )
159 nSize = (INT16)Application::GetDefaultDevice()
160 ->LogicToPixel( Size(nSize,0), MapMode(MAP_TWIP) ).Width();
163 ByteString sOut( '<' );
164 (((((((((sOut += OOO_STRING_SVTOOLS_HTML_spacer)
165 += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=') += OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal)
166 += ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=')
167 +=ByteString::CreateFromInt32(nSize)) += '>';
169 rWrt.Strm() << sOut.GetBuffer();
171 return rWrt;
174 USHORT SwHTMLWriter::GetDefListLvl( const String& rNm, USHORT nPoolId )
176 if( nPoolId == RES_POOLCOLL_HTML_DD )
178 return 1 | HTML_DLCOLL_DD;
180 else if( nPoolId == RES_POOLCOLL_HTML_DT )
182 return 1 | HTML_DLCOLL_DT;
185 String sDTDD( String::CreateFromAscii(OOO_STRING_SVTOOLS_HTML_dt) );
186 sDTDD += ' ';
187 if( COMPARE_EQUAL == sDTDD.CompareTo( rNm, sDTDD.Len() ) )
188 // DefinitionList - term
189 return (USHORT)rNm.Copy( sDTDD.Len() ).ToInt32() | HTML_DLCOLL_DT;
191 sDTDD.AssignAscii( OOO_STRING_SVTOOLS_HTML_dd );
192 sDTDD += ' ';
193 if( COMPARE_EQUAL == sDTDD.CompareTo( rNm, sDTDD.Len() ) )
194 // DefinitionList - definition
195 return (USHORT)rNm.Copy( sDTDD.Len() ).ToInt32() | HTML_DLCOLL_DD;
197 return 0;
200 void SwHTMLWriter::OutAndSetDefList( USHORT nNewLvl )
202 // eventuell muss erst mal eine Liste aufgemacht werden
203 if( nDefListLvl < nNewLvl )
205 // output </pre> for the previous(!) pararagraph, if required.
206 // Preferable, the <pre> is exported by OutHTML_SwFmtOff for the
207 // previous paragraph already, but that's not possible, because a very
208 // deep look at the next paragraph (this one) is required to figure
209 // out that a def list starts here.
211 ChangeParaToken( 0 );
213 // entsprechend dem Level-Unterschied schreiben!
214 for( USHORT i=nDefListLvl; i<nNewLvl; i++ )
216 if( bLFPossible )
217 OutNewLine();
218 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_deflist, TRUE );
219 IncIndentLevel();
220 bLFPossible = TRUE;
223 else if( nDefListLvl > nNewLvl )
225 for( USHORT i=nNewLvl ; i < nDefListLvl; i++ )
227 DecIndentLevel();
228 if( bLFPossible )
229 OutNewLine();
230 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_deflist, FALSE );
231 bLFPossible = TRUE;
235 nDefListLvl = nNewLvl;
239 void SwHTMLWriter::ChangeParaToken( USHORT nNew )
241 if( nNew != nLastParaToken && HTML_PREFORMTXT_ON == nLastParaToken )
243 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_preformtxt, FALSE );
244 bLFPossible = TRUE;
246 nLastParaToken = nNew;
249 sal_uInt16 SwHTMLWriter::GetCSS1ScriptForScriptType( sal_uInt16 nScriptType )
251 sal_uInt16 nRet = CSS1_OUTMODE_ANY_SCRIPT;
253 switch( nScriptType )
255 case i18n::ScriptType::LATIN:
256 nRet = CSS1_OUTMODE_WESTERN;
257 break;
258 case i18n::ScriptType::ASIAN:
259 nRet = CSS1_OUTMODE_CJK;
260 break;
261 case i18n::ScriptType::COMPLEX:
262 nRet = CSS1_OUTMODE_CTL;
263 break;
266 return nRet;
269 // fuer die Formate muesste eine einzige Ausgabe-Funktion genuegen !
271 * Formate wie folgt ausgeben:
272 * - fuer Formate, fuer die es entsprechende HTML-Tags gibt wird das
273 * Tag ausgegeben
274 * - fuer alle anderen wird ein Absatz-Tag <P> ausgegeben und bUserFmt
275 * gesetzt
276 * - Wenn eine Absatz-Ausrichtung am uebergebenen Item-Set des Nodes
277 * oder im Item-Set des Format gesetzt ist, wird ein ALIGN=xxx ausgegeben,
278 * sofern HTML es zulaesst
279 * - in jedem Fall wird harte Attributierung als STYLE-Option geschrieben.
280 * Wenn bUserFmt nicht gesetzt ist, wird nur der uebergebene Item-Set
281 * betrachtet. Sonst werden auch Attribute des Formats ausgegeben.
284 struct SwHTMLTxtCollOutputInfo
286 ByteString aToken; // auszugendens End-Token
287 SfxItemSet *pItemSet; // harte Attributierung
289 BOOL bInNumBulList; // in einer Aufzaehlungs-Liste;
290 BOOL bParaPossible; // ein </P> darf zusaetzlich ausgegeben werden
291 BOOL bOutPara; // ein </P> soll ausgegeben werden
292 BOOL bOutDiv; // write a </DIV>
294 SwHTMLTxtCollOutputInfo() :
295 pItemSet( 0 ),
296 bInNumBulList( FALSE ),
297 bParaPossible( FALSE ),
298 bOutPara( FALSE ),
299 bOutDiv( FALSE )
302 ~SwHTMLTxtCollOutputInfo();
304 BOOL HasParaToken() const { return aToken.Len()==1 && aToken.GetChar(0)=='P'; }
305 BOOL ShouldOutputToken() const { return bOutPara || !HasParaToken(); }
308 SwHTMLTxtCollOutputInfo::~SwHTMLTxtCollOutputInfo()
310 delete pItemSet;
313 struct SwHTMLFmtInfo
315 const SwFmt *pFmt; // das Format selbst
316 const SwFmt *pRefFmt; // das Vergleichs-Format
318 ByteString aToken; // das auszugebende Token
319 String aClass; // die auszugebende Klasse
321 SfxItemSet *pItemSet; // der auszugebende Attribut-Set
323 sal_Int32 nLeftMargin; // ein par default-Werte fuer
324 sal_Int32 nRightMargin; // Absatz-Vorlagen
325 short nFirstLineIndent;
327 USHORT nTopMargin;
328 USHORT nBottomMargin;
330 sal_Bool bScriptDependent;
332 // Konstruktor fuer einen Dummy zum Suchen
333 SwHTMLFmtInfo( const SwFmt *pF ) :
334 pFmt( pF ), pItemSet( 0 )
338 // Konstruktor zum Erstellen der Format-Info
339 SwHTMLFmtInfo( const SwFmt *pFmt, SwDoc *pDoc, SwDoc *pTemlate,
340 BOOL bOutStyles, LanguageType eDfltLang=LANGUAGE_DONTKNOW,
341 sal_uInt16 nScript=CSS1_OUTMODE_ANY_SCRIPT,
342 BOOL bHardDrop=FALSE );
343 ~SwHTMLFmtInfo();
345 friend BOOL operator==( const SwHTMLFmtInfo& rInfo1,
346 const SwHTMLFmtInfo& rInfo2 )
348 return (long)rInfo1.pFmt == (long)rInfo2.pFmt;
351 friend BOOL operator<( const SwHTMLFmtInfo& rInfo1,
352 const SwHTMLFmtInfo& rInfo2 )
354 return (long)rInfo1.pFmt < (long)rInfo2.pFmt;
359 SV_IMPL_OP_PTRARR_SORT( SwHTMLFmtInfos, SwHTMLFmtInfo* )
361 SwHTMLFmtInfo::SwHTMLFmtInfo( const SwFmt *pF, SwDoc *pDoc, SwDoc *pTemplate,
362 BOOL bOutStyles,
363 LanguageType eDfltLang,
364 sal_uInt16 nCSS1Script, BOOL bHardDrop ) :
365 pFmt( pF ), pItemSet( 0 ), bScriptDependent( sal_False )
367 USHORT nRefPoolId = 0;
368 // Den Selektor des Formats holen
369 USHORT nDeep = SwHTMLWriter::GetCSS1Selector( pFmt, aToken, aClass,
370 nRefPoolId );
371 ASSERT( nDeep ? aToken.Len()>0 : aToken.Len()==0,
372 "Hier stimmt doch was mit dem Token nicht!" );
373 ASSERT( nDeep ? nRefPoolId : !nRefPoolId,
374 "Hier stimmt doch was mit der Vergleichs-Vorlage nicht!" );
376 BOOL bTxtColl = pFmt->Which() == RES_TXTFMTCOLL ||
377 pFmt->Which() == RES_CONDTXTFMTCOLL;
379 const SwFmt *pReferenceFmt = 0; // Vergleichs-Format
380 sal_Bool bSetDefaults = sal_True, bClearSame = sal_True;
381 if( nDeep != 0 )
383 // Es ist eine HTML-Tag-Vorlage oder die Vorlage ist von einer
384 // solchen abgeleitet
385 if( !bOutStyles )
387 // wenn keine Styles exportiert werden, muss evtl. zusaetlich
388 // harte Attributierung geschrieben werden
389 switch( nDeep )
391 case CSS1_FMT_ISTAG:
392 case CSS1_FMT_CMPREF:
393 // fuer HTML-Tag-Vorlagen die Unterscheide zum Original
394 // (sofern verfuegbar)
395 pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId,
396 pTemplate );
397 break;
399 default:
400 // sonst die zur HTML-Tag-Vorlage des Originals oder des
401 // aktuellen Doks, wenn die nicht verfuegbar ist
402 if( pTemplate )
403 pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId,
404 pTemplate );
405 else
406 pReferenceFmt = SwHTMLWriter::GetParentFmt( *pFmt, nDeep );
407 break;
411 else if( bTxtColl )
413 // Nicht von einer HTML-Tag-Vorlage abgeleitete Absatz-Vorlagen
414 // muessen als harte Attributierung relativ zur Textkoerper-Volage
415 // exportiert werden. Fuer Nicht-Styles-Export sollte die der
416 // HTML-Vorlage als Referenz dienen
417 if( !bOutStyles && pTemplate )
418 pReferenceFmt = pTemplate->GetTxtCollFromPool( RES_POOLCOLL_TEXT, false );
419 else
420 pReferenceFmt = pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT, false );
423 if( pReferenceFmt || nDeep==0 )
425 pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
426 pFmt->GetAttrSet().GetRanges() );
427 // wenn Unterschiede zu einer anderen Vorlage geschrieben werden
428 // sollen ist harte Attributierung noetig. Fuer Vorlagen, die
429 // nicht von HTML-Tag-Vorlagen abgeleitet sind, gilt das immer
431 pItemSet->Set( pFmt->GetAttrSet(), TRUE );
433 if( pReferenceFmt )
434 SwHTMLWriter::SubtractItemSet( *pItemSet, pReferenceFmt->GetAttrSet(),
435 bSetDefaults, bClearSame );
437 // einen leeren Item-Set gleich loeschen, das spart speater
438 // Arbeit
439 if( !pItemSet->Count() )
441 delete pItemSet;
442 pItemSet = 0;
446 if( bTxtColl )
448 if( bOutStyles )
450 // We have to add hard attributes for any script dependent
451 // item that is not accessed by the style
452 static sal_uInt16 aWhichIds[3][4] =
454 { RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
455 RES_CHRATR_POSTURE, RES_CHRATR_WEIGHT },
456 { RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE,
457 RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT },
458 { RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE,
459 RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT }
462 sal_uInt16 nRef = 0;
463 sal_uInt16 aSets[2] = {0,0};
464 switch( nCSS1Script )
466 case CSS1_OUTMODE_WESTERN:
467 nRef = 0;
468 aSets[0] = 1;
469 aSets[1] = 2;
470 break;
471 case CSS1_OUTMODE_CJK:
472 nRef = 1;
473 aSets[0] = 0;
474 aSets[1] = 2;
475 break;
476 case CSS1_OUTMODE_CTL:
477 nRef = 2;
478 aSets[0] = 0;
479 aSets[1] = 1;
480 break;
482 for( sal_uInt16 i=0; i<4; i++ )
484 const SfxPoolItem& rRef = pFmt->GetFmtAttr( aWhichIds[nRef][i] );
485 for( sal_uInt16 j=0; j<2; j++ )
487 const SfxPoolItem& rSet = pFmt->GetFmtAttr( aWhichIds[aSets[j]][i] );
488 if( rSet != rRef )
490 if( !pItemSet )
491 pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
492 pFmt->GetAttrSet().GetRanges() );
493 pItemSet->Put( rSet );
499 // Ggf. noch ein DropCap-Attribut uebernehmen
500 if( bOutStyles && bHardDrop && nDeep != 0 )
502 const SfxPoolItem *pItem;
503 if( SFX_ITEM_SET==pFmt->GetAttrSet().GetItemState(
504 RES_PARATR_DROP, TRUE, &pItem ) )
506 BOOL bPut = TRUE;
507 if( pTemplate )
509 pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId, pTemplate );
510 const SfxPoolItem *pRefItem;
511 BOOL bRefItemSet =
512 SFX_ITEM_SET==pReferenceFmt->GetAttrSet().GetItemState(
513 RES_PARATR_DROP, TRUE, &pRefItem );
514 bPut = !bRefItemSet || *pItem!=*pRefItem;
516 if( bPut )
518 if( !pItemSet )
519 pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
520 pFmt->GetAttrSet().GetRanges() );
521 pItemSet->Put( *pItem );
527 // Die diversen default-Abstaende aus der Vorlage oder der
528 // Vergleischs-Vorlage merken
529 const SvxLRSpaceItem &rLRSpace =
530 (pReferenceFmt ? pReferenceFmt : pFmt)->GetLRSpace();
531 nLeftMargin = rLRSpace.GetTxtLeft();
532 nRightMargin = rLRSpace.GetRight();
533 nFirstLineIndent = rLRSpace.GetTxtFirstLineOfst();
535 const SvxULSpaceItem &rULSpace =
536 (pReferenceFmt ? pReferenceFmt : pFmt)->GetULSpace();
537 nTopMargin = rULSpace.GetUpper();
538 nBottomMargin = rULSpace.GetLower();
540 // export language if it differs from the default language
541 sal_uInt16 nWhichId =
542 SwHTMLWriter::GetLangWhichIdFromScript( nCSS1Script );
543 const SvxLanguageItem& rLang =
544 (const SvxLanguageItem&)pFmt->GetFmtAttr( nWhichId );
545 LanguageType eLang = rLang.GetLanguage();
546 if( eLang != eDfltLang )
548 if( !pItemSet )
549 pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
550 pFmt->GetAttrSet().GetRanges() );
551 pItemSet->Put( rLang );
554 static sal_uInt16 aWhichIds[3] =
555 { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
556 RES_CHRATR_CTL_LANGUAGE };
557 for( sal_uInt16 i=0; i<3; i++ )
559 if( aWhichIds[i] != nWhichId )
561 const SvxLanguageItem& rTmpLang =
562 (const SvxLanguageItem&)pFmt->GetFmtAttr(aWhichIds[i]);
563 if( rTmpLang.GetLanguage() != eLang )
565 if( !pItemSet )
566 pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
567 pFmt->GetAttrSet().GetRanges() );
568 pItemSet->Put( rTmpLang );
575 SwHTMLFmtInfo::~SwHTMLFmtInfo()
577 delete pItemSet;
580 void OutHTML_SwFmt( Writer& rWrt, const SwFmt& rFmt,
581 const SfxItemSet *pNodeItemSet,
582 SwHTMLTxtCollOutputInfo& rInfo )
584 ASSERT( RES_CONDTXTFMTCOLL==rFmt.Which() || RES_TXTFMTCOLL==rFmt.Which(),
585 "keine Absatz-Vorlage" );
587 SwHTMLWriter & rHWrt = (SwHTMLWriter&)rWrt;
589 // Erstmal ein par Flags ...
590 USHORT nNewDefListLvl = 0;
591 USHORT nNumStart = USHRT_MAX;
592 BOOL bForceDL = FALSE;
593 BOOL bDT = FALSE;
594 rInfo.bInNumBulList = FALSE; // Wir sind in einer Liste?
595 BOOL bNumbered = FALSE; // Der aktuelle Absatz ist numeriert
596 BOOL bPara = FALSE; // das aktuelle Token ist <P>
597 rInfo.bParaPossible = FALSE; // ein <P> darf zusaetzlich ausgegeben werden
598 BOOL bNoEndTag = FALSE; // kein End-Tag ausgeben
600 rHWrt.bNoAlign = FALSE; // kein ALIGN=... moeglich
601 BOOL bNoStyle = FALSE; // kein STYLE=... moeglich
602 BYTE nBulletGrfLvl = 255; // Die auszugebende Bullet-Grafik
604 // Sind wir in einer Aufzaehlungs- oder Numerierungliste?
605 const SwTxtNode* pTxtNd = rWrt.pCurPam->GetNode()->GetTxtNode();
607 SwHTMLNumRuleInfo aNumInfo;
608 if( rHWrt.GetNextNumInfo() )
610 aNumInfo = *rHWrt.GetNextNumInfo();
611 rHWrt.ClearNextNumInfo();
613 else
615 aNumInfo.Set( *pTxtNd );
618 if( aNumInfo.GetNumRule() )
620 rInfo.bInNumBulList = TRUE;
621 nNewDefListLvl = 0;
623 // ist der aktuelle Absatz numeriert?
624 bNumbered = aNumInfo.IsNumbered();
625 BYTE nLvl = aNumInfo.GetLevel();
627 ASSERT( pTxtNd->GetActualListLevel() == nLvl,
628 "Gemerkter Num-Level ist falsch" );
629 ASSERT( bNumbered == static_cast< BOOL >(pTxtNd->IsCountedInList()),
630 "Gemerkter Numerierungs-Zustand ist falsch" );
632 if( bNumbered )
634 nBulletGrfLvl = nLvl; // nur veruebergehend!!!
635 // --> OD 2005-11-15 #i57919#
636 // correction of re-factoring done by cws swnumtree:
637 // - <nNumStart> has to contain the restart value, if the
638 // numbering is restarted at this text node. Value <USHRT_MAX>
639 // indicates, that no additional restart value has to be written.
640 if ( pTxtNd->IsListRestart() )
642 nNumStart = static_cast< USHORT >(pTxtNd->GetActualListStartValue());
644 // <--
645 DBG_ASSERT( rHWrt.nLastParaToken == 0,
646 "<PRE> wurde nicht vor <LI> beendet." );
650 // Jetzt holen wir das Token und ggf. die Klasse
651 SwHTMLFmtInfo aFmtInfo( &rFmt );
652 USHORT nArrayPos;
653 const SwHTMLFmtInfo *pFmtInfo;
654 if( rHWrt.aTxtCollInfos.Seek_Entry( &aFmtInfo, &nArrayPos ) )
656 pFmtInfo = rHWrt.aTxtCollInfos[nArrayPos];
658 else
660 pFmtInfo = new SwHTMLFmtInfo( &rFmt, rWrt.pDoc, rHWrt.pTemplate,
661 rHWrt.bCfgOutStyles, rHWrt.eLang,
662 rHWrt.nCSS1Script,
663 !rHWrt.IsHTMLMode(HTMLMODE_DROPCAPS) );
664 rHWrt.aTxtCollInfos.C40_PTR_INSERT( SwHTMLFmtInfo, pFmtInfo );
665 String aName( rFmt.GetName() );
666 if( rHWrt.aScriptParaStyles.Seek_Entry( &aName ) )
667 ((SwHTMLFmtInfo *)pFmtInfo)->bScriptDependent = sal_True;
670 // Jetzt wird festgelegt, was aufgrund des Tokens so moeglich ist
671 USHORT nToken = 0; // Token fuer Tag-Wechsel
672 BOOL bOutNewLine = FALSE; // nur ein LF ausgeben?
673 if( pFmtInfo->aToken.Len() )
675 // Es ist eine HTML-Tag-Vorlage oder die Vorlage ist von einer
676 // solchen abgeleitet
677 rInfo.aToken = pFmtInfo->aToken;
679 // der erste Buchstabe reicht meistens
680 switch( rInfo.aToken.GetChar( 0 ) )
682 case 'A': ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_address),
683 "Doch kein ADDRESS?" );
684 rInfo.bParaPossible = TRUE;
685 rHWrt.bNoAlign = TRUE;
686 break;
688 case 'B': ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_blockquote),
689 "Doch kein BLOCKQUOTE?" );
690 rInfo.bParaPossible = TRUE;
691 rHWrt.bNoAlign = TRUE;
692 break;
694 case 'P': if( rInfo.aToken.Len() == 1 )
696 bPara = TRUE;
698 else
700 ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_preformtxt),
701 "Doch kein PRE?" );
702 if( HTML_PREFORMTXT_ON == rHWrt.nLastParaToken )
704 bOutNewLine = TRUE;
706 else
708 nToken = HTML_PREFORMTXT_ON;
709 rHWrt.bNoAlign = TRUE;
710 bNoEndTag = TRUE;
713 break;
715 case 'D': ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dt) ||
716 rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dd),
717 "Doch kein DD/DT?" );
718 bDT = rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dt);
719 rInfo.bParaPossible = !bDT;
720 rHWrt.bNoAlign = TRUE;
721 bForceDL = TRUE;
722 break;
725 else
727 // alle Vorlagen, die nicht einem HTML-Tag entsprechen oder von
728 // diesem abgeleitet sind, werden als <P> exportiert
730 rInfo.aToken = OOO_STRING_SVTOOLS_HTML_parabreak;
731 bPara = TRUE;
734 // Falls noetig, die harte Attributierung der Vorlage uebernehmen
735 if( pFmtInfo->pItemSet )
737 ASSERT( !rInfo.pItemSet, "Wo kommt der Item-Set her?" );
738 rInfo.pItemSet = new SfxItemSet( *pFmtInfo->pItemSet );
741 // und noch die harte Attributierung des Absatzes dazunehmen
742 if( pNodeItemSet )
744 if( rInfo.pItemSet )
745 rInfo.pItemSet->Put( *pNodeItemSet );
746 else
747 rInfo.pItemSet = new SfxItemSet( *pNodeItemSet );
750 // den unteren Absatz-Abstand brauchen wir noch
751 const SvxULSpaceItem& rULSpace =
752 pNodeItemSet ? ((const SvxULSpaceItem &)pNodeItemSet->Get(RES_UL_SPACE))
753 : rFmt.GetULSpace();
756 if( (rHWrt.bOutHeader &&
757 rWrt.pCurPam->GetPoint()->nNode.GetIndex() ==
758 rWrt.pCurPam->GetMark()->nNode.GetIndex()) ||
759 rHWrt.bOutFooter )
761 if( rHWrt.bCfgOutStyles )
763 SvxULSpaceItem aULSpaceItem( rULSpace );
764 if( rHWrt.bOutHeader )
765 aULSpaceItem.SetLower( rHWrt.nHeaderFooterSpace );
766 else
767 aULSpaceItem.SetUpper( rHWrt.nHeaderFooterSpace );
769 if( !rInfo.pItemSet )
770 rInfo.pItemSet = new SfxItemSet(
771 *rFmt.GetAttrSet().GetPool(),
772 RES_UL_SPACE, RES_UL_SPACE );
773 rInfo.pItemSet->Put( aULSpaceItem );
775 rHWrt.bOutHeader = FALSE;
776 rHWrt.bOutFooter = FALSE;
779 if( bOutNewLine )
781 // nur einen Zeilen-Umbruch (ohne Einrueckung) am Absatz-Anfang
782 // ausgeben
783 rInfo.aToken.Erase(); // kein End-Tag ausgeben
784 rWrt.Strm() << SwHTMLWriter::sNewLine;
786 return;
790 // soll ein ALIGN=... geschrieben werden?
791 const SfxPoolItem* pAdjItem = 0;
792 const SfxPoolItem* pItem;
794 if( rInfo.pItemSet &&
795 SFX_ITEM_SET == rInfo.pItemSet->GetItemState( RES_PARATR_ADJUST,
796 FALSE, &pItem ) )
798 pAdjItem = pItem;
801 // Unteren Absatz-Abstand beachten ? (nie im letzen Absatz von
802 // Tabellen)
803 BOOL bUseParSpace = !rHWrt.bOutTable ||
804 (rWrt.pCurPam->GetPoint()->nNode.GetIndex() !=
805 rWrt.pCurPam->GetMark()->nNode.GetIndex());
806 // Wenn Styles exportiert werden, wird aus eingerueckten Absaetzen
807 // eine Definitions-Liste
808 const SvxLRSpaceItem& rLRSpace =
809 pNodeItemSet ? ((const SvxLRSpaceItem &)pNodeItemSet->Get(RES_LR_SPACE))
810 : rFmt.GetLRSpace();
811 if( (!rHWrt.bCfgOutStyles || bForceDL) && !rInfo.bInNumBulList )
813 sal_Int32 nLeftMargin;
814 if( bForceDL )
815 nLeftMargin = rLRSpace.GetTxtLeft();
816 else
817 nLeftMargin = rLRSpace.GetTxtLeft() > pFmtInfo->nLeftMargin
818 ? rLRSpace.GetTxtLeft() - pFmtInfo->nLeftMargin
819 : 0;
821 if( nLeftMargin > 0 && rHWrt.nDefListMargin > 0 )
823 nNewDefListLvl = static_cast< USHORT >((nLeftMargin + (rHWrt.nDefListMargin/2)) /
824 rHWrt.nDefListMargin);
825 if( nNewDefListLvl == 0 && bForceDL && !bDT )
826 nNewDefListLvl = 1;
828 else
830 // If the left margin is 0 or negative, emulating indent
831 // with <dd> does not work. We then set a def list only if
832 // the dd style is used.
833 nNewDefListLvl = (bForceDL&& !bDT) ? 1 : 0;
836 BOOL bIsNextTxtNode =
837 rWrt.pDoc->GetNodes()[rWrt.pCurPam->GetPoint()->nNode.GetIndex()+1]
838 ->IsTxtNode();
840 if( bForceDL && bDT )
842 // Statt eines DD muessen wir hier auch ein DT der Ebene
843 // darueber nehmen
844 nNewDefListLvl++;
846 else if( !nNewDefListLvl && !rHWrt.bCfgOutStyles && bPara &&
847 rULSpace.GetLower()==0 &&
848 ((bUseParSpace && bIsNextTxtNode) || rHWrt.nDefListLvl==1) &&
849 (!pAdjItem || SVX_ADJUST_LEFT==
850 ((const SvxAdjustItem *)pAdjItem)->GetAdjust()) )
852 // Absaetze ohne unteren Abstand als DT exportieren
853 nNewDefListLvl = 1;
854 bDT = TRUE;
855 rInfo.bParaPossible = FALSE;
856 rHWrt.bNoAlign = TRUE;
860 if( nNewDefListLvl != rHWrt.nDefListLvl )
861 rHWrt.OutAndSetDefList( nNewDefListLvl );
863 // ggf. eine Aufzaehlung- oder Numerierungsliste beginnen
864 if( rInfo.bInNumBulList )
866 ASSERT( !rHWrt.nDefListLvl, "DL in OL geht nicht!" );
867 OutHTML_NumBulListStart( rHWrt, aNumInfo );
869 if( bNumbered )
871 if( rHWrt.aBulletGrfs[nBulletGrfLvl].Len() )
872 bNumbered = FALSE;
873 else
874 nBulletGrfLvl = 255;
878 // Die Defaults aus der Vorlage merken, denn sie muessen nicht
879 // exportiert werden
880 rHWrt.nDfltLeftMargin = pFmtInfo->nLeftMargin;
881 rHWrt.nDfltRightMargin = pFmtInfo->nRightMargin;
882 rHWrt.nDfltFirstLineIndent = pFmtInfo->nFirstLineIndent;
884 if( rInfo.bInNumBulList )
886 if( !rHWrt.IsHTMLMode( HTMLMODE_LSPACE_IN_NUMBUL ) )
887 rHWrt.nDfltLeftMargin = rLRSpace.GetTxtLeft();
889 // In Numerierungs-Listen keinen Ertzeilen-Einzug ausgeben.
890 rHWrt.nFirstLineIndent = rLRSpace.GetTxtFirstLineOfst();
893 if( rInfo.bInNumBulList && bNumbered && bPara && !rHWrt.bCfgOutStyles )
895 // ein einzelnes LI hat keinen Abstand
896 rHWrt.nDfltTopMargin = 0;
897 rHWrt.nDfltBottomMargin = 0;
899 else if( rHWrt.nDefListLvl && bPara )
901 // ein einzelnes DD hat auch keinen Abstand
902 rHWrt.nDfltTopMargin = 0;
903 rHWrt.nDfltBottomMargin = 0;
905 else
907 rHWrt.nDfltTopMargin = pFmtInfo->nTopMargin;
908 // #60393#: Wenn im letzten Absatz einer Tabelle der
909 // untere Absatz-Abstand veraendert wird, vertut sich
910 // Netscape total. Deshalb exportieren wir hier erstmal
911 // nichts, indem wir den Abstand aus dem Absatz als Default
912 // setzen.
913 if( rHWrt.bCfgNetscape4 && !bUseParSpace )
914 rHWrt.nDfltBottomMargin = rULSpace.GetLower();
915 else
916 rHWrt.nDfltBottomMargin = pFmtInfo->nBottomMargin;
919 if( rHWrt.nDefListLvl )
921 rHWrt.nLeftMargin =
922 (rHWrt.nDefListLvl-1) * rHWrt.nDefListMargin;
925 if( rHWrt.bLFPossible )
926 rHWrt.OutNewLine(); // Absatz-Tag in neue Zeile
927 rInfo.bOutPara = FALSE;
929 // das ist jetzt unser neues Token
930 rHWrt.ChangeParaToken( nToken );
932 BOOL bHasParSpace = bUseParSpace && rULSpace.GetLower() > 0;
934 // ggf ein List-Item aufmachen
935 if( rInfo.bInNumBulList && bNumbered )
937 ByteString sOut( '<' );
938 sOut += OOO_STRING_SVTOOLS_HTML_li;
939 if( USHRT_MAX != nNumStart )
940 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_value) += '=')
941 += ByteString::CreateFromInt32(nNumStart);
942 sOut += '>';
943 rWrt.Strm() << sOut.GetBuffer();
946 if( rHWrt.nDefListLvl > 0 && !bForceDL )
948 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), bDT ? OOO_STRING_SVTOOLS_HTML_dt : OOO_STRING_SVTOOLS_HTML_dd );
951 if( pAdjItem &&
952 rHWrt.IsHTMLMode( HTMLMODE_NO_CONTROL_CENTERING ) &&
953 rHWrt.HasControls() )
955 // #64687#: The align=... attribute does behave strange in netscape
956 // if there are controls in a paragraph, because the control and
957 // all text behind the control does not recognize this attribute.
958 ByteString sOut( '<' );
959 sOut += OOO_STRING_SVTOOLS_HTML_division;
960 rWrt.Strm() << sOut.GetBuffer();
962 rHWrt.bTxtAttr = FALSE;
963 rHWrt.bOutOpts = TRUE;
964 OutHTML_SvxAdjust( rWrt, *pAdjItem );
965 rWrt.Strm() << '>';
966 pAdjItem = 0;
967 rHWrt.bNoAlign = FALSE;
968 rInfo.bOutDiv = TRUE;
969 rHWrt.IncIndentLevel();
970 rHWrt.bLFPossible = TRUE;
971 rHWrt.OutNewLine();
974 // fuer BLOCKQUOTE, ADDRESS und DD wird noch ein Absatz-Token
975 // ausgegeben, wenn,
976 // - keine Styles geschrieben werden, und
977 // - ein untere Abstand oder eine Absatz-Ausrichtung existiert
978 ByteString aToken = rInfo.aToken;
979 if( !rHWrt.bCfgOutStyles && rInfo.bParaPossible && !bPara &&
980 (bHasParSpace || pAdjItem) )
982 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rInfo.aToken.GetBuffer() );
983 aToken = OOO_STRING_SVTOOLS_HTML_parabreak;
984 bPara = TRUE;
985 rHWrt.bNoAlign = FALSE;
986 bNoStyle = FALSE;
989 LanguageType eLang = rInfo.pItemSet
990 ? ((const SvxLanguageItem&)rInfo.pItemSet->Get(SwHTMLWriter::GetLangWhichIdFromScript(rHWrt.nCSS1Script))).GetLanguage()
991 : rHWrt.eLang;
993 if( rInfo.pItemSet )
995 static sal_uInt16 aWhichIds[3] = { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE };
997 for( sal_uInt16 i=0; i<3; i++ )
999 // export language if it differs from the default language only.
1000 const SfxPoolItem *pTmpItem;
1001 if( SFX_ITEM_SET == rInfo.pItemSet->GetItemState( aWhichIds[i],
1002 sal_True, &pTmpItem ) &&
1003 ((const SvxLanguageItem *)pTmpItem)->GetLanguage() == eLang )
1004 rInfo.pItemSet->ClearItem( aWhichIds[i] );
1008 // and the text direction
1009 sal_uInt16 nDir = rHWrt.GetHTMLDirection(
1010 (pNodeItemSet ? static_cast < const SvxFrameDirectionItem& >(
1011 pNodeItemSet->Get( RES_FRAMEDIR ) )
1012 : rFmt.GetFrmDir() ).GetValue() );
1014 // Ein <P> wird nur geschrieben, wenn
1015 // - wir in keiner OL/UL/DL sind, oder
1016 // - der Absatz einer OL/UL nicht numeriert ist, oder
1017 // - keine Styles exportiert werden und
1018 // - ein unterer Abstand oder
1019 // - eine Absatz-Ausrichtung existiert, ode
1020 // - Styles exportiert werden und,
1021 // - die Textkoerper-Vorlage geaendert wurde, oder
1022 // - ein Benutzer-Format exportiert wird, oder
1023 // - Absatz-Attribute existieren
1024 if( !bPara ||
1025 (!rInfo.bInNumBulList && !rHWrt.nDefListLvl) ||
1026 (rInfo.bInNumBulList && !bNumbered) ||
1027 (!rHWrt.bCfgOutStyles &&
1028 (bHasParSpace || pAdjItem ||
1029 (eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.eLang))) ||
1030 nDir != rHWrt.nDirection ||
1031 rHWrt.bCfgOutStyles )
1033 // jetzt werden Optionen ausgegeben
1034 rHWrt.bTxtAttr = FALSE;
1035 rHWrt.bOutOpts = TRUE;
1037 ByteString sOut( '<' );
1038 sOut += aToken;
1040 if( eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.eLang )
1042 rWrt.Strm() << sOut.GetBuffer();
1043 rHWrt.OutLanguage( eLang );
1044 sOut.Erase();
1047 if( nDir != rHWrt.nDirection )
1049 if( sOut.Len() )
1051 rWrt.Strm() << sOut.GetBuffer();
1052 sOut.Erase();
1054 rHWrt.OutDirection( nDir );
1057 if( rHWrt.bCfgOutStyles &&
1058 (pFmtInfo->aClass.Len() || pFmtInfo->bScriptDependent) )
1060 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"";
1061 rWrt.Strm() << sOut.GetBuffer();
1062 String aClass( pFmtInfo->aClass );
1063 if( pFmtInfo->bScriptDependent )
1065 if( aClass.Len() )
1066 aClass += '-';
1067 switch( rHWrt.nCSS1Script )
1069 case CSS1_OUTMODE_WESTERN:
1070 aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("western") );
1071 break;
1072 case CSS1_OUTMODE_CJK:
1073 aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("cjk") );
1074 break;
1075 case CSS1_OUTMODE_CTL:
1076 aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("ctl") );
1077 break;
1080 HTMLOutFuncs::Out_String( rWrt.Strm(), aClass,
1081 rHWrt.eDestEnc, &rHWrt.aNonConvertableCharacters );
1082 sOut = '\"';
1084 rWrt.Strm() << sOut.GetBuffer();
1086 // ggf. Ausrichtung ausgeben.
1087 if( !rHWrt.bNoAlign && pAdjItem )
1088 OutHTML_SvxAdjust( rWrt, *pAdjItem );
1090 // und nun ggf. noch die STYLE-Option
1091 if( rHWrt.bCfgOutStyles && rInfo.pItemSet && !bNoStyle)
1093 OutCSS1_ParaTagStyleOpt( rWrt, *rInfo.pItemSet );
1096 rWrt.Strm() << '>';
1098 // Soll ein </P> geschrieben wenrden
1099 rInfo.bOutPara =
1100 bPara &&
1101 ( rHWrt.bCfgOutStyles ||
1102 (!rHWrt.bCfgOutStyles && bHasParSpace) );
1104 // wenn kein End-Tag geschrieben werden soll, es loeschen
1105 if( bNoEndTag )
1106 rInfo.aToken.Erase();
1109 // ??? Warum nicht ueber den Hint-Mechanismus ???
1110 if( rHWrt.IsHTMLMode(HTMLMODE_FIRSTLINE) )
1112 const SvxLRSpaceItem& rLRSpaceTmp =
1113 pNodeItemSet ? ((const SvxLRSpaceItem &)pNodeItemSet->Get(RES_LR_SPACE))
1114 : rFmt.GetLRSpace();
1115 if( rLRSpaceTmp.GetTxtFirstLineOfst() > 0 )
1117 OutHTML_HoriSpacer( rWrt, rLRSpaceTmp.GetTxtFirstLineOfst() );
1121 if( nBulletGrfLvl != 255 )
1123 ASSERT( aNumInfo.GetNumRule(), "Wo ist die Numerierung geblieben???" );
1124 ASSERT( nBulletGrfLvl < MAXLEVEL, "So viele Ebenen gibt's nicht" );
1125 const SwNumFmt& rNumFmt = aNumInfo.GetNumRule()->Get(nBulletGrfLvl);
1127 OutHTML_BulletImage( rWrt, OOO_STRING_SVTOOLS_HTML_image, 0,
1128 rHWrt.aBulletGrfs[nBulletGrfLvl],
1129 rNumFmt.GetGraphicSize(), rNumFmt.GetGraphicOrientation() );
1132 rHWrt.GetNumInfo() = aNumInfo;
1134 // die Defaults zuruecksetzen
1135 rHWrt.nDfltLeftMargin = 0;
1136 rHWrt.nDfltRightMargin = 0;
1137 rHWrt.nDfltFirstLineIndent = 0;
1138 rHWrt.nDfltTopMargin = 0;
1139 rHWrt.nDfltBottomMargin = 0;
1140 rHWrt.nLeftMargin = 0;
1141 rHWrt.nFirstLineIndent = 0;
1144 void OutHTML_SwFmtOff( Writer& rWrt, const SwHTMLTxtCollOutputInfo& rInfo )
1146 SwHTMLWriter & rHWrt = (SwHTMLWriter&)rWrt;
1148 // wenn es kein Token gibt haben wir auch nichts auszugeben
1149 if( !rInfo.aToken.Len() )
1151 rHWrt.FillNextNumInfo();
1152 const SwHTMLNumRuleInfo& rNextInfo = *rHWrt.GetNextNumInfo();
1153 // Auch in PRE muss eine Bullet-Liste beendet werden
1154 if( rInfo.bInNumBulList )
1157 const SwHTMLNumRuleInfo& rNRInfo = rHWrt.GetNumInfo();
1158 if( rNextInfo.GetNumRule() != rNRInfo.GetNumRule() ||
1159 rNextInfo.GetDepth() != rNRInfo.GetDepth() ||
1160 rNextInfo.IsNumbered() || rNextInfo.IsRestart() )
1161 rHWrt.ChangeParaToken( 0 );
1162 OutHTML_NumBulListEnd( rHWrt, rNextInfo );
1164 else if( rNextInfo.GetNumRule() != 0 )
1165 rHWrt.ChangeParaToken( 0 );
1167 return;
1170 if( rInfo.ShouldOutputToken() )
1172 if( rHWrt.bLFPossible )
1173 rHWrt.OutNewLine( TRUE );
1175 // fuer BLOCKQUOTE, ADDRESS und DD wird ggf noch ein
1176 // Absatz-Token ausgegeben, wenn
1177 // - keine Styles geschrieben werden, und
1178 // - ein untere Abstand existiert
1179 if( rInfo.bParaPossible && rInfo.bOutPara )
1180 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_parabreak, FALSE );
1182 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rInfo.aToken.GetBuffer(),
1183 FALSE );
1184 rHWrt.bLFPossible = !rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_dt ) &&
1185 !rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_dd ) &&
1186 !rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_li );
1188 if( rInfo.bOutDiv )
1190 rHWrt.DecIndentLevel();
1191 if( rHWrt.bLFPossible )
1192 rHWrt.OutNewLine();
1193 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_division, FALSE );
1194 rHWrt.bLFPossible = TRUE;
1197 // ggf. eine Aufzaehlung- oder Numerierungsliste beenden
1198 if( rInfo.bInNumBulList )
1200 rHWrt.FillNextNumInfo();
1201 OutHTML_NumBulListEnd( rHWrt, *rHWrt.GetNextNumInfo() );
1206 class HTMLSttEndPos
1208 xub_StrLen nStart;
1209 xub_StrLen nEnd;
1210 SfxPoolItem* pItem;
1212 public:
1214 HTMLSttEndPos( const SfxPoolItem& rItem, xub_StrLen nStt, xub_StrLen nE );
1215 ~HTMLSttEndPos();
1217 const SfxPoolItem *GetItem() const { return pItem; }
1219 void SetStart( xub_StrLen nStt ) { nStart = nStt; }
1220 xub_StrLen GetStart() const { return nStart; }
1222 xub_StrLen GetEnd() const { return nEnd; }
1223 void SetEnd( xub_StrLen nE ) { nEnd = nE; }
1226 HTMLSttEndPos::HTMLSttEndPos( const SfxPoolItem& rItem, xub_StrLen nStt,
1227 xub_StrLen nE ) :
1228 nStart( nStt ),
1229 nEnd( nE ),
1230 pItem( rItem.Clone() )
1233 HTMLSttEndPos::~HTMLSttEndPos()
1235 delete pItem;
1238 typedef HTMLSttEndPos *HTMLSttEndPosPtr;
1239 SV_DECL_PTRARR( _HTMLEndLst, HTMLSttEndPosPtr, 5, 5 )
1241 enum HTMLOnOffState { HTML_NOT_SUPPORTED, // nicht unterst. Attribut
1242 HTML_REAL_VALUE, // Attribut mit Wert
1243 HTML_ON_VALUE, // Attribut entspricht On-Tag
1244 HTML_OFF_VALUE, // Attribut entspricht Off-Tag
1245 HTML_CHRFMT_VALUE, // Attribut fuer Zeichenvorlage
1246 HTML_COLOR_VALUE, // Attribut fuer Vordergrundfarbe
1247 HTML_STYLE_VALUE, // Attribut muss als Style exp.
1248 HTML_DROPCAP_VALUE, // DropCap-Attributs
1249 HTML_AUTOFMT_VALUE }; // Attribute for automatic character styles
1252 class HTMLEndPosLst
1254 _HTMLEndLst aStartLst; // nach Anfangs-Psoitionen sortierte Liste
1255 _HTMLEndLst aEndLst; // nach End-Psotionen sortierte Liste
1256 SvXub_StrLens aScriptChgLst; // positions where script changes
1257 // 0 is not contained in this list,
1258 // but the text length
1259 SvUShorts aScriptLst; // the script that is valif up to the position
1260 // contained in aScriptChgList at the same index
1262 SwDoc *pDoc; // das aktuelle Dokument
1263 SwDoc* pTemplate; // die HTML-Vorlage (oder 0)
1264 const Color* pDfltColor;// die Default-Vordergrund-Farbe
1265 SvStringsSortDtor& rScriptTxtStyles; //
1267 ULONG nHTMLMode;
1268 BOOL bOutStyles : 1; // werden Styles exportiert
1271 // die Position eines Items in der Start-/Ende-Liste suchen
1272 USHORT _FindStartPos( const HTMLSttEndPos *pPos ) const;
1273 USHORT _FindEndPos( const HTMLSttEndPos *pPos ) const;
1275 // Eine SttEndPos in die Start- und Ende-Listen eintragen bzw. aus
1276 // ihnen loeschen, wobei die Ende-Position bekannt ist
1277 void _InsertItem( HTMLSttEndPos *pPos, USHORT nEndPos );
1278 void _RemoveItem( USHORT nEndPos );
1280 // die "Art" es Attributs ermitteln
1281 HTMLOnOffState GetHTMLItemState( const SfxPoolItem& rItem );
1283 // Existiert ein bestimmtes On-Tag-Item
1284 BOOL ExistsOnTagItem( USHORT nWhich, xub_StrLen nPos );
1286 // Existiert ein Item zum ausschalten eines Attributs, das genauso
1287 // exportiert wird wie das uebergebene Item im gleichen Bereich?
1288 BOOL ExistsOffTagItem( USHORT nWhich, xub_StrLen nStartPos,
1289 xub_StrLen nEndPos );
1292 // das Ende eines gesplitteten Items anpassen
1293 void FixSplittedItem( HTMLSttEndPos *pPos, USHORT nStartPos,
1294 xub_StrLen nNewEnd );
1296 // Ein Attribut in die Listen eintragen und ggf. aufteilen
1297 void InsertItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1298 xub_StrLen nEnd );
1300 // Ein bereits vorhandenes Attribut aufteilen
1301 void SplitItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1302 xub_StrLen nEnd );
1304 // Insert without taking care of script
1305 void InsertNoScript( const SfxPoolItem& rItem, xub_StrLen nStart,
1306 xub_StrLen nEnd, SwHTMLFmtInfos& rFmtInfos,
1307 BOOL bParaAttrs=FALSE );
1309 const SwHTMLFmtInfo *GetFmtInfo( const SwFmt& rFmt,
1310 SwHTMLFmtInfos& rFmtInfos );
1312 public:
1314 HTMLEndPosLst( SwDoc *pDoc, SwDoc* pTemplate, const Color* pDfltColor,
1315 BOOL bOutStyles, ULONG nHTMLMode,
1316 const String& rText, SvStringsSortDtor& rStyles );
1317 ~HTMLEndPosLst();
1319 // Ein Attribut einfuegen
1320 void Insert( const SfxPoolItem& rItem, xub_StrLen nStart, xub_StrLen nEnd,
1321 SwHTMLFmtInfos& rFmtInfos, BOOL bParaAttrs=FALSE );
1322 void Insert( const SfxItemSet& rItemSet, xub_StrLen nStart, xub_StrLen nEnd,
1323 SwHTMLFmtInfos& rFmtInfos, BOOL bDeep,
1324 BOOL bParaAttrs=FALSE );
1325 void Insert( const SwDrawFrmFmt& rFmt, xub_StrLen nPos,
1326 SwHTMLFmtInfos& rFmtInfos );
1328 sal_uInt16 GetScriptAtPos( xub_StrLen nPos,
1329 sal_uInt16 nWeak=CSS1_OUTMODE_ANY_SCRIPT );
1331 void OutStartAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
1332 HTMLOutContext *pContext = 0 );
1333 void OutEndAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
1334 HTMLOutContext *pContext = 0 );
1336 USHORT Count() const { return aEndLst.Count(); }
1338 BOOL IsHTMLMode( ULONG nMode ) const { return (nHTMLMode & nMode) != 0; }
1342 USHORT HTMLEndPosLst::_FindStartPos( const HTMLSttEndPos *pPos ) const
1344 USHORT i;
1345 for( i = 0; i < aStartLst.Count() && aStartLst[i] != pPos; i++ )
1348 ASSERT( i != aStartLst.Count(), "Item nicht in Start-Liste gefunden!" );
1350 return i==aStartLst.Count() ? USHRT_MAX : i;
1353 USHORT HTMLEndPosLst::_FindEndPos( const HTMLSttEndPos *pPos ) const
1355 USHORT i;
1357 for( i = 0; i < aEndLst.Count() && aEndLst[i] != pPos; i++ )
1360 ASSERT( i != aEndLst.Count(), "Item nicht in Ende-Liste gefunden" );
1362 return i==aEndLst.Count() ? USHRT_MAX : i;
1366 void HTMLEndPosLst::_InsertItem( HTMLSttEndPos *pPos, USHORT nEndPos )
1368 // In der Start-Liste das Attribut hinter allen vorher und an
1369 // der gleichen Position gestarteten Attributen einfuegen
1370 xub_StrLen nStart = pPos->GetStart();
1371 USHORT i;
1373 for( i = 0; i < aStartLst.Count() &&
1374 aStartLst[i]->GetStart() <= nStart; i++ )
1376 aStartLst.Insert( pPos, i );
1378 // die Position in der Ende-Liste wurde uebergeben
1379 aEndLst.Insert( pPos, nEndPos );
1382 void HTMLEndPosLst::_RemoveItem( USHORT nEndPos )
1384 HTMLSttEndPos *pPos = aEndLst[nEndPos];
1386 // jetzt Suchen wir es in der Start-Liste
1387 USHORT nStartPos = _FindStartPos( pPos );
1388 if( nStartPos != USHRT_MAX )
1389 aStartLst.Remove( nStartPos, 1 );
1391 aEndLst.Remove( nEndPos, 1 );
1393 delete pPos;
1396 HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem )
1398 HTMLOnOffState eState = HTML_NOT_SUPPORTED;
1399 switch( rItem.Which() )
1401 case RES_CHRATR_POSTURE:
1402 case RES_CHRATR_CJK_POSTURE:
1403 case RES_CHRATR_CTL_POSTURE:
1404 switch( ((const SvxPostureItem&)rItem).GetPosture() )
1406 case ITALIC_NORMAL:
1407 eState = HTML_ON_VALUE;
1408 break;
1409 case ITALIC_NONE:
1410 eState = HTML_OFF_VALUE;
1411 break;
1412 default:
1413 if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1414 eState = HTML_STYLE_VALUE;
1415 break;
1417 break;
1419 case RES_CHRATR_CROSSEDOUT:
1420 switch( ((const SvxCrossedOutItem&)rItem).GetStrikeout() )
1422 case STRIKEOUT_SINGLE:
1423 case STRIKEOUT_DOUBLE:
1424 eState = HTML_ON_VALUE;
1425 break;
1426 case STRIKEOUT_NONE:
1427 eState = HTML_OFF_VALUE;
1428 break;
1429 default:
1432 break;
1434 case RES_CHRATR_ESCAPEMENT:
1435 switch( (const SvxEscapement)
1436 ((const SvxEscapementItem&)rItem).GetEnumValue() )
1438 case SVX_ESCAPEMENT_SUPERSCRIPT:
1439 case SVX_ESCAPEMENT_SUBSCRIPT:
1440 eState = HTML_ON_VALUE;
1441 break;
1442 case SVX_ESCAPEMENT_OFF:
1443 eState = HTML_OFF_VALUE;
1444 break;
1445 default:
1448 break;
1450 case RES_CHRATR_UNDERLINE:
1451 switch( ((const SvxUnderlineItem&)rItem).GetLineStyle() )
1453 case UNDERLINE_SINGLE:
1454 eState = HTML_ON_VALUE;
1455 break;
1456 case UNDERLINE_NONE:
1457 eState = HTML_OFF_VALUE;
1458 break;
1459 default:
1460 if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1461 eState = HTML_STYLE_VALUE;
1462 break;
1464 break;
1466 case RES_CHRATR_OVERLINE:
1467 if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1468 eState = HTML_STYLE_VALUE;
1469 break;
1471 case RES_CHRATR_WEIGHT:
1472 case RES_CHRATR_CJK_WEIGHT:
1473 case RES_CHRATR_CTL_WEIGHT:
1474 switch( ((const SvxWeightItem&)rItem).GetWeight() )
1476 case WEIGHT_BOLD:
1477 eState = HTML_ON_VALUE;
1478 break;
1479 case WEIGHT_NORMAL:
1480 eState = HTML_OFF_VALUE;
1481 break;
1482 default:
1483 if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1484 eState = HTML_STYLE_VALUE;
1485 break;
1487 break;
1489 case RES_CHRATR_BLINK:
1490 if( IsHTMLMode(HTMLMODE_BLINK) )
1491 eState = ((const SvxBlinkItem&)rItem).GetValue() ? HTML_ON_VALUE
1492 : HTML_OFF_VALUE;
1493 break;
1495 case RES_CHRATR_COLOR:
1496 eState = HTML_COLOR_VALUE;
1497 break;
1499 case RES_CHRATR_FONT:
1500 case RES_CHRATR_FONTSIZE:
1501 case RES_CHRATR_LANGUAGE:
1502 case RES_CHRATR_CJK_FONT:
1503 case RES_CHRATR_CJK_FONTSIZE:
1504 case RES_CHRATR_CJK_LANGUAGE:
1505 case RES_CHRATR_CTL_FONT:
1506 case RES_CHRATR_CTL_FONTSIZE:
1507 case RES_CHRATR_CTL_LANGUAGE:
1508 case RES_TXTATR_INETFMT:
1509 eState = HTML_REAL_VALUE;
1510 break;
1512 case RES_TXTATR_CHARFMT:
1513 eState = HTML_CHRFMT_VALUE;
1514 break;
1516 case RES_TXTATR_AUTOFMT:
1517 eState = HTML_AUTOFMT_VALUE;
1518 break;
1520 case RES_CHRATR_CASEMAP:
1521 if( IsHTMLMode(HTMLMODE_SMALL_CAPS) )
1522 eState = HTML_STYLE_VALUE;
1524 case RES_CHRATR_KERNING:
1525 if( IsHTMLMode(HTMLMODE_FULL_STYLES) )
1526 eState = HTML_STYLE_VALUE;
1527 break;
1529 case RES_CHRATR_BACKGROUND:
1530 if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1531 eState = HTML_STYLE_VALUE;
1532 break;
1534 case RES_PARATR_DROP:
1535 eState = HTML_DROPCAP_VALUE;
1536 break;
1538 // default:
1539 // eState = HTML_NOT_SUPPORTED;
1540 // break;
1543 return eState;
1546 BOOL HTMLEndPosLst::ExistsOnTagItem( USHORT nWhich, xub_StrLen nPos )
1548 for( USHORT i=0; i<aStartLst.Count(); i++ )
1550 HTMLSttEndPos *pTest = aStartLst[i];
1552 if( pTest->GetStart() > nPos )
1554 // dieses uns alle folgenden Attribute beginnen spaeter
1555 break;
1557 else if( pTest->GetEnd() > nPos )
1559 // das Attribut beginnt vor oder an der aktuellen Position
1560 // und endet hinter ihr
1561 const SfxPoolItem *pItem = pTest->GetItem();
1562 if( pItem->Which() == nWhich &&
1563 HTML_ON_VALUE == GetHTMLItemState(*pItem) )
1565 // ein On-Tag-Attibut wurde gefunden
1566 return TRUE;
1571 return FALSE;
1574 BOOL HTMLEndPosLst::ExistsOffTagItem( USHORT nWhich, xub_StrLen nStartPos,
1575 xub_StrLen nEndPos )
1577 if( nWhich != RES_CHRATR_CROSSEDOUT &&
1578 nWhich != RES_CHRATR_UNDERLINE &&
1579 nWhich != RES_CHRATR_BLINK )
1581 return FALSE;
1584 for( USHORT i=0; i<aStartLst.Count(); i++ )
1586 HTMLSttEndPos *pTest = aStartLst[i];
1588 if( pTest->GetStart() > nStartPos )
1590 // dieses uns alle folgenden Attribute beginnen spaeter
1591 break;
1593 else if( pTest->GetStart()==nStartPos &&
1594 pTest->GetEnd()==nEndPos )
1596 // das Attribut beginnt vor oder an der aktuellen Position
1597 // und endet hinter ihr
1598 const SfxPoolItem *pItem = pTest->GetItem();
1599 USHORT nTstWhich = pItem->Which() ;
1600 if( (nTstWhich == RES_CHRATR_CROSSEDOUT ||
1601 nTstWhich == RES_CHRATR_UNDERLINE ||
1602 nTstWhich == RES_CHRATR_BLINK) &&
1603 HTML_OFF_VALUE == GetHTMLItemState(*pItem) )
1605 // Ein Off-Tag-Attibut wurde gefunden, das genauso
1606 // exportiert wird, wie das aktuelle Item
1607 return TRUE;
1612 return FALSE;
1615 void HTMLEndPosLst::FixSplittedItem( HTMLSttEndPos *pPos, xub_StrLen nNewEnd,
1616 USHORT nStartPos )
1618 // die End-Position entsprechend fixen
1619 pPos->SetEnd( nNewEnd );
1621 // das Item aus der End-Liste entfernen
1622 USHORT nEndPos = _FindEndPos( pPos );
1623 if( nEndPos != USHRT_MAX )
1624 aEndLst.Remove( nEndPos, 1 );
1626 // es wird von nun an als letztes an der entsprechenden Position
1627 // beendet
1628 for( nEndPos=0; nEndPos < aEndLst.Count() &&
1629 aEndLst[nEndPos]->GetEnd() <= nNewEnd; nEndPos++ )
1631 aEndLst.Insert( pPos, nEndPos );
1633 // jetzt noch die spaeter gestarteten Attribute anpassen
1634 for( USHORT i=nStartPos+1; i<aStartLst.Count(); i++ )
1636 HTMLSttEndPos *pTest = aStartLst[i];
1637 xub_StrLen nTestEnd = pTest->GetEnd();
1638 if( pTest->GetStart() >= nNewEnd )
1640 // das Test-Attribut und alle folgenden beginnen, nachdem das
1641 // gesplittete Attribut endet
1642 break;
1644 else if( nTestEnd > nNewEnd )
1646 // das Test-Attribut beginnt, bevor das gesplittete Attribut
1647 // endet und endet danach, muss also auch gesplittet werden
1649 // das neue Ende setzen
1650 pTest->SetEnd( nNewEnd );
1652 // das Attribut aus der End-Liste entfernen
1653 USHORT nEPos = _FindEndPos( pTest );
1654 if( nEPos != USHRT_MAX )
1655 aEndLst.Remove( nEPos, 1 );
1657 // es endet jetzt als erstes Attribut an der entsprechenden
1658 // Position. Diese Position in der Ende-Liste kennen wir schon.
1659 aEndLst.Insert(pTest, nEndPos );
1661 // den "Rest" des Attributs neu einfuegen
1662 InsertItem( *pTest->GetItem(), nNewEnd, nTestEnd );
1668 void HTMLEndPosLst::InsertItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1669 xub_StrLen nEnd )
1671 USHORT i;
1672 for( i = 0; i < aEndLst.Count(); i++ )
1674 HTMLSttEndPos *pTest = aEndLst[i];
1675 xub_StrLen nTestEnd = pTest->GetEnd();
1676 if( nTestEnd <= nStart )
1678 // das Test-Attribut endet, bevor das neue beginnt
1679 continue;
1681 else if( nTestEnd < nEnd )
1683 // das Test-Attribut endet, bevor das neue endet. Das
1684 // neue Attribut muss deshalb aufgesplittet werden
1685 _InsertItem( new HTMLSttEndPos( rItem, nStart, nTestEnd ), i );
1686 nStart = nTestEnd;
1688 else
1690 // das Test-Attribut (und alle folgenden) endet, bevor das neue
1691 // endet
1692 break;
1696 // ein Attribut muss noch eingefuegt werden
1697 _InsertItem( new HTMLSttEndPos( rItem, nStart, nEnd ), i );
1702 void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1703 xub_StrLen nEnd )
1705 USHORT nWhich = rItem.Which();
1707 // erstmal muessen wir die alten Items anhand der Startliste suchen
1708 // und die neuen Item-Bereiche festlegen
1710 for( USHORT i=0; i<aStartLst.Count(); i++ )
1712 HTMLSttEndPos *pTest = aStartLst[i];
1713 xub_StrLen nTestStart = pTest->GetStart();
1714 xub_StrLen nTestEnd = pTest->GetEnd();
1716 if( nTestStart >= nEnd )
1718 // dieses und alle nachfolgenden Attribute beginnen spaeter
1719 break;
1721 else if( nTestEnd > nStart )
1723 // das Test Attribut endet im zu loeschenenden Bereich
1724 const SfxPoolItem *pItem = pTest->GetItem();
1726 // nur entsprechende On-Tag Attribute muessen beruecksichtigt
1727 // werden
1728 if( pItem->Which() == nWhich &&
1729 HTML_ON_VALUE == GetHTMLItemState( *pItem ) )
1731 BOOL bDelete = TRUE;
1733 if( nTestStart < nStart )
1735 // der Start des neuen Attribut entspricht
1736 // dem neuen Ende des Attribts
1737 FixSplittedItem( pTest, nStart, i );
1738 bDelete = FALSE;
1740 else
1742 // das Test-Item beginnt erst hinter dem neuen
1743 // Ende des Attribts und kann deshalb komplett
1744 // geloescht werden
1745 aStartLst.Remove( i, 1 );
1746 i--;
1748 USHORT nEndPos = _FindEndPos( pTest );
1749 if( nEndPos != USHRT_MAX )
1750 aEndLst.Remove( nEndPos, 1 );
1753 // ggf den zweiten Teil des gesplitteten Attribts einfuegen
1754 if( nTestEnd > nEnd )
1756 InsertItem( *pTest->GetItem(), nEnd, nTestEnd );
1759 if( bDelete )
1760 delete pTest;
1766 const SwHTMLFmtInfo *HTMLEndPosLst::GetFmtInfo( const SwFmt& rFmt,
1767 SwHTMLFmtInfos& rFmtInfos )
1769 const SwHTMLFmtInfo *pFmtInfo;
1770 SwHTMLFmtInfo aFmtInfo( &rFmt );
1771 USHORT nPos;
1772 if( rFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
1774 pFmtInfo = rFmtInfos[nPos];
1776 else
1778 pFmtInfo = new SwHTMLFmtInfo( &rFmt, pDoc, pTemplate,
1779 bOutStyles );
1780 rFmtInfos.C40_PTR_INSERT( SwHTMLFmtInfo, pFmtInfo );
1781 String aName( rFmt.GetName() );
1782 if( rScriptTxtStyles.Seek_Entry( &aName ) )
1783 ((SwHTMLFmtInfo *)pFmtInfo)->bScriptDependent = sal_True;
1786 return pFmtInfo;
1789 HTMLEndPosLst::HTMLEndPosLst( SwDoc *pD, SwDoc* pTempl,
1790 const Color* pDfltCol, BOOL bStyles,
1791 ULONG nMode, const String& rText,
1792 SvStringsSortDtor& rStyles ):
1793 pDoc( pD ),
1794 pTemplate( pTempl ),
1795 pDfltColor( pDfltCol ),
1796 rScriptTxtStyles( rStyles ),
1797 nHTMLMode( nMode ),
1798 bOutStyles( bStyles )
1800 xub_StrLen nEndPos = rText.Len();
1801 xub_StrLen nPos = 0;
1802 while( nPos < nEndPos )
1804 sal_uInt16 nScript = pBreakIt->GetBreakIter()->getScriptType( rText, nPos );
1805 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rText, nPos, nScript );
1806 aScriptChgLst.Insert( nPos, aScriptChgLst.Count() );
1807 aScriptLst.Insert( nScript, aScriptLst.Count() );
1811 HTMLEndPosLst::~HTMLEndPosLst()
1813 ASSERT( !aStartLst.Count(), "Start-Liste im Destruktor nicht leer" );
1814 ASSERT( !aEndLst.Count(), "End-Liste im Destruktor nicht leer" );
1819 void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem,
1820 xub_StrLen nStart, xub_StrLen nEnd,
1821 SwHTMLFmtInfos& rFmtInfos, BOOL bParaAttrs )
1823 // kein Bereich ?? dann nicht aufnehmen, wird nie wirksam !!
1824 if( nStart != nEnd )
1826 BOOL bSet = FALSE, bSplit = FALSE;
1827 switch( GetHTMLItemState(rItem) )
1829 case HTML_ON_VALUE:
1830 // das Attribut wird ausgegeben, wenn es nicht sowieso
1831 // schon an ist
1832 if( !ExistsOnTagItem( rItem.Which(), nStart ) )
1833 bSet = TRUE;
1834 break;
1836 case HTML_OFF_VALUE:
1837 // wenn das entsprechne Attribut an ist, wird es gesplittet,
1838 // Zusaetlich wird es aber als Style ausgegeben, wenn es nicht
1839 // am ganzen Absatz gesetzt ist, weil es dann ja schon mit dem
1840 // ABsatz-Tag ausgegeben wurde.
1841 if( ExistsOnTagItem( rItem.Which(), nStart ) )
1842 bSplit = TRUE;
1843 bSet = bOutStyles && !bParaAttrs &&
1844 !ExistsOffTagItem( rItem.Which(), nStart, nEnd );
1845 break;
1847 case HTML_REAL_VALUE:
1848 // das Attribut kann immer ausgegeben werden
1849 bSet = TRUE;
1850 break;
1852 case HTML_STYLE_VALUE:
1853 // Das Attribut kann nur als CSS1 ausgegeben werden. Wenn
1854 // es am Absatz gesetzt ist, wurde es schon mit dem
1855 // Absatz-Tag ausgegeben. Einzige Ausnahme ist das
1856 // Zeichen-Hintergrund-Attribut. Es muss immer wie ein
1857 // Hint behandelt werden.
1858 bSet = bOutStyles &&
1859 (!bParaAttrs
1860 || rItem.Which()==RES_CHRATR_BACKGROUND
1861 || rItem.Which()==RES_CHRATR_OVERLINE);
1862 break;
1864 case HTML_CHRFMT_VALUE:
1866 ASSERT( RES_TXTATR_CHARFMT == rItem.Which(),
1867 "Doch keine Zeichen-Vorlage" );
1868 const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rItem;
1869 const SwCharFmt* pFmt = rChrFmt.GetCharFmt();
1871 const SwHTMLFmtInfo *pFmtInfo = GetFmtInfo( *pFmt, rFmtInfos );
1872 if( pFmtInfo->aToken.Len() )
1874 // das Zeichenvorlagen-Tag muss vor den harten
1875 // Attributen ausgegeben werden
1876 InsertItem( rItem, nStart, nEnd );
1878 if( pFmtInfo->pItemSet )
1880 Insert( *pFmtInfo->pItemSet, nStart, nEnd,
1881 rFmtInfos, TRUE, bParaAttrs );
1884 break;
1886 case HTML_AUTOFMT_VALUE:
1888 const SwFmtAutoFmt& rAutoFmt = (const SwFmtAutoFmt&)rItem;
1889 const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle();
1890 if( pSet.get() )
1891 Insert( *pSet.get(), nStart, nEnd, rFmtInfos, TRUE, bParaAttrs );
1893 break;
1895 case HTML_COLOR_VALUE:
1896 // Eine Vordergrund-Farbe als Absatz-Attribut wird nur
1897 // exportiert, wenn sie nicht der Default-Farbe entspricht.
1899 ASSERT( RES_CHRATR_COLOR == rItem.Which(),
1900 "Doch keine Vordergrund-Farbe" );
1901 Color aColor( ((const SvxColorItem&)rItem).GetValue() );
1902 if( COL_AUTO == aColor.GetColor() )
1903 aColor.SetColor( COL_BLACK );
1904 bSet = !bParaAttrs || !pDfltColor ||
1905 !pDfltColor->IsRGBEqual( aColor );
1907 break;
1909 case HTML_DROPCAP_VALUE:
1911 ASSERT( RES_PARATR_DROP == rItem.Which(),
1912 "Doch kein Drop-Cap" );
1913 const SwFmtDrop& rDrop = (const SwFmtDrop&)rItem;
1914 nEnd = nStart + rDrop.GetChars();
1915 if( !bOutStyles )
1917 // Zumindest die Attribute der Zeichenvorlage uebernehmen
1918 const SwCharFmt *pCharFmt = rDrop.GetCharFmt();
1919 if( pCharFmt )
1921 Insert( pCharFmt->GetAttrSet(), nStart, nEnd,
1922 rFmtInfos, TRUE, bParaAttrs );
1925 else
1927 bSet = TRUE;
1930 break;
1931 default:
1935 if( bSet )
1936 InsertItem( rItem, nStart, nEnd );
1937 if( bSplit )
1938 SplitItem( rItem, nStart, nEnd );
1942 void HTMLEndPosLst::Insert( const SfxPoolItem& rItem,
1943 xub_StrLen nStart, xub_StrLen nEnd,
1944 SwHTMLFmtInfos& rFmtInfos, BOOL bParaAttrs )
1946 sal_Bool bDependsOnScript = sal_False, bDependsOnAnyScript = sal_False;
1947 sal_uInt16 nScript = i18n::ScriptType::LATIN;
1948 switch( rItem.Which() )
1950 case RES_CHRATR_FONT:
1951 case RES_CHRATR_FONTSIZE:
1952 case RES_CHRATR_LANGUAGE:
1953 case RES_CHRATR_POSTURE:
1954 case RES_CHRATR_WEIGHT:
1955 bDependsOnScript = sal_True;
1956 nScript = i18n::ScriptType::LATIN;
1957 break;
1959 case RES_CHRATR_CJK_FONT:
1960 case RES_CHRATR_CJK_FONTSIZE:
1961 case RES_CHRATR_CJK_LANGUAGE:
1962 case RES_CHRATR_CJK_POSTURE:
1963 case RES_CHRATR_CJK_WEIGHT:
1964 bDependsOnScript = sal_True;
1965 nScript = i18n::ScriptType::ASIAN;
1966 break;
1968 case RES_CHRATR_CTL_FONT:
1969 case RES_CHRATR_CTL_FONTSIZE:
1970 case RES_CHRATR_CTL_LANGUAGE:
1971 case RES_CHRATR_CTL_POSTURE:
1972 case RES_CHRATR_CTL_WEIGHT:
1973 bDependsOnScript = sal_True;
1974 nScript = i18n::ScriptType::COMPLEX;
1975 break;
1976 case RES_TXTATR_CHARFMT:
1978 const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rItem;
1979 const SwCharFmt* pFmt = rChrFmt.GetCharFmt();
1980 const SwHTMLFmtInfo *pFmtInfo = GetFmtInfo( *pFmt, rFmtInfos );
1981 if( pFmtInfo->bScriptDependent )
1983 bDependsOnScript = sal_True;
1984 bDependsOnAnyScript = sal_True;
1987 break;
1988 case RES_TXTATR_INETFMT:
1990 if( GetFmtInfo( *pDoc->GetCharFmtFromPool(
1991 RES_POOLCHR_INET_NORMAL), rFmtInfos )->bScriptDependent ||
1992 GetFmtInfo( *pDoc->GetCharFmtFromPool(
1993 RES_POOLCHR_INET_VISIT), rFmtInfos )->bScriptDependent )
1995 bDependsOnScript = sal_True;
1996 bDependsOnAnyScript = sal_True;
1999 break;
2002 if( bDependsOnScript )
2004 sal_uInt16 nScriptChgs = aScriptChgLst.Count();
2005 xub_StrLen nPos = nStart;
2006 for( sal_uInt16 i=0; i < nScriptChgs; i++ )
2008 xub_StrLen nChgPos = aScriptChgLst[i];
2009 if( nPos >= nChgPos )
2011 // the hint starts behind or at the next script change,
2012 // so we may continue with this position.
2013 continue;
2015 if( nEnd <= nChgPos )
2017 // the (rest of) the hint ends before or at the next script
2018 // change, so we can insert it, but only if it belongs
2019 // to the current script.
2020 if( bDependsOnAnyScript || nScript == aScriptLst[i] )
2021 InsertNoScript( rItem, nPos, nEnd, rFmtInfos,
2022 bParaAttrs );
2023 break;
2026 // the hint starts before the next script change and ends behind
2027 // it, so we can insert a hint upto the next script change and
2028 // continue with the rest of the hint.
2029 if( bDependsOnAnyScript || nScript == aScriptLst[i] )
2030 InsertNoScript( rItem, nPos, nChgPos, rFmtInfos, bParaAttrs );
2031 nPos = nChgPos;
2034 else
2036 InsertNoScript( rItem, nStart, nEnd, rFmtInfos, bParaAttrs );
2040 void HTMLEndPosLst::Insert( const SfxItemSet& rItemSet,
2041 xub_StrLen nStart, xub_StrLen nEnd,
2042 SwHTMLFmtInfos& rFmtInfos,
2043 BOOL bDeep, BOOL bParaAttrs )
2045 SfxWhichIter aIter( rItemSet );
2047 USHORT nWhich = aIter.FirstWhich();
2048 while( nWhich )
2050 const SfxPoolItem *pItem;
2051 if( SFX_ITEM_SET == rItemSet.GetItemState( nWhich, bDeep, &pItem ) )
2053 Insert( *pItem, nStart, nEnd, rFmtInfos, bParaAttrs );
2056 nWhich = aIter.NextWhich();
2060 void HTMLEndPosLst::Insert( const SwDrawFrmFmt& rFmt, xub_StrLen nPos,
2061 SwHTMLFmtInfos& rFmtInfos )
2063 // der Type-Cast ist nur noetig, um nicht seinetwegen
2064 // svdrwobt.hxx zu includem
2065 const SdrObject* pTextObj =
2066 (const SdrObject *)SwHTMLWriter::GetMarqueeTextObj( rFmt );
2068 if( pTextObj )
2070 // die Edit-Engine-Attribute des Objekts als SW-Attribute holen
2071 // und als Hints einsortieren. Wegen der Menge der Hints werden
2072 // Styles hierbei nicht beruecksichtigt!
2073 const SfxItemSet& rFmtItemSet = rFmt.GetAttrSet();
2074 SfxItemSet aItemSet( *rFmtItemSet.GetPool(), RES_CHRATR_BEGIN,
2075 RES_CHRATR_END );
2076 SwHTMLWriter::GetEEAttrsFromDrwObj( aItemSet, pTextObj, TRUE );
2077 BOOL bOutStylesOld = bOutStyles;
2078 bOutStyles = FALSE;
2079 Insert( aItemSet, nPos, nPos+1, rFmtInfos, FALSE, FALSE );
2080 bOutStyles = bOutStylesOld;
2084 sal_uInt16 HTMLEndPosLst::GetScriptAtPos( xub_StrLen nPos ,
2085 sal_uInt16 nWeak )
2087 sal_uInt16 nRet = CSS1_OUTMODE_ANY_SCRIPT;
2089 sal_uInt16 nScriptChgs = aScriptChgLst.Count();
2090 sal_uInt16 i=0;
2091 while( i < nScriptChgs && nPos >= aScriptChgLst[i] )
2092 i++;
2093 ASSERT( i < nScriptChgs, "script list is to short" );
2094 if( i < nScriptChgs )
2096 if( i18n::ScriptType::WEAK == aScriptLst[i] )
2097 nRet = nWeak;
2098 else
2099 nRet = SwHTMLWriter::GetCSS1ScriptForScriptType( aScriptLst[i] );
2102 return nRet;
2105 void HTMLEndPosLst::OutStartAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
2106 HTMLOutContext *pContext )
2108 rHWrt.bTagOn = TRUE;
2110 // die Attribute in der Start-Liste sind aufsteigend sortiert
2111 for( USHORT i=0; i< aStartLst.Count(); i++ )
2113 HTMLSttEndPos *pPos = aStartLst[i];
2114 xub_StrLen nStart = pPos->GetStart();
2115 if( nStart > nPos )
2117 // dieses und alle folgenden Attribute werden erst noch geoeffnet
2118 break;
2120 else if( nStart == nPos )
2122 // das Attribut ausgeben
2123 sal_uInt16 nCSS1Script = rHWrt.nCSS1Script;
2124 sal_uInt16 nWhich = pPos->GetItem()->Which();
2125 if( RES_TXTATR_CHARFMT == nWhich ||
2126 RES_TXTATR_INETFMT == nWhich ||
2127 RES_PARATR_DROP == nWhich )
2129 rHWrt.nCSS1Script = GetScriptAtPos( nPos, nCSS1Script );
2131 if( pContext )
2133 HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext );
2134 pContext = 0; // one time ony
2136 Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt );
2137 rHWrt.nCSS1Script = nCSS1Script;
2142 void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
2143 HTMLOutContext *pContext )
2145 rHWrt.bTagOn = FALSE;
2147 // die Attribute in der End-Liste sind aufsteigend sortiert
2148 USHORT i=0;
2149 while( i < aEndLst.Count() )
2151 HTMLSttEndPos *pPos = aEndLst[i];
2152 xub_StrLen nEnd = pPos->GetEnd();
2154 if( STRING_MAXLEN==nPos || nEnd == nPos )
2156 if( pContext )
2158 HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext );
2159 pContext = 0; // one time ony
2161 Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt );
2162 _RemoveItem( i );
2164 else if( nEnd > nPos )
2166 // dieses und alle folgenden Attribute werden erst spaeter beendet
2167 break;
2169 else
2171 // Das Attribut wird vor der aktuellen Position beendet. Das
2172 // darf nicht sein, aber wie koennen trotzdem damit umgehen
2173 ASSERT( nEnd >= nPos,
2174 "Das Attribut sollte schon laengst beendet sein" );
2175 i++;
2181 /* Ausgabe der Nodes */
2182 Writer& OutHTML_SwTxtNode( Writer& rWrt, const SwCntntNode& rNode )
2184 SwTxtNode * pNd = &((SwTxtNode&)rNode);
2185 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
2187 const String& rStr = pNd->GetTxt();
2188 xub_StrLen nEnde = rStr.Len();
2190 // Besonderheit: leere Node und HR-Vorlage (horizontaler Strich)
2191 // nur ein <HR> ausgeben
2192 USHORT nPoolId = pNd->GetAnyFmtColl().GetPoolFmtId();
2194 if( !nEnde && (RES_POOLCOLL_HTML_HR==nPoolId ||
2195 pNd->GetAnyFmtColl().GetName().EqualsAscii( OOO_STRING_SVTOOLS_HTML_horzrule) ) )
2197 // dann die absatz-gebundenen Grafiken/OLE-Objekte im Absatz
2198 // MIB 8.7.97: Ein <PRE> spannen wir um die Linie auf. Dann stimmen
2199 // zwar die Abstaende nicht, aber sonst bekommen wir einen leeren
2200 // Absatz hinter dem <HR> und das ist noch unschoener.
2201 rHTMLWrt.ChangeParaToken( 0 );
2203 // Alle an dem Node verankerten Rahmen ausgeben
2204 rHTMLWrt.OutFlyFrm( rNode.GetIndex(), 0, HTML_POS_ANY );
2206 if( rHTMLWrt.bLFPossible )
2207 rHTMLWrt.OutNewLine(); // Absatz-Tag in eine neue Zeile
2209 rHTMLWrt.bLFPossible = TRUE;
2211 ByteString sOut( '<' );
2212 sOut += OOO_STRING_SVTOOLS_HTML_horzrule;
2214 const SfxItemSet* pItemSet = pNd->GetpSwAttrSet();
2215 if( !pItemSet )
2217 rWrt.Strm() << sOut.GetBuffer() << '>';
2218 return rHTMLWrt;
2220 const SfxPoolItem* pItem;
2221 if( SFX_ITEM_SET == pItemSet->GetItemState( RES_LR_SPACE, FALSE, &pItem ))
2223 sal_Int32 nLeft = ((SvxLRSpaceItem*)pItem)->GetLeft();
2224 sal_Int32 nRight = ((SvxLRSpaceItem*)pItem)->GetRight();
2225 if( nLeft || nRight )
2227 const SwFrmFmt& rPgFmt =
2228 rHTMLWrt.pDoc->GetPageDescFromPool
2229 ( RES_POOLPAGE_HTML, false )->GetMaster();
2230 const SwFmtFrmSize& rSz = rPgFmt.GetFrmSize();
2231 const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace();
2232 const SwFmtCol& rCol = rPgFmt.GetCol();
2234 long nPageWidth = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight();
2236 if( 1 < rCol.GetNumCols() )
2237 nPageWidth /= rCol.GetNumCols();
2239 const SwTableNode* pTblNd = pNd->FindTableNode();
2240 if( pTblNd )
2242 const SwTableBox* pBox = pTblNd->GetTable().GetTblBox(
2243 pNd->StartOfSectionIndex() );
2244 if( pBox )
2245 nPageWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
2248 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width) += '=';
2249 rWrt.Strm() << sOut.GetBuffer();
2250 rWrt.OutULong( rHTMLWrt.ToPixel(nPageWidth-nLeft-nRight) );
2252 ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=';
2253 if( !nLeft )
2254 sOut += OOO_STRING_SVTOOLS_HTML_AL_left;
2255 else if( !nRight )
2256 sOut += OOO_STRING_SVTOOLS_HTML_AL_right;
2257 else
2258 sOut += OOO_STRING_SVTOOLS_HTML_AL_center;
2261 rWrt.Strm() << sOut.GetBuffer();
2262 if( SFX_ITEM_SET == pItemSet->GetItemState( RES_BOX, FALSE, &pItem ))
2264 const SvxBoxItem* pBoxItem = (const SvxBoxItem*)pItem;
2265 const SvxBorderLine* pBorderLine = pBoxItem->GetBottom();
2266 if( pBorderLine )
2268 USHORT nWidth = pBorderLine->GetOutWidth() +
2269 pBorderLine->GetInWidth() +
2270 pBorderLine->GetDistance();
2271 ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=';
2272 rWrt.Strm() << sOut.GetBuffer();
2273 rWrt.OutULong( rHTMLWrt.ToPixel(nWidth) );
2275 const Color& rBorderColor = pBorderLine->GetColor();
2276 if( !rBorderColor.IsRGBEqual( Color(COL_GRAY) ) )
2278 ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '=';
2279 rWrt.Strm() << sOut.GetBuffer();
2280 HTMLOutFuncs::Out_Color( rWrt.Strm(), rBorderColor,
2281 rHTMLWrt.eDestEnc );
2284 if( !pBorderLine->GetInWidth() )
2286 (sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_noshade;
2287 rWrt.Strm() << sOut.GetBuffer();
2291 rWrt.Strm() << '>';
2292 return rHTMLWrt;
2295 // Die leeren Nodes mit 2pt Font-Hoehe und der Stand-Vorlage, die
2296 // vor Tabellen und Bereichen eingefuegt werden, nicht exportieren,
2297 // Bookmarks oder absatzgebundene Grafiken aber schon.
2298 // MIB 21.7.97: Ausserdem auch keine leeren Tabellen-Zellen exportieren.
2299 if( !nEnde && (nPoolId == RES_POOLCOLL_STANDARD ||
2300 nPoolId == RES_POOLCOLL_TABLE ||
2301 nPoolId == RES_POOLCOLL_TABLE_HDLN) )
2303 // Der aktuelle Node ist leer und enthaelt Standard-Vorlage ...
2304 const SfxPoolItem* pItem;
2305 const SfxItemSet *pItemSet = pNd->GetpSwAttrSet();
2306 if( pItemSet && pItemSet->Count() &&
2307 SFX_ITEM_SET == pItemSet->GetItemState( RES_CHRATR_FONTSIZE, FALSE, &pItem ) &&
2308 40 == ((const SvxFontHeightItem *)pItem)->GetHeight() )
2310 // ... ausserdem ist die 2pt Schrift eingestellt ...
2311 ULONG nNdPos = rWrt.pCurPam->GetPoint()->nNode.GetIndex();
2312 const SwNode *pNextNd = rWrt.pDoc->GetNodes()[nNdPos+1];
2313 const SwNode *pPrevNd = rWrt.pDoc->GetNodes()[nNdPos-1];
2314 BOOL bStdColl = nPoolId == RES_POOLCOLL_STANDARD;
2315 if( ( bStdColl && (pNextNd->IsTableNode() ||
2316 pNextNd->IsSectionNode()) ) ||
2317 ( !bStdColl && pNextNd->IsEndNode() &&
2318 pPrevNd->IsStartNode() &&
2319 SwTableBoxStartNode==
2320 pPrevNd->GetStartNode()->GetStartNodeType() ) )
2322 // ... und er steht vor einer Tabelle ohne einem Bereich
2323 rHTMLWrt.OutBookmarks();
2324 rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken;
2326 // Alle an dem Node verankerten Rahmen ausgeben
2327 rHTMLWrt.OutFlyFrm( rNode.GetIndex(), 0, HTML_POS_ANY );
2328 rHTMLWrt.bLFPossible = FALSE;
2330 return rWrt;
2335 // PagePreaks uns PagDescs abfangen
2336 BOOL bPageBreakBehind = FALSE;
2337 if( rHTMLWrt.bCfgFormFeed &&
2338 !(rHTMLWrt.bOutTable || rHTMLWrt.bOutFlyFrame) &&
2339 rHTMLWrt.pStartNdIdx->GetIndex() !=
2340 rHTMLWrt.pCurPam->GetPoint()->nNode.GetIndex() )
2342 BOOL bPageBreakBefore = FALSE;
2343 const SfxPoolItem* pItem;
2344 const SfxItemSet* pItemSet = pNd->GetpSwAttrSet();
2346 if( pItemSet )
2348 if( SFX_ITEM_SET ==
2349 pItemSet->GetItemState( RES_PAGEDESC, TRUE, &pItem ) &&
2350 ((SwFmtPageDesc *)pItem)->GetPageDesc() )
2351 bPageBreakBefore = TRUE;
2352 else if( SFX_ITEM_SET ==
2353 pItemSet->GetItemState( RES_BREAK, TRUE, &pItem ) )
2355 switch( ((SvxFmtBreakItem *)pItem)->GetBreak() )
2357 case SVX_BREAK_PAGE_BEFORE:
2358 bPageBreakBefore = TRUE;
2359 break;
2360 case SVX_BREAK_PAGE_AFTER:
2361 bPageBreakBehind = TRUE;
2362 break;
2363 case SVX_BREAK_PAGE_BOTH:
2364 bPageBreakBefore = TRUE;
2365 bPageBreakBehind = TRUE;
2366 break;
2367 default:
2373 if( bPageBreakBefore )
2374 rWrt.Strm() << '\f';
2377 // eventuell eine Form oeffnen
2378 rHTMLWrt.OutForm();
2380 // An dem Node "verankerte" Seitenegebunde Rahmen ausgeben
2381 BOOL bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2382 0, HTML_POS_PREFIX );
2383 // An dem Node verankerte Rahmen ausgeben, die vor dem
2384 // Absatz-Tag geschrieben werden sollen.
2385 if( bFlysLeft )
2386 bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2387 0, HTML_POS_BEFORE );
2389 if( rHTMLWrt.pCurPam->GetPoint()->nNode == rHTMLWrt.pCurPam->GetMark()->nNode )
2390 nEnde = rHTMLWrt.pCurPam->GetMark()->nContent.GetIndex();
2392 // gibt es harte Attribute, die als Optionen geschrieben werden muessen?
2393 rHTMLWrt.bTagOn = TRUE;
2395 // jetzt das Tag des Absatzes ausgeben
2396 const SwFmt& rFmt = pNd->GetAnyFmtColl();
2397 SwHTMLTxtCollOutputInfo aFmtInfo;
2398 BOOL bOldLFPossible = rHTMLWrt.bLFPossible;
2399 OutHTML_SwFmt( rWrt, rFmt, pNd->GetpSwAttrSet(), aFmtInfo );
2401 // Wenn vor dem Absatz-Tag keine neue Zeile aufgemacht wurde, dann
2402 // tun wir das jetzt
2403 rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken;
2404 if( !bOldLFPossible && rHTMLWrt.bLFPossible )
2405 rHTMLWrt.OutNewLine();
2408 // dann die Bookmarks (inkl. End-Tag)
2409 rHTMLWrt.bOutOpts = FALSE;
2410 rHTMLWrt.OutBookmarks();
2412 // jetzt ist noch mal eine gute Gelegenheit fuer ein LF, sofern es noch
2413 // erlaubt ist
2414 if( rHTMLWrt.bLFPossible &&
2415 rHTMLWrt.GetLineLen() >= rHTMLWrt.nWhishLineLen )
2417 rHTMLWrt.OutNewLine();
2419 rHTMLWrt.bLFPossible = FALSE;
2421 // Text, der aus einer Outline-Numerierung kommt ermitteln
2422 xub_StrLen nOffset = 0;
2423 String aOutlineTxt;
2424 String aFullText;
2425 // --> OD 2006-06-12 #b6435904#
2426 // export numbering string as plain text only for the outline numbering,
2427 // because the outline numbering isn't exported as a numbering - see <SwHTMLNumRuleInfo::Set(..)>
2428 if ( pNd->IsOutline() &&
2429 pNd->GetNumRule() == pNd->GetDoc()->GetOutlineNumRule() )
2430 // <--
2432 aOutlineTxt = pNd->GetNumString();
2433 nOffset = nOffset + aOutlineTxt.Len();
2434 aFullText = aOutlineTxt;
2436 String aFootEndNoteSym;
2437 if( rHTMLWrt.pFmtFtn )
2439 aFootEndNoteSym = rHTMLWrt.GetFootEndNoteSym( *rHTMLWrt.pFmtFtn );
2440 nOffset = nOffset + aFootEndNoteSym.Len();
2441 aFullText += aFootEndNoteSym;
2444 // gibt es harte Attribute, die als Tags geschrieben werden muessen?
2445 aFullText += rStr;
2446 HTMLEndPosLst aEndPosLst( rWrt.pDoc, rHTMLWrt.pTemplate,
2447 rHTMLWrt.pDfltColor, rHTMLWrt.bCfgOutStyles,
2448 rHTMLWrt.GetHTMLMode(), aFullText,
2449 rHTMLWrt.aScriptTextStyles );
2450 if( aFmtInfo.pItemSet )
2452 aEndPosLst.Insert( *aFmtInfo.pItemSet, 0, nEnde + nOffset,
2453 rHTMLWrt.aChrFmtInfos, FALSE, TRUE );
2457 if( aOutlineTxt.Len() || rHTMLWrt.pFmtFtn )
2459 // Absatz-Attribute ausgeben, damit der Text die Attribute des
2460 // Absatzes bekommt.
2461 aEndPosLst.OutStartAttrs( rHTMLWrt, 0 );
2463 // Theoretisch muesste man hier die Zeichen-Vorlage der Numerierung
2464 // beachten. Da man die ueber die UI nicht setzen kann, ignorieren
2465 // wir sie erstmal.
2467 if( aOutlineTxt.Len() )
2468 HTMLOutFuncs::Out_String( rWrt.Strm(), aOutlineTxt,
2469 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters);
2471 if( rHTMLWrt.pFmtFtn )
2473 rHTMLWrt.OutFootEndNoteSym( *rHTMLWrt.pFmtFtn, aFootEndNoteSym,
2474 aEndPosLst.GetScriptAtPos( aOutlineTxt.Len(), rHTMLWrt.nCSS1Script ) );
2475 rHTMLWrt.pFmtFtn = 0;
2479 // erstmal den Start berichtigen. D.h. wird nur ein Teil vom Satz
2480 // ausgegeben, so muessen auch da die Attribute stimmen!!
2481 rHTMLWrt.bTxtAttr = TRUE;
2484 USHORT nAttrPos = 0;
2485 xub_StrLen nStrPos = rHTMLWrt.pCurPam->GetPoint()->nContent.GetIndex();
2486 const SwTxtAttr * pHt = 0;
2487 USHORT nCntAttr = pNd->HasHints() ? pNd->GetSwpHints().Count() : 0;
2488 if( nCntAttr && nStrPos > *( pHt = pNd->GetSwpHints()[ 0 ] )->GetStart() )
2490 // Ok, es gibt vorher Attribute, die ausgegeben werden muessen
2491 do {
2492 aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset );
2494 nAttrPos++;
2495 if( RES_TXTATR_FIELD == pHt->Which() ) // Felder nicht
2496 continue; // ausgeben
2498 if( pHt->GetEnd() )
2500 xub_StrLen nHtEnd = *pHt->GetEnd(),
2501 nHtStt = *pHt->GetStart();
2502 if( !rHTMLWrt.bWriteAll && nHtEnd <= nStrPos )
2503 continue;
2505 // leere Hints am Anfang nicht beachten, oder ??
2506 if( nHtEnd == nHtStt )
2507 continue;
2509 // Attribut in die Liste aufnehemen
2510 if( rHTMLWrt.bWriteAll )
2511 aEndPosLst.Insert( pHt->GetAttr(), nHtStt + nOffset,
2512 nHtEnd + nOffset,
2513 rHTMLWrt.aChrFmtInfos );
2514 else
2516 xub_StrLen nTmpStt = nHtStt < nStrPos ? nStrPos : nHtStt;
2517 xub_StrLen nTmpEnd = nHtEnd < nEnde ? nHtEnd : nEnde;
2518 aEndPosLst.Insert( pHt->GetAttr(), nTmpStt + nOffset,
2519 nTmpEnd + nOffset,
2520 rHTMLWrt.aChrFmtInfos );
2522 continue;
2523 // aber nicht ausgeben, das erfolgt spaeter !!
2526 } while( nAttrPos < nCntAttr && nStrPos >
2527 *( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() );
2529 // dann gebe mal alle gesammelten Attribute von der String-Pos aus
2530 aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset );
2531 aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset );
2534 BOOL bWriteBreak = (HTML_PREFORMTXT_ON != rHTMLWrt.nLastParaToken);
2535 if( bWriteBreak && pNd->GetNumRule() )
2536 bWriteBreak = FALSE;
2539 HTMLOutContext aContext( rHTMLWrt.eDestEnc );
2541 xub_StrLen nPreSplitPos = 0;
2542 for( ; nStrPos < nEnde; nStrPos++ )
2544 aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext );
2546 // Die an der aktuellen Position verankerten Rahmen ausgeben
2547 if( bFlysLeft )
2548 bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2549 nStrPos, HTML_POS_INSIDE,
2550 &aContext );
2552 BOOL bOutChar = TRUE;
2553 const SwTxtAttr * pTxtHt = 0;
2554 if( nAttrPos < nCntAttr && *pHt->GetStart() == nStrPos
2555 && nStrPos != nEnde )
2557 do {
2558 if( pHt->GetEnd() )
2560 if( RES_CHRATR_KERNING == pHt->Which() &&
2561 rHTMLWrt.IsHTMLMode(HTMLMODE_FIRSTLINE) &&
2562 *pHt->GetEnd() - nStrPos == 1 &&
2563 ' ' == rStr.GetChar(nStrPos) &&
2564 ((const SvxKerningItem&)pHt->GetAttr()).GetValue() > 0 )
2566 // Wenn erlaubt, wird das Ding als Spacer exportiert
2568 bOutChar = FALSE; // Space nicht ausgeben
2569 bWriteBreak = FALSE; // der Absatz ist aber auch nicht leer
2570 HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2571 OutHTML_HoriSpacer( rWrt,
2572 ((const SvxKerningItem&)pHt->GetAttr()).GetValue() );
2574 // Der Hint braucht nun doch nicht weiter
2575 // beruecksichtigt werden.
2577 else if( *pHt->GetEnd() != nStrPos )
2579 // Hints mit Ende einsortieren, wenn sie keinen
2580 // leeren Bereich aufspannen (Hints, die keinen
2581 // Bereich aufspannen werden ignoriert
2582 aEndPosLst.Insert( pHt->GetAttr(), nStrPos + nOffset,
2583 *pHt->GetEnd() + nOffset,
2584 rHTMLWrt.aChrFmtInfos );
2587 else
2589 // Hints ohne-Ende werden als letztes ausgebeben
2590 ASSERT( !pTxtHt,
2591 "Wieso gibt es da schon ein Attribut ohne Ende?" );
2592 if( rHTMLWrt.nTxtAttrsToIgnore>0 )
2594 rHTMLWrt.nTxtAttrsToIgnore--;
2596 else
2598 pTxtHt = pHt;
2599 USHORT nFldWhich;
2600 if( RES_TXTATR_FIELD != pHt->Which() ||
2601 ( RES_POSTITFLD != (nFldWhich = ((const SwFmtFld&)pHt->GetAttr()).GetFld()->Which()) &&
2602 RES_SCRIPTFLD != nFldWhich ) )
2603 bWriteBreak = FALSE;
2605 bOutChar = FALSE; // keine 255 ausgeben
2607 } while( ++nAttrPos < nCntAttr && nStrPos ==
2608 *( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() );
2611 // Manche Draw-Formate koennen auch noch Attribute mitbringen
2612 if( pTxtHt && RES_TXTATR_FLYCNT == pTxtHt->Which() )
2614 const SwFrmFmt* pFrmFmt =
2615 ((const SwFmtFlyCnt &)pTxtHt->GetAttr()).GetFrmFmt();
2617 if( RES_DRAWFRMFMT == pFrmFmt->Which() )
2618 aEndPosLst.Insert( *((const SwDrawFrmFmt *)pFrmFmt),
2619 nStrPos + nOffset,
2620 rHTMLWrt.aChrFmtInfos );
2623 aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext );
2624 aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset, &aContext );
2626 if( pTxtHt )
2628 rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken && nStrPos > 0 &&
2629 rStr.GetChar(nStrPos-1) == ' ';
2630 sal_uInt16 nCSS1Script = rHTMLWrt.nCSS1Script;
2631 rHTMLWrt.nCSS1Script = aEndPosLst.GetScriptAtPos(
2632 nStrPos + nOffset, nCSS1Script );
2633 HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2634 Out( aHTMLAttrFnTab, pTxtHt->GetAttr(), rHTMLWrt );
2635 rHTMLWrt.nCSS1Script = nCSS1Script;
2636 rHTMLWrt.bLFPossible = FALSE;
2639 if( bOutChar )
2641 sal_Unicode c = rStr.GetChar( nStrPos );
2642 // versuche nach ungefaehr 255 Zeichen eine neue Zeile zu
2643 // beginnen, aber nicht in PRE und nur bei Spaces
2644 if( ' '==c && !rHTMLWrt.nLastParaToken )
2646 xub_StrLen nLineLen;
2647 if( rHTMLWrt.nLastParaToken )
2648 nLineLen = nStrPos - nPreSplitPos;
2649 else
2650 nLineLen = rHTMLWrt.GetLineLen();
2652 xub_StrLen nWordLen = rStr.Search( ' ', nStrPos+1 );
2653 if( nWordLen == STRING_NOTFOUND )
2654 nWordLen = nEnde;
2655 nWordLen = nWordLen - nStrPos;
2657 if( nLineLen >= rHTMLWrt.nWhishLineLen ||
2658 (nLineLen+nWordLen) >= rHTMLWrt.nWhishLineLen )
2660 HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2661 rHTMLWrt.OutNewLine();
2662 bOutChar = FALSE;
2663 if( rHTMLWrt.nLastParaToken )
2664 nPreSplitPos = nStrPos+1;
2668 if( bOutChar )
2670 if( 0x0a == c )
2672 HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2673 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak );
2675 else
2676 HTMLOutFuncs::Out_Char( rWrt.Strm(), c, aContext, &rHTMLWrt.aNonConvertableCharacters );
2678 // Wenn das letzte Zeichen eines Absatzed ein harter
2679 // Zeilen-Umbruch ist brauchen wir noch ein <BR> mehr, weil
2680 // Netscape & Co in diesem Fall fuer den naechsten Absatz
2681 // nicht in die naechste Zeile gehen.
2682 bWriteBreak = (0x0a == c) &&
2683 (HTML_PREFORMTXT_ON != rHTMLWrt.nLastParaToken);
2687 HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2690 aEndPosLst.OutEndAttrs( rHTMLWrt, STRING_MAXLEN );
2692 // Die an der letzten Position verankerten Rahmen ausgeben
2693 if( bFlysLeft )
2694 bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2695 nEnde, HTML_POS_INSIDE );
2696 ASSERT( !bFlysLeft, "Es wurden nicht alle Rahmen gespeichert!" );
2698 rHTMLWrt.bTxtAttr = FALSE;
2700 if( bWriteBreak )
2702 BOOL bEndOfCell = rHTMLWrt.bOutTable &&
2703 rWrt.pCurPam->GetPoint()->nNode.GetIndex() ==
2704 rWrt.pCurPam->GetMark()->nNode.GetIndex();
2706 if( bEndOfCell && !nEnde &&
2707 rHTMLWrt.IsHTMLMode(HTMLMODE_NBSP_IN_TABLES) )
2709 // Wenn der letzte Absatz einer Tabellezelle leer ist und
2710 // wir fuer den MS-IE exportieren, schreiben wir statt eines
2711 // <BR> ein &nbsp;
2712 rWrt.Strm() << '&' << OOO_STRING_SVTOOLS_HTML_S_nbsp << ';';
2714 else
2716 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak );
2717 const SvxULSpaceItem& rULSpace =
2718 (const SvxULSpaceItem &)pNd->GetSwAttrSet().Get(RES_UL_SPACE);
2719 if( rULSpace.GetLower() > 0 && !bEndOfCell &&
2720 !rHTMLWrt.IsHTMLMode(HTMLMODE_NO_BR_AT_PAREND) )
2721 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak );
2722 rHTMLWrt.bLFPossible = TRUE;
2726 if( rHTMLWrt.bClearLeft || rHTMLWrt.bClearRight )
2728 const sal_Char *pStr;
2729 if( rHTMLWrt.bClearLeft )
2731 if( rHTMLWrt.bClearRight )
2732 pStr = OOO_STRING_SVTOOLS_HTML_AL_all;
2733 else
2734 pStr = OOO_STRING_SVTOOLS_HTML_AL_left;
2736 else
2737 pStr = OOO_STRING_SVTOOLS_HTML_AL_right;
2739 ByteString sOut( OOO_STRING_SVTOOLS_HTML_linebreak );
2740 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_clear) += '=') += pStr;
2742 HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), sOut.GetBuffer() );
2743 rHTMLWrt.bClearLeft = FALSE;
2744 rHTMLWrt.bClearRight = FALSE;
2746 rHTMLWrt.bLFPossible = TRUE;
2749 // wenn ein LF nicht schon erlaubt ist wird es erlaubt, wenn der
2750 // Absatz mit einem ' ' endet
2751 if( !rHTMLWrt.bLFPossible && !rHTMLWrt.nLastParaToken &&
2752 nEnde > 0 && ' ' == rStr.GetChar(nEnde-1) )
2753 rHTMLWrt.bLFPossible = TRUE;
2755 rHTMLWrt.bTagOn = FALSE;
2756 OutHTML_SwFmtOff( rWrt, aFmtInfo );
2758 // eventuell eine Form schliessen
2759 rHTMLWrt.OutForm( FALSE );
2761 if( bPageBreakBehind )
2762 rWrt.Strm() << '\f';
2764 return rHTMLWrt;
2768 sal_uInt32 SwHTMLWriter::ToPixel( sal_uInt32 nVal ) const
2770 if( Application::GetDefaultDevice() && nVal )
2772 nVal = Application::GetDefaultDevice()->LogicToPixel(
2773 Size( nVal, nVal ), MapMode( MAP_TWIP ) ).Width();
2774 if( !nVal ) // wo ein Twip ist sollte auch ein Pixel sein
2775 nVal = 1;
2777 return nVal;
2781 static Writer& OutHTML_CSS1Attr( Writer& rWrt, const SfxPoolItem& rHt )
2783 // wenn gerade Hints geschrieben werden versuchen wir den Hint als
2784 // CSS1-Attribut zu schreiben
2786 if( ((SwHTMLWriter&)rWrt).bCfgOutStyles && ((SwHTMLWriter&)rWrt).bTxtAttr )
2787 OutCSS1_HintSpanTag( rWrt, rHt );
2789 return rWrt;
2793 /* File CHRATR.HXX: */
2795 static Writer& OutHTML_SvxColor( Writer& rWrt, const SfxPoolItem& rHt )
2797 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2798 if( rHTMLWrt.bOutOpts )
2799 return rWrt;
2801 // die Default-Farbe nur Schreiben, wenn sie als Hint vorkommt
2802 //if( rHTMLWrt.bTagOn && !rHTMLWrt.bTxtAttr && rHTMLWrt.pDfltColor
2803 // && rColor == *rHTMLWrt.pDfltColor )
2804 // return rWrt;
2806 if( !rHTMLWrt.bTxtAttr && rHTMLWrt.bCfgOutStyles && rHTMLWrt.bCfgPreferStyles )
2808 // Font-Farbe nicht als Tag schreiben, wenn Styles normalen Tags
2809 // vorgezogen werden
2810 return rWrt;
2813 if( rHTMLWrt.bTagOn )
2815 Color aColor( ((const SvxColorItem&)rHt).GetValue() );
2816 if( COL_AUTO == aColor.GetColor() )
2817 aColor.SetColor( COL_BLACK );
2819 ByteString sOut( '<' );
2820 (((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '=';
2821 rWrt.Strm() << sOut.GetBuffer();
2822 HTMLOutFuncs::Out_Color( rWrt.Strm(), aColor, rHTMLWrt.eDestEnc ) << '>';
2824 else
2825 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font, FALSE );
2827 return rWrt;
2831 static Writer& OutHTML_SwPosture( Writer& rWrt, const SfxPoolItem& rHt )
2833 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2834 if( rHTMLWrt.bOutOpts )
2835 return rWrt;
2837 const FontItalic nPosture = ((const SvxPostureItem&)rHt).GetPosture();
2838 if( ITALIC_NORMAL == nPosture )
2840 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_italic, rHTMLWrt.bTagOn );
2842 else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
2844 // vielleicht als CSS1-Attribut ?
2845 OutCSS1_HintSpanTag( rWrt, rHt );
2848 return rWrt;
2851 static Writer& OutHTML_SvxFont( Writer& rWrt, const SfxPoolItem& rHt )
2853 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2854 if( rHTMLWrt.bOutOpts )
2855 return rWrt;
2857 if( rHTMLWrt.bTagOn )
2859 String aNames;
2860 SwHTMLWriter::PrepareFontList( ((const SvxFontItem&)rHt), aNames, 0,
2861 rHTMLWrt.IsHTMLMode(HTMLMODE_FONT_GENERIC) );
2862 ByteString sOut( '<' );
2863 (((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_face) += "=\"";
2864 rWrt.Strm() << sOut.GetBuffer();
2865 HTMLOutFuncs::Out_String( rWrt.Strm(), aNames, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters )
2866 << "\">";
2868 else
2869 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font , FALSE );
2871 return rWrt;
2874 static Writer& OutHTML_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt )
2876 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2877 if( rHTMLWrt.bOutOpts )
2878 return rWrt;
2880 if( rHTMLWrt.bTagOn )
2882 ByteString sOut( '<' );
2883 sOut += OOO_STRING_SVTOOLS_HTML_font;
2885 UINT32 nHeight = ((const SvxFontHeightItem&)rHt).GetHeight();
2886 USHORT nSize = rHTMLWrt.GetHTMLFontSize( nHeight );
2887 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=')
2888 += ByteString::CreateFromInt32( nSize );
2889 rWrt.Strm() << sOut.GetBuffer();
2891 if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr &&
2892 rHTMLWrt.aFontHeights[nSize-1] != nHeight )
2894 // wenn die Groesse keiner HTML-Groesse entspricht,
2895 // wird sie noch zusatzlich als Style-Option exportiert
2896 OutCSS1_HintStyleOpt( rWrt, rHt );
2898 rWrt.Strm() << '>';
2900 else
2902 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font, FALSE );
2905 return rWrt;
2908 static Writer& OutHTML_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt )
2910 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2911 if( rHTMLWrt.bOutOpts )
2912 return rWrt;
2914 LanguageType eLang = ((const SvxLanguageItem &)rHt).GetLanguage();
2915 if( LANGUAGE_DONTKNOW == eLang )
2916 return rWrt;
2918 if( rHTMLWrt.bTagOn )
2920 ByteString sOut( '<' );
2921 sOut += OOO_STRING_SVTOOLS_HTML_span;
2922 rWrt.Strm() << sOut.GetBuffer();
2923 rHTMLWrt.OutLanguage( ((const SvxLanguageItem &)rHt).GetLanguage() );
2924 rWrt.Strm() << '>';
2926 else
2928 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_span, FALSE );
2931 return rWrt;
2933 static Writer& OutHTML_SwWeight( Writer& rWrt, const SfxPoolItem& rHt )
2935 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2936 if( rHTMLWrt.bOutOpts )
2937 return rWrt;
2939 const FontWeight nBold = ((const SvxWeightItem&)rHt).GetWeight();
2940 if( WEIGHT_BOLD == nBold )
2942 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_bold, rHTMLWrt.bTagOn );
2944 else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
2946 // vielleicht als CSS1-Attribut ?
2947 OutCSS1_HintSpanTag( rWrt, rHt );
2950 return rWrt;
2954 static Writer& OutHTML_SwCrossedOut( Writer& rWrt, const SfxPoolItem& rHt )
2956 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2957 if( rHTMLWrt.bOutOpts )
2958 return rWrt;
2960 // Wegen Netscape schrieben wir hier STRIKE und nicht S raus!
2961 const FontStrikeout nStrike = ((const SvxCrossedOutItem&)rHt).GetStrikeout();
2962 if( STRIKEOUT_NONE != nStrike )
2964 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_strike, rHTMLWrt.bTagOn );
2966 else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
2968 // vielleicht als CSS1-Attribut ?
2969 OutCSS1_HintSpanTag( rWrt, rHt );
2972 return rWrt;
2976 static Writer& OutHTML_SvxEscapement( Writer& rWrt, const SfxPoolItem& rHt )
2978 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2979 if( rHTMLWrt.bOutOpts )
2980 return rWrt;
2982 const SvxEscapement eEscape =
2983 (const SvxEscapement)((const SvxEscapementItem&)rHt).GetEnumValue();
2984 const sal_Char *pStr = 0;
2985 switch( eEscape )
2987 case SVX_ESCAPEMENT_SUPERSCRIPT: pStr = OOO_STRING_SVTOOLS_HTML_superscript; break;
2988 case SVX_ESCAPEMENT_SUBSCRIPT: pStr = OOO_STRING_SVTOOLS_HTML_subscript; break;
2989 default:
2993 if( pStr )
2995 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), pStr, rHTMLWrt.bTagOn );
2997 else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
2999 // vielleicht als CSS1-Attribut ?
3000 OutCSS1_HintSpanTag( rWrt, rHt );
3003 return rWrt;
3008 static Writer& OutHTML_SwUnderline( Writer& rWrt, const SfxPoolItem& rHt )
3010 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3011 if( rHTMLWrt.bOutOpts )
3012 return rWrt;
3014 const FontUnderline eUnder = ((const SvxUnderlineItem&)rHt).GetLineStyle();
3015 if( UNDERLINE_NONE != eUnder )
3017 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_underline, rHTMLWrt.bTagOn );
3019 else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
3021 // vielleicht als CSS1-Attribut ?
3022 OutCSS1_HintSpanTag( rWrt, rHt );
3025 return rWrt;
3029 static Writer& OutHTML_SwFlyCnt( Writer& rWrt, const SfxPoolItem& rHt )
3031 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
3032 SwFmtFlyCnt& rFlyCnt = (SwFmtFlyCnt&)rHt;
3034 const SwFrmFmt& rFmt = *rFlyCnt.GetFrmFmt();
3035 const SdrObject *pSdrObj = 0;
3037 SwHTMLFrmType eType =
3038 (SwHTMLFrmType)rHTMLWrt.GuessFrmType( rFmt, pSdrObj );
3039 BYTE nMode = aHTMLOutFrmAsCharTable[eType][rHTMLWrt.nExportMode];
3040 rHTMLWrt.OutFrmFmt( nMode, rFmt, pSdrObj );
3041 return rWrt;
3044 static Writer& OutHTML_SwHardBlank( Writer& rWrt, const SfxPoolItem& rHt )
3046 HTMLOutContext aContext ( ((SwHTMLWriter&)rWrt).eDestEnc );
3047 HTMLOutFuncs::Out_Char( rWrt.Strm(), ((SwFmtHardBlank&)rHt).GetChar(),
3048 aContext,
3049 &((SwHTMLWriter&)rWrt).aNonConvertableCharacters);
3050 HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
3051 return rWrt;
3054 // Das ist jetzt unser Blink-Item. Blinkend wird eingeschaltet, indem man
3055 // das Item auf TRUE setzt!
3056 static Writer& OutHTML_SwBlink( Writer& rWrt, const SfxPoolItem& rHt )
3058 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3059 if( rHTMLWrt.bOutOpts || !rHTMLWrt.IsHTMLMode(HTMLMODE_BLINK) )
3060 return rWrt;
3062 if( ((const SvxBlinkItem&)rHt).GetValue() )
3064 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_blink, rHTMLWrt.bTagOn );
3066 else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
3068 // vielleicht als CSS1-Attribut ?
3069 OutCSS1_HintSpanTag( rWrt, rHt );
3072 return rWrt;
3075 Writer& OutHTML_INetFmt( Writer& rWrt, const SwFmtINetFmt& rINetFmt, BOOL bOn )
3077 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3079 String aURL( rINetFmt.GetValue() );
3080 const SvxMacroTableDtor *pMacTable = rINetFmt.GetMacroTbl();
3081 BOOL bEvents = pMacTable != 0 && pMacTable->Count() > 0;
3083 // Gibt es ueberhaupt etwas auszugeben?
3084 if( !aURL.Len() && !bEvents && !rINetFmt.GetName().Len() )
3085 return rWrt;
3087 // Tag aus? Dann nur ein </A> ausgeben.
3088 if( !bOn )
3090 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_anchor, FALSE );
3091 return rWrt;
3094 ByteString sOut( '<' );
3095 sOut += OOO_STRING_SVTOOLS_HTML_anchor;
3097 sal_Bool bScriptDependent = sal_False;
3099 const SwCharFmt* pFmt = rWrt.pDoc->GetCharFmtFromPool(
3100 RES_POOLCHR_INET_NORMAL );
3101 SwHTMLFmtInfo aFmtInfo( pFmt );
3102 USHORT nPos;
3103 if( rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
3105 bScriptDependent = rHTMLWrt.aChrFmtInfos[nPos]->bScriptDependent;
3108 if( !bScriptDependent )
3110 const SwCharFmt* pFmt = rWrt.pDoc->GetCharFmtFromPool(
3111 RES_POOLCHR_INET_VISIT );
3112 SwHTMLFmtInfo aFmtInfo( pFmt );
3113 USHORT nPos;
3114 if( rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
3116 bScriptDependent = rHTMLWrt.aChrFmtInfos[nPos]->bScriptDependent;
3120 if( bScriptDependent )
3122 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"";
3123 switch( rHTMLWrt.nCSS1Script )
3125 case CSS1_OUTMODE_WESTERN:
3126 sOut += "western";
3127 break;
3128 case CSS1_OUTMODE_CJK:
3129 sOut += "cjk";
3130 break;
3131 case CSS1_OUTMODE_CTL:
3132 sOut += "ctl";
3133 break;
3135 sOut += '\"';
3138 rWrt.Strm() << sOut.GetBuffer();
3140 #define REL_HACK
3141 #ifdef REL_HACK
3142 String sRel;
3143 #endif
3145 if( aURL.Len() || bEvents )
3147 #ifdef REL_HACK
3148 String sTmp( aURL );
3149 sTmp.ToUpperAscii();
3150 xub_StrLen nPos = sTmp.SearchAscii( "\" REL=" );
3151 if( nPos!=STRING_NOTFOUND )
3153 sRel = aURL.Copy( nPos+1 );
3154 aURL.Erase( nPos );
3156 #endif
3157 aURL.EraseLeadingChars().EraseTrailingChars();
3159 ((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\"";
3160 rWrt.Strm() << sOut.GetBuffer();
3161 rHTMLWrt.OutHyperlinkHRefValue( aURL );
3162 sOut = '\"';
3164 else
3165 sOut.Erase();
3167 if( rINetFmt.GetName().Len() )
3169 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\"";
3170 rWrt.Strm() << sOut.GetBuffer();
3171 HTMLOutFuncs::Out_String( rWrt.Strm(), rINetFmt.GetName(),
3172 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
3173 sOut = '\"';
3176 const String& rTarget = rINetFmt.GetTargetFrame();
3177 if( rTarget.Len() )
3179 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_target) += "=\"";
3180 rWrt.Strm() << sOut.GetBuffer();
3181 HTMLOutFuncs::Out_String( rWrt.Strm(), rTarget, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
3182 sOut = '\"';
3185 #ifdef REL_HACK
3186 if( sRel.Len() )
3187 sOut += ByteString( sRel, RTL_TEXTENCODING_ASCII_US );
3188 #endif
3189 if( sOut.Len() )
3190 rWrt.Strm() << sOut.GetBuffer();
3192 if( bEvents )
3193 HTMLOutFuncs::Out_Events( rWrt.Strm(), *pMacTable, aAnchorEventTable,
3194 rHTMLWrt.bCfgStarBasic, rHTMLWrt.eDestEnc,
3195 &rHTMLWrt.aNonConvertableCharacters );
3196 rWrt.Strm() << ">";
3198 return rWrt;
3201 static Writer& OutHTML_SwFmtINetFmt( Writer& rWrt, const SfxPoolItem& rHt )
3203 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3205 if( rHTMLWrt.bOutOpts )
3206 return rWrt;
3208 const SwFmtINetFmt& rINetFmt = (const SwFmtINetFmt&)rHt;
3210 if( rHTMLWrt.bTagOn )
3212 // ggf. ein noch offenes Attribut voruebergehend beenden
3213 if( rHTMLWrt.aINetFmts.Count() )
3215 SwFmtINetFmt *pINetFmt =
3216 rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
3217 OutHTML_INetFmt( rWrt, *pINetFmt, FALSE );
3220 // jetzt das neue aufmachen
3221 OutHTML_INetFmt( rWrt, rINetFmt, TRUE );
3223 // und merken
3224 const SwFmtINetFmt *pINetFmt = new SwFmtINetFmt( rINetFmt );
3225 rHTMLWrt.aINetFmts.C40_INSERT( SwFmtINetFmt, pINetFmt,
3226 rHTMLWrt.aINetFmts.Count() );
3228 else
3230 // das
3231 OutHTML_INetFmt( rWrt, rINetFmt, FALSE );
3233 ASSERT( rHTMLWrt.aINetFmts.Count(), "da fehlt doch ein URL-Attribut" );
3234 if( rHTMLWrt.aINetFmts.Count() )
3236 // das eigene Attribut vom Stack holen
3237 SwFmtINetFmt *pINetFmt =
3238 rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
3240 rHTMLWrt.aINetFmts.Remove( rHTMLWrt.aINetFmts.Count()-1, 1 );
3241 delete pINetFmt;
3244 if( rHTMLWrt.aINetFmts.Count() )
3246 // es ist noch ein Attribut auf dem Stack, das wieder geoeffnet
3247 // werden muss
3248 SwFmtINetFmt *pINetFmt =
3249 rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
3250 OutHTML_INetFmt( rWrt, *pINetFmt, TRUE );
3254 return rWrt;
3257 static Writer& OutHTML_SwTxtCharFmt( Writer& rWrt, const SfxPoolItem& rHt )
3259 SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3260 if( rHTMLWrt.bOutOpts )
3261 return rWrt;
3263 const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rHt;
3264 const SwCharFmt* pFmt = rChrFmt.GetCharFmt();
3266 if( !pFmt )
3268 return rWrt;
3271 SwHTMLFmtInfo aFmtInfo( pFmt );
3272 USHORT nPos;
3273 if( !rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
3274 return rWrt;
3276 const SwHTMLFmtInfo *pFmtInfo = rHTMLWrt.aChrFmtInfos[nPos];
3277 ASSERT( pFmtInfo, "Wieso gint es keine Infos ueber die Zeichenvorlage?" );
3279 if( rHTMLWrt.bTagOn )
3281 ByteString sOut( '<' );
3282 if( pFmtInfo->aToken.Len() > 0 )
3283 sOut += pFmtInfo->aToken;
3284 else
3285 sOut += OOO_STRING_SVTOOLS_HTML_span;
3286 if( rHTMLWrt.bCfgOutStyles &&
3287 (pFmtInfo->aClass.Len() || pFmtInfo->bScriptDependent) )
3289 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"";
3290 rWrt.Strm() << sOut.GetBuffer();
3291 String aClass( pFmtInfo->aClass );
3292 if( pFmtInfo->bScriptDependent )
3294 if( aClass.Len() )
3295 aClass += '-';
3296 switch( rHTMLWrt.nCSS1Script )
3298 case CSS1_OUTMODE_WESTERN:
3299 aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("western") );
3300 break;
3301 case CSS1_OUTMODE_CJK:
3302 aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("cjk") );
3303 break;
3304 case CSS1_OUTMODE_CTL:
3305 aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("ctl") );
3306 break;
3309 HTMLOutFuncs::Out_String( rWrt.Strm(), aClass,
3310 rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
3311 sOut = '\"';
3313 sOut += '>';
3314 rWrt.Strm() << sOut.GetBuffer();
3316 else
3318 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
3319 pFmtInfo->aToken.Len() ? pFmtInfo->aToken.GetBuffer()
3320 : OOO_STRING_SVTOOLS_HTML_span,
3321 FALSE );
3324 return rWrt;
3327 static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt )
3329 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
3330 if( !rHTMLWrt.bOutOpts || !rHTMLWrt.bTagOn )
3331 return rWrt;
3333 SvxAdjustItem& rAdjust = (SvxAdjustItem&)rHt;
3334 const sal_Char* pStr = 0;
3335 switch( rAdjust.GetAdjust() )
3337 case SVX_ADJUST_CENTER: pStr = OOO_STRING_SVTOOLS_HTML_AL_center; break;
3338 case SVX_ADJUST_LEFT: pStr = OOO_STRING_SVTOOLS_HTML_AL_left; break;
3339 case SVX_ADJUST_RIGHT: pStr = OOO_STRING_SVTOOLS_HTML_AL_right; break;
3340 case SVX_ADJUST_BLOCK: pStr = OOO_STRING_SVTOOLS_HTML_AL_justify; break;
3341 default:
3344 if( pStr )
3346 ByteString sOut( ' ' );
3347 ((sOut += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += pStr;
3348 rWrt.Strm() << sOut.GetBuffer();
3351 return rWrt;
3355 * lege hier die Tabellen fuer die HTML-Funktions-Pointer auf
3356 * die Ausgabe-Funktionen an.
3357 * Es sind lokale Strukturen, die nur innerhalb der HTML-DLL
3358 * bekannt sein muessen.
3362 SwAttrFnTab aHTMLAttrFnTab = {
3363 /* RES_CHRATR_CASEMAP */ OutHTML_CSS1Attr,
3364 /* RES_CHRATR_CHARSETCOLOR */ 0,
3365 /* RES_CHRATR_COLOR */ OutHTML_SvxColor,
3366 /* RES_CHRATR_CONTOUR */ 0,
3367 /* RES_CHRATR_CROSSEDOUT */ OutHTML_SwCrossedOut,
3368 /* RES_CHRATR_ESCAPEMENT */ OutHTML_SvxEscapement,
3369 /* RES_CHRATR_FONT */ OutHTML_SvxFont,
3370 /* RES_CHRATR_FONTSIZE */ OutHTML_SvxFontHeight,
3371 /* RES_CHRATR_KERNING */ OutHTML_CSS1Attr,
3372 /* RES_CHRATR_LANGUAGE */ OutHTML_SvxLanguage,
3373 /* RES_CHRATR_POSTURE */ OutHTML_SwPosture,
3374 /* RES_CHRATR_PROPORTIONALFONTSIZE*/0,
3375 /* RES_CHRATR_SHADOWED */ 0,
3376 /* RES_CHRATR_UNDERLINE */ OutHTML_SwUnderline,
3377 /* RES_CHRATR_WEIGHT */ OutHTML_SwWeight,
3378 /* RES_CHRATR_WORDLINEMODE */ 0,
3379 /* RES_CHRATR_AUTOKERN */ 0,
3380 /* RES_CHRATR_BLINK */ OutHTML_SwBlink,
3381 /* RES_CHRATR_NOHYPHEN */ 0, // Neu: nicht trennen
3382 /* RES_CHRATR_NOLINEBREAK */ 0, // Neu: nicht umbrechen
3383 /* RES_CHRATR_BACKGROUND */ OutHTML_CSS1Attr, // Neu: Zeichenhintergrund
3384 /* RES_CHRATR_CJK_FONT */ OutHTML_SvxFont,
3385 /* RES_CHRATR_CJK_FONTSIZE */ OutHTML_SvxFontHeight,
3386 /* RES_CHRATR_CJK_LANGUAGE */ OutHTML_SvxLanguage,
3387 /* RES_CHRATR_CJK_POSTURE */ OutHTML_SwPosture,
3388 /* RES_CHRATR_CJK_WEIGHT */ OutHTML_SwWeight,
3389 /* RES_CHRATR_CTL_FONT */ OutHTML_SvxFont,
3390 /* RES_CHRATR_CTL_FONTSIZE */ OutHTML_SvxFontHeight,
3391 /* RES_CHRATR_CTL_LANGUAGE */ OutHTML_SvxLanguage,
3392 /* RES_CHRATR_CTL_POSTURE */ OutHTML_SwPosture,
3393 /* RES_CHRATR_CTL_WEIGHT */ OutHTML_SwWeight,
3394 /* RES_CHRATR_ROTATE */ 0,
3395 /* RES_CHRATR_EMPHASIS_MARK */ 0,
3396 /* RES_CHRATR_TWO_LINES */ 0,
3397 /* RES_CHRATR_SCALEW */ 0,
3398 /* RES_CHRATR_RELIEF */ 0,
3399 /* RES_CHRATR_HIDDEN */ 0,
3400 /* RES_CHRATR_OVERLINE */ OutHTML_CSS1Attr,
3401 /* RES_CHRATR_DUMMY1 */ 0,
3402 /* RES_CHRATR_DUMMY2 */ 0,
3404 /* RES_TXTATR_DUMMY4 */ 0,
3405 /* RES_TXTATR_INETFMT */ OutHTML_SwFmtINetFmt,
3406 /* RES_TXTATR_REFMARK*/ 0,
3407 /* RES_TXTATR_TOXMARK */ 0,
3408 /* RES_TXTATR_CHARFMT */ OutHTML_SwTxtCharFmt,
3409 /* RES_TXTATR_TWO_LINES */ 0,
3410 /* RES_TXTATR_CJK_RUBY */ 0,
3411 /* RES_TXTATR_UNKNOWN_CONTAINER */ 0,
3412 /* RES_TXTATR_DUMMY5 */ 0,
3413 /* RES_TXTATR_DUMMY6 */ 0,
3415 /* RES_TXTATR_FIELD */ OutHTML_SwFmtFld,
3416 /* RES_TXTATR_FLYCNT */ OutHTML_SwFlyCnt,
3417 /* RES_TXTATR_FTN */ OutHTML_SwFmtFtn,
3418 /* RES_TXTATR_SOFTHYPH */ 0,
3419 /* RES_TXTATR_HARDBLANK*/ OutHTML_SwHardBlank,
3420 /* RES_TXTATR_DUMMY1 */ 0, // Dummy:
3421 /* RES_TXTATR_DUMMY2 */ 0, // Dummy:
3423 /* RES_PARATR_LINESPACING */ 0,
3424 /* RES_PARATR_ADJUST */ OutHTML_SvxAdjust,
3425 /* RES_PARATR_SPLIT */ 0,
3426 /* RES_PARATR_WIDOWS */ 0,
3427 /* RES_PARATR_ORPHANS */ 0,
3428 /* RES_PARATR_TABSTOP */ 0,
3429 /* RES_PARATR_HYPHENZONE*/ 0,
3430 /* RES_PARATR_DROP */ OutHTML_CSS1Attr,
3431 /* RES_PARATR_REGISTER */ 0, // neu: Registerhaltigkeit
3432 /* RES_PARATR_NUMRULE */ 0, // Dummy:
3433 /* RES_PARATR_SCRIPTSPACE */ 0, // Dummy:
3434 /* RES_PARATR_HANGINGPUNCTUATION */ 0, // Dummy:
3435 /* RES_PARATR_FORBIDDEN_RULES */ 0, // new
3436 /* RES_PARATR_VERTALIGN */ 0, // new
3437 /* RES_PARATR_SNAPTOGRID*/ 0, // new
3438 /* RES_PARATR_CONNECT_TO_BORDER */ 0, // new
3440 /* RES_PARATR_LIST_ID */ 0, // new
3441 /* RES_PARATR_LIST_LEVEL */ 0, // new
3442 /* RES_PARATR_LIST_ISRESTART */ 0, // new
3443 /* RES_PARATR_LIST_RESTARTVALUE */ 0, // new
3444 /* RES_PARATR_LIST_ISCOUNTED */ 0, // new
3446 /* RES_FILL_ORDER */ 0,
3447 /* RES_FRM_SIZE */ 0,
3448 /* RES_PAPER_BIN */ 0,
3449 /* RES_LR_SPACE */ 0,
3450 /* RES_UL_SPACE */ 0,
3451 /* RES_PAGEDESC */ 0,
3452 /* RES_BREAK */ 0,
3453 /* RES_CNTNT */ 0,
3454 /* RES_HEADER */ 0,
3455 /* RES_FOOTER */ 0,
3456 /* RES_PRINT */ 0,
3457 /* RES_OPAQUE */ 0,
3458 /* RES_PROTECT */ 0,
3459 /* RES_SURROUND */ 0,
3460 /* RES_VERT_ORIENT */ 0,
3461 /* RES_HORI_ORIENT */ 0,
3462 /* RES_ANCHOR */ 0,
3463 /* RES_BACKGROUND */ 0,
3464 /* RES_BOX */ 0,
3465 /* RES_SHADOW */ 0,
3466 /* RES_FRMMACRO */ 0,
3467 /* RES_COL */ 0,
3468 /* RES_KEEP */ 0,
3469 /* RES_URL */ 0,
3470 /* RES_EDIT_IN_READONLY */ 0,
3471 /* RES_LAYOUT_SPLIT */ 0,
3472 /* RES_FRMATR_DUMMY1 */ 0, // Dummy:
3473 /* RES_FRMATR_DUMMY2 */ 0, // Dummy:
3474 /* RES_AUTO_STYLE */ 0, // Dummy:
3475 /* RES_FRMATR_DUMMY4 */ 0, // Dummy:
3476 /* RES_FRMATR_DUMMY5 */ 0, // Dummy:
3477 /* RES_FRMATR_DUMMY6 */ 0, // Dummy:
3478 /* RES_FRMATR_DUMMY7 */ 0, // Dummy:
3479 /* RES_FRMATR_DUMMY8 */ 0, // Dummy:
3480 /* RES_FRMATR_DUMMY9 */ 0, // Dummy:
3481 /* RES_FOLLOW_TEXT_FLOW */ 0,
3482 /* RES_WRAP_INFLUENCE_ON_OBJPOS */ 0,
3483 /* RES_FRMATR_DUMMY2 */ 0, // Dummy:
3484 /* RES_AUTO_STYLE */ 0, // Dummy:
3485 /* RES_FRMATR_DUMMY4 */ 0, // Dummy:
3486 /* RES_FRMATR_DUMMY5 */ 0, // Dummy:
3488 /* RES_GRFATR_MIRRORGRF */ 0,
3489 /* RES_GRFATR_CROPGRF */ 0,
3490 /* RES_GRFATR_ROTATION */ 0,
3491 /* RES_GRFATR_LUMINANCE */ 0,
3492 /* RES_GRFATR_CONTRAST */ 0,
3493 /* RES_GRFATR_CHANNELR */ 0,
3494 /* RES_GRFATR_CHANNELG */ 0,
3495 /* RES_GRFATR_CHANNELB */ 0,
3496 /* RES_GRFATR_GAMMA */ 0,
3497 /* RES_GRFATR_INVERT */ 0,
3498 /* RES_GRFATR_TRANSPARENCY */ 0,
3499 /* RES_GRFATR_DRWAMODE */ 0,
3500 /* RES_GRFATR_DUMMY1 */ 0,
3501 /* RES_GRFATR_DUMMY2 */ 0,
3502 /* RES_GRFATR_DUMMY3 */ 0,
3503 /* RES_GRFATR_DUMMY4 */ 0,
3504 /* RES_GRFATR_DUMMY5 */ 0,
3506 /* RES_BOXATR_FORMAT */ 0,
3507 /* RES_BOXATR_FORMULA */ 0,
3508 /* RES_BOXATR_VALUE */ 0