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