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