xref: /trunk/main/sw/source/filter/html/htmlatr.cxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <hintids.hxx>
29 #include <com/sun/star/i18n/ScriptType.hpp>
30 #include <vcl/svapp.hxx>
31 #include <vcl/wrkwin.hxx>
32 #include <tools/urlobj.hxx>
33 #include <sfx2/sfx.hrc>
34 #if !defined _SVSTDARR_XUB_STRLEN_DECL || !defined _SVSTDARR_USHORTS_DECL
35 #define _SVSTDARR_XUB_STRLEN
36 #define _SVSTDARR_USHORTS
37 #include <svl/svstdarr.hxx>
38 #endif
39 #include <svtools/htmlout.hxx>
40 #include <svtools/htmlkywd.hxx>
41 #include <svtools/htmltokn.h>
42 #include <svl/whiter.hxx>
43 #include <svx/htmlmode.hxx>
44 #include <editeng/escpitem.hxx>
45 #include <editeng/brkitem.hxx>
46 #include <editeng/boxitem.hxx>
47 #include <editeng/ulspitem.hxx>
48 #include <editeng/udlnitem.hxx>
49 #include <editeng/crsditem.hxx>
50 #include <editeng/blnkitem.hxx>
51 #include <editeng/cmapitem.hxx>
52 #include <editeng/colritem.hxx>
53 #include <editeng/fontitem.hxx>
54 #include <editeng/fhgtitem.hxx>
55 #include <editeng/postitem.hxx>
56 #include <editeng/kernitem.hxx>
57 #include <editeng/wghtitem.hxx>
58 #include <editeng/lspcitem.hxx>
59 #include <editeng/adjitem.hxx>
60 #include <editeng/lrspitem.hxx>
61 #include <editeng/brshitem.hxx>
62 #include <editeng/langitem.hxx>
63 #include <editeng/frmdiritem.hxx>
64 #include <fchrfmt.hxx>
65 #include <fmtautofmt.hxx>
66 #include <fmtfsize.hxx>
67 #include <fmtclds.hxx>
68 #include <fmtpdsc.hxx>
69 #include <fmtflcnt.hxx>
70 #include <fmtinfmt.hxx>
71 #include <fmtftn.hxx>
72 #include <txatbase.hxx>
73 #include <frmatr.hxx>
74 #include <charfmt.hxx>
75 #include <fmtfld.hxx>
76 #include <doc.hxx>
77 #include <pam.hxx>
78 #include <ndtxt.hxx>
79 #include <paratr.hxx>
80 #include <poolfmt.hxx>
81 #include <pagedesc.hxx>
82 #include <swtable.hxx>
83 #include "fldbas.hxx"
84 #include <breakit.hxx>
85 #include <htmlnum.hxx>
86 #include <wrthtml.hxx>
87 #include <htmlfly.hxx>
88 #include <numrule.hxx>
89 
90 using namespace ::com::sun::star;
91 
92 /*
93  * um nicht immer wieder nach einem Update festzustellen, das irgendwelche
94  * Hint-Ids dazugekommen sind, wird hier definiert, die Groesse der Tabelle
95  * definiert und mit der akt. verglichen. Bei unterschieden wird der
96  * Compiler schon meckern.
97  *
98  * diese Section und die dazugeherigen Tabellen muessen in folgenden Files
99  * gepflegt werden: rtf\rtfatr.cxx, sw6\sw6atr.cxx, w4w\w4watr.cxx
100  */
101 #if !defined(UNX) && !defined(MSC) && !defined(PPC) && !defined(CSET) && !defined(__MWERKS__) && !defined(WTC) && !defined(__MINGW32__) && !defined(OS2)
102 
103 #define ATTRFNTAB_SIZE 130
104 #if ATTRFNTAB_SIZE != POOLATTR_END - POOLATTR_BEGIN
105 #error Attribut-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
106 #endif
107 
108 #ifdef FORMAT_TABELLE
109 // da sie nicht benutzt wird!
110 #define FORMATTAB_SIZE 7
111 #if FORMATTAB_SIZE != RES_FMT_END - RES_FMT_BEGIN
112 #error Format-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
113 #endif
114 #endif
115 
116 #define NODETAB_SIZE 3
117 #if NODETAB_SIZE != RES_NODE_END - RES_NODE_BEGIN
118 #error Node-Tabelle ist ungueltigt. Wurden neue Hint-IDs zugefuegt ??
119 #endif
120 
121 #endif
122 
123 #define HTML_BULLETCHAR_DISC	34
124 #define HTML_BULLETCHAR_CIRCLE	38
125 #define HTML_BULLETCHAR_SQUARE	36
126 
127 #define COLFUZZY 20
128 
129 //-----------------------------------------------------------------------
130 
131 HTMLOutEvent __FAR_DATA aAnchorEventTable[] =
132 {
133 	{ OOO_STRING_SVTOOLS_HTML_O_SDonclick,		OOO_STRING_SVTOOLS_HTML_O_onclick,		SFX_EVENT_MOUSECLICK_OBJECT	},
134 	{ OOO_STRING_SVTOOLS_HTML_O_SDonmouseover,	OOO_STRING_SVTOOLS_HTML_O_onmouseover,	SFX_EVENT_MOUSEOVER_OBJECT	},
135 	{ OOO_STRING_SVTOOLS_HTML_O_SDonmouseout,		OOO_STRING_SVTOOLS_HTML_O_onmouseout,		SFX_EVENT_MOUSEOUT_OBJECT	},
136 	{ 0,						0,					  	0							}
137 };
138 
139 static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt );
140 
OutHTML_HoriSpacer(Writer & rWrt,sal_Int16 nSize)141 static Writer& OutHTML_HoriSpacer( Writer& rWrt, sal_Int16 nSize )
142 {
143 	ASSERT( nSize>0, "horizontaler SPACER mit negativem Wert?" )
144 	if( nSize <= 0 )
145 		return rWrt;
146 
147 	if( Application::GetDefaultDevice() )
148 	{
149 		nSize = (sal_Int16)Application::GetDefaultDevice()
150 			->LogicToPixel( Size(nSize,0), MapMode(MAP_TWIP) ).Width();
151 	}
152 
153 	ByteString sOut( '<' );
154 	(((((((((sOut += OOO_STRING_SVTOOLS_HTML_spacer)
155 		+= ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=') += OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal)
156 		+= ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=')
157 						+=ByteString::CreateFromInt32(nSize)) += '>';
158 
159 	rWrt.Strm() << sOut.GetBuffer();
160 
161 	return rWrt;
162 }
163 
GetDefListLvl(const String & rNm,sal_uInt16 nPoolId)164 sal_uInt16 SwHTMLWriter::GetDefListLvl( const String& rNm, sal_uInt16 nPoolId )
165 {
166 	if( nPoolId == RES_POOLCOLL_HTML_DD )
167 	{
168 		return 1 | HTML_DLCOLL_DD;
169 	}
170 	else if( nPoolId == RES_POOLCOLL_HTML_DT )
171 	{
172 		return 1 | HTML_DLCOLL_DT;
173 	}
174 
175 	String sDTDD( String::CreateFromAscii(OOO_STRING_SVTOOLS_HTML_dt) );
176 	sDTDD += ' ';
177 	if( COMPARE_EQUAL == sDTDD.CompareTo( rNm, sDTDD.Len() ) )
178 		// DefinitionList - term
179 		return (sal_uInt16)rNm.Copy( sDTDD.Len() ).ToInt32() | HTML_DLCOLL_DT;
180 
181 	sDTDD.AssignAscii( OOO_STRING_SVTOOLS_HTML_dd );
182 	sDTDD += ' ';
183 	if( COMPARE_EQUAL == sDTDD.CompareTo( rNm, sDTDD.Len() ) )
184 		// DefinitionList - definition
185 		return (sal_uInt16)rNm.Copy( sDTDD.Len() ).ToInt32() | HTML_DLCOLL_DD;
186 
187 	return 0;
188 }
189 
OutAndSetDefList(sal_uInt16 nNewLvl)190 void SwHTMLWriter::OutAndSetDefList( sal_uInt16 nNewLvl )
191 {
192 	// eventuell muss erst mal eine Liste aufgemacht werden
193 	if( nDefListLvl < nNewLvl )
194 	{
195 		// output </pre> for the previous(!) pararagraph, if required.
196 		// Preferable, the <pre> is exported by OutHTML_SwFmtOff for the
197 	   	// previous	paragraph already, but that's not possible, because a very
198 		// deep look at the next paragraph (this one) is required to figure
199 		// out that a def list starts here.
200 
201 		ChangeParaToken( 0 );
202 
203 		// entsprechend dem Level-Unterschied schreiben!
204 		for( sal_uInt16 i=nDefListLvl; i<nNewLvl; i++ )
205 		{
206 			if( bLFPossible )
207 				OutNewLine();
208 			HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_deflist, sal_True );
209 			IncIndentLevel();
210 			bLFPossible = sal_True;
211 		}
212 	}
213 	else if( nDefListLvl > nNewLvl )
214 	{
215 		for( sal_uInt16 i=nNewLvl ; i < nDefListLvl; i++ )
216 		{
217 			DecIndentLevel();
218 			if( bLFPossible )
219 				OutNewLine();
220 			HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_deflist, sal_False );
221 			bLFPossible = sal_True;
222 		}
223 	}
224 
225 	nDefListLvl = nNewLvl;
226 }
227 
228 
ChangeParaToken(sal_uInt16 nNew)229 void SwHTMLWriter::ChangeParaToken( sal_uInt16 nNew )
230 {
231 	if( nNew != nLastParaToken && HTML_PREFORMTXT_ON == nLastParaToken )
232 	{
233 		HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_preformtxt, sal_False );
234 		bLFPossible = sal_True;
235 	}
236 	nLastParaToken = nNew;
237 }
238 
GetCSS1ScriptForScriptType(sal_uInt16 nScriptType)239 sal_uInt16 SwHTMLWriter::GetCSS1ScriptForScriptType( sal_uInt16 nScriptType )
240 {
241 	sal_uInt16 nRet = CSS1_OUTMODE_ANY_SCRIPT;
242 
243 	switch( nScriptType )
244 	{
245     case i18n::ScriptType::LATIN:
246 		nRet = CSS1_OUTMODE_WESTERN;
247 		break;
248     case i18n::ScriptType::ASIAN:
249 		nRet = CSS1_OUTMODE_CJK;
250 		break;
251     case i18n::ScriptType::COMPLEX:
252 		nRet = CSS1_OUTMODE_CTL;
253 		break;
254 	}
255 
256 	return nRet;
257 }
258 
259 // fuer die Formate muesste eine einzige Ausgabe-Funktion genuegen !
260 /*
261  * Formate wie folgt ausgeben:
262  * - fuer Formate, fuer die es entsprechende HTML-Tags gibt wird das
263  *   Tag ausgegeben
264  * - fuer alle anderen wird ein Absatz-Tag <P> ausgegeben und bUserFmt
265  *   gesetzt
266  * - Wenn eine Absatz-Ausrichtung am uebergebenen Item-Set des Nodes
267  *   oder im Item-Set des Format gesetzt ist, wird ein ALIGN=xxx ausgegeben,
268  *   sofern HTML es zulaesst
269  * - in jedem Fall wird harte Attributierung als STYLE-Option geschrieben.
270  *   Wenn bUserFmt nicht gesetzt ist, wird nur der uebergebene Item-Set
271  *   betrachtet. Sonst werden auch Attribute des Formats ausgegeben.
272  */
273 
274 struct SwHTMLTxtCollOutputInfo
275 {
276 	ByteString aToken;				// auszugendens End-Token
277 	SfxItemSet *pItemSet;		// harte Attributierung
278 
279 	sal_Bool bInNumBulList;			// in einer Aufzaehlungs-Liste;
280 	sal_Bool bParaPossible;			// ein </P> darf zusaetzlich ausgegeben werden
281 	sal_Bool bOutPara;				// ein </P> soll ausgegeben werden
282 	sal_Bool bOutDiv;				// write a </DIV>
283 
SwHTMLTxtCollOutputInfoSwHTMLTxtCollOutputInfo284 	SwHTMLTxtCollOutputInfo() :
285 		pItemSet( 0 ),
286 		bInNumBulList( sal_False ),
287 		bParaPossible( sal_False ),
288 		bOutPara( sal_False ),
289 		bOutDiv( sal_False )
290 	{}
291 
292 	~SwHTMLTxtCollOutputInfo();
293 
HasParaTokenSwHTMLTxtCollOutputInfo294 	sal_Bool HasParaToken() const { return aToken.Len()==1 && aToken.GetChar(0)=='P'; }
ShouldOutputTokenSwHTMLTxtCollOutputInfo295 	sal_Bool ShouldOutputToken() const { return bOutPara || !HasParaToken(); }
296 };
297 
~SwHTMLTxtCollOutputInfo()298 SwHTMLTxtCollOutputInfo::~SwHTMLTxtCollOutputInfo()
299 {
300 	delete pItemSet;
301 }
302 
303 struct SwHTMLFmtInfo
304 {
305 	const SwFmt *pFmt;		// das Format selbst
306 	const SwFmt *pRefFmt;	// das Vergleichs-Format
307 
308 	ByteString aToken;			// das auszugebende Token
309 	String aClass;			// die auszugebende Klasse
310 
311 	SfxItemSet *pItemSet;	// der auszugebende Attribut-Set
312 
313 	sal_Int32 nLeftMargin;		// ein par default-Werte fuer
314 	sal_Int32 nRightMargin;	// Absatz-Vorlagen
315 	short nFirstLineIndent;
316 
317 	sal_uInt16 nTopMargin;
318 	sal_uInt16 nBottomMargin;
319 
320 	sal_Bool bScriptDependent;
321 
322 	// Konstruktor fuer einen Dummy zum Suchen
SwHTMLFmtInfoSwHTMLFmtInfo323 	SwHTMLFmtInfo( const SwFmt *pF ) :
324 		pFmt( pF ), pItemSet( 0 )
325 	{}
326 
327 
328 	// Konstruktor zum Erstellen der Format-Info
329 	SwHTMLFmtInfo( const SwFmt *pFmt, SwDoc *pDoc, SwDoc *pTemlate,
330 				   sal_Bool bOutStyles, LanguageType eDfltLang=LANGUAGE_DONTKNOW,
331 				   sal_uInt16 nScript=CSS1_OUTMODE_ANY_SCRIPT,
332 				   sal_Bool bHardDrop=sal_False );
333 	~SwHTMLFmtInfo();
334 
operator ==(const SwHTMLFmtInfo & rInfo1,const SwHTMLFmtInfo & rInfo2)335 	friend sal_Bool operator==( const SwHTMLFmtInfo& rInfo1,
336 							const SwHTMLFmtInfo& rInfo2 )
337 	{
338 		return (long)rInfo1.pFmt == (long)rInfo2.pFmt;
339 	}
340 
operator <(const SwHTMLFmtInfo & rInfo1,const SwHTMLFmtInfo & rInfo2)341 	friend sal_Bool operator<( const SwHTMLFmtInfo& rInfo1,
342 							const SwHTMLFmtInfo& rInfo2 )
343 	{
344 		return (long)rInfo1.pFmt < (long)rInfo2.pFmt;
345 	}
346 
347 };
348 
SV_IMPL_OP_PTRARR_SORT(SwHTMLFmtInfos,SwHTMLFmtInfo *)349 SV_IMPL_OP_PTRARR_SORT( SwHTMLFmtInfos, SwHTMLFmtInfo* )
350 
351 SwHTMLFmtInfo::SwHTMLFmtInfo( const SwFmt *pF, SwDoc *pDoc, SwDoc *pTemplate,
352 							  sal_Bool bOutStyles,
353 							  LanguageType eDfltLang,
354 							  sal_uInt16 nCSS1Script, sal_Bool bHardDrop ) :
355 	pFmt( pF ), pItemSet( 0 ), bScriptDependent( sal_False )
356 {
357 	sal_uInt16 nRefPoolId = 0;
358 	// Den Selektor des Formats holen
359 	sal_uInt16 nDeep = SwHTMLWriter::GetCSS1Selector( pFmt, aToken, aClass,
360 												  nRefPoolId );
361 	ASSERT( nDeep ? aToken.Len()>0 : aToken.Len()==0,
362 			"Hier stimmt doch was mit dem Token nicht!" );
363 	ASSERT( nDeep ? nRefPoolId : !nRefPoolId,
364 			"Hier stimmt doch was mit der Vergleichs-Vorlage nicht!" );
365 
366 	sal_Bool bTxtColl = pFmt->Which() == RES_TXTFMTCOLL ||
367 					pFmt->Which() == RES_CONDTXTFMTCOLL;
368 
369 	const SwFmt *pReferenceFmt = 0;	// Vergleichs-Format
370 	sal_Bool bSetDefaults = sal_True, bClearSame = sal_True;
371 	if( nDeep != 0 )
372 	{
373 		// Es ist eine HTML-Tag-Vorlage oder die Vorlage ist von einer
374 		// solchen abgeleitet
375 		if( !bOutStyles )
376 		{
377 			// wenn keine Styles exportiert werden, muss evtl. zusaetlich
378 			// harte Attributierung geschrieben werden
379 			switch( nDeep )
380 			{
381 			case CSS1_FMT_ISTAG:
382 			case CSS1_FMT_CMPREF:
383 				// fuer HTML-Tag-Vorlagen die Unterscheide zum Original
384 				// (sofern verfuegbar)
385 				pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId,
386 														pTemplate );
387 				break;
388 
389 			default:
390 				// sonst die zur HTML-Tag-Vorlage des Originals oder des
391 				// aktuellen Doks, wenn die nicht verfuegbar ist
392 				if( pTemplate )
393 					pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId,
394 															pTemplate );
395 				else
396 					pReferenceFmt = SwHTMLWriter::GetParentFmt( *pFmt, nDeep );
397 				break;
398 			}
399 		}
400 	}
401 	else if( bTxtColl )
402 	{
403 		// Nicht von einer HTML-Tag-Vorlage abgeleitete Absatz-Vorlagen
404 		// muessen als harte Attributierung relativ zur Textkoerper-Volage
405 		// exportiert werden. Fuer Nicht-Styles-Export sollte die der
406 		// HTML-Vorlage als Referenz dienen
407 		if( !bOutStyles && pTemplate )
408             pReferenceFmt = pTemplate->GetTxtCollFromPool( RES_POOLCOLL_TEXT, false );
409 		else
410             pReferenceFmt = pDoc->GetTxtCollFromPool( RES_POOLCOLL_TEXT, false );
411 	}
412 
413 	if( pReferenceFmt || nDeep==0 )
414 	{
415 		pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
416 							   		pFmt->GetAttrSet().GetRanges() );
417 		// wenn Unterschiede zu einer anderen Vorlage geschrieben werden
418 		// sollen ist harte Attributierung noetig. Fuer Vorlagen, die
419 		// nicht von HTML-Tag-Vorlagen abgeleitet sind, gilt das immer
420 
421 		pItemSet->Set( pFmt->GetAttrSet(), sal_True );
422 
423 		if( pReferenceFmt )
424 			SwHTMLWriter::SubtractItemSet( *pItemSet, pReferenceFmt->GetAttrSet(),
425 										   bSetDefaults, bClearSame );
426 
427 		// einen leeren Item-Set gleich loeschen, das spart speater
428 		// Arbeit
429 		if( !pItemSet->Count() )
430 		{
431 			delete pItemSet;
432 			pItemSet = 0;
433 		}
434 	}
435 
436 	if( bTxtColl )
437 	{
438 		if( bOutStyles )
439 		{
440 			// We have to add hard attributes for any script dependent
441 			// item that is not accessed by the style
442 			static sal_uInt16 aWhichIds[3][4] =
443 			{
444 				{ RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
445 					RES_CHRATR_POSTURE, RES_CHRATR_WEIGHT },
446 				{ RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE,
447 					RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT },
448 				{ RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE,
449 					RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT }
450 			};
451 
452 			sal_uInt16 nRef = 0;
453 			sal_uInt16 aSets[2] = {0,0};
454 			switch( nCSS1Script )
455 			{
456 			case CSS1_OUTMODE_WESTERN:
457 				nRef = 0;
458 				aSets[0] = 1;
459 				aSets[1] = 2;
460 				break;
461 			case CSS1_OUTMODE_CJK:
462 				nRef = 1;
463 				aSets[0] = 0;
464 				aSets[1] = 2;
465 				break;
466 			case CSS1_OUTMODE_CTL:
467 				nRef = 2;
468 				aSets[0] = 0;
469 				aSets[1] = 1;
470 				break;
471 			}
472 			for( sal_uInt16 i=0; i<4; i++ )
473 			{
474                 const SfxPoolItem& rRef = pFmt->GetFmtAttr( aWhichIds[nRef][i] );
475 				for( sal_uInt16 j=0; j<2; j++ )
476 				{
477                     const SfxPoolItem& rSet = pFmt->GetFmtAttr( aWhichIds[aSets[j]][i] );
478 					if( rSet != rRef )
479 					{
480 						if( !pItemSet )
481 							pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
482 													   pFmt->GetAttrSet().GetRanges() );
483 						pItemSet->Put( rSet );
484 					}
485 				}
486 			}
487 		}
488 
489 		// Ggf. noch ein DropCap-Attribut uebernehmen
490 		if( bOutStyles && bHardDrop && nDeep != 0 )
491 		{
492 			const SfxPoolItem *pItem;
493 			if( SFX_ITEM_SET==pFmt->GetAttrSet().GetItemState(
494 									RES_PARATR_DROP, sal_True, &pItem ) )
495 			{
496 				sal_Bool bPut = sal_True;
497 				if( pTemplate )
498 				{
499 					pReferenceFmt = SwHTMLWriter::GetTemplateFmt( nRefPoolId, pTemplate );
500 					const SfxPoolItem *pRefItem;
501 					sal_Bool bRefItemSet =
502 						SFX_ITEM_SET==pReferenceFmt->GetAttrSet().GetItemState(
503 										RES_PARATR_DROP, sal_True, &pRefItem );
504 					bPut = !bRefItemSet || *pItem!=*pRefItem;
505 				}
506 				if( bPut )
507 				{
508 					if( !pItemSet )
509 						pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
510 												   pFmt->GetAttrSet().GetRanges() );
511 					pItemSet->Put( *pItem );
512 				}
513 			}
514 		}
515 
516 
517 		// Die diversen default-Abstaende aus der Vorlage oder der
518 		// Vergleischs-Vorlage merken
519 		const SvxLRSpaceItem &rLRSpace =
520 			(pReferenceFmt ? pReferenceFmt : pFmt)->GetLRSpace();
521 		nLeftMargin = rLRSpace.GetTxtLeft();
522 		nRightMargin = rLRSpace.GetRight();
523 		nFirstLineIndent = rLRSpace.GetTxtFirstLineOfst();
524 
525 		const SvxULSpaceItem &rULSpace =
526 			(pReferenceFmt ? pReferenceFmt : pFmt)->GetULSpace();
527 		nTopMargin = rULSpace.GetUpper();
528 		nBottomMargin = rULSpace.GetLower();
529 
530 		// export language if it differs from the default language
531 		sal_uInt16 nWhichId =
532 			SwHTMLWriter::GetLangWhichIdFromScript( nCSS1Script );
533 		const SvxLanguageItem& rLang =
534             (const SvxLanguageItem&)pFmt->GetFmtAttr( nWhichId );
535 		LanguageType eLang = rLang.GetLanguage();
536 		if( eLang != eDfltLang )
537 		{
538 			if( !pItemSet )
539 				pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
540 										   pFmt->GetAttrSet().GetRanges() );
541 			pItemSet->Put( rLang );
542 		}
543 
544 		static sal_uInt16 aWhichIds[3] =
545 			{ RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE,
546 				RES_CHRATR_CTL_LANGUAGE };
547 		for( sal_uInt16 i=0; i<3; i++ )
548 		{
549 			if( aWhichIds[i] != nWhichId )
550 			{
551 				const SvxLanguageItem& rTmpLang =
552                     (const SvxLanguageItem&)pFmt->GetFmtAttr(aWhichIds[i]);
553 				if( rTmpLang.GetLanguage() != eLang )
554 				{
555 					if( !pItemSet )
556 						pItemSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
557 												   pFmt->GetAttrSet().GetRanges() );
558 					pItemSet->Put( rTmpLang );
559 				}
560 			}
561 		}
562 	}
563 }
564 
~SwHTMLFmtInfo()565 SwHTMLFmtInfo::~SwHTMLFmtInfo()
566 {
567 	delete pItemSet;
568 }
569 
OutHTML_SwFmt(Writer & rWrt,const SwFmt & rFmt,const SfxItemSet * pNodeItemSet,SwHTMLTxtCollOutputInfo & rInfo)570 void OutHTML_SwFmt( Writer& rWrt, const SwFmt& rFmt,
571 					const SfxItemSet *pNodeItemSet,
572 					SwHTMLTxtCollOutputInfo& rInfo )
573 {
574 	ASSERT( RES_CONDTXTFMTCOLL==rFmt.Which() || RES_TXTFMTCOLL==rFmt.Which(),
575 			"keine Absatz-Vorlage" );
576 
577 	SwHTMLWriter & rHWrt = (SwHTMLWriter&)rWrt;
578 
579 	// Erstmal ein par Flags ...
580 	sal_uInt16 nNewDefListLvl = 0;
581 	sal_uInt16 nNumStart = USHRT_MAX;
582 	sal_Bool bForceDL = sal_False;
583 	sal_Bool bDT = sal_False;
584 	rInfo.bInNumBulList = sal_False;  	// Wir sind in einer Liste?
585 	sal_Bool bNumbered = sal_False;			// Der aktuelle Absatz ist numeriert
586 	sal_Bool bPara = sal_False;				// das aktuelle Token ist <P>
587 	rInfo.bParaPossible = sal_False;	// ein <P> darf zusaetzlich ausgegeben werden
588 	sal_Bool bNoEndTag = sal_False;			// kein End-Tag ausgeben
589 
590 	rHWrt.bNoAlign = sal_False;			// kein ALIGN=... moeglich
591 	sal_Bool bNoStyle = sal_False;			// kein STYLE=... moeglich
592 	sal_uInt8 nBulletGrfLvl = 255;	  	// Die auszugebende Bullet-Grafik
593 
594 	// Sind wir in einer Aufzaehlungs- oder Numerierungliste?
595 	const SwTxtNode* pTxtNd = rWrt.pCurPam->GetNode()->GetTxtNode();
596 
597 	SwHTMLNumRuleInfo aNumInfo;
598 	if( rHWrt.GetNextNumInfo() )
599 	{
600 		aNumInfo = *rHWrt.GetNextNumInfo();
601 		rHWrt.ClearNextNumInfo();
602 	}
603 	else
604 	{
605 		aNumInfo.Set( *pTxtNd );
606 	}
607 
608 	if( aNumInfo.GetNumRule() )
609 	{
610 		rInfo.bInNumBulList = sal_True;
611 		nNewDefListLvl = 0;
612 
613 		// ist der aktuelle Absatz numeriert?
614 		bNumbered = aNumInfo.IsNumbered();
615 		sal_uInt8 nLvl = aNumInfo.GetLevel();
616 
617         ASSERT( pTxtNd->GetActualListLevel() == nLvl,
618 				"Gemerkter Num-Level ist falsch" );
619         ASSERT( bNumbered == static_cast< sal_Bool >(pTxtNd->IsCountedInList()),
620 				"Gemerkter Numerierungs-Zustand ist falsch" );
621 
622 		if( bNumbered )
623 		{
624 			nBulletGrfLvl = nLvl; // nur veruebergehend!!!
625             // --> OD 2005-11-15 #i57919#
626             // correction of re-factoring done by cws swnumtree:
627             // - <nNumStart> has to contain the restart value, if the
628             //   numbering is restarted at this text node. Value <USHRT_MAX>
629             //   indicates, that no additional restart value has to be written.
630             if ( pTxtNd->IsListRestart() )
631             {
632                 nNumStart = static_cast< sal_uInt16 >(pTxtNd->GetActualListStartValue());
633             }
634             // <--
635 			DBG_ASSERT( rHWrt.nLastParaToken == 0,
636 				"<PRE> wurde nicht vor <LI> beendet." );
637 		}
638 	}
639 
640 	// Jetzt holen wir das Token und ggf. die Klasse
641 	SwHTMLFmtInfo aFmtInfo( &rFmt );
642 	sal_uInt16 nArrayPos;
643 	const SwHTMLFmtInfo *pFmtInfo;
644 	if( rHWrt.aTxtCollInfos.Seek_Entry( &aFmtInfo, &nArrayPos ) )
645 	{
646 		pFmtInfo = rHWrt.aTxtCollInfos[nArrayPos];
647 	}
648 	else
649 	{
650 		pFmtInfo = new SwHTMLFmtInfo( &rFmt, rWrt.pDoc, rHWrt.pTemplate,
651 									  rHWrt.bCfgOutStyles, rHWrt.eLang,
652 									  rHWrt.nCSS1Script,
653 									  !rHWrt.IsHTMLMode(HTMLMODE_DROPCAPS) );
654 		rHWrt.aTxtCollInfos.C40_PTR_INSERT( SwHTMLFmtInfo, pFmtInfo );
655 		String aName( rFmt.GetName() );
656 		if( rHWrt.aScriptParaStyles.Seek_Entry( &aName ) )
657 			((SwHTMLFmtInfo *)pFmtInfo)->bScriptDependent = sal_True;
658 	}
659 
660 	// Jetzt wird festgelegt, was aufgrund des Tokens so moeglich ist
661 	sal_uInt16 nToken = 0;			// Token fuer Tag-Wechsel
662 	sal_Bool bOutNewLine = sal_False;	// nur ein LF ausgeben?
663 	if( pFmtInfo->aToken.Len() )
664 	{
665 		// Es ist eine HTML-Tag-Vorlage oder die Vorlage ist von einer
666 		// solchen abgeleitet
667 		rInfo.aToken = pFmtInfo->aToken;
668 
669 		// der erste Buchstabe reicht meistens
670 		switch( rInfo.aToken.GetChar( 0 ) )
671 		{
672 		case 'A':	ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_address),
673 							"Doch kein ADDRESS?" );
674 					rInfo.bParaPossible = sal_True;
675 					rHWrt.bNoAlign = sal_True;
676 					break;
677 
678 		case 'B':	ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_blockquote),
679 							"Doch kein BLOCKQUOTE?" );
680 					rInfo.bParaPossible = sal_True;
681 					rHWrt.bNoAlign = sal_True;
682 					break;
683 
684 		case 'P':	if( rInfo.aToken.Len() == 1 )
685 					{
686 						bPara = sal_True;
687 					}
688 					else
689 					{
690 						ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_preformtxt),
691 								"Doch kein PRE?" );
692 						if( HTML_PREFORMTXT_ON == rHWrt.nLastParaToken )
693 						{
694 							bOutNewLine = sal_True;
695 						}
696 						else
697 						{
698 							nToken = HTML_PREFORMTXT_ON;
699 							rHWrt.bNoAlign = sal_True;
700 							bNoEndTag = sal_True;
701 						}
702 					}
703 					break;
704 
705 		case 'D':	ASSERT( rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dt) ||
706 							rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dd),
707 							"Doch kein DD/DT?" );
708 					bDT = rInfo.aToken.Equals(OOO_STRING_SVTOOLS_HTML_dt);
709 					rInfo.bParaPossible = !bDT;
710 					rHWrt.bNoAlign = sal_True;
711 					bForceDL = sal_True;
712 					break;
713 		}
714 	}
715 	else
716 	{
717 		// alle Vorlagen, die nicht einem HTML-Tag entsprechen oder von
718 		// diesem abgeleitet sind, werden als <P> exportiert
719 
720 		rInfo.aToken = OOO_STRING_SVTOOLS_HTML_parabreak;
721 		bPara = sal_True;
722 	}
723 
724 	// Falls noetig, die harte Attributierung der Vorlage uebernehmen
725 	if( pFmtInfo->pItemSet )
726 	{
727 		ASSERT( !rInfo.pItemSet, "Wo kommt der Item-Set her?" );
728 		rInfo.pItemSet = new SfxItemSet( *pFmtInfo->pItemSet );
729 	}
730 
731 	// und noch die harte Attributierung des Absatzes dazunehmen
732 	if( pNodeItemSet )
733 	{
734 		if( rInfo.pItemSet )
735 			rInfo.pItemSet->Put( *pNodeItemSet );
736 		else
737 			rInfo.pItemSet = new SfxItemSet( *pNodeItemSet );
738 	}
739 
740 	// den unteren Absatz-Abstand brauchen wir noch
741 	const SvxULSpaceItem& rULSpace =
742 		pNodeItemSet ? ((const SvxULSpaceItem &)pNodeItemSet->Get(RES_UL_SPACE))
743 					 : rFmt.GetULSpace();
744 
745 
746 	if( (rHWrt.bOutHeader &&
747 		 rWrt.pCurPam->GetPoint()->nNode.GetIndex() ==
748 			rWrt.pCurPam->GetMark()->nNode.GetIndex()) ||
749 		 rHWrt.bOutFooter )
750 	{
751 		if( rHWrt.bCfgOutStyles )
752 		{
753 			SvxULSpaceItem aULSpaceItem( rULSpace );
754 			if( rHWrt.bOutHeader )
755 				aULSpaceItem.SetLower( rHWrt.nHeaderFooterSpace );
756 			else
757 				aULSpaceItem.SetUpper( rHWrt.nHeaderFooterSpace );
758 
759 			if( !rInfo.pItemSet )
760 				rInfo.pItemSet = new SfxItemSet(
761 									*rFmt.GetAttrSet().GetPool(),
762 									RES_UL_SPACE, RES_UL_SPACE );
763 			rInfo.pItemSet->Put( aULSpaceItem );
764 		}
765 		rHWrt.bOutHeader = sal_False;
766 		rHWrt.bOutFooter = sal_False;
767 	}
768 
769 	if( bOutNewLine )
770 	{
771 		// nur einen Zeilen-Umbruch (ohne Einrueckung) am Absatz-Anfang
772 		// ausgeben
773 		rInfo.aToken.Erase();	// kein End-Tag ausgeben
774 		rWrt.Strm() << SwHTMLWriter::sNewLine;
775 
776 		return;
777 	}
778 
779 
780 	// soll ein ALIGN=... geschrieben werden?
781 	const SfxPoolItem* pAdjItem = 0;
782 	const SfxPoolItem* pItem;
783 
784 	if( rInfo.pItemSet &&
785 		SFX_ITEM_SET == rInfo.pItemSet->GetItemState( RES_PARATR_ADJUST,
786 													  sal_False, &pItem ) )
787 	{
788 		pAdjItem = pItem;
789 	}
790 
791 	// Unteren Absatz-Abstand beachten ? (nie im letzen Absatz von
792 	// Tabellen)
793 	sal_Bool bUseParSpace =	!rHWrt.bOutTable ||
794 						(rWrt.pCurPam->GetPoint()->nNode.GetIndex() !=
795 						 rWrt.pCurPam->GetMark()->nNode.GetIndex());
796 	// Wenn Styles exportiert werden, wird aus eingerueckten Absaetzen
797 	// eine Definitions-Liste
798 	const SvxLRSpaceItem& rLRSpace =
799 		pNodeItemSet ? ((const SvxLRSpaceItem &)pNodeItemSet->Get(RES_LR_SPACE))
800 					 : rFmt.GetLRSpace();
801 	if( (!rHWrt.bCfgOutStyles || bForceDL) && !rInfo.bInNumBulList )
802 	{
803 		sal_Int32 nLeftMargin;
804 		if( bForceDL )
805 			nLeftMargin = rLRSpace.GetTxtLeft();
806 		else
807 			nLeftMargin = rLRSpace.GetTxtLeft() > pFmtInfo->nLeftMargin
808 				? rLRSpace.GetTxtLeft() - pFmtInfo->nLeftMargin
809 				: 0;
810 
811 		if( nLeftMargin > 0 && rHWrt.nDefListMargin > 0 )
812 		{
813             nNewDefListLvl = static_cast< sal_uInt16 >((nLeftMargin + (rHWrt.nDefListMargin/2)) /
814                                                     rHWrt.nDefListMargin);
815 			if( nNewDefListLvl == 0 && bForceDL && !bDT )
816 				nNewDefListLvl = 1;
817 		}
818 		else
819 		{
820 			// If the left margin is 0 or negative, emulating indent
821 			// with <dd> does not work. We then set a def list only if
822 			// the dd style is used.
823 			nNewDefListLvl = (bForceDL&& !bDT) ? 1 : 0;
824 		}
825 
826 		sal_Bool bIsNextTxtNode =
827 			rWrt.pDoc->GetNodes()[rWrt.pCurPam->GetPoint()->nNode.GetIndex()+1]
828 					 ->IsTxtNode();
829 
830 		if( bForceDL && bDT )
831 		{
832 			// Statt eines DD muessen wir hier auch ein DT der Ebene
833 			// darueber nehmen
834 			nNewDefListLvl++;
835 		}
836 		else if( !nNewDefListLvl && !rHWrt.bCfgOutStyles && bPara &&
837 				 rULSpace.GetLower()==0 &&
838 				 ((bUseParSpace && bIsNextTxtNode) || rHWrt.nDefListLvl==1) &&
839 				 (!pAdjItem || SVX_ADJUST_LEFT==
840 					((const SvxAdjustItem *)pAdjItem)->GetAdjust()) )
841 		{
842 			// Absaetze ohne unteren Abstand als DT exportieren
843 			nNewDefListLvl = 1;
844 			bDT = sal_True;
845 			rInfo.bParaPossible = sal_False;
846 			rHWrt.bNoAlign = sal_True;
847 		}
848 	}
849 
850 	if( nNewDefListLvl != rHWrt.nDefListLvl )
851 		rHWrt.OutAndSetDefList( nNewDefListLvl );
852 
853 	// ggf. eine Aufzaehlung- oder Numerierungsliste beginnen
854 	if( rInfo.bInNumBulList )
855 	{
856 		ASSERT( !rHWrt.nDefListLvl, "DL in OL geht nicht!" );
857 		OutHTML_NumBulListStart( rHWrt, aNumInfo );
858 
859 		if( bNumbered )
860 		{
861 			if( rHWrt.aBulletGrfs[nBulletGrfLvl].Len()  )
862 				bNumbered = sal_False;
863 			else
864 				nBulletGrfLvl = 255;
865 		}
866 	}
867 
868 	// Die Defaults aus der Vorlage merken, denn sie muessen nicht
869 	// exportiert werden
870 	rHWrt.nDfltLeftMargin = pFmtInfo->nLeftMargin;
871 	rHWrt.nDfltRightMargin = pFmtInfo->nRightMargin;
872 	rHWrt.nDfltFirstLineIndent = pFmtInfo->nFirstLineIndent;
873 
874 	if( rInfo.bInNumBulList )
875 	{
876 		if( !rHWrt.IsHTMLMode( HTMLMODE_LSPACE_IN_NUMBUL ) )
877 			rHWrt.nDfltLeftMargin = rLRSpace.GetTxtLeft();
878 
879 		// In Numerierungs-Listen keinen Ertzeilen-Einzug ausgeben.
880 		rHWrt.nFirstLineIndent = rLRSpace.GetTxtFirstLineOfst();
881 	}
882 
883 	if( rInfo.bInNumBulList && bNumbered && bPara && !rHWrt.bCfgOutStyles )
884 	{
885 		// ein einzelnes LI hat keinen Abstand
886 		rHWrt.nDfltTopMargin = 0;
887 		rHWrt.nDfltBottomMargin = 0;
888 	}
889 	else if( rHWrt.nDefListLvl && bPara )
890 	{
891 		// ein einzelnes DD hat auch keinen Abstand
892 		rHWrt.nDfltTopMargin = 0;
893 		rHWrt.nDfltBottomMargin = 0;
894 	}
895 	else
896 	{
897 		rHWrt.nDfltTopMargin = pFmtInfo->nTopMargin;
898 		// #60393#: Wenn im letzten Absatz einer Tabelle der
899 		// untere Absatz-Abstand veraendert wird, vertut sich
900 		// Netscape total. Deshalb exportieren wir hier erstmal
901 		// nichts, indem wir den Abstand aus dem Absatz als Default
902 		// setzen.
903 		if( rHWrt.bCfgNetscape4 && !bUseParSpace )
904 			rHWrt.nDfltBottomMargin = rULSpace.GetLower();
905 		else
906 			rHWrt.nDfltBottomMargin = pFmtInfo->nBottomMargin;
907 	}
908 
909 	if( rHWrt.nDefListLvl )
910 	{
911 		rHWrt.nLeftMargin =
912 			(rHWrt.nDefListLvl-1) * rHWrt.nDefListMargin;
913 	}
914 
915 	if( rHWrt.bLFPossible )
916 		rHWrt.OutNewLine(); // Absatz-Tag in neue Zeile
917 	rInfo.bOutPara = sal_False;
918 
919 	// das ist jetzt unser neues Token
920 	rHWrt.ChangeParaToken( nToken );
921 
922 	sal_Bool bHasParSpace = bUseParSpace && rULSpace.GetLower() > 0;
923 
924 	// ggf ein List-Item aufmachen
925 	if( rInfo.bInNumBulList && bNumbered )
926 	{
927 		ByteString sOut( '<' );
928 		sOut += OOO_STRING_SVTOOLS_HTML_li;
929 		if( USHRT_MAX != nNumStart )
930 			(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_value) += '=')
931 				+= ByteString::CreateFromInt32(nNumStart);
932 		sOut += '>';
933 		rWrt.Strm() << sOut.GetBuffer();
934 	}
935 
936 	if( rHWrt.nDefListLvl > 0 && !bForceDL )
937 	{
938 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), bDT ? OOO_STRING_SVTOOLS_HTML_dt : OOO_STRING_SVTOOLS_HTML_dd );
939 	}
940 
941 	if( pAdjItem &&
942 		rHWrt.IsHTMLMode( HTMLMODE_NO_CONTROL_CENTERING ) &&
943 		rHWrt.HasControls() )
944 	{
945 		// #64687#: The align=... attribute does behave strange in netscape
946 		// if there are controls in a paragraph, because the control and
947 		// all text behind the control does not recognize this attribute.
948 		ByteString sOut( '<' );
949 		sOut += OOO_STRING_SVTOOLS_HTML_division;
950 		rWrt.Strm() << sOut.GetBuffer();
951 
952 		rHWrt.bTxtAttr = sal_False;
953 		rHWrt.bOutOpts = sal_True;
954 		OutHTML_SvxAdjust( rWrt, *pAdjItem );
955 		rWrt.Strm() << '>';
956 		pAdjItem = 0;
957 		rHWrt.bNoAlign = sal_False;
958 		rInfo.bOutDiv = sal_True;
959 		rHWrt.IncIndentLevel();
960 		rHWrt.bLFPossible = sal_True;
961 			rHWrt.OutNewLine();
962 	}
963 
964 	// fuer BLOCKQUOTE, ADDRESS und DD wird noch ein Absatz-Token
965 	// ausgegeben, wenn,
966 	// - keine Styles geschrieben werden, und
967 	// - ein untere Abstand oder eine Absatz-Ausrichtung existiert
968 	ByteString aToken = rInfo.aToken;
969 	if( !rHWrt.bCfgOutStyles && rInfo.bParaPossible && !bPara &&
970 		(bHasParSpace || pAdjItem) )
971 	{
972 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rInfo.aToken.GetBuffer() );
973 		aToken = OOO_STRING_SVTOOLS_HTML_parabreak;
974 		bPara = sal_True;
975 		rHWrt.bNoAlign = sal_False;
976 		bNoStyle = sal_False;
977 	}
978 
979 	LanguageType eLang = rInfo.pItemSet
980 		? ((const SvxLanguageItem&)rInfo.pItemSet->Get(SwHTMLWriter::GetLangWhichIdFromScript(rHWrt.nCSS1Script))).GetLanguage()
981 	   	: rHWrt.eLang;
982 
983 	if( rInfo.pItemSet )
984 	{
985 		static sal_uInt16 aWhichIds[3] = { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE };
986 
987 		for( sal_uInt16 i=0; i<3; i++ )
988 		{
989 			// export language if it differs from the default language only.
990 			const SfxPoolItem *pTmpItem;
991 			if( SFX_ITEM_SET == rInfo.pItemSet->GetItemState( aWhichIds[i],
992 						sal_True, &pTmpItem ) &&
993 				((const SvxLanguageItem *)pTmpItem)->GetLanguage() == eLang )
994 				rInfo.pItemSet->ClearItem( aWhichIds[i] );
995 		}
996 	}
997 
998 	// and the text direction
999 	sal_uInt16 nDir = rHWrt.GetHTMLDirection(
1000 			(pNodeItemSet ? static_cast < const SvxFrameDirectionItem& >(
1001 									pNodeItemSet->Get( RES_FRAMEDIR ) )
1002 						  : rFmt.GetFrmDir() ).GetValue() );
1003 
1004 	// Ein <P> wird nur geschrieben, wenn
1005 	// - wir in keiner OL/UL/DL sind, oder
1006 	// - der Absatz einer OL/UL nicht numeriert ist, oder
1007 	// - keine Styles exportiert werden und
1008 	//      - ein unterer Abstand oder
1009 	//      - eine Absatz-Ausrichtung existiert, ode
1010 	// - Styles exportiert werden und,
1011 	//		- die Textkoerper-Vorlage geaendert wurde, oder
1012 	//   	- ein Benutzer-Format exportiert wird, oder
1013 	//		- Absatz-Attribute existieren
1014 	if( !bPara ||
1015 		(!rInfo.bInNumBulList && !rHWrt.nDefListLvl) ||
1016 		(rInfo.bInNumBulList && !bNumbered) ||
1017 		(!rHWrt.bCfgOutStyles &&
1018 		 (bHasParSpace || pAdjItem ||
1019 		  (eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.eLang))) ||
1020 		nDir != rHWrt.nDirection ||
1021 		rHWrt.bCfgOutStyles )
1022 	{
1023 		// jetzt werden Optionen ausgegeben
1024 		rHWrt.bTxtAttr = sal_False;
1025 		rHWrt.bOutOpts = sal_True;
1026 
1027 		ByteString sOut( '<' );
1028 		sOut += aToken;
1029 
1030 		if( eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.eLang )
1031 		{
1032 			rWrt.Strm() << sOut.GetBuffer();
1033 			rHWrt.OutLanguage( eLang );
1034 			sOut.Erase();
1035 		}
1036 
1037 		if( nDir != rHWrt.nDirection )
1038 		{
1039 			if( sOut.Len() )
1040 			{
1041 				rWrt.Strm() << sOut.GetBuffer();
1042 				sOut.Erase();
1043 			}
1044 			rHWrt.OutDirection( nDir );
1045 		}
1046 
1047 		if( rHWrt.bCfgOutStyles &&
1048 			(pFmtInfo->aClass.Len() || pFmtInfo->bScriptDependent) )
1049 		{
1050 			((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"";
1051 			rWrt.Strm() << sOut.GetBuffer();
1052 			String aClass( pFmtInfo->aClass );
1053 			if( pFmtInfo->bScriptDependent )
1054 			{
1055 				if( aClass.Len() )
1056 				   aClass += '-';
1057 				switch( rHWrt.nCSS1Script )
1058 				{
1059 				case CSS1_OUTMODE_WESTERN:
1060 					aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("western") );
1061 					break;
1062 				case CSS1_OUTMODE_CJK:
1063 					aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("cjk") );
1064 					break;
1065 				case CSS1_OUTMODE_CTL:
1066 					aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("ctl") );
1067 					break;
1068 				}
1069 			}
1070 			HTMLOutFuncs::Out_String( rWrt.Strm(), aClass,
1071 									  rHWrt.eDestEnc, &rHWrt.aNonConvertableCharacters );
1072 			sOut = '\"';
1073 		}
1074 		rWrt.Strm() << sOut.GetBuffer();
1075 
1076 		// ggf. Ausrichtung ausgeben.
1077 		if( !rHWrt.bNoAlign && pAdjItem )
1078 			OutHTML_SvxAdjust( rWrt, *pAdjItem );
1079 
1080 		// und nun ggf. noch die STYLE-Option
1081 		if( rHWrt.bCfgOutStyles && rInfo.pItemSet && !bNoStyle)
1082 		{
1083 			OutCSS1_ParaTagStyleOpt( rWrt, *rInfo.pItemSet );
1084 		}
1085 
1086 		rWrt.Strm() << '>';
1087 
1088 		// Soll ein </P> geschrieben wenrden
1089 		rInfo.bOutPara =
1090 			bPara &&
1091 			( rHWrt.bCfgOutStyles ||
1092 				(!rHWrt.bCfgOutStyles && bHasParSpace) );
1093 
1094 		// wenn kein End-Tag geschrieben werden soll, es loeschen
1095 		if( bNoEndTag )
1096 			rInfo.aToken.Erase();
1097 	}
1098 
1099 	// ??? Warum nicht ueber den Hint-Mechanismus ???
1100 	if( rHWrt.IsHTMLMode(HTMLMODE_FIRSTLINE) )
1101 	{
1102 		const SvxLRSpaceItem& rLRSpaceTmp =
1103 			pNodeItemSet ? ((const SvxLRSpaceItem &)pNodeItemSet->Get(RES_LR_SPACE))
1104 						 : rFmt.GetLRSpace();
1105 		if( rLRSpaceTmp.GetTxtFirstLineOfst() > 0 )
1106 		{
1107 			OutHTML_HoriSpacer( rWrt, rLRSpaceTmp.GetTxtFirstLineOfst() );
1108 		}
1109 	}
1110 
1111 	if( nBulletGrfLvl != 255 )
1112 	{
1113 		ASSERT( aNumInfo.GetNumRule(), "Wo ist die Numerierung geblieben???" );
1114 		ASSERT( nBulletGrfLvl < MAXLEVEL, "So viele Ebenen gibt's nicht" );
1115 		const SwNumFmt& rNumFmt = aNumInfo.GetNumRule()->Get(nBulletGrfLvl);
1116 
1117 		OutHTML_BulletImage( rWrt, OOO_STRING_SVTOOLS_HTML_image, 0,
1118 							 rHWrt.aBulletGrfs[nBulletGrfLvl],
1119 							 rNumFmt.GetGraphicSize(), rNumFmt.GetGraphicOrientation() );
1120 	}
1121 
1122 	rHWrt.GetNumInfo() = aNumInfo;
1123 
1124 	// die Defaults zuruecksetzen
1125 	rHWrt.nDfltLeftMargin = 0;
1126 	rHWrt.nDfltRightMargin = 0;
1127 	rHWrt.nDfltFirstLineIndent = 0;
1128 	rHWrt.nDfltTopMargin = 0;
1129 	rHWrt.nDfltBottomMargin = 0;
1130 	rHWrt.nLeftMargin = 0;
1131 	rHWrt.nFirstLineIndent = 0;
1132 }
1133 
OutHTML_SwFmtOff(Writer & rWrt,const SwHTMLTxtCollOutputInfo & rInfo)1134 void OutHTML_SwFmtOff( Writer& rWrt, const SwHTMLTxtCollOutputInfo& rInfo )
1135 {
1136 	SwHTMLWriter & rHWrt = (SwHTMLWriter&)rWrt;
1137 
1138 	// wenn es kein Token gibt haben wir auch nichts auszugeben
1139 	if( !rInfo.aToken.Len() )
1140 	{
1141 		rHWrt.FillNextNumInfo();
1142 		const SwHTMLNumRuleInfo& rNextInfo = *rHWrt.GetNextNumInfo();
1143 		// Auch in PRE muss eine Bullet-Liste beendet werden
1144 		if( rInfo.bInNumBulList )
1145 		{
1146 
1147 			const SwHTMLNumRuleInfo& rNRInfo = rHWrt.GetNumInfo();
1148 			if( rNextInfo.GetNumRule() != rNRInfo.GetNumRule() ||
1149 				rNextInfo.GetDepth() != rNRInfo.GetDepth() ||
1150 				rNextInfo.IsNumbered() || rNextInfo.IsRestart() )
1151 				rHWrt.ChangeParaToken( 0 );
1152 			OutHTML_NumBulListEnd( rHWrt, rNextInfo );
1153 		}
1154 		else if( rNextInfo.GetNumRule() != 0 )
1155 			rHWrt.ChangeParaToken( 0 );
1156 
1157 		return;
1158 	}
1159 
1160 	if( rInfo.ShouldOutputToken() )
1161 	{
1162 		if( rHWrt.bLFPossible )
1163 			rHWrt.OutNewLine( sal_True );
1164 
1165 		// fuer BLOCKQUOTE, ADDRESS und DD wird ggf noch ein
1166 		// Absatz-Token ausgegeben, wenn
1167 		// - keine Styles geschrieben werden, und
1168 		// - ein untere Abstand existiert
1169 		if( rInfo.bParaPossible && rInfo.bOutPara )
1170 			HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_parabreak, sal_False );
1171 
1172 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rInfo.aToken.GetBuffer(),
1173 									sal_False );
1174 		rHWrt.bLFPossible = !rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_dt ) &&
1175 							!rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_dd ) &&
1176 							!rInfo.aToken.Equals( OOO_STRING_SVTOOLS_HTML_li );
1177 	}
1178 	if( rInfo.bOutDiv )
1179 	{
1180 		rHWrt.DecIndentLevel();
1181 		if( rHWrt.bLFPossible )
1182 			rHWrt.OutNewLine();
1183 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_division, sal_False );
1184 		rHWrt.bLFPossible = sal_True;
1185 	}
1186 
1187 	// ggf. eine Aufzaehlung- oder Numerierungsliste beenden
1188 	if( rInfo.bInNumBulList )
1189 	{
1190 		rHWrt.FillNextNumInfo();
1191 		OutHTML_NumBulListEnd( rHWrt, *rHWrt.GetNextNumInfo() );
1192 	}
1193 }
1194 
1195 
1196 class HTMLSttEndPos
1197 {
1198 	xub_StrLen nStart;
1199 	xub_StrLen nEnd;
1200 	SfxPoolItem* pItem;
1201 
1202 public:
1203 
1204 	HTMLSttEndPos( const SfxPoolItem& rItem, xub_StrLen nStt, xub_StrLen nE );
1205 	~HTMLSttEndPos();
1206 
GetItem() const1207 	const SfxPoolItem *GetItem() const { return pItem; }
1208 
SetStart(xub_StrLen nStt)1209 	void SetStart( xub_StrLen nStt ) { nStart = nStt; }
GetStart() const1210 	xub_StrLen GetStart() const { return nStart; }
1211 
GetEnd() const1212 	xub_StrLen GetEnd() const { return nEnd; }
SetEnd(xub_StrLen nE)1213 	void SetEnd( xub_StrLen nE ) { nEnd = nE; }
1214 };
1215 
HTMLSttEndPos(const SfxPoolItem & rItem,xub_StrLen nStt,xub_StrLen nE)1216 HTMLSttEndPos::HTMLSttEndPos( const SfxPoolItem& rItem, xub_StrLen nStt,
1217 														xub_StrLen nE ) :
1218 	nStart( nStt ),
1219 	nEnd( nE ),
1220 	pItem( rItem.Clone() )
1221 {}
1222 
~HTMLSttEndPos()1223 HTMLSttEndPos::~HTMLSttEndPos()
1224 {
1225 	delete pItem;
1226 }
1227 
1228 typedef HTMLSttEndPos *HTMLSttEndPosPtr;
1229 SV_DECL_PTRARR( _HTMLEndLst, HTMLSttEndPosPtr, 5, 5 )
1230 
1231 enum HTMLOnOffState { HTML_NOT_SUPPORTED, 	// nicht unterst. Attribut
1232 					  HTML_REAL_VALUE, 		// Attribut mit Wert
1233 					  HTML_ON_VALUE, 		// Attribut entspricht On-Tag
1234 					  HTML_OFF_VALUE,		// Attribut entspricht Off-Tag
1235 					  HTML_CHRFMT_VALUE,	// Attribut fuer Zeichenvorlage
1236 					  HTML_COLOR_VALUE,		// Attribut fuer Vordergrundfarbe
1237 					  HTML_STYLE_VALUE,		// Attribut muss als Style exp.
1238 					  HTML_DROPCAP_VALUE, 	// DropCap-Attributs
1239 					  HTML_AUTOFMT_VALUE };	// Attribute for automatic character styles
1240 
1241 
1242 class HTMLEndPosLst
1243 {
1244 	_HTMLEndLst aStartLst;	// nach Anfangs-Psoitionen sortierte Liste
1245 	_HTMLEndLst aEndLst;	// nach End-Psotionen sortierte Liste
1246 	SvXub_StrLens aScriptChgLst;	// positions where script changes
1247 									// 0 is not contained in this list,
1248 									// but the text length
1249     // the script that is valif up to the position
1250     // contained in aScriptChgList at the same index
1251     ::std::vector<sal_uInt16> aScriptLst;
1252 
1253 	SwDoc *pDoc;			// das aktuelle Dokument
1254 	SwDoc* pTemplate;		// die HTML-Vorlage (oder 0)
1255 	const Color* pDfltColor;// die Default-Vordergrund-Farbe
1256 	SvStringsSortDtor& rScriptTxtStyles;	//
1257 
1258 	sal_uLong nHTMLMode;
1259 	sal_Bool bOutStyles : 1;	// werden Styles exportiert
1260 
1261 
1262 	// die Position eines Items in der Start-/Ende-Liste suchen
1263 	sal_uInt16 _FindStartPos( const HTMLSttEndPos *pPos ) const;
1264 	sal_uInt16 _FindEndPos( const HTMLSttEndPos *pPos ) const;
1265 
1266 	// Eine SttEndPos in die Start- und Ende-Listen eintragen bzw. aus
1267 	// ihnen loeschen, wobei die Ende-Position bekannt ist
1268 	void _InsertItem( HTMLSttEndPos *pPos, sal_uInt16 nEndPos );
1269 	void _RemoveItem( sal_uInt16 nEndPos );
1270 
1271 	// die "Art" es Attributs ermitteln
1272 	HTMLOnOffState GetHTMLItemState( const SfxPoolItem& rItem );
1273 
1274 	// Existiert ein bestimmtes On-Tag-Item
1275 	sal_Bool ExistsOnTagItem( sal_uInt16 nWhich, xub_StrLen nPos );
1276 
1277 	// Existiert ein Item zum ausschalten eines Attributs, das genauso
1278 	// exportiert wird wie das uebergebene Item im gleichen Bereich?
1279 	sal_Bool ExistsOffTagItem( sal_uInt16 nWhich, xub_StrLen nStartPos,
1280 										  xub_StrLen nEndPos );
1281 
1282 
1283 	// das Ende eines gesplitteten Items anpassen
1284 	void FixSplittedItem( HTMLSttEndPos *pPos, sal_uInt16 nStartPos,
1285 						  xub_StrLen nNewEnd );
1286 
1287 	// Ein Attribut in die Listen eintragen und ggf. aufteilen
1288 	void InsertItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1289 											   xub_StrLen nEnd );
1290 
1291 	// Ein bereits vorhandenes Attribut aufteilen
1292 	void SplitItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1293 											  xub_StrLen nEnd );
1294 
1295 	// Insert without taking care of script
1296 	void InsertNoScript( const SfxPoolItem& rItem, xub_StrLen nStart,
1297 					 	 xub_StrLen nEnd, SwHTMLFmtInfos& rFmtInfos,
1298 						 sal_Bool bParaAttrs=sal_False );
1299 
1300 	const SwHTMLFmtInfo *GetFmtInfo( const SwFmt& rFmt,
1301 									 SwHTMLFmtInfos& rFmtInfos );
1302 
1303 public:
1304 
1305 	HTMLEndPosLst( SwDoc *pDoc, SwDoc* pTemplate, const Color* pDfltColor,
1306 				   sal_Bool bOutStyles, sal_uLong nHTMLMode,
1307 				   const String& rText, SvStringsSortDtor& rStyles );
1308 	~HTMLEndPosLst();
1309 
1310 	// Ein Attribut einfuegen
1311 	void Insert( const SfxPoolItem& rItem, xub_StrLen nStart,  xub_StrLen nEnd,
1312 				 SwHTMLFmtInfos& rFmtInfos, sal_Bool bParaAttrs=sal_False );
1313 	void Insert( const SfxItemSet& rItemSet, xub_StrLen nStart, xub_StrLen nEnd,
1314 				 SwHTMLFmtInfos& rFmtInfos, sal_Bool bDeep,
1315 				 sal_Bool bParaAttrs=sal_False );
1316 	void Insert( const SwDrawFrmFmt& rFmt, xub_StrLen nPos,
1317 				 SwHTMLFmtInfos& rFmtInfos );
1318 
1319 	sal_uInt16 GetScriptAtPos( xub_StrLen nPos,
1320 							   sal_uInt16 nWeak=CSS1_OUTMODE_ANY_SCRIPT );
1321 
1322 	void OutStartAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
1323 						HTMLOutContext *pContext = 0 );
1324 	void OutEndAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
1325 					  HTMLOutContext *pContext = 0 );
1326 
Count() const1327 	sal_uInt16 Count() const { return aEndLst.Count(); }
1328 
IsHTMLMode(sal_uLong nMode) const1329 	sal_Bool IsHTMLMode( sal_uLong nMode ) const { return (nHTMLMode & nMode) != 0; }
1330 };
1331 
1332 
_FindStartPos(const HTMLSttEndPos * pPos) const1333 sal_uInt16 HTMLEndPosLst::_FindStartPos( const HTMLSttEndPos *pPos ) const
1334 {
1335 	sal_uInt16 i;
1336 	for( i = 0; i < aStartLst.Count() && aStartLst[i] != pPos;  i++ )
1337 		;
1338 
1339 	ASSERT( i != aStartLst.Count(), "Item nicht in Start-Liste gefunden!" );
1340 
1341 	return i==aStartLst.Count() ? USHRT_MAX : i;
1342 }
1343 
_FindEndPos(const HTMLSttEndPos * pPos) const1344 sal_uInt16 HTMLEndPosLst::_FindEndPos( const HTMLSttEndPos *pPos ) const
1345 {
1346 	sal_uInt16 i;
1347 
1348 	for( i = 0; i < aEndLst.Count() && aEndLst[i] != pPos;  i++ )
1349 		;
1350 
1351 	ASSERT( i != aEndLst.Count(), "Item nicht in Ende-Liste gefunden" );
1352 
1353 	return i==aEndLst.Count() ? USHRT_MAX : i;
1354 }
1355 
1356 
_InsertItem(HTMLSttEndPos * pPos,sal_uInt16 nEndPos)1357 void HTMLEndPosLst::_InsertItem( HTMLSttEndPos *pPos, sal_uInt16 nEndPos )
1358 {
1359 	// In der Start-Liste das Attribut hinter allen vorher und an
1360 	// der gleichen Position gestarteten Attributen einfuegen
1361 	xub_StrLen nStart = pPos->GetStart();
1362 	sal_uInt16 i;
1363 
1364 	for( i = 0; i < aStartLst.Count() &&
1365 					 aStartLst[i]->GetStart() <= nStart; i++ )
1366 		;
1367 	aStartLst.Insert( pPos, i );
1368 
1369 	// die Position in der Ende-Liste wurde uebergeben
1370 	aEndLst.Insert( pPos, nEndPos );
1371 }
1372 
_RemoveItem(sal_uInt16 nEndPos)1373 void HTMLEndPosLst::_RemoveItem( sal_uInt16 nEndPos )
1374 {
1375 	HTMLSttEndPos *pPos = aEndLst[nEndPos];
1376 
1377 	// jetzt Suchen wir es in der Start-Liste
1378 	sal_uInt16 nStartPos = _FindStartPos( pPos );
1379 	if( nStartPos != USHRT_MAX )
1380 		aStartLst.Remove( nStartPos, 1 );
1381 
1382 	aEndLst.Remove( nEndPos, 1 );
1383 
1384 	delete pPos;
1385 }
1386 
GetHTMLItemState(const SfxPoolItem & rItem)1387 HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem )
1388 {
1389 	HTMLOnOffState eState = HTML_NOT_SUPPORTED;
1390 	switch( rItem.Which() )
1391 	{
1392 	case RES_CHRATR_POSTURE:
1393 	case RES_CHRATR_CJK_POSTURE:
1394 	case RES_CHRATR_CTL_POSTURE:
1395 		switch( ((const SvxPostureItem&)rItem).GetPosture() )
1396 		{
1397 		case ITALIC_NORMAL:
1398 			eState = HTML_ON_VALUE;
1399 			break;
1400 		case ITALIC_NONE:
1401 			eState = HTML_OFF_VALUE;
1402 			break;
1403 		default:
1404 			if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1405 				eState = HTML_STYLE_VALUE;
1406 			break;
1407 		}
1408 		break;
1409 
1410 	case RES_CHRATR_CROSSEDOUT:
1411 		switch( ((const SvxCrossedOutItem&)rItem).GetStrikeout() )
1412 		{
1413 		case STRIKEOUT_SINGLE:
1414 		case STRIKEOUT_DOUBLE:
1415 			eState = HTML_ON_VALUE;
1416 			break;
1417 		case STRIKEOUT_NONE:
1418 			eState = HTML_OFF_VALUE;
1419 			break;
1420 		default:
1421 			;
1422 		}
1423 		break;
1424 
1425 	case RES_CHRATR_ESCAPEMENT:
1426 		switch( (const SvxEscapement)
1427 						((const SvxEscapementItem&)rItem).GetEnumValue() )
1428 		{
1429 		case SVX_ESCAPEMENT_SUPERSCRIPT:
1430 		case SVX_ESCAPEMENT_SUBSCRIPT:
1431 			eState = HTML_ON_VALUE;
1432 			break;
1433 		case SVX_ESCAPEMENT_OFF:
1434 			eState = HTML_OFF_VALUE;
1435 			break;
1436 		default:
1437 			;
1438 		}
1439 		break;
1440 
1441 	case RES_CHRATR_UNDERLINE:
1442 		switch( ((const SvxUnderlineItem&)rItem).GetLineStyle() )
1443 		{
1444 		case UNDERLINE_SINGLE:
1445 			eState = HTML_ON_VALUE;
1446 			break;
1447 		case UNDERLINE_NONE:
1448 			eState = HTML_OFF_VALUE;
1449 			break;
1450 		default:
1451 			if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1452 				eState = HTML_STYLE_VALUE;
1453 			break;
1454 		}
1455 		break;
1456 
1457 	case RES_CHRATR_OVERLINE:
1458 		if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1459 			eState = HTML_STYLE_VALUE;
1460 		break;
1461 
1462 	case RES_CHRATR_WEIGHT:
1463 	case RES_CHRATR_CJK_WEIGHT:
1464 	case RES_CHRATR_CTL_WEIGHT:
1465 		switch( ((const SvxWeightItem&)rItem).GetWeight() )
1466 		{
1467 		case WEIGHT_BOLD:
1468 			eState = HTML_ON_VALUE;
1469 			break;
1470 		case WEIGHT_NORMAL:
1471 			eState = HTML_OFF_VALUE;
1472 			break;
1473 		default:
1474 			if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1475 				eState = HTML_STYLE_VALUE;
1476 			break;
1477 		}
1478 		break;
1479 
1480 	case RES_CHRATR_BLINK:
1481 		if( IsHTMLMode(HTMLMODE_BLINK) )
1482 			eState = ((const SvxBlinkItem&)rItem).GetValue() ? HTML_ON_VALUE
1483 															 : HTML_OFF_VALUE;
1484 		break;
1485 
1486 	case RES_CHRATR_COLOR:
1487 		eState = HTML_COLOR_VALUE;
1488 		break;
1489 
1490 	case RES_CHRATR_FONT:
1491 	case RES_CHRATR_FONTSIZE:
1492 	case RES_CHRATR_LANGUAGE:
1493 	case RES_CHRATR_CJK_FONT:
1494 	case RES_CHRATR_CJK_FONTSIZE:
1495 	case RES_CHRATR_CJK_LANGUAGE:
1496 	case RES_CHRATR_CTL_FONT:
1497 	case RES_CHRATR_CTL_FONTSIZE:
1498 	case RES_CHRATR_CTL_LANGUAGE:
1499 	case RES_TXTATR_INETFMT:
1500 		eState = HTML_REAL_VALUE;
1501 		break;
1502 
1503 	case RES_TXTATR_CHARFMT:
1504 		eState = HTML_CHRFMT_VALUE;
1505 		break;
1506 
1507 	case RES_TXTATR_AUTOFMT:
1508 		eState = HTML_AUTOFMT_VALUE;
1509 		break;
1510 
1511 	case RES_CHRATR_CASEMAP:
1512 		if( IsHTMLMode(HTMLMODE_SMALL_CAPS) )
1513 			eState = HTML_STYLE_VALUE;
1514 
1515 	case RES_CHRATR_KERNING:
1516 		if( IsHTMLMode(HTMLMODE_FULL_STYLES) )
1517 			eState = HTML_STYLE_VALUE;
1518 		break;
1519 
1520 	case RES_CHRATR_BACKGROUND:
1521 		if( IsHTMLMode(HTMLMODE_SOME_STYLES) )
1522 			eState = HTML_STYLE_VALUE;
1523 		break;
1524 
1525 	case RES_PARATR_DROP:
1526 		eState = HTML_DROPCAP_VALUE;
1527 		break;
1528 
1529 //	default:
1530 //		eState = HTML_NOT_SUPPORTED;
1531 //		break;
1532 	}
1533 
1534 	return eState;
1535 }
1536 
ExistsOnTagItem(sal_uInt16 nWhich,xub_StrLen nPos)1537 sal_Bool HTMLEndPosLst::ExistsOnTagItem( sal_uInt16 nWhich, xub_StrLen nPos )
1538 {
1539 	for( sal_uInt16 i=0; i<aStartLst.Count(); i++ )
1540 	{
1541 		HTMLSttEndPos *pTest = aStartLst[i];
1542 
1543 		if( pTest->GetStart() > nPos )
1544 		{
1545 			// dieses uns alle folgenden Attribute beginnen spaeter
1546 			break;
1547 		}
1548 		else if( pTest->GetEnd() > nPos )
1549 		{
1550 			// das Attribut beginnt vor oder an der aktuellen Position
1551 			// und endet hinter ihr
1552 			const SfxPoolItem *pItem = pTest->GetItem();
1553 			if( pItem->Which() == nWhich &&
1554 				HTML_ON_VALUE == GetHTMLItemState(*pItem) )
1555 			{
1556 				// ein On-Tag-Attibut wurde gefunden
1557 				return sal_True;
1558 			}
1559 		}
1560 	}
1561 
1562 	return sal_False;
1563 }
1564 
ExistsOffTagItem(sal_uInt16 nWhich,xub_StrLen nStartPos,xub_StrLen nEndPos)1565 sal_Bool HTMLEndPosLst::ExistsOffTagItem( sal_uInt16 nWhich, xub_StrLen nStartPos,
1566 									  xub_StrLen nEndPos )
1567 {
1568 	if( nWhich != RES_CHRATR_CROSSEDOUT &&
1569 		nWhich != RES_CHRATR_UNDERLINE &&
1570 		nWhich != RES_CHRATR_BLINK )
1571 	{
1572 		return sal_False;
1573 	}
1574 
1575 	for( sal_uInt16 i=0; i<aStartLst.Count(); i++ )
1576 	{
1577 		HTMLSttEndPos *pTest = aStartLst[i];
1578 
1579 		if( pTest->GetStart() > nStartPos )
1580 		{
1581 			// dieses uns alle folgenden Attribute beginnen spaeter
1582 			break;
1583 		}
1584 		else if( pTest->GetStart()==nStartPos &&
1585 				 pTest->GetEnd()==nEndPos )
1586 		{
1587 			// das Attribut beginnt vor oder an der aktuellen Position
1588 			// und endet hinter ihr
1589 			const SfxPoolItem *pItem = pTest->GetItem();
1590 			sal_uInt16 nTstWhich = pItem->Which() ;
1591 			if( (nTstWhich == RES_CHRATR_CROSSEDOUT ||
1592 				 nTstWhich == RES_CHRATR_UNDERLINE ||
1593 				 nTstWhich == RES_CHRATR_BLINK) &&
1594 				HTML_OFF_VALUE == GetHTMLItemState(*pItem) )
1595 			{
1596 				// Ein Off-Tag-Attibut wurde gefunden, das genauso
1597 				// exportiert wird, wie das aktuelle Item
1598 				return sal_True;
1599 			}
1600 		}
1601 	}
1602 
1603 	return sal_False;
1604 }
1605 
FixSplittedItem(HTMLSttEndPos * pPos,xub_StrLen nNewEnd,sal_uInt16 nStartPos)1606 void HTMLEndPosLst::FixSplittedItem( HTMLSttEndPos *pPos, xub_StrLen nNewEnd,
1607 									 sal_uInt16 nStartPos )
1608 {
1609 	// die End-Position entsprechend fixen
1610 	pPos->SetEnd( nNewEnd );
1611 
1612 	// das Item aus der End-Liste entfernen
1613 	sal_uInt16 nEndPos = _FindEndPos( pPos );
1614 	if( nEndPos != USHRT_MAX )
1615 		aEndLst.Remove( nEndPos, 1 );
1616 
1617 	// es wird von nun an als letztes an der entsprechenden Position
1618 	// beendet
1619 	for( nEndPos=0; nEndPos < aEndLst.Count() &&
1620 					aEndLst[nEndPos]->GetEnd() <= nNewEnd; nEndPos++ )
1621 		;
1622 	aEndLst.Insert( pPos, nEndPos );
1623 
1624 	// jetzt noch die spaeter gestarteten Attribute anpassen
1625 	for( sal_uInt16 i=nStartPos+1; i<aStartLst.Count(); i++ )
1626 	{
1627 		HTMLSttEndPos *pTest = aStartLst[i];
1628 		xub_StrLen nTestEnd = pTest->GetEnd();
1629 		if( pTest->GetStart() >= nNewEnd )
1630 		{
1631 			// das Test-Attribut und alle folgenden beginnen, nachdem das
1632 			// gesplittete Attribut endet
1633 			break;
1634 		}
1635 		else if( nTestEnd > nNewEnd )
1636 		{
1637 			// das Test-Attribut beginnt, bevor das gesplittete Attribut
1638 			// endet und endet danach, muss also auch gesplittet werden
1639 
1640 			// das neue Ende setzen
1641 			pTest->SetEnd( nNewEnd );
1642 
1643 			// das Attribut aus der End-Liste entfernen
1644 			sal_uInt16 nEPos = _FindEndPos( pTest );
1645 			if( nEPos != USHRT_MAX )
1646 				aEndLst.Remove( nEPos, 1 );
1647 
1648 			// es endet jetzt als erstes Attribut an der entsprechenden
1649 			// Position. Diese Position in der Ende-Liste kennen wir schon.
1650 			aEndLst.Insert(pTest, nEndPos );
1651 
1652 			// den "Rest" des Attributs neu einfuegen
1653 			InsertItem( *pTest->GetItem(), nNewEnd, nTestEnd );
1654 		}
1655 	}
1656 }
1657 
1658 
InsertItem(const SfxPoolItem & rItem,xub_StrLen nStart,xub_StrLen nEnd)1659 void HTMLEndPosLst::InsertItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1660 														  xub_StrLen nEnd )
1661 {
1662 	sal_uInt16 i;
1663 	for( i = 0; i < aEndLst.Count(); i++ )
1664 	{
1665 		HTMLSttEndPos *pTest = aEndLst[i];
1666 		xub_StrLen nTestEnd = pTest->GetEnd();
1667 		if( nTestEnd <= nStart )
1668 		{
1669 			// das Test-Attribut endet, bevor das neue beginnt
1670 			continue;
1671 		}
1672 		else if( nTestEnd < nEnd )
1673 		{
1674 			// das Test-Attribut endet, bevor das neue endet. Das
1675 			// neue Attribut muss deshalb aufgesplittet werden
1676 			_InsertItem( new HTMLSttEndPos( rItem, nStart, nTestEnd ), i );
1677 			nStart = nTestEnd;
1678 		}
1679 		else
1680 		{
1681 			// das Test-Attribut (und alle folgenden) endet, bevor das neue
1682 			// endet
1683 			break;
1684 		}
1685 	}
1686 
1687 	// ein Attribut muss noch eingefuegt werden
1688 	_InsertItem( new HTMLSttEndPos( rItem, nStart, nEnd ), i );
1689 }
1690 
1691 
1692 
SplitItem(const SfxPoolItem & rItem,xub_StrLen nStart,xub_StrLen nEnd)1693 void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, xub_StrLen nStart,
1694 													  	 xub_StrLen nEnd )
1695 {
1696 	sal_uInt16 nWhich = rItem.Which();
1697 
1698 	// erstmal muessen wir die alten Items anhand der Startliste suchen
1699 	// und die neuen Item-Bereiche festlegen
1700 
1701 	for( sal_uInt16 i=0; i<aStartLst.Count(); i++ )
1702 	{
1703 		HTMLSttEndPos *pTest = aStartLst[i];
1704 		xub_StrLen nTestStart = pTest->GetStart();
1705 		xub_StrLen nTestEnd = pTest->GetEnd();
1706 
1707 		if( nTestStart >= nEnd )
1708 		{
1709 			// dieses und alle nachfolgenden Attribute beginnen spaeter
1710 			break;
1711 		}
1712 		else if( nTestEnd > nStart )
1713 		{
1714 			// das Test Attribut endet im zu loeschenenden Bereich
1715 			const SfxPoolItem *pItem = pTest->GetItem();
1716 
1717 			// nur entsprechende On-Tag Attribute muessen beruecksichtigt
1718 			// werden
1719 			if( pItem->Which() == nWhich &&
1720 				HTML_ON_VALUE == GetHTMLItemState( *pItem ) )
1721 			{
1722 				sal_Bool bDelete = sal_True;
1723 
1724 				if( nTestStart < nStart )
1725 				{
1726 					// der Start des neuen Attribut entspricht
1727 					// dem neuen Ende des Attribts
1728 					FixSplittedItem( pTest, nStart, i );
1729 					bDelete = sal_False;
1730 				}
1731 				else
1732 				{
1733 					// das Test-Item beginnt erst hinter dem neuen
1734 					// Ende des Attribts und kann deshalb komplett
1735 					// geloescht werden
1736 					aStartLst.Remove( i, 1 );
1737 					i--;
1738 
1739 					sal_uInt16 nEndPos = _FindEndPos( pTest );
1740 					if( nEndPos != USHRT_MAX )
1741 						aEndLst.Remove( nEndPos, 1 );
1742 				}
1743 
1744 				// ggf den zweiten Teil des gesplitteten Attribts einfuegen
1745 				if( nTestEnd > nEnd )
1746 				{
1747 					InsertItem( *pTest->GetItem(), nEnd, nTestEnd );
1748 				}
1749 
1750 				if( bDelete )
1751 					delete pTest;
1752 			}
1753 		}
1754 	}
1755 }
1756 
GetFmtInfo(const SwFmt & rFmt,SwHTMLFmtInfos & rFmtInfos)1757 const SwHTMLFmtInfo *HTMLEndPosLst::GetFmtInfo( const SwFmt& rFmt,
1758 												SwHTMLFmtInfos& rFmtInfos )
1759 {
1760 	const SwHTMLFmtInfo *pFmtInfo;
1761 	SwHTMLFmtInfo aFmtInfo( &rFmt );
1762 	sal_uInt16 nPos;
1763 	if( rFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
1764 	{
1765 		pFmtInfo = rFmtInfos[nPos];
1766 	}
1767 	else
1768 	{
1769 		pFmtInfo = new SwHTMLFmtInfo( &rFmt, pDoc, pTemplate,
1770 									  bOutStyles );
1771 		rFmtInfos.C40_PTR_INSERT( SwHTMLFmtInfo, pFmtInfo );
1772 		String aName( rFmt.GetName() );
1773 		if( rScriptTxtStyles.Seek_Entry( &aName ) )
1774 			((SwHTMLFmtInfo *)pFmtInfo)->bScriptDependent = sal_True;
1775 	}
1776 
1777 	return pFmtInfo;
1778 }
1779 
HTMLEndPosLst(SwDoc * pD,SwDoc * pTempl,const Color * pDfltCol,sal_Bool bStyles,sal_uLong nMode,const String & rText,SvStringsSortDtor & rStyles)1780 HTMLEndPosLst::HTMLEndPosLst( SwDoc *pD, SwDoc* pTempl,
1781 							  const Color* pDfltCol, sal_Bool bStyles,
1782 							  sal_uLong nMode, const String& rText,
1783 							  SvStringsSortDtor& rStyles ):
1784 	pDoc( pD ),
1785 	pTemplate( pTempl ),
1786 	pDfltColor( pDfltCol ),
1787 	rScriptTxtStyles( rStyles ),
1788 	nHTMLMode( nMode ),
1789 	bOutStyles( bStyles )
1790 {
1791 	xub_StrLen nEndPos = rText.Len();
1792 	xub_StrLen nPos = 0;
1793 	while( nPos < nEndPos )
1794 	{
1795 		sal_uInt16 nScript = pBreakIt->GetBreakIter()->getScriptType( rText, nPos );
1796 		nPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rText, nPos, nScript );
1797 		aScriptChgLst.push_back( nPos );
1798         aScriptLst.push_back( nScript );
1799     }
1800 }
1801 
~HTMLEndPosLst()1802 HTMLEndPosLst::~HTMLEndPosLst()
1803 {
1804 	ASSERT( !aStartLst.Count(), "Start-Liste im Destruktor nicht leer" );
1805 	ASSERT( !aEndLst.Count(), "End-Liste im Destruktor nicht leer" );
1806 }
1807 
1808 
1809 
InsertNoScript(const SfxPoolItem & rItem,xub_StrLen nStart,xub_StrLen nEnd,SwHTMLFmtInfos & rFmtInfos,sal_Bool bParaAttrs)1810 void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem,
1811 							xub_StrLen nStart, xub_StrLen nEnd,
1812 							SwHTMLFmtInfos& rFmtInfos, sal_Bool bParaAttrs )
1813 {
1814 	// kein Bereich ?? dann nicht aufnehmen, wird nie wirksam !!
1815 	if( nStart != nEnd )
1816 	{
1817 		sal_Bool bSet = sal_False, bSplit = sal_False;
1818 		switch( GetHTMLItemState(rItem) )
1819 		{
1820 		case HTML_ON_VALUE:
1821 			// das Attribut wird ausgegeben, wenn es nicht sowieso
1822 			// schon an ist
1823 			if( !ExistsOnTagItem( rItem.Which(), nStart ) )
1824 				bSet = sal_True;
1825 			break;
1826 
1827 		case HTML_OFF_VALUE:
1828 			// wenn das entsprechne Attribut an ist, wird es gesplittet,
1829 			// Zusaetlich wird es aber als Style ausgegeben, wenn es nicht
1830 			// am ganzen Absatz gesetzt ist, weil es dann ja schon mit dem
1831 			// ABsatz-Tag ausgegeben wurde.
1832 			if( ExistsOnTagItem( rItem.Which(), nStart ) )
1833 				bSplit = sal_True;
1834 			bSet = bOutStyles && !bParaAttrs &&
1835 				   !ExistsOffTagItem( rItem.Which(), nStart, nEnd );
1836 			break;
1837 
1838 		case HTML_REAL_VALUE:
1839 			// das Attribut kann immer ausgegeben werden
1840 			bSet = sal_True;
1841 			break;
1842 
1843 		case HTML_STYLE_VALUE:
1844 			// Das Attribut kann nur als CSS1 ausgegeben werden. Wenn
1845 			// es am Absatz gesetzt ist, wurde es schon mit dem
1846 			// Absatz-Tag ausgegeben. Einzige Ausnahme ist das
1847 			// Zeichen-Hintergrund-Attribut. Es muss immer wie ein
1848 			// Hint behandelt werden.
1849 			bSet = bOutStyles &&
1850 				   (!bParaAttrs
1851 				  || rItem.Which()==RES_CHRATR_BACKGROUND
1852 				  || rItem.Which()==RES_CHRATR_OVERLINE);
1853 			break;
1854 
1855 		case HTML_CHRFMT_VALUE:
1856 			{
1857 				ASSERT( RES_TXTATR_CHARFMT == rItem.Which(),
1858 						"Doch keine Zeichen-Vorlage" );
1859 				const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rItem;
1860 				const SwCharFmt* pFmt = rChrFmt.GetCharFmt();
1861 
1862 				const SwHTMLFmtInfo *pFmtInfo = GetFmtInfo( *pFmt, rFmtInfos );
1863 				if( pFmtInfo->aToken.Len() )
1864 				{
1865 					// das Zeichenvorlagen-Tag muss vor den harten
1866 					// Attributen ausgegeben werden
1867 					InsertItem( rItem, nStart, nEnd );
1868 				}
1869 				if( pFmtInfo->pItemSet )
1870 				{
1871 					Insert( *pFmtInfo->pItemSet, nStart, nEnd,
1872 							rFmtInfos, sal_True, bParaAttrs );
1873 				}
1874 			}
1875 			break;
1876 
1877 		case HTML_AUTOFMT_VALUE:
1878 			{
1879 				const SwFmtAutoFmt& rAutoFmt = (const SwFmtAutoFmt&)rItem;
1880                 const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle();
1881                 if( pSet.get() )
1882 					Insert( *pSet.get(), nStart, nEnd, rFmtInfos, sal_True, bParaAttrs );
1883 			}
1884 			break;
1885 
1886 		case HTML_COLOR_VALUE:
1887 			// Eine Vordergrund-Farbe als Absatz-Attribut wird nur
1888 			// exportiert, wenn sie nicht der Default-Farbe entspricht.
1889 			{
1890 				ASSERT( RES_CHRATR_COLOR == rItem.Which(),
1891 						"Doch keine Vordergrund-Farbe" );
1892 				Color aColor( ((const SvxColorItem&)rItem).GetValue() );
1893 				if( COL_AUTO == aColor.GetColor() )
1894 					aColor.SetColor( COL_BLACK );
1895 				bSet = !bParaAttrs || !pDfltColor ||
1896 					   !pDfltColor->IsRGBEqual( aColor );
1897 			}
1898 			break;
1899 
1900 		case HTML_DROPCAP_VALUE:
1901 			{
1902 				ASSERT( RES_PARATR_DROP == rItem.Which(),
1903 						"Doch kein Drop-Cap" );
1904 				const SwFmtDrop& rDrop = (const SwFmtDrop&)rItem;
1905 				nEnd = nStart + rDrop.GetChars();
1906 				if( !bOutStyles )
1907 				{
1908 					// Zumindest die Attribute der Zeichenvorlage uebernehmen
1909 					const SwCharFmt *pCharFmt = rDrop.GetCharFmt();
1910 					if( pCharFmt )
1911 					{
1912 						Insert( pCharFmt->GetAttrSet(), nStart, nEnd,
1913 								rFmtInfos, sal_True, bParaAttrs );
1914 					}
1915 				}
1916 				else
1917 				{
1918 					bSet = sal_True;
1919 				}
1920 			}
1921 			break;
1922 		default:
1923 			;
1924 		}
1925 
1926 		if( bSet )
1927 			InsertItem( rItem, nStart, nEnd );
1928 		if( bSplit )
1929 			SplitItem( rItem, nStart, nEnd );
1930 	}
1931 }
1932 
Insert(const SfxPoolItem & rItem,xub_StrLen nStart,xub_StrLen nEnd,SwHTMLFmtInfos & rFmtInfos,sal_Bool bParaAttrs)1933 void HTMLEndPosLst::Insert( const SfxPoolItem& rItem,
1934 							xub_StrLen nStart, xub_StrLen nEnd,
1935 							SwHTMLFmtInfos& rFmtInfos, sal_Bool bParaAttrs )
1936 {
1937 	sal_Bool bDependsOnScript = sal_False, bDependsOnAnyScript = sal_False;
1938     sal_uInt16 nScript = i18n::ScriptType::LATIN;
1939 	switch( rItem.Which() )
1940 	{
1941 	case RES_CHRATR_FONT:
1942 	case RES_CHRATR_FONTSIZE:
1943 	case RES_CHRATR_LANGUAGE:
1944 	case RES_CHRATR_POSTURE:
1945 	case RES_CHRATR_WEIGHT:
1946 		bDependsOnScript = sal_True;
1947         nScript = i18n::ScriptType::LATIN;
1948 		break;
1949 
1950 	case RES_CHRATR_CJK_FONT:
1951 	case RES_CHRATR_CJK_FONTSIZE:
1952 	case RES_CHRATR_CJK_LANGUAGE:
1953 	case RES_CHRATR_CJK_POSTURE:
1954 	case RES_CHRATR_CJK_WEIGHT:
1955 		bDependsOnScript = sal_True;
1956         nScript = i18n::ScriptType::ASIAN;
1957 		break;
1958 
1959 	case RES_CHRATR_CTL_FONT:
1960 	case RES_CHRATR_CTL_FONTSIZE:
1961 	case RES_CHRATR_CTL_LANGUAGE:
1962 	case RES_CHRATR_CTL_POSTURE:
1963 	case RES_CHRATR_CTL_WEIGHT:
1964 		bDependsOnScript = sal_True;
1965         nScript = i18n::ScriptType::COMPLEX;
1966 		break;
1967 	case RES_TXTATR_CHARFMT:
1968 		{
1969 			const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rItem;
1970 			const SwCharFmt* pFmt = rChrFmt.GetCharFmt();
1971 			const SwHTMLFmtInfo *pFmtInfo = GetFmtInfo( *pFmt, rFmtInfos );
1972 			if( pFmtInfo->bScriptDependent )
1973 			{
1974 				bDependsOnScript = sal_True;
1975 				bDependsOnAnyScript = sal_True;
1976 			}
1977 		}
1978 		break;
1979 	case RES_TXTATR_INETFMT:
1980 		{
1981 			if( GetFmtInfo( *pDoc->GetCharFmtFromPool(
1982 					 RES_POOLCHR_INET_NORMAL), rFmtInfos )->bScriptDependent ||
1983 				GetFmtInfo( *pDoc->GetCharFmtFromPool(
1984 					 RES_POOLCHR_INET_VISIT), rFmtInfos )->bScriptDependent )
1985 			{
1986 				bDependsOnScript = sal_True;
1987 				bDependsOnAnyScript = sal_True;
1988 			}
1989 		}
1990 		break;
1991 	}
1992 
1993 	if( bDependsOnScript )
1994 	{
1995 		xub_StrLen nPos = nStart;
1996 		for( size_t i=0; i < aScriptChgLst.size(); i++ )
1997 		{
1998 			xub_StrLen nChgPos = aScriptChgLst[i];
1999 			if( nPos >= nChgPos )
2000 			{
2001 				// the hint starts behind or at the next script change,
2002 				// so we may continue with this position.
2003 				continue;
2004 			}
2005 			if( nEnd <= nChgPos )
2006 			{
2007 				// the (rest of) the hint ends before or at the next script
2008 				// change, so we can insert it, but only if it belongs
2009 				// to the current script.
2010 				if( bDependsOnAnyScript || nScript == aScriptLst[i] )
2011 					InsertNoScript( rItem, nPos, nEnd, rFmtInfos,
2012 									bParaAttrs );
2013 				break;
2014 			}
2015 
2016 			// the hint starts before the next script change and ends behind
2017 			// it, so we can insert a hint up to the next script change and
2018 			// continue with the rest of the hint.
2019 			if( bDependsOnAnyScript || nScript == aScriptLst[i] )
2020 				InsertNoScript( rItem, nPos, nChgPos, rFmtInfos, bParaAttrs );
2021 			nPos = nChgPos;
2022 		}
2023 	}
2024 	else
2025 	{
2026 		InsertNoScript( rItem, nStart, nEnd, rFmtInfos, bParaAttrs );
2027 	}
2028 }
2029 
Insert(const SfxItemSet & rItemSet,xub_StrLen nStart,xub_StrLen nEnd,SwHTMLFmtInfos & rFmtInfos,sal_Bool bDeep,sal_Bool bParaAttrs)2030 void HTMLEndPosLst::Insert( const SfxItemSet& rItemSet,
2031 							xub_StrLen nStart, xub_StrLen nEnd,
2032 							SwHTMLFmtInfos& rFmtInfos,
2033 							sal_Bool bDeep, sal_Bool bParaAttrs )
2034 {
2035 	SfxWhichIter aIter( rItemSet );
2036 
2037 	sal_uInt16 nWhich = aIter.FirstWhich();
2038 	while( nWhich )
2039 	{
2040 		const SfxPoolItem *pItem;
2041 		if( SFX_ITEM_SET == rItemSet.GetItemState( nWhich, bDeep, &pItem ) )
2042 		{
2043 			Insert( *pItem, nStart, nEnd, rFmtInfos, bParaAttrs );
2044 		}
2045 
2046 		nWhich = aIter.NextWhich();
2047 	}
2048 }
2049 
Insert(const SwDrawFrmFmt & rFmt,xub_StrLen nPos,SwHTMLFmtInfos & rFmtInfos)2050 void HTMLEndPosLst::Insert( const SwDrawFrmFmt& rFmt, xub_StrLen nPos,
2051 							SwHTMLFmtInfos& rFmtInfos )
2052 {
2053 	// der Type-Cast ist nur noetig, um nicht seinetwegen
2054 	// svdrwobt.hxx zu includem
2055 	const SdrObject* pTextObj =
2056 		(const SdrObject *)SwHTMLWriter::GetMarqueeTextObj( rFmt );
2057 
2058 	if( pTextObj )
2059 	{
2060 		// die Edit-Engine-Attribute des Objekts als SW-Attribute holen
2061 		// und als Hints einsortieren. Wegen der Menge der Hints werden
2062 		// Styles hierbei nicht beruecksichtigt!
2063 		const SfxItemSet& rFmtItemSet = rFmt.GetAttrSet();
2064 		SfxItemSet aItemSet( *rFmtItemSet.GetPool(), RES_CHRATR_BEGIN,
2065 													 RES_CHRATR_END );
2066 		SwHTMLWriter::GetEEAttrsFromDrwObj( aItemSet, pTextObj, sal_True );
2067 		sal_Bool bOutStylesOld = bOutStyles;
2068 		bOutStyles = sal_False;
2069 		Insert( aItemSet, nPos, nPos+1, rFmtInfos, sal_False, sal_False );
2070 		bOutStyles = bOutStylesOld;
2071 	}
2072 }
2073 
GetScriptAtPos(xub_StrLen nPos,sal_uInt16 nWeak)2074 sal_uInt16 HTMLEndPosLst::GetScriptAtPos( xub_StrLen nPos ,
2075 							   			  sal_uInt16 nWeak )
2076 {
2077 	sal_uInt16 nRet = CSS1_OUTMODE_ANY_SCRIPT;
2078 
2079 	size_t nScriptChgs = aScriptChgLst.size();
2080 	size_t i=0;
2081 	while( i < nScriptChgs && nPos >= aScriptChgLst[i] )
2082 		i++;
2083 	ASSERT( i < nScriptChgs, "script list is to short" );
2084 	if( i < nScriptChgs )
2085 	{
2086         if( i18n::ScriptType::WEAK == aScriptLst[i] )
2087 			nRet = nWeak;
2088 		else
2089 			nRet = SwHTMLWriter::GetCSS1ScriptForScriptType( aScriptLst[i] );
2090 	}
2091 
2092 	return nRet;
2093 }
2094 
OutStartAttrs(SwHTMLWriter & rHWrt,xub_StrLen nPos,HTMLOutContext * pContext)2095 void HTMLEndPosLst::OutStartAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
2096 	   							   HTMLOutContext *pContext	)
2097 {
2098 	rHWrt.bTagOn = sal_True;
2099 
2100 	// die Attribute in der Start-Liste sind aufsteigend sortiert
2101 	for( sal_uInt16 i=0; i< aStartLst.Count(); i++ )
2102 	{
2103 		HTMLSttEndPos *pPos = aStartLst[i];
2104 		xub_StrLen nStart = pPos->GetStart();
2105 		if( nStart > nPos )
2106 		{
2107 			// dieses und alle folgenden Attribute werden erst noch geoeffnet
2108 			break;
2109 		}
2110 		else if( nStart == nPos )
2111 		{
2112 			// das Attribut ausgeben
2113 			sal_uInt16 nCSS1Script = rHWrt.nCSS1Script;
2114 			sal_uInt16 nWhich = pPos->GetItem()->Which();
2115 			if( RES_TXTATR_CHARFMT == nWhich ||
2116 				RES_TXTATR_INETFMT == nWhich ||
2117 			 	RES_PARATR_DROP == nWhich )
2118 			{
2119 				rHWrt.nCSS1Script = GetScriptAtPos( nPos, nCSS1Script );
2120 			}
2121 			if( pContext )
2122 			{
2123 				HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext );
2124 				pContext = 0; // one time ony
2125 			}
2126 			Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt );
2127 			rHWrt.nCSS1Script = nCSS1Script;
2128 		}
2129 	}
2130 }
2131 
OutEndAttrs(SwHTMLWriter & rHWrt,xub_StrLen nPos,HTMLOutContext * pContext)2132 void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rHWrt, xub_StrLen nPos,
2133 	   						 	 HTMLOutContext *pContext )
2134 {
2135 	rHWrt.bTagOn = sal_False;
2136 
2137 	// die Attribute in der End-Liste sind aufsteigend sortiert
2138 	sal_uInt16 i=0;
2139 	while( i < aEndLst.Count() )
2140 	{
2141 		HTMLSttEndPos *pPos = aEndLst[i];
2142 		xub_StrLen nEnd = pPos->GetEnd();
2143 
2144 		if( STRING_MAXLEN==nPos || nEnd == nPos )
2145 		{
2146 			if( pContext )
2147 			{
2148 				HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext );
2149 				pContext = 0; // one time ony
2150 			}
2151 			Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt );
2152 			_RemoveItem( i );
2153 		}
2154 		else if( nEnd > nPos )
2155 		{
2156 			// dieses und alle folgenden Attribute werden erst spaeter beendet
2157 			break;
2158 		}
2159 		else
2160 		{
2161 			// Das Attribut wird vor der aktuellen Position beendet. Das
2162 			// darf nicht sein, aber wie koennen trotzdem damit umgehen
2163 			ASSERT( nEnd >= nPos,
2164 					"Das Attribut sollte schon laengst beendet sein" );
2165 			i++;
2166 		}
2167 	}
2168 }
2169 
2170 
2171 /* Ausgabe der Nodes */
OutHTML_SwTxtNode(Writer & rWrt,const SwCntntNode & rNode)2172 Writer& OutHTML_SwTxtNode( Writer& rWrt, const SwCntntNode& rNode )
2173 {
2174 	SwTxtNode * pNd = &((SwTxtNode&)rNode);
2175 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
2176 
2177 	const String& rStr = pNd->GetTxt();
2178 	xub_StrLen nEnde = rStr.Len();
2179 
2180 	// Besonderheit: leere Node und HR-Vorlage (horizontaler Strich)
2181 	// 				nur ein <HR> ausgeben
2182 	sal_uInt16 nPoolId = pNd->GetAnyFmtColl().GetPoolFmtId();
2183 
2184 	if( !nEnde && (RES_POOLCOLL_HTML_HR==nPoolId ||
2185 				   pNd->GetAnyFmtColl().GetName().EqualsAscii( OOO_STRING_SVTOOLS_HTML_horzrule) ) )
2186 	{
2187 		// dann die absatz-gebundenen Grafiken/OLE-Objekte im Absatz
2188 		// MIB 8.7.97: Ein <PRE> spannen wir um die Linie auf. Dann stimmen
2189 		// zwar die Abstaende nicht, aber sonst bekommen wir einen leeren
2190 		// Absatz hinter dem <HR> und das ist noch unschoener.
2191 		rHTMLWrt.ChangeParaToken( 0 );
2192 
2193 		// Alle an dem Node verankerten Rahmen ausgeben
2194 		rHTMLWrt.OutFlyFrm( rNode.GetIndex(), 0, HTML_POS_ANY );
2195 
2196 		if( rHTMLWrt.bLFPossible )
2197 			rHTMLWrt.OutNewLine(); // Absatz-Tag in eine neue Zeile
2198 
2199 		rHTMLWrt.bLFPossible = sal_True;
2200 
2201 		ByteString sOut( '<' );
2202 		sOut += OOO_STRING_SVTOOLS_HTML_horzrule;
2203 
2204 		const SfxItemSet* pItemSet = pNd->GetpSwAttrSet();
2205 		if( !pItemSet )
2206 		{
2207 			rWrt.Strm() << sOut.GetBuffer() << '>';
2208 			return rHTMLWrt;
2209 		}
2210 		const SfxPoolItem* pItem;
2211 		if( SFX_ITEM_SET == pItemSet->GetItemState( RES_LR_SPACE, sal_False, &pItem ))
2212 		{
2213 			sal_Int32 nLeft = ((SvxLRSpaceItem*)pItem)->GetLeft();
2214 			sal_Int32 nRight = ((SvxLRSpaceItem*)pItem)->GetRight();
2215 			if( nLeft || nRight )
2216 			{
2217 				const SwFrmFmt& rPgFmt =
2218                     rHTMLWrt.pDoc->GetPageDescFromPool
2219                     ( RES_POOLPAGE_HTML, false )->GetMaster();
2220 				const SwFmtFrmSize& rSz   = rPgFmt.GetFrmSize();
2221 				const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace();
2222 				const SwFmtCol& rCol = rPgFmt.GetCol();
2223 
2224 				long nPageWidth = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight();
2225 
2226 				if( 1 < rCol.GetNumCols() )
2227 					nPageWidth /= rCol.GetNumCols();
2228 
2229 				const SwTableNode* pTblNd = pNd->FindTableNode();
2230 				if( pTblNd )
2231 				{
2232 					const SwTableBox* pBox = pTblNd->GetTable().GetTblBox(
2233 									pNd->StartOfSectionIndex() );
2234 					if( pBox )
2235 						nPageWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
2236 				}
2237 
2238 				((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width) += '=';
2239 				rWrt.Strm() << sOut.GetBuffer();
2240 				rWrt.OutULong( rHTMLWrt.ToPixel(nPageWidth-nLeft-nRight) );
2241 
2242 				((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=';
2243 				if( !nLeft )
2244 					sOut += OOO_STRING_SVTOOLS_HTML_AL_left;
2245 				else if( !nRight )
2246 					sOut += OOO_STRING_SVTOOLS_HTML_AL_right;
2247 				else
2248 					sOut += OOO_STRING_SVTOOLS_HTML_AL_center;
2249 			}
2250 		}
2251 		rWrt.Strm() << sOut.GetBuffer();
2252 		if( SFX_ITEM_SET == pItemSet->GetItemState( RES_BOX, sal_False, &pItem ))
2253 		{
2254 			const SvxBoxItem* pBoxItem = (const SvxBoxItem*)pItem;
2255 			const SvxBorderLine* pBorderLine = pBoxItem->GetBottom();
2256 			if( pBorderLine )
2257 			{
2258 				sal_uInt16 nWidth = pBorderLine->GetOutWidth() +
2259 								pBorderLine->GetInWidth() +
2260 								pBorderLine->GetDistance();
2261 				((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=';
2262 				rWrt.Strm() << sOut.GetBuffer();
2263 				rWrt.OutULong( rHTMLWrt.ToPixel(nWidth) );
2264 
2265 				const Color& rBorderColor = pBorderLine->GetColor();
2266 				if( !rBorderColor.IsRGBEqual( Color(COL_GRAY) ) )
2267 				{
2268 					((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '=';
2269 					rWrt.Strm() << sOut.GetBuffer();
2270 					HTMLOutFuncs::Out_Color( rWrt.Strm(), rBorderColor,
2271 											 rHTMLWrt.eDestEnc );
2272 				}
2273 
2274 				if( !pBorderLine->GetInWidth() )
2275 				{
2276 					(sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_noshade;
2277 					rWrt.Strm() << sOut.GetBuffer();
2278 				}
2279 			}
2280 		}
2281 		rWrt.Strm() << '>';
2282 		return rHTMLWrt;
2283 	}
2284 
2285 	// Die leeren Nodes mit 2pt Font-Hoehe und der Stand-Vorlage, die
2286 	// vor Tabellen und Bereichen eingefuegt werden, nicht exportieren,
2287 	// Bookmarks oder absatzgebundene Grafiken aber schon.
2288 	// MIB 21.7.97: Ausserdem auch keine leeren Tabellen-Zellen exportieren.
2289 	if( !nEnde && (nPoolId == RES_POOLCOLL_STANDARD ||
2290 				   nPoolId == RES_POOLCOLL_TABLE ||
2291 				   nPoolId == RES_POOLCOLL_TABLE_HDLN) )
2292 	{
2293 		// Der aktuelle Node ist leer und enthaelt Standard-Vorlage ...
2294 		const SfxPoolItem* pItem;
2295 		const SfxItemSet *pItemSet = pNd->GetpSwAttrSet();
2296 		if( pItemSet && pItemSet->Count() &&
2297 			SFX_ITEM_SET == pItemSet->GetItemState( RES_CHRATR_FONTSIZE, sal_False, &pItem ) &&
2298 			40 == ((const SvxFontHeightItem *)pItem)->GetHeight() )
2299 		{
2300 			// ... ausserdem ist die 2pt Schrift eingestellt ...
2301 			sal_uLong nNdPos = rWrt.pCurPam->GetPoint()->nNode.GetIndex();
2302 			const SwNode *pNextNd = rWrt.pDoc->GetNodes()[nNdPos+1];
2303 			const SwNode *pPrevNd = rWrt.pDoc->GetNodes()[nNdPos-1];
2304 			sal_Bool bStdColl = nPoolId == RES_POOLCOLL_STANDARD;
2305 			if( ( bStdColl && (pNextNd->IsTableNode() ||
2306 							   pNextNd->IsSectionNode()) ) ||
2307 				( !bStdColl && pNextNd->IsEndNode() &&
2308 							   pPrevNd->IsStartNode() &&
2309 							   SwTableBoxStartNode==
2310 								pPrevNd->GetStartNode()->GetStartNodeType() ) )
2311 			{
2312 				// ... und er steht vor einer Tabelle ohne einem Bereich
2313 				rHTMLWrt.OutBookmarks();
2314 				rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken;
2315 
2316 				// Alle an dem Node verankerten Rahmen ausgeben
2317 				rHTMLWrt.OutFlyFrm( rNode.GetIndex(), 0, HTML_POS_ANY );
2318 				rHTMLWrt.bLFPossible = sal_False;
2319 
2320 				return rWrt;
2321 			}
2322 		}
2323 	}
2324 
2325 	// PagePreaks uns PagDescs abfangen
2326 	sal_Bool bPageBreakBehind = sal_False;
2327 	if( rHTMLWrt.bCfgFormFeed &&
2328 		!(rHTMLWrt.bOutTable || rHTMLWrt.bOutFlyFrame) &&
2329 		rHTMLWrt.pStartNdIdx->GetIndex() !=
2330 		rHTMLWrt.pCurPam->GetPoint()->nNode.GetIndex() )
2331 	{
2332 		sal_Bool bPageBreakBefore = sal_False;
2333 		const SfxPoolItem* pItem;
2334 		const SfxItemSet* pItemSet = pNd->GetpSwAttrSet();
2335 
2336 		if( pItemSet )
2337 		{
2338 			if( SFX_ITEM_SET ==
2339 				pItemSet->GetItemState( RES_PAGEDESC, sal_True, &pItem ) &&
2340 				((SwFmtPageDesc *)pItem)->GetPageDesc() )
2341 				bPageBreakBefore = sal_True;
2342 			else if( SFX_ITEM_SET ==
2343 					 pItemSet->GetItemState( RES_BREAK, sal_True, &pItem ) )
2344 			{
2345 				switch( ((SvxFmtBreakItem *)pItem)->GetBreak() )
2346 				{
2347 				case SVX_BREAK_PAGE_BEFORE:
2348 					bPageBreakBefore = sal_True;
2349 					break;
2350 				case SVX_BREAK_PAGE_AFTER:
2351 					bPageBreakBehind = sal_True;
2352 					break;
2353 				case SVX_BREAK_PAGE_BOTH:
2354 					bPageBreakBefore = sal_True;
2355 					bPageBreakBehind = sal_True;
2356 					break;
2357 				default:
2358 					;
2359 				}
2360 			}
2361 		}
2362 
2363 		if( bPageBreakBefore )
2364 			rWrt.Strm() << '\f';
2365 	}
2366 
2367 	// eventuell eine Form oeffnen
2368 	rHTMLWrt.OutForm();
2369 
2370 	// An dem Node "verankerte" Seitenegebunde Rahmen ausgeben
2371 	sal_Bool bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2372 										 0, HTML_POS_PREFIX );
2373 	// An dem Node verankerte Rahmen ausgeben, die vor dem
2374 	// Absatz-Tag geschrieben werden sollen.
2375 	if( bFlysLeft )
2376 		bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2377 										0, HTML_POS_BEFORE );
2378 
2379 	if( rHTMLWrt.pCurPam->GetPoint()->nNode == rHTMLWrt.pCurPam->GetMark()->nNode )
2380 		nEnde = rHTMLWrt.pCurPam->GetMark()->nContent.GetIndex();
2381 
2382 	// gibt es harte Attribute, die als Optionen geschrieben werden muessen?
2383 	rHTMLWrt.bTagOn = sal_True;
2384 
2385 	// jetzt das Tag des Absatzes ausgeben
2386 	const SwFmt& rFmt = pNd->GetAnyFmtColl();
2387 	SwHTMLTxtCollOutputInfo aFmtInfo;
2388 	sal_Bool bOldLFPossible = rHTMLWrt.bLFPossible;
2389 	OutHTML_SwFmt( rWrt, rFmt, pNd->GetpSwAttrSet(), aFmtInfo );
2390 
2391 	// Wenn vor dem Absatz-Tag keine neue Zeile aufgemacht wurde, dann
2392 	// tun wir das jetzt
2393 	rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken;
2394 	if( !bOldLFPossible && rHTMLWrt.bLFPossible )
2395 		rHTMLWrt.OutNewLine();
2396 
2397 
2398 	// dann die Bookmarks (inkl. End-Tag)
2399 	rHTMLWrt.bOutOpts = sal_False;
2400 	rHTMLWrt.OutBookmarks();
2401 
2402 	// jetzt ist noch mal eine gute Gelegenheit fuer ein LF, sofern es noch
2403 	// erlaubt ist
2404 	if( rHTMLWrt.bLFPossible &&
2405 		rHTMLWrt.GetLineLen() >= rHTMLWrt.nWhishLineLen )
2406 	{
2407 		rHTMLWrt.OutNewLine();
2408 	}
2409 	rHTMLWrt.bLFPossible = sal_False;
2410 
2411 	// Text, der aus einer Outline-Numerierung kommt ermitteln
2412 	xub_StrLen nOffset = 0;
2413 	String aOutlineTxt;
2414 	String aFullText;
2415     // --> OD 2006-06-12 #b6435904#
2416     // export numbering string as plain text only for the outline numbering,
2417     // because the outline numbering isn't exported as a numbering - see <SwHTMLNumRuleInfo::Set(..)>
2418     if ( pNd->IsOutline() &&
2419          pNd->GetNumRule() == pNd->GetDoc()->GetOutlineNumRule() )
2420     // <--
2421 	{
2422 		aOutlineTxt = pNd->GetNumString();
2423         nOffset = nOffset + aOutlineTxt.Len();
2424 		aFullText = aOutlineTxt;
2425 	}
2426 	String aFootEndNoteSym;
2427 	if( rHTMLWrt.pFmtFtn )
2428 	{
2429 		aFootEndNoteSym = rHTMLWrt.GetFootEndNoteSym( *rHTMLWrt.pFmtFtn );
2430         nOffset = nOffset + aFootEndNoteSym.Len();
2431 		aFullText += aFootEndNoteSym;
2432 	}
2433 
2434 	// gibt es harte Attribute, die als Tags geschrieben werden muessen?
2435 	aFullText += rStr;
2436 	HTMLEndPosLst aEndPosLst( rWrt.pDoc, rHTMLWrt.pTemplate,
2437 							  rHTMLWrt.pDfltColor, rHTMLWrt.bCfgOutStyles,
2438 							  rHTMLWrt.GetHTMLMode(), aFullText,
2439 						   	  rHTMLWrt.aScriptTextStyles );
2440 	if( aFmtInfo.pItemSet )
2441 	{
2442 		aEndPosLst.Insert( *aFmtInfo.pItemSet, 0, nEnde + nOffset,
2443 						   rHTMLWrt.aChrFmtInfos, sal_False, sal_True );
2444 	}
2445 
2446 
2447 	if( aOutlineTxt.Len() || rHTMLWrt.pFmtFtn )
2448 	{
2449 		// Absatz-Attribute ausgeben, damit der Text die Attribute des
2450 		// Absatzes bekommt.
2451 		aEndPosLst.OutStartAttrs( rHTMLWrt, 0 );
2452 
2453 		// Theoretisch muesste man hier die Zeichen-Vorlage der Numerierung
2454 		// beachten. Da man die ueber die UI nicht setzen kann, ignorieren
2455 		// wir sie erstmal.
2456 
2457 		if( aOutlineTxt.Len() )
2458 			HTMLOutFuncs::Out_String( rWrt.Strm(), aOutlineTxt,
2459 								   	  rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters);
2460 
2461 		if( rHTMLWrt.pFmtFtn )
2462 		{
2463 			rHTMLWrt.OutFootEndNoteSym( *rHTMLWrt.pFmtFtn, aFootEndNoteSym,
2464 										aEndPosLst.GetScriptAtPos( aOutlineTxt.Len(), rHTMLWrt.nCSS1Script ) );
2465 			rHTMLWrt.pFmtFtn = 0;
2466 		}
2467 	}
2468 
2469 	// erstmal den Start berichtigen. D.h. wird nur ein Teil vom Satz
2470 	// ausgegeben, so muessen auch da die Attribute stimmen!!
2471 	rHTMLWrt.bTxtAttr = sal_True;
2472 
2473 
2474 	sal_uInt16 nAttrPos = 0;
2475 	xub_StrLen nStrPos = rHTMLWrt.pCurPam->GetPoint()->nContent.GetIndex();
2476 	const SwTxtAttr * pHt = 0;
2477 	sal_uInt16 nCntAttr = pNd->HasHints() ? pNd->GetSwpHints().Count() : 0;
2478 	if( nCntAttr && nStrPos > *( pHt = pNd->GetSwpHints()[ 0 ] )->GetStart() )
2479 	{
2480 		// Ok, es gibt vorher Attribute, die ausgegeben werden muessen
2481 		do {
2482 			aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset );
2483 
2484             nAttrPos++;
2485             if( pHt->Which() == RES_TXTATR_FIELD
2486                 || pHt->Which() == RES_TXTATR_ANNOTATION )
2487                 continue;
2488 
2489             if ( pHt->End() && !pHt->HasDummyChar() )
2490 			{
2491 				const xub_StrLen nHtEnd = *pHt->End(),
2492 					   nHtStt = *pHt->GetStart();
2493 				if( !rHTMLWrt.bWriteAll && nHtEnd <= nStrPos )
2494 					continue;
2495 
2496 				// leere Hints am Anfang nicht beachten, oder ??
2497 				if( nHtEnd == nHtStt )
2498 					continue;
2499 
2500 				// Attribut in die Liste aufnehemen
2501 				if( rHTMLWrt.bWriteAll )
2502 					aEndPosLst.Insert( pHt->GetAttr(), nHtStt + nOffset,
2503 									   nHtEnd + nOffset,
2504 									   rHTMLWrt.aChrFmtInfos );
2505 				else
2506 				{
2507 					xub_StrLen nTmpStt = nHtStt < nStrPos ? nStrPos : nHtStt;
2508 					xub_StrLen nTmpEnd = nHtEnd < nEnde ? nHtEnd : nEnde;
2509 					aEndPosLst.Insert( pHt->GetAttr(), nTmpStt + nOffset,
2510 									   nTmpEnd + nOffset,
2511 									   rHTMLWrt.aChrFmtInfos );
2512 				}
2513 				continue;
2514 				// aber nicht ausgeben, das erfolgt spaeter !!
2515 			}
2516 
2517 		} while( nAttrPos < nCntAttr && nStrPos >
2518 			*( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() );
2519 
2520 		// dann gebe mal alle gesammelten Attribute von der String-Pos aus
2521 		aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset );
2522 		aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset );
2523 	}
2524 
2525 	sal_Bool bWriteBreak = (HTML_PREFORMTXT_ON != rHTMLWrt.nLastParaToken);
2526 	if( bWriteBreak && pNd->GetNumRule()  )
2527 		bWriteBreak = sal_False;
2528 
2529 	{
2530 		HTMLOutContext aContext( rHTMLWrt.eDestEnc );
2531 
2532 		xub_StrLen nPreSplitPos = 0;
2533 		for( ; nStrPos < nEnde; nStrPos++ )
2534 		{
2535 			aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext );
2536 
2537 			// Die an der aktuellen Position verankerten Rahmen ausgeben
2538 			if( bFlysLeft )
2539 				bFlysLeft =	rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2540 												nStrPos, HTML_POS_INSIDE,
2541 												&aContext );
2542 
2543 			sal_Bool bOutChar = sal_True;
2544 			const SwTxtAttr * pTxtHt = 0;
2545 			if( nAttrPos < nCntAttr && *pHt->GetStart() == nStrPos
2546 				&& nStrPos != nEnde )
2547 			{
2548 				do {
2549                     if ( pHt->End() && !pHt->HasDummyChar() )
2550 					{
2551 						if( RES_CHRATR_KERNING == pHt->Which() &&
2552 							rHTMLWrt.IsHTMLMode(HTMLMODE_FIRSTLINE) &&
2553 							*pHt->End() - nStrPos == 1 &&
2554 							' ' == rStr.GetChar(nStrPos) &&
2555 							((const SvxKerningItem&)pHt->GetAttr()).GetValue() > 0 )
2556 						{
2557 							// Wenn erlaubt, wird das Ding als Spacer exportiert
2558 
2559 							bOutChar = sal_False;	// Space nicht ausgeben
2560 							bWriteBreak = sal_False;	// der Absatz ist aber auch nicht leer
2561 							HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2562 							OutHTML_HoriSpacer( rWrt,
2563 								((const SvxKerningItem&)pHt->GetAttr()).GetValue() );
2564 
2565 							// Der Hint braucht nun doch nicht weiter
2566 							// beruecksichtigt werden.
2567 						}
2568 						else if( *pHt->End() != nStrPos )
2569 						{
2570 							// Hints mit Ende einsortieren, wenn sie keinen
2571 							// leeren Bereich aufspannen (Hints, die keinen
2572 							// Bereich aufspannen werden ignoriert
2573 							aEndPosLst.Insert( pHt->GetAttr(), nStrPos + nOffset,
2574 											   *pHt->End() + nOffset,
2575 											   rHTMLWrt.aChrFmtInfos );
2576 						}
2577 					}
2578 					else
2579 					{
2580                         // Hints ohne-Ende werden als letztes ausgebeben
2581                         ASSERT( !pTxtHt, "Wieso gibt es da schon ein Attribut ohne Ende?" );
2582                         if( rHTMLWrt.nTxtAttrsToIgnore>0 )
2583                         {
2584                             rHTMLWrt.nTxtAttrsToIgnore--;
2585                         }
2586                         else
2587                         {
2588                             pTxtHt = pHt;
2589                             sal_uInt16 nFldWhich;
2590                             if( RES_TXTATR_FIELD != pHt->Which()
2591                                 || ( RES_POSTITFLD != (nFldWhich = ((const SwFmtFld&)pHt->GetAttr()).GetField()->Which())
2592                                      && RES_SCRIPTFLD != nFldWhich ) )
2593                             {
2594                                 bWriteBreak = sal_False;
2595                             }
2596                         }
2597                         bOutChar = sal_False;		// keine 255 ausgeben
2598                     }
2599 				} while( ++nAttrPos < nCntAttr && nStrPos ==
2600 					*( pHt = pNd->GetSwpHints()[ nAttrPos ] )->GetStart() );
2601 			}
2602 
2603 			// Manche Draw-Formate koennen auch noch Attribute mitbringen
2604 			if( pTxtHt && RES_TXTATR_FLYCNT == pTxtHt->Which() )
2605 			{
2606 				const SwFrmFmt* pFrmFmt =
2607 					((const SwFmtFlyCnt &)pTxtHt->GetAttr()).GetFrmFmt();
2608 
2609 				if( RES_DRAWFRMFMT == pFrmFmt->Which() )
2610 					aEndPosLst.Insert( *((const SwDrawFrmFmt *)pFrmFmt),
2611 										nStrPos + nOffset,
2612 										rHTMLWrt.aChrFmtInfos );
2613 			}
2614 
2615 			aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext );
2616 			aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset, &aContext );
2617 
2618 			if( pTxtHt )
2619 			{
2620 				rHTMLWrt.bLFPossible = !rHTMLWrt.nLastParaToken && nStrPos > 0 &&
2621 									   rStr.GetChar(nStrPos-1) == ' ';
2622 				sal_uInt16 nCSS1Script = rHTMLWrt.nCSS1Script;
2623 				rHTMLWrt.nCSS1Script = aEndPosLst.GetScriptAtPos(
2624 												nStrPos + nOffset, nCSS1Script );
2625 				HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2626 				Out( aHTMLAttrFnTab, pTxtHt->GetAttr(), rHTMLWrt );
2627 				rHTMLWrt.nCSS1Script = nCSS1Script;
2628 				rHTMLWrt.bLFPossible = sal_False;
2629 			}
2630 
2631 			if( bOutChar )
2632 			{
2633 				// #i120442#: get the UTF-32 codepoint by converting an eventual UTF-16 unicode surrogate pair
2634 				sal_uInt64 c = rStr.GetChar( nStrPos );
2635 				if( nStrPos < nEnde - 1 )
2636 				{
2637 					const sal_Unicode d = rStr.GetChar( nStrPos + 1 );
2638 					if( (c >= 0xd800 && c <= 0xdbff) && (d >= 0xdc00 && d <= 0xdfff) )
2639 					{
2640 						sal_uInt64 templow = d&0x03ff;
2641 						sal_uInt64 temphi = ((c&0x03ff) + 0x0040)<<10;
2642 						c = temphi|templow;
2643 						nStrPos++;
2644 					}
2645 				}
2646 
2647 				// try to split a line after about 255 characters
2648 				// at a space character unless in a PRE-context
2649 				if( ' '==c && !rHTMLWrt.nLastParaToken  )
2650 				{
2651 					xub_StrLen nLineLen;
2652 					if( rHTMLWrt.nLastParaToken )
2653 						nLineLen = nStrPos - nPreSplitPos;
2654 					else
2655 						nLineLen = rHTMLWrt.GetLineLen();
2656 
2657 					xub_StrLen nWordLen = rStr.Search( ' ', nStrPos+1 );
2658 					if( nWordLen == STRING_NOTFOUND )
2659 						nWordLen = nEnde;
2660 					nWordLen -= nStrPos;
2661 
2662 					if( nLineLen >= rHTMLWrt.nWhishLineLen ||
2663 						(nLineLen+nWordLen) >= rHTMLWrt.nWhishLineLen )
2664 					{
2665 						HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2666 						rHTMLWrt.OutNewLine();
2667 						bOutChar = sal_False;
2668 						if( rHTMLWrt.nLastParaToken )
2669 							nPreSplitPos = nStrPos+1;
2670 					}
2671 				}
2672 
2673 				if( bOutChar )
2674 				{
2675 					if( 0x0a == c )
2676 					{
2677 						HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2678 						HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak );
2679 					}
2680 					// #i120442#: if c is outside the unicode base plane output it as "&#******;"
2681 					else if( c > 0xffff)
2682 					{
2683 						ByteString sOut("&#");
2684 						sOut += ByteString::CreateFromInt64( (sal_uInt64)c );
2685 						sOut += ';';
2686 						rWrt.Strm() << sOut.GetBuffer();
2687 					}
2688 					else
2689 						HTMLOutFuncs::Out_Char( rWrt.Strm(), (sal_Unicode)c, aContext, &rHTMLWrt.aNonConvertableCharacters );
2690 
2691 					// if a paragraph's last character is a hard line break
2692 					// then we need to add an extra <br>
2693 					// because browsers like Mozilla wouldn't add a line for the next paragraph
2694 					bWriteBreak = (0x0a == c) &&
2695 								  (HTML_PREFORMTXT_ON != rHTMLWrt.nLastParaToken);
2696 				}
2697 			}
2698 		}
2699 		HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext );
2700 	}
2701 
2702 	aEndPosLst.OutEndAttrs( rHTMLWrt, STRING_MAXLEN );
2703 
2704 	// Die an der letzten Position verankerten Rahmen ausgeben
2705 	if( bFlysLeft )
2706 		bFlysLeft = rHTMLWrt.OutFlyFrm( rNode.GetIndex(),
2707 									   nEnde, HTML_POS_INSIDE );
2708 	ASSERT( !bFlysLeft, "Es wurden nicht alle Rahmen gespeichert!" );
2709 
2710 	rHTMLWrt.bTxtAttr = sal_False;
2711 
2712 	if( bWriteBreak )
2713 	{
2714 		sal_Bool bEndOfCell = rHTMLWrt.bOutTable &&
2715 						 rWrt.pCurPam->GetPoint()->nNode.GetIndex() ==
2716 						 rWrt.pCurPam->GetMark()->nNode.GetIndex();
2717 
2718 		if( bEndOfCell && !nEnde &&
2719 			rHTMLWrt.IsHTMLMode(HTMLMODE_NBSP_IN_TABLES) )
2720 		{
2721 			// Wenn der letzte Absatz einer Tabellezelle leer ist und
2722 			// wir fuer den MS-IE exportieren, schreiben wir statt eines
2723 			// <BR> ein &nbsp;
2724 			rWrt.Strm() << '&' << OOO_STRING_SVTOOLS_HTML_S_nbsp << ';';
2725 		}
2726 		else
2727 		{
2728 			HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak );
2729 			const SvxULSpaceItem& rULSpace =
2730 				(const SvxULSpaceItem &)pNd->GetSwAttrSet().Get(RES_UL_SPACE);
2731 			if( rULSpace.GetLower() > 0 && !bEndOfCell &&
2732 				!rHTMLWrt.IsHTMLMode(HTMLMODE_NO_BR_AT_PAREND) )
2733 				HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_linebreak );
2734 			rHTMLWrt.bLFPossible = sal_True;
2735 		}
2736 	}
2737 
2738 	if( rHTMLWrt.bClearLeft || rHTMLWrt.bClearRight )
2739 	{
2740 		const sal_Char *pStr;
2741 		if( rHTMLWrt.bClearLeft )
2742 		{
2743 			if( rHTMLWrt.bClearRight )
2744 				pStr = OOO_STRING_SVTOOLS_HTML_AL_all;
2745 			else
2746 				pStr = OOO_STRING_SVTOOLS_HTML_AL_left;
2747 		}
2748 		else
2749 			pStr = OOO_STRING_SVTOOLS_HTML_AL_right;
2750 
2751 		ByteString sOut( OOO_STRING_SVTOOLS_HTML_linebreak );
2752 		(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_clear) += '=') += pStr;
2753 
2754 		HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), sOut.GetBuffer() );
2755 		rHTMLWrt.bClearLeft = sal_False;
2756 		rHTMLWrt.bClearRight = sal_False;
2757 
2758 		rHTMLWrt.bLFPossible = sal_True;
2759 	}
2760 
2761 	// wenn ein LF nicht schon erlaubt ist wird es erlaubt, wenn der
2762 	// Absatz mit einem ' ' endet
2763 	if( !rHTMLWrt.bLFPossible && !rHTMLWrt.nLastParaToken &&
2764 		nEnde > 0 && ' ' == rStr.GetChar(nEnde-1) )
2765 		rHTMLWrt.bLFPossible = sal_True;
2766 
2767 	rHTMLWrt.bTagOn = sal_False;
2768 	OutHTML_SwFmtOff( rWrt, aFmtInfo );
2769 
2770 	// eventuell eine Form schliessen
2771 	rHTMLWrt.OutForm( sal_False );
2772 
2773 	if( bPageBreakBehind )
2774 		rWrt.Strm() << '\f';
2775 
2776 	return rHTMLWrt;
2777 }
2778 
2779 
ToPixel(sal_uInt32 nVal) const2780 sal_uInt32 SwHTMLWriter::ToPixel( sal_uInt32 nVal ) const
2781 {
2782 	if( Application::GetDefaultDevice() && nVal )
2783 	{
2784 		nVal = Application::GetDefaultDevice()->LogicToPixel(
2785 					Size( nVal, nVal ), MapMode( MAP_TWIP ) ).Width();
2786 		if( !nVal )		// wo ein Twip ist sollte auch ein Pixel sein
2787 			nVal = 1;
2788 	}
2789 	return nVal;
2790 }
2791 
2792 
OutHTML_CSS1Attr(Writer & rWrt,const SfxPoolItem & rHt)2793 static Writer& OutHTML_CSS1Attr( Writer& rWrt, const SfxPoolItem& rHt )
2794 {
2795 	// wenn gerade Hints geschrieben werden versuchen wir den Hint als
2796 	// CSS1-Attribut zu schreiben
2797 
2798 	if( ((SwHTMLWriter&)rWrt).bCfgOutStyles && ((SwHTMLWriter&)rWrt).bTxtAttr )
2799 		OutCSS1_HintSpanTag( rWrt, rHt );
2800 
2801 	return rWrt;
2802 }
2803 
2804 
2805 /* File CHRATR.HXX: */
2806 
OutHTML_SvxColor(Writer & rWrt,const SfxPoolItem & rHt)2807 static Writer& OutHTML_SvxColor( Writer& rWrt, const SfxPoolItem& rHt )
2808 {
2809 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2810 	if( rHTMLWrt.bOutOpts )
2811 		return rWrt;
2812 
2813 	// die Default-Farbe nur Schreiben, wenn sie als Hint vorkommt
2814 	//if( rHTMLWrt.bTagOn && !rHTMLWrt.bTxtAttr && rHTMLWrt.pDfltColor
2815 	//	&& rColor == *rHTMLWrt.pDfltColor )
2816 	//	return rWrt;
2817 
2818 	if( !rHTMLWrt.bTxtAttr && rHTMLWrt.bCfgOutStyles && rHTMLWrt.bCfgPreferStyles )
2819 	{
2820 		// Font-Farbe nicht als Tag schreiben, wenn Styles normalen Tags
2821 		// vorgezogen werden
2822 		return rWrt;
2823 	}
2824 
2825 	if( rHTMLWrt.bTagOn )
2826 	{
2827 		Color aColor( ((const SvxColorItem&)rHt).GetValue() );
2828 		if( COL_AUTO == aColor.GetColor() )
2829 			aColor.SetColor( COL_BLACK );
2830 
2831 		ByteString sOut( '<' );
2832 		(((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '=';
2833 		rWrt.Strm() << sOut.GetBuffer();
2834 		HTMLOutFuncs::Out_Color( rWrt.Strm(), aColor, rHTMLWrt.eDestEnc ) << '>';
2835 	}
2836 	else
2837 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font, sal_False );
2838 
2839 	return rWrt;
2840 }
2841 
2842 
OutHTML_SwPosture(Writer & rWrt,const SfxPoolItem & rHt)2843 static Writer& OutHTML_SwPosture( Writer& rWrt, const SfxPoolItem& rHt )
2844 {
2845 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2846 	if( rHTMLWrt.bOutOpts )
2847 		return rWrt;
2848 
2849 	const FontItalic nPosture = ((const SvxPostureItem&)rHt).GetPosture();
2850 	if( ITALIC_NORMAL == nPosture )
2851 	{
2852 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_italic, rHTMLWrt.bTagOn );
2853 	}
2854 	else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
2855 	{
2856 		// vielleicht als CSS1-Attribut ?
2857 		OutCSS1_HintSpanTag( rWrt, rHt );
2858 	}
2859 
2860 	return rWrt;
2861 }
2862 
OutHTML_SvxFont(Writer & rWrt,const SfxPoolItem & rHt)2863 static Writer& OutHTML_SvxFont( Writer& rWrt, const SfxPoolItem& rHt )
2864 {
2865 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2866 	if( rHTMLWrt.bOutOpts )
2867 		return rWrt;
2868 
2869 	if( rHTMLWrt.bTagOn )
2870 	{
2871 		String aNames;
2872 		SwHTMLWriter::PrepareFontList( ((const SvxFontItem&)rHt), aNames, 0,
2873 						   rHTMLWrt.IsHTMLMode(HTMLMODE_FONT_GENERIC) );
2874 		ByteString sOut( '<' );
2875 		(((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_face) += "=\"";
2876 		rWrt.Strm() << sOut.GetBuffer();
2877 		HTMLOutFuncs::Out_String( rWrt.Strm(), aNames, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters )
2878 			<< "\">";
2879 	}
2880 	else
2881 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font , sal_False );
2882 
2883 	return rWrt;
2884 }
2885 
OutHTML_SvxFontHeight(Writer & rWrt,const SfxPoolItem & rHt)2886 static Writer& OutHTML_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt )
2887 {
2888 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2889 	if( rHTMLWrt.bOutOpts )
2890 		return rWrt;
2891 
2892 	if( rHTMLWrt.bTagOn )
2893 	{
2894 		ByteString sOut( '<' );
2895 		sOut += OOO_STRING_SVTOOLS_HTML_font;
2896 
2897 		sal_uInt32 nHeight = ((const SvxFontHeightItem&)rHt).GetHeight();
2898 		sal_uInt16 nSize = rHTMLWrt.GetHTMLFontSize( nHeight );
2899 		(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_size) += '=')
2900 			+= ByteString::CreateFromInt32( nSize );
2901 		rWrt.Strm() << sOut.GetBuffer();
2902 
2903 		if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr &&
2904 			rHTMLWrt.aFontHeights[nSize-1] != nHeight )
2905 		{
2906 			// wenn die Groesse keiner HTML-Groesse entspricht,
2907 			// wird sie noch zusatzlich als Style-Option exportiert
2908 			OutCSS1_HintStyleOpt( rWrt, rHt );
2909 		}
2910 		rWrt.Strm() << '>';
2911 	}
2912 	else
2913 	{
2914 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_font, sal_False );
2915 	}
2916 
2917 	return rWrt;
2918 }
2919 
OutHTML_SvxLanguage(Writer & rWrt,const SfxPoolItem & rHt)2920 static Writer& OutHTML_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt )
2921 {
2922 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2923 	if( rHTMLWrt.bOutOpts )
2924 		return rWrt;
2925 
2926 	LanguageType eLang = ((const SvxLanguageItem &)rHt).GetLanguage();
2927 	if( LANGUAGE_DONTKNOW == eLang )
2928 		return rWrt;
2929 
2930 	if( rHTMLWrt.bTagOn )
2931 	{
2932 		ByteString sOut( '<' );
2933 		sOut += OOO_STRING_SVTOOLS_HTML_span;
2934 		rWrt.Strm() << sOut.GetBuffer();
2935 		rHTMLWrt.OutLanguage( ((const SvxLanguageItem &)rHt).GetLanguage() );
2936 		rWrt.Strm() << '>';
2937 	}
2938 	else
2939 	{
2940 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_span, sal_False );
2941 	}
2942 
2943 	return rWrt;
2944 }
OutHTML_SwWeight(Writer & rWrt,const SfxPoolItem & rHt)2945 static Writer& OutHTML_SwWeight( Writer& rWrt, const SfxPoolItem& rHt )
2946 {
2947 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2948 	if( rHTMLWrt.bOutOpts )
2949 		return rWrt;
2950 
2951 	const FontWeight nBold = ((const SvxWeightItem&)rHt).GetWeight();
2952 	if( WEIGHT_BOLD == nBold )
2953 	{
2954 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_bold, rHTMLWrt.bTagOn );
2955 	}
2956 	else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
2957 	{
2958 		// vielleicht als CSS1-Attribut ?
2959 		OutCSS1_HintSpanTag( rWrt, rHt );
2960 	}
2961 
2962 	return rWrt;
2963 }
2964 
2965 
OutHTML_SwCrossedOut(Writer & rWrt,const SfxPoolItem & rHt)2966 static Writer& OutHTML_SwCrossedOut( Writer& rWrt, const SfxPoolItem& rHt )
2967 {
2968 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2969 	if( rHTMLWrt.bOutOpts )
2970 		return rWrt;
2971 
2972 	// Wegen Netscape schrieben wir hier STRIKE und nicht S raus!
2973 	const FontStrikeout nStrike = ((const SvxCrossedOutItem&)rHt).GetStrikeout();
2974 	if( STRIKEOUT_NONE != nStrike )
2975 	{
2976 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_strike, rHTMLWrt.bTagOn );
2977 	}
2978 	else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
2979 	{
2980 		// vielleicht als CSS1-Attribut ?
2981 		OutCSS1_HintSpanTag( rWrt, rHt );
2982 	}
2983 
2984 	return rWrt;
2985 }
2986 
2987 
OutHTML_SvxEscapement(Writer & rWrt,const SfxPoolItem & rHt)2988 static Writer& OutHTML_SvxEscapement( Writer& rWrt, const SfxPoolItem& rHt )
2989 {
2990 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
2991 	if( rHTMLWrt.bOutOpts )
2992 		return rWrt;
2993 
2994 	const SvxEscapement eEscape =
2995 		(const SvxEscapement)((const SvxEscapementItem&)rHt).GetEnumValue();
2996 	const sal_Char *pStr = 0;
2997 	switch( eEscape )
2998 	{
2999 	case SVX_ESCAPEMENT_SUPERSCRIPT: pStr = OOO_STRING_SVTOOLS_HTML_superscript; break;
3000 	case SVX_ESCAPEMENT_SUBSCRIPT: pStr = OOO_STRING_SVTOOLS_HTML_subscript; break;
3001 	default:
3002 		;
3003 	}
3004 
3005 	if( pStr )
3006 	{
3007 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), pStr, rHTMLWrt.bTagOn );
3008 	}
3009 	else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
3010 	{
3011 		// vielleicht als CSS1-Attribut ?
3012 		OutCSS1_HintSpanTag( rWrt, rHt );
3013 	}
3014 
3015 	return rWrt;
3016 }
3017 
3018 
3019 
OutHTML_SwUnderline(Writer & rWrt,const SfxPoolItem & rHt)3020 static Writer& OutHTML_SwUnderline( Writer& rWrt, const SfxPoolItem& rHt )
3021 {
3022 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3023 	if( rHTMLWrt.bOutOpts )
3024 		return rWrt;
3025 
3026 	const FontUnderline eUnder = ((const SvxUnderlineItem&)rHt).GetLineStyle();
3027 	if( UNDERLINE_NONE != eUnder )
3028 	{
3029 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_underline, rHTMLWrt.bTagOn );
3030 	}
3031 	else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
3032 	{
3033 		// vielleicht als CSS1-Attribut ?
3034 		OutCSS1_HintSpanTag( rWrt, rHt );
3035 	}
3036 
3037 	return rWrt;
3038 }
3039 
3040 
OutHTML_SwFlyCnt(Writer & rWrt,const SfxPoolItem & rHt)3041 static Writer& OutHTML_SwFlyCnt( Writer& rWrt, const SfxPoolItem& rHt )
3042 {
3043 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
3044 	SwFmtFlyCnt& rFlyCnt = (SwFmtFlyCnt&)rHt;
3045 
3046 	const SwFrmFmt& rFmt = *rFlyCnt.GetFrmFmt();
3047 	const SdrObject *pSdrObj = 0;
3048 
3049 	SwHTMLFrmType eType =
3050 		(SwHTMLFrmType)rHTMLWrt.GuessFrmType( rFmt, pSdrObj );
3051 	sal_uInt8 nMode = aHTMLOutFrmAsCharTable[eType][rHTMLWrt.nExportMode];
3052 	rHTMLWrt.OutFrmFmt( nMode, rFmt, pSdrObj );
3053 	return rWrt;
3054 }
3055 
3056 
3057 // Das ist jetzt unser Blink-Item. Blinkend wird eingeschaltet, indem man
3058 // das Item auf sal_True setzt!
OutHTML_SwBlink(Writer & rWrt,const SfxPoolItem & rHt)3059 static Writer& OutHTML_SwBlink( Writer& rWrt, const SfxPoolItem& rHt )
3060 {
3061 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3062 	if( rHTMLWrt.bOutOpts || !rHTMLWrt.IsHTMLMode(HTMLMODE_BLINK) )
3063 		return rWrt;
3064 
3065 	if( ((const SvxBlinkItem&)rHt).GetValue() )
3066 	{
3067 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_blink, rHTMLWrt.bTagOn );
3068 	}
3069 	else if( rHTMLWrt.bCfgOutStyles && rHTMLWrt.bTxtAttr )
3070 	{
3071 		// vielleicht als CSS1-Attribut ?
3072 		OutCSS1_HintSpanTag( rWrt, rHt );
3073 	}
3074 
3075 	return rWrt;
3076 }
3077 
OutHTML_INetFmt(Writer & rWrt,const SwFmtINetFmt & rINetFmt,sal_Bool bOn)3078 Writer& OutHTML_INetFmt( Writer& rWrt, const SwFmtINetFmt& rINetFmt, sal_Bool bOn )
3079 {
3080 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3081 
3082 	String aURL( rINetFmt.GetValue() );
3083 	const SvxMacroTableDtor *pMacTable = rINetFmt.GetMacroTbl();
3084 	sal_Bool bEvents = pMacTable != 0 && pMacTable->Count() > 0;
3085 
3086 	// Gibt es ueberhaupt etwas auszugeben?
3087 	if( !aURL.Len() && !bEvents && !rINetFmt.GetName().Len() )
3088 		return rWrt;
3089 
3090 	// Tag aus? Dann nur ein </A> ausgeben.
3091 	if( !bOn )
3092 	{
3093 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_anchor, sal_False );
3094 		return rWrt;
3095 	}
3096 
3097 	ByteString sOut( '<' );
3098 	sOut += OOO_STRING_SVTOOLS_HTML_anchor;
3099 
3100 	sal_Bool bScriptDependent = sal_False;
3101 	{
3102 		const SwCharFmt* pFmt = rWrt.pDoc->GetCharFmtFromPool(
3103 				 RES_POOLCHR_INET_NORMAL );
3104 		SwHTMLFmtInfo aFmtInfo( pFmt );
3105 		sal_uInt16 nPos;
3106 		if( rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
3107 		{
3108 			bScriptDependent = rHTMLWrt.aChrFmtInfos[nPos]->bScriptDependent;
3109 		}
3110 	}
3111 	if( !bScriptDependent )
3112 	{
3113 		const SwCharFmt* pFmt = rWrt.pDoc->GetCharFmtFromPool(
3114 				 RES_POOLCHR_INET_VISIT );
3115 		SwHTMLFmtInfo aFmtInfo( pFmt );
3116 		sal_uInt16 nPos;
3117 		if( rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
3118 		{
3119 			bScriptDependent = rHTMLWrt.aChrFmtInfos[nPos]->bScriptDependent;
3120 		}
3121 	}
3122 
3123 	if( bScriptDependent )
3124 	{
3125 		((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"";
3126 		switch( rHTMLWrt.nCSS1Script )
3127 		{
3128 		case CSS1_OUTMODE_WESTERN:
3129 			sOut += "western";
3130 			break;
3131 		case CSS1_OUTMODE_CJK:
3132 			sOut += "cjk";
3133 			break;
3134 		case CSS1_OUTMODE_CTL:
3135 			sOut += "ctl";
3136 			break;
3137 		}
3138 		sOut += '\"';
3139 	}
3140 
3141 	rWrt.Strm() << sOut.GetBuffer();
3142 
3143 #define REL_HACK
3144 #ifdef REL_HACK
3145 	String sRel;
3146 #endif
3147 
3148 	if( aURL.Len() || bEvents )
3149 	{
3150 #ifdef REL_HACK
3151 		String sTmp( aURL );
3152 		sTmp.ToUpperAscii();
3153 		xub_StrLen nPos = sTmp.SearchAscii( "\" REL=" );
3154 		if( nPos!=STRING_NOTFOUND )
3155 		{
3156 			sRel = aURL.Copy( nPos+1 );
3157 			aURL.Erase( nPos );
3158 		}
3159 #endif
3160 		aURL.EraseLeadingChars().EraseTrailingChars();
3161 
3162 		((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\"";
3163 		rWrt.Strm() << sOut.GetBuffer();
3164 		rHTMLWrt.OutHyperlinkHRefValue( aURL );
3165 		sOut = '\"';
3166 	}
3167 	else
3168 		sOut.Erase();
3169 
3170 	if( rINetFmt.GetName().Len() )
3171 	{
3172 		((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\"";
3173 		rWrt.Strm() << sOut.GetBuffer();
3174 		HTMLOutFuncs::Out_String( rWrt.Strm(), rINetFmt.GetName(),
3175 								  rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
3176 		sOut = '\"';
3177 	}
3178 
3179 	const String& rTarget = rINetFmt.GetTargetFrame();
3180 	if( rTarget.Len() )
3181 	{
3182 		((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_target) += "=\"";
3183 		rWrt.Strm() << sOut.GetBuffer();
3184 		HTMLOutFuncs::Out_String( rWrt.Strm(), rTarget, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
3185 		sOut = '\"';
3186 	}
3187 
3188 #ifdef REL_HACK
3189 	if( sRel.Len() )
3190 		sOut += ByteString( sRel, RTL_TEXTENCODING_ASCII_US );
3191 #endif
3192 	if( sOut.Len() )
3193 		rWrt.Strm() << sOut.GetBuffer();
3194 
3195 	if( bEvents )
3196 		HTMLOutFuncs::Out_Events( rWrt.Strm(), *pMacTable, aAnchorEventTable,
3197 								  rHTMLWrt.bCfgStarBasic, rHTMLWrt.eDestEnc,
3198 							   	  &rHTMLWrt.aNonConvertableCharacters	);
3199 	rWrt.Strm() << ">";
3200 
3201 	return rWrt;
3202 }
3203 
OutHTML_SwFmtINetFmt(Writer & rWrt,const SfxPoolItem & rHt)3204 static Writer& OutHTML_SwFmtINetFmt( Writer& rWrt, const SfxPoolItem& rHt )
3205 {
3206 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3207 
3208 	if( rHTMLWrt.bOutOpts )
3209 		return rWrt;
3210 
3211 	const SwFmtINetFmt& rINetFmt = (const SwFmtINetFmt&)rHt;
3212 
3213 	if( rHTMLWrt.bTagOn )
3214 	{
3215 		// ggf. ein noch offenes Attribut voruebergehend beenden
3216 		if( rHTMLWrt.aINetFmts.Count() )
3217 		{
3218 			SwFmtINetFmt *pINetFmt =
3219 				rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
3220 			OutHTML_INetFmt( rWrt, *pINetFmt, sal_False );
3221 		}
3222 
3223 		// jetzt das neue aufmachen
3224 		OutHTML_INetFmt( rWrt, rINetFmt, sal_True );
3225 
3226 		// und merken
3227 		const SwFmtINetFmt *pINetFmt = new SwFmtINetFmt( rINetFmt );
3228 		rHTMLWrt.aINetFmts.C40_INSERT( SwFmtINetFmt, pINetFmt,
3229 									   rHTMLWrt.aINetFmts.Count() );
3230 	}
3231 	else
3232 	{
3233 		// das
3234 		OutHTML_INetFmt( rWrt, rINetFmt, sal_False );
3235 
3236 		ASSERT( rHTMLWrt.aINetFmts.Count(), "da fehlt doch ein URL-Attribut" );
3237 		if( rHTMLWrt.aINetFmts.Count() )
3238 		{
3239 			// das eigene Attribut vom Stack holen
3240 			SwFmtINetFmt *pINetFmt =
3241 				rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
3242 
3243 			rHTMLWrt.aINetFmts.Remove( rHTMLWrt.aINetFmts.Count()-1, 1 );
3244 			delete pINetFmt;
3245 		}
3246 
3247 		if( rHTMLWrt.aINetFmts.Count() )
3248 		{
3249 			// es ist noch ein Attribut auf dem Stack, das wieder geoeffnet
3250 			// werden muss
3251 			SwFmtINetFmt *pINetFmt =
3252 				rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
3253 			OutHTML_INetFmt( rWrt, *pINetFmt, sal_True );
3254 		}
3255 	}
3256 
3257 	return rWrt;
3258 }
3259 
OutHTML_SwTxtCharFmt(Writer & rWrt,const SfxPoolItem & rHt)3260 static Writer& OutHTML_SwTxtCharFmt( Writer& rWrt, const SfxPoolItem& rHt )
3261 {
3262 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
3263 	if( rHTMLWrt.bOutOpts )
3264 		return rWrt;
3265 
3266 	const SwFmtCharFmt& rChrFmt = (const SwFmtCharFmt&)rHt;
3267 	const SwCharFmt* pFmt = rChrFmt.GetCharFmt();
3268 
3269 	if( !pFmt )
3270 	{
3271 		return rWrt;
3272 	}
3273 
3274 	SwHTMLFmtInfo aFmtInfo( pFmt );
3275 	sal_uInt16 nPos;
3276 	if( !rHTMLWrt.aChrFmtInfos.Seek_Entry( &aFmtInfo, &nPos ) )
3277 		return rWrt;
3278 
3279 	const SwHTMLFmtInfo *pFmtInfo = rHTMLWrt.aChrFmtInfos[nPos];
3280 	ASSERT( pFmtInfo, "Wieso gint es keine Infos ueber die Zeichenvorlage?" );
3281 
3282 	if( rHTMLWrt.bTagOn )
3283 	{
3284 		ByteString sOut( '<' );
3285 		if( pFmtInfo->aToken.Len() > 0 )
3286 			sOut += pFmtInfo->aToken;
3287 		else
3288 			sOut += OOO_STRING_SVTOOLS_HTML_span;
3289 		if( rHTMLWrt.bCfgOutStyles &&
3290 			(pFmtInfo->aClass.Len() || pFmtInfo->bScriptDependent) )
3291 		{
3292 			((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"";
3293 			rWrt.Strm() << sOut.GetBuffer();
3294 			String aClass( pFmtInfo->aClass );
3295 			if( pFmtInfo->bScriptDependent )
3296 			{
3297 				if( aClass.Len() )
3298 				   aClass += '-';
3299 				switch( rHTMLWrt.nCSS1Script )
3300 				{
3301 				case CSS1_OUTMODE_WESTERN:
3302 					aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("western") );
3303 					break;
3304 				case CSS1_OUTMODE_CJK:
3305 					aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("cjk") );
3306 					break;
3307 				case CSS1_OUTMODE_CTL:
3308 					aClass.AppendAscii( RTL_CONSTASCII_STRINGPARAM("ctl") );
3309 					break;
3310 				}
3311 			}
3312 			HTMLOutFuncs::Out_String( rWrt.Strm(), aClass,
3313 						  		  	  rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
3314 			sOut = '\"';
3315 		}
3316 		sOut += '>';
3317 		rWrt.Strm() << sOut.GetBuffer();
3318 	}
3319 	else
3320 	{
3321 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
3322 				pFmtInfo->aToken.Len() ? pFmtInfo->aToken.GetBuffer()
3323 									   : OOO_STRING_SVTOOLS_HTML_span,
3324 				sal_False );
3325 	}
3326 
3327 	return rWrt;
3328 }
3329 
OutHTML_SvxAdjust(Writer & rWrt,const SfxPoolItem & rHt)3330 static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt )
3331 {
3332 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
3333 	if( !rHTMLWrt.bOutOpts || !rHTMLWrt.bTagOn )
3334 		return  rWrt;
3335 
3336 	SvxAdjustItem& rAdjust = (SvxAdjustItem&)rHt;
3337 	const sal_Char* pStr = 0;
3338 	switch( rAdjust.GetAdjust() )
3339 	{
3340 	case SVX_ADJUST_CENTER: pStr = OOO_STRING_SVTOOLS_HTML_AL_center; break;
3341 	case SVX_ADJUST_LEFT: pStr = OOO_STRING_SVTOOLS_HTML_AL_left; break;
3342 	case SVX_ADJUST_RIGHT: pStr = OOO_STRING_SVTOOLS_HTML_AL_right; break;
3343 	case SVX_ADJUST_BLOCK: pStr = OOO_STRING_SVTOOLS_HTML_AL_justify; break;
3344 	default:
3345 		;
3346 	}
3347 	if( pStr )
3348 	{
3349 		ByteString sOut( ' ' );
3350 		((sOut += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += pStr;
3351 		rWrt.Strm() << sOut.GetBuffer();
3352 	}
3353 
3354 	return rWrt;
3355 }
3356 
3357 /*
3358  * lege hier die Tabellen fuer die HTML-Funktions-Pointer auf
3359  * die Ausgabe-Funktionen an.
3360  * Es sind lokale Strukturen, die nur innerhalb der HTML-DLL
3361  * bekannt sein muessen.
3362  */
3363 
3364 
3365 SwAttrFnTab aHTMLAttrFnTab = {
3366 /* RES_CHRATR_CASEMAP	*/          OutHTML_CSS1Attr,
3367 /* RES_CHRATR_CHARSETCOLOR	*/      0,
3368 /* RES_CHRATR_COLOR	*/              OutHTML_SvxColor,
3369 /* RES_CHRATR_CONTOUR	*/          0,
3370 /* RES_CHRATR_CROSSEDOUT	*/      OutHTML_SwCrossedOut,
3371 /* RES_CHRATR_ESCAPEMENT	*/      OutHTML_SvxEscapement,
3372 /* RES_CHRATR_FONT	*/              OutHTML_SvxFont,
3373 /* RES_CHRATR_FONTSIZE	*/          OutHTML_SvxFontHeight,
3374 /* RES_CHRATR_KERNING	*/          OutHTML_CSS1Attr,
3375 /* RES_CHRATR_LANGUAGE	*/          OutHTML_SvxLanguage,
3376 /* RES_CHRATR_POSTURE	*/          OutHTML_SwPosture,
3377 /* RES_CHRATR_PROPORTIONALFONTSIZE*/0,
3378 /* RES_CHRATR_SHADOWED	*/          0,
3379 /* RES_CHRATR_UNDERLINE	*/          OutHTML_SwUnderline,
3380 /* RES_CHRATR_WEIGHT	*/          OutHTML_SwWeight,
3381 /* RES_CHRATR_WORDLINEMODE	*/      0,
3382 /* RES_CHRATR_AUTOKERN	*/          0,
3383 /* RES_CHRATR_BLINK	*/          	OutHTML_SwBlink,
3384 /* RES_CHRATR_NOHYPHEN	*/          0, // Neu: nicht trennen
3385 /* RES_CHRATR_NOLINEBREAK */        0, // Neu: nicht umbrechen
3386 /* RES_CHRATR_BACKGROUND */        	OutHTML_CSS1Attr, // Neu: Zeichenhintergrund
3387 /* RES_CHRATR_CJK_FONT */			OutHTML_SvxFont,
3388 /* RES_CHRATR_CJK_FONTSIZE */		OutHTML_SvxFontHeight,
3389 /* RES_CHRATR_CJK_LANGUAGE */		OutHTML_SvxLanguage,
3390 /* RES_CHRATR_CJK_POSTURE */		OutHTML_SwPosture,
3391 /* RES_CHRATR_CJK_WEIGHT */			OutHTML_SwWeight,
3392 /* RES_CHRATR_CTL_FONT */			OutHTML_SvxFont,
3393 /* RES_CHRATR_CTL_FONTSIZE */		OutHTML_SvxFontHeight,
3394 /* RES_CHRATR_CTL_LANGUAGE */		OutHTML_SvxLanguage,
3395 /* RES_CHRATR_CTL_POSTURE */		OutHTML_SwPosture,
3396 /* RES_CHRATR_CTL_WEIGHT */			OutHTML_SwWeight,
3397 /* RES_CHRATR_ROTATE */             0,
3398 /* RES_CHRATR_EMPHASIS_MARK */      0,
3399 /* RES_CHRATR_TWO_LINES */          0,
3400 /* RES_CHRATR_SCALEW */             0,
3401 /* RES_CHRATR_RELIEF */             0,
3402 /* RES_CHRATR_HIDDEN */             0,
3403 /* RES_CHRATR_OVERLINE */           OutHTML_CSS1Attr,
3404 /* RES_CHRATR_DUMMY1 */             0,
3405 /* RES_CHRATR_DUMMY2 */             0,
3406 //For i120935, Insert blank entry for RES_CHRATR_BIDITRL and RES_CHRATR_IDCTHINT, for keep the identical res order
3407 /*RES_CHRATR_BIDIRTL*/			0,
3408 /*RES_CHRATR_IDCTHINT*/		0,
3409 /* RES_TXTATR_REFMARK */            0,
3410 /* RES_TXTATR_TOXMARK */            0,
3411 /* RES_TXTATR_META */               0,
3412 /* RES_TXTATR_METAFIELD */          0,
3413 /* RES_TXTATR_AUTOFMT */            0,
3414 /* RES_TXTATR_INETFMT */            OutHTML_SwFmtINetFmt,
3415 /* RES_TXTATR_CHARFMT */            OutHTML_SwTxtCharFmt,
3416 /* RES_TXTATR_CJK_RUBY */           0,
3417 /* RES_TXTATR_UNKNOWN_CONTAINER */  0,
3418 /* RES_TXTATR_INPUTFIELD */         OutHTML_SwFmtFld,
3419 
3420 /* RES_TXTATR_FIELD */              OutHTML_SwFmtFld,
3421 /* RES_TXTATR_FLYCNT */             OutHTML_SwFlyCnt,
3422 /* RES_TXTATR_FTN */                OutHTML_SwFmtFtn,
3423 /* RES_TXTATR_ANNOTATION */         OutHTML_SwFmtFld,
3424 /* RES_TXTATR_DUMMY3 */             0,
3425 /* RES_TXTATR_DUMMY1 */             0, // Dummy:
3426 /* RES_TXTATR_DUMMY2 */             0, // Dummy:
3427 
3428 /* RES_PARATR_LINESPACING	*/      0,
3429 /* RES_PARATR_ADJUST	*/          OutHTML_SvxAdjust,
3430 /* RES_PARATR_SPLIT	*/				0,
3431 /* RES_PARATR_WIDOWS	*/          0,
3432 /* RES_PARATR_ORPHANS	*/          0,
3433 /* RES_PARATR_TABSTOP	*/          0,
3434 /* RES_PARATR_HYPHENZONE*/          0,
3435 /* RES_PARATR_DROP */				OutHTML_CSS1Attr,
3436 /* RES_PARATR_REGISTER */        	0, // neu:  Registerhaltigkeit
3437 /* RES_PARATR_NUMRULE */      	    0, // Dummy:
3438 /* RES_PARATR_SCRIPTSPACE */   	    0, // Dummy:
3439 /* RES_PARATR_HANGINGPUNCTUATION */	0, // Dummy:
3440 /* RES_PARATR_FORBIDDEN_RULES */    0, // new
3441 /* RES_PARATR_VERTALIGN */          0, // new
3442 /* RES_PARATR_SNAPTOGRID*/          0, // new
3443 /* RES_PARATR_CONNECT_TO_BORDER */  0, // new
3444 
3445 /* RES_PARATR_LIST_ID */            0, // new
3446 /* RES_PARATR_LIST_LEVEL */         0, // new
3447 /* RES_PARATR_LIST_ISRESTART */     0, // new
3448 /* RES_PARATR_LIST_RESTARTVALUE */  0, // new
3449 /* RES_PARATR_LIST_ISCOUNTED */     0, // new
3450 
3451 /* RES_FILL_ORDER	*/				0,
3452 /* RES_FRM_SIZE	*/					0,
3453 /* RES_PAPER_BIN	*/              0,
3454 /* RES_LR_SPACE	*/                  0,
3455 /* RES_UL_SPACE	*/                  0,
3456 /* RES_PAGEDESC */					0,
3457 /* RES_BREAK */						0,
3458 /* RES_CNTNT */						0,
3459 /* RES_HEADER */		   			0,
3460 /* RES_FOOTER */		   			0,
3461 /* RES_PRINT */						0,
3462 /* RES_OPAQUE */					0,
3463 /* RES_PROTECT */					0,
3464 /* RES_SURROUND */					0,
3465 /* RES_VERT_ORIENT */				0,
3466 /* RES_HORI_ORIENT */				0,
3467 /* RES_ANCHOR */					0,
3468 /* RES_BACKGROUND */				0,
3469 /* RES_BOX	*/                      0,
3470 /* RES_SHADOW */					0,
3471 /* RES_FRMMACRO */					0,
3472 /* RES_COL */						0,
3473 /* RES_KEEP */						0,
3474 /* RES_URL */        	    		0,
3475 /* RES_EDIT_IN_READONLY */        	0,
3476 /* RES_LAYOUT_SPLIT */ 	    		0,
3477 /* RES_FRMATR_DUMMY1 */        	    0, // Dummy:
3478 /* RES_FRMATR_DUMMY2 */        	    0, // Dummy:
3479 /* RES_AUTO_STYLE */        	    0, // Dummy:
3480 /* RES_FRMATR_DUMMY4 */        	    0, // Dummy:
3481 /* RES_FRMATR_DUMMY5 */        	    0, // Dummy:
3482 /* RES_FRMATR_DUMMY6 */        	    0, // Dummy:
3483 /* RES_FRMATR_DUMMY7 */        	    0, // Dummy:
3484 /* RES_FRMATR_DUMMY8 */        	    0, // Dummy:
3485 /* RES_FRMATR_DUMMY9 */        	    0, // Dummy:
3486 /* RES_FOLLOW_TEXT_FLOW */          0,
3487 /* RES_WRAP_INFLUENCE_ON_OBJPOS */  0,
3488 /* RES_FRMATR_DUMMY2 */             0, // Dummy:
3489 /* RES_AUTO_STYLE */                0, // Dummy:
3490 /* RES_FRMATR_DUMMY4 */             0, // Dummy:
3491 /* RES_FRMATR_DUMMY5 */             0, // Dummy:
3492 
3493 /* RES_GRFATR_MIRRORGRF	*/			0,
3494 /* RES_GRFATR_CROPGRF	*/			0,
3495 /* RES_GRFATR_ROTATION */			0,
3496 /* RES_GRFATR_LUMINANCE */			0,
3497 /* RES_GRFATR_CONTRAST */			0,
3498 /* RES_GRFATR_CHANNELR */			0,
3499 /* RES_GRFATR_CHANNELG */			0,
3500 /* RES_GRFATR_CHANNELB */			0,
3501 /* RES_GRFATR_GAMMA */				0,
3502 /* RES_GRFATR_INVERT */				0,
3503 /* RES_GRFATR_TRANSPARENCY */		0,
3504 /* RES_GRFATR_DRWAMODE */			0,
3505 /* RES_GRFATR_DUMMY1 */				0,
3506 /* RES_GRFATR_DUMMY2 */				0,
3507 /* RES_GRFATR_DUMMY3 */				0,
3508 /* RES_GRFATR_DUMMY4 */				0,
3509 /* RES_GRFATR_DUMMY5 */				0,
3510 
3511 /* RES_BOXATR_FORMAT */				0,
3512 /* RES_BOXATR_FORMULA */			0,
3513 /* RES_BOXATR_VALUE */				0
3514 };
3515