xref: /trunk/main/sw/source/filter/html/htmlctxt.cxx (revision efeef26f)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include "hintids.hxx"
29 #include <svl/itemiter.hxx>
30 #include <editeng/lrspitem.hxx>
31 #include <editeng/ulspitem.hxx>
32 #include <editeng/brshitem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <svtools/htmltokn.h>
35 
36 #include "doc.hxx"
37 #include "pam.hxx"
38 #include "ndtxt.hxx"
39 #include "shellio.hxx"
40 #include "paratr.hxx"
41 #include "htmlnum.hxx"
42 #include "css1kywd.hxx"
43 #include "swcss1.hxx"
44 #include "swhtml.hxx"
45 
46 using namespace ::com::sun::star;
47 
48 
49 /*  */
50 
51 
52 class _HTMLAttrContext_SaveDoc
53 {
54 	SwHTMLNumRuleInfo aNumRuleInfo;	// In Umgebung gueltige Numerierung
55 	SwPosition  *pPos;				// hierhin beim verlassen den
56 									// Kontexts zurueckgesprungen
57 	_HTMLAttrTable *pAttrTab;		// In Umgebung gueltige Attribute,
58 									// wenn Attributierung nicht
59 									// beibehalten werden soll.
60 
61 	sal_uInt16 nContextStMin;			// In Umgebung gueltige Stack-
62 									// Untergrenze, wenn der Stack
63 									// geschuetzt werden soll.
64 	sal_uInt16 nContextStAttrMin;		// In Umgebung gueltige Stack-
65 									// Untergrenze, wenn die Attribute
66 									// nicht beibehalten werden sollen.
67 
68 	sal_Bool bStripTrailingPara : 1;	// letzen Absatz entfernen?
69 	sal_Bool bKeepNumRules : 1;			// Numerierung beibehalten?
70 	sal_Bool bPopStack : 1;				// Stack-Elemente oberhalb des
71 									// zu schliessenden entfernen?
72 	sal_Bool bFixHeaderDist : 1;
73 	sal_Bool bFixFooterDist : 1;
74 
75 public:
76 
_HTMLAttrContext_SaveDoc()77 	_HTMLAttrContext_SaveDoc() :
78 		pPos( 0 ), pAttrTab( 0 ),
79 		nContextStMin( USHRT_MAX ), nContextStAttrMin( USHRT_MAX ),
80 		bStripTrailingPara( sal_False ), bKeepNumRules( sal_False ),
81 		bPopStack( sal_False ),
82 		bFixHeaderDist( sal_False ), bFixFooterDist( sal_False )
83 	{}
84 
~_HTMLAttrContext_SaveDoc()85 	~_HTMLAttrContext_SaveDoc() { delete pPos; delete pAttrTab; }
86 
87 	// Die Position gehoert uns, muss also angelegt und zerstoert werden
SetPos(const SwPosition & rPos)88 	void SetPos( const SwPosition& rPos ) { pPos = new SwPosition(rPos); }
GetPos() const89 	const SwPosition *GetPos() const { return pPos; }
90 
91 	// Der Index gehoert uns nicht. Kein Anlgen und Zerstoeren.
SetNumInfo(const SwHTMLNumRuleInfo & rInf)92 	void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { aNumRuleInfo.Set(rInf); }
GetNumInfo() const93 	const SwHTMLNumRuleInfo& GetNumInfo() const { return aNumRuleInfo; }
94 
95 	_HTMLAttrTable *GetAttrTab( sal_Bool bCreate= sal_False );
96 
SetContextStMin(sal_uInt16 nMin)97 	void SetContextStMin( sal_uInt16 nMin ) { nContextStMin = nMin; }
GetContextStMin() const98 	sal_uInt16 GetContextStMin() const { return nContextStMin; }
99 
SetContextStAttrMin(sal_uInt16 nMin)100 	void SetContextStAttrMin( sal_uInt16 nMin ) { nContextStAttrMin = nMin; }
GetContextStAttrMin() const101 	sal_uInt16 GetContextStAttrMin() const { return nContextStAttrMin; }
102 
SetStripTrailingPara(sal_Bool bSet)103 	void SetStripTrailingPara( sal_Bool bSet ) { bStripTrailingPara = bSet; }
GetStripTrailingPara() const104 	sal_Bool GetStripTrailingPara() const { return bStripTrailingPara; }
105 
SetKeepNumRules(sal_Bool bSet)106 	void SetKeepNumRules( sal_Bool bSet ) { bKeepNumRules = bSet; }
GetKeepNumRules() const107 	sal_Bool GetKeepNumRules() const { return bKeepNumRules; }
108 
SetFixHeaderDist(sal_Bool bSet)109 	void SetFixHeaderDist( sal_Bool bSet ) { bFixHeaderDist = bSet; }
GetFixHeaderDist() const110 	sal_Bool GetFixHeaderDist() const { return bFixHeaderDist; }
111 
SetFixFooterDist(sal_Bool bSet)112 	void SetFixFooterDist( sal_Bool bSet ) { bFixFooterDist = bSet; }
GetFixFooterDist() const113 	sal_Bool GetFixFooterDist() const { return bFixFooterDist; }
114 };
115 
GetAttrTab(sal_Bool bCreate)116 _HTMLAttrTable *_HTMLAttrContext_SaveDoc::GetAttrTab( sal_Bool bCreate )
117 {
118 	if( !pAttrTab && bCreate )
119 	{
120 		pAttrTab = new _HTMLAttrTable;
121 		memset( pAttrTab, 0, sizeof( _HTMLAttrTable ));
122 	}
123 	return pAttrTab;
124 }
125 
126 /*  */
127 
GetSaveDocContext(sal_Bool bCreate)128 _HTMLAttrContext_SaveDoc *_HTMLAttrContext::GetSaveDocContext( sal_Bool bCreate )
129 {
130 	if( !pSaveDocContext && bCreate )
131 		pSaveDocContext = new _HTMLAttrContext_SaveDoc;
132 
133 	return pSaveDocContext;
134 }
135 
ClearSaveDocContext()136 void _HTMLAttrContext::ClearSaveDocContext()
137 {
138 	delete pSaveDocContext;
139 	pSaveDocContext = 0;
140 }
141 
142 /*  */
143 
SplitAttrTab(const SwPosition & rNewPos)144 void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos )
145 {
146 	// Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
147 	// koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
148 	ASSERT( !aParaAttrs.Count(),
149 		"Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
150 	if( aParaAttrs.Count() )
151 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
152 
153 	const SwNodeIndex* pOldEndPara = &pPam->GetPoint()->nNode;
154 	xub_StrLen nOldEndCnt = pPam->GetPoint()->nContent.GetIndex();
155 
156 	const SwNodeIndex& rNewSttPara = rNewPos.nNode;
157 	xub_StrLen nNewSttCnt = rNewPos.nContent.GetIndex();
158 
159 	sal_Bool bMoveBack = sal_False;
160 
161 	// alle noch offenen Attribute beenden und hinter der Tabelle
162 	// neu aufspannen
163 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
164 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
165 			nCnt--; ++pTbl )
166 	{
167 		_HTMLAttr *pAttr = *pTbl;
168 		while( pAttr )
169 		{
170 			_HTMLAttr *pNext = pAttr->GetNext();
171 			_HTMLAttr *pPrev = pAttr->GetPrev();
172 
173 			sal_uInt16 nWhich = pAttr->pItem->Which();
174 			if( !nOldEndCnt && RES_PARATR_BEGIN <= nWhich &&
175 				pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() )
176 			{
177 				// Das Attribut muss eine Content-Position weiter vorne
178 				// beendet werden
179 				if( !bMoveBack )
180 				{
181 					bMoveBack = pPam->Move( fnMoveBackward );
182 					nOldEndCnt = pPam->GetPoint()->nContent.GetIndex();
183 				}
184 			}
185 			else if( bMoveBack )
186 			{
187 				pPam->Move( fnMoveForward );
188 				nOldEndCnt = pPam->GetPoint()->nContent.GetIndex();
189 			}
190 
191 			if( (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
192 				pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() ||
193 				(pAttr->GetSttPara() == *pOldEndPara &&
194 				 pAttr->GetSttCnt() != nOldEndCnt) )
195 			{
196 				// Das Attribut muss gesetzt werden. Da wir
197 				// das Original noch brauchen, weil Zeiger auf das Attribut
198 				// noch in den Kontexten existieren, muessen wir es clonen.
199 				// Die Next-Liste geht dabei verloren, aber die
200 				// Previous-Liste bleibt erhalten
201 				_HTMLAttr *pSetAttr = pAttr->Clone( *pOldEndPara, nOldEndCnt );
202 
203 				if( pNext )
204 					pNext->InsertPrev( pSetAttr );
205 				else
206 				{
207 					sal_uInt16 nTmp =
208 						pSetAttr->bInsAtStart ? 0 : aSetAttrTab.Count();
209 					aSetAttrTab.Insert( pSetAttr, nTmp );
210 				}
211 			}
212 			else if( pPrev )
213 			{
214 				// Wenn das Attribut nicht gesetzt vor der Tabelle
215 				// gesetzt werden muss, muessen der Previous-Attribute
216 				// trotzdem gesetzt werden.
217 				if( pNext )
218 					pNext->InsertPrev( pPrev );
219 				else
220 				{
221 					sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
222 					aSetAttrTab.Insert( pPrev, nTmp );
223 				}
224 			}
225 
226 			// den Start des Attributs neu setzen
227 			pAttr->nSttPara = rNewSttPara;
228 			pAttr->nEndPara = rNewSttPara;
229 			pAttr->nSttCntnt = nNewSttCnt;
230 			pAttr->nEndCntnt = nNewSttCnt;
231 			pAttr->pPrev = 0;
232 
233 			pAttr = pNext;
234 		}
235 	}
236 
237 	if( bMoveBack )
238 		pPam->Move( fnMoveForward );
239 
240 }
241 
SaveDocContext(_HTMLAttrContext * pCntxt,sal_uInt16 nFlags,const SwPosition * pNewPos)242 void SwHTMLParser::SaveDocContext( _HTMLAttrContext *pCntxt,
243 								   sal_uInt16 nFlags,
244 								   const SwPosition *pNewPos )
245 {
246 	_HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext( sal_True );
247 	pSave->SetStripTrailingPara( (HTML_CNTXT_STRIP_PARA & nFlags) != 0 );
248 	pSave->SetKeepNumRules( (HTML_CNTXT_KEEP_NUMRULE & nFlags) != 0 );
249 	pSave->SetFixHeaderDist( (HTML_CNTXT_HEADER_DIST & nFlags) != 0 );
250 	pSave->SetFixFooterDist( (HTML_CNTXT_FOOTER_DIST & nFlags) != 0 );
251 
252 	if( pNewPos )
253 	{
254 		// Wenn der PaM an eine andere Position gesetzt wird, muss
255 		// die Numerierung gerettet werden..
256 		if( !pSave->GetKeepNumRules() )
257 		{
258 			// Die Numerierung soll nicht beibehalten werden. Also muss
259 			// der aktuelle Zustand gerettet und die Numerierung
260 			// anschliessend ausgeschaltet werden.
261 			pSave->SetNumInfo( GetNumInfo() );
262 			GetNumInfo().Clear();
263 		}
264 
265 		if( (HTML_CNTXT_KEEP_ATTRS & nFlags) != 0 )
266 		{
267 			// Attribute an aktueller Position beenden und an neuer neu anfangen
268 			SplitAttrTab( *pNewPos );
269 		}
270 		else
271 		{
272 			_HTMLAttrTable *pSaveAttrTab = pSave->GetAttrTab( sal_True );
273 			SaveAttrTab( *pSaveAttrTab );
274 		}
275 
276 
277 		pSave->SetPos( *pPam->GetPoint() );
278 		*pPam->GetPoint() = *pNewPos;
279 	}
280 
281 	// Mit dem Setzen von nContextStMin koennen automatisch auch
282 	// keine gerade offenen Listen (DL/OL/UL) mehr beendet werden.
283 	if( (HTML_CNTXT_PROTECT_STACK & nFlags) != 0  )
284 	{
285 		pSave->SetContextStMin( nContextStMin );
286 		nContextStMin = aContexts.Count();
287 
288 		if( (HTML_CNTXT_KEEP_ATTRS & nFlags) == 0 )
289 		{
290 			pSave->SetContextStAttrMin( nContextStAttrMin );
291 			nContextStAttrMin = aContexts.Count();
292 		}
293 	}
294 }
295 
RestoreDocContext(_HTMLAttrContext * pCntxt)296 void SwHTMLParser::RestoreDocContext( _HTMLAttrContext *pCntxt )
297 {
298 	_HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext();
299 	if( !pSave )
300 		return;
301 
302 	if( pSave->GetStripTrailingPara() )
303 		StripTrailingPara();
304 
305 	if( pSave->GetPos() )
306 	{
307 		if( pSave->GetFixHeaderDist() || pSave->GetFixFooterDist() )
308 			FixHeaderFooterDistance( pSave->GetFixHeaderDist(),
309 									 pSave->GetPos() );
310 
311 		_HTMLAttrTable *pSaveAttrTab = pSave->GetAttrTab();
312 		if( !pSaveAttrTab )
313 		{
314 			// Attribute an aktueller Position beenden und an alter neu
315 			// anfangen.
316 			SplitAttrTab( *pSave->GetPos() );
317 		}
318 		else
319 		{
320 			RestoreAttrTab( *pSaveAttrTab );
321 		}
322 
323 		*pPam->GetPoint() = *pSave->GetPos();
324 
325 		// Die bisherigen Attribute koennen wir schonmal setzen.
326 		SetAttr();
327 	}
328 
329 	if( USHRT_MAX != pSave->GetContextStMin() )
330 	{
331 		nContextStMin = pSave->GetContextStMin();
332 		if( USHRT_MAX != pSave->GetContextStAttrMin() )
333 			nContextStAttrMin = pSave->GetContextStAttrMin();
334 	}
335 
336 	if( !pSave->GetKeepNumRules() )
337 	{
338 		// Die bisherige gemerkte Numerierung wieder setzen
339 		GetNumInfo().Set( pSave->GetNumInfo() );
340 	}
341 
342 	pCntxt->ClearSaveDocContext();
343 }
344 
345 /*  */
346 
EndContext(_HTMLAttrContext * pContext)347 void SwHTMLParser::EndContext( _HTMLAttrContext *pContext )
348 {
349 	if( pContext->GetPopStack() )
350 	{
351 		// Alle noch offenen Kontexte beenden. Der eigene
352 		// Kontext muss bereits geloscht sein!
353 		while( aContexts.Count() > nContextStMin )
354 		{
355 			_HTMLAttrContext *pCntxt = PopContext();
356 			ASSERT( pCntxt != pContext,
357 					"Kontext noch im Stack" );
358 			if( pCntxt == pContext )
359 				break;
360 
361 			EndContext( pCntxt );
362 			delete pCntxt;
363 		}
364 	}
365 
366 	// Alle noch offenen Attribute beenden
367 	if( pContext->HasAttrs() )
368 		EndContextAttrs( pContext );
369 
370 	// Falls ein Bereich geoeffnet wurde, den verlassen. Da Bereiche
371 	// auch innerhalb von absolut positionierten Objekten angelegt werden,
372 	// muss das passieren, bever ein alter Dokument-Kontext restauriert wird.
373 	if( pContext->GetSpansSection() )
374 		EndSection();
375 
376 	// Rahmen und sonstige Sonderbereiche verlassen.
377 	if( pContext->HasSaveDocContext() )
378 		RestoreDocContext( pContext );
379 
380 	// Ggf. noch einen Ansatz-Umbruch einfuegen
381 	if( AM_NONE != pContext->GetAppendMode() &&
382 		pPam->GetPoint()->nContent.GetIndex() )
383 		AppendTxtNode( pContext->GetAppendMode() );
384 
385 	// PRE-/LISTING- und XMP-Umgebungen wieder starten
386 	if( pContext->IsFinishPREListingXMP() )
387 		FinishPREListingXMP();
388 
389 	if( pContext->IsRestartPRE() )
390 		StartPRE();
391 
392 	if( pContext->IsRestartXMP() )
393 		StartXMP();
394 
395 	if( pContext->IsRestartListing() )
396 		StartListing();
397 }
398 
ClearContext(_HTMLAttrContext * pContext)399 void SwHTMLParser::ClearContext( _HTMLAttrContext *pContext )
400 {
401 	_HTMLAttrs &rAttrs = pContext->GetAttrs();
402 	for( sal_uInt16 i=0; i<rAttrs.Count(); i++ )
403 	{
404 		// einfaches Loeschen reicht hier nicht, weil das
405 		// Attribut auch aus seiner Liste ausgetragen werden
406 		// muss. Theoretisch koennt man natuerlich auch die Liste
407 		// und die Attribute getrennt loeschen, aber wenn man
408 		// dann was falsch gemacht hat, sieht es uebel aus.
409 		DeleteAttr( rAttrs[i] );
410 	}
411 
412 	ASSERT( !pContext->GetSpansSection(),
413 			"Bereich kann nicht mehr verlassen werden" );
414 
415 	ASSERT( !pContext->HasSaveDocContext(),
416 			"Rahmen kann nicht mehr verlassen werden" );
417 
418 	// PRE-/LISTING- und XMP-Umgebungen wieder starten
419 	if( pContext->IsFinishPREListingXMP() )
420 		FinishPREListingXMP();
421 
422 	if( pContext->IsRestartPRE() )
423 		StartPRE();
424 
425 	if( pContext->IsRestartXMP() )
426 		StartXMP();
427 
428 	if( pContext->IsRestartListing() )
429 		StartListing();
430 }
431 
432 /*  */
433 
DoPositioning(SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,_HTMLAttrContext * pContext)434 sal_Bool SwHTMLParser::DoPositioning( SfxItemSet &rItemSet,
435 								  SvxCSS1PropertyInfo &rPropInfo,
436 								  _HTMLAttrContext *pContext )
437 {
438 	sal_Bool bRet = sal_False;
439 
440 	// Unter folgenden Umstaenden wird jetzt ein Rahmen aufgemacht:
441 	// - das Tag wird absolut positioniert und left/top sind beide
442 	//   gegeben und enthalten auch keine %-Angabe, oder
443 	// - das Tag soll fliessen, und
444 	// - es wurde eine Breite angegeben (in beiden Faellen noetig)
445 	if( SwCSS1Parser::MayBePositioned( rPropInfo ) )
446 	{
447 		SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
448 								RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
449 		if( !IsNewDoc() )
450 			Reader::ResetFrmFmtAttrs(aFrmItemSet );
451 
452 		// Ausrichtung setzen
453         SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, rItemSet, rPropInfo,
454 								aFrmItemSet );
455 
456 		// Groesse setzen
457 		SetVarSize( rItemSet, rPropInfo, aFrmItemSet );
458 
459 		// Abstaende setzen
460 		SetSpace( Size(0,0), rItemSet, rPropInfo, aFrmItemSet );
461 
462 		// Sonstige CSS1-Attribute Setzen
463 		SetFrmFmtAttrs( rItemSet, rPropInfo,
464 						HTML_FF_BOX|HTML_FF_PADDING|HTML_FF_BACKGROUND|HTML_FF_DIRECTION,
465 						aFrmItemSet );
466 
467 		InsertFlyFrame( aFrmItemSet, pContext, rPropInfo.aId,
468 						CONTEXT_FLAGS_ABSPOS );
469 		pContext->SetPopStack( sal_True );
470 		rPropInfo.aId.Erase();
471 		bRet = sal_True;
472 	}
473 
474 	return bRet;
475 }
476 
CreateContainer(const String & rClass,SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,_HTMLAttrContext * pContext)477 sal_Bool SwHTMLParser::CreateContainer( const String& rClass,
478 									SfxItemSet &rItemSet,
479 									SvxCSS1PropertyInfo &rPropInfo,
480 									_HTMLAttrContext *pContext )
481 {
482 	sal_Bool bRet = sal_False;
483 	if( rClass.EqualsIgnoreCaseAscii(sCSS1_class_abs_pos) &&
484 		pCSS1Parser->MayBePositioned( rPropInfo ) )
485 	{
486 		// Container-Klasse
487 		SfxItemSet *pFrmItemSet = pContext->GetFrmItemSet( pDoc );
488 		if( !IsNewDoc() )
489 			Reader::ResetFrmFmtAttrs( *pFrmItemSet );
490 
491         SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE,
492 								rItemSet, rPropInfo, *pFrmItemSet );
493 		Size aDummy(0,0);
494 		SetFixSize( aDummy, aDummy, sal_False, sal_False, rItemSet, rPropInfo,
495 					*pFrmItemSet );
496 		SetSpace( aDummy, rItemSet, rPropInfo, *pFrmItemSet );
497 		SetFrmFmtAttrs( rItemSet, rPropInfo, HTML_FF_BOX|HTML_FF_BACKGROUND|HTML_FF_DIRECTION,
498 						*pFrmItemSet );
499 
500 		bRet = sal_True;
501 	}
502 
503 	return bRet;
504 }
505 
506 /*  */
507 
InsertAttrs(SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,_HTMLAttrContext * pContext,sal_Bool bCharLvl)508 void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet,
509 								SvxCSS1PropertyInfo &rPropInfo,
510 								_HTMLAttrContext *pContext,
511 								sal_Bool bCharLvl )
512 {
513 	// Ein DropCap-Attribut basteln, wenn auf Zeichen-Ebene vor dem
514 	// ersten Zeichen ein float: left vorkommt
515 	if( bCharLvl && !pPam->GetPoint()->nContent.GetIndex() &&
516 		SVX_ADJUST_LEFT == rPropInfo.eFloat )
517 	{
518 		SwFmtDrop aDrop;
519 		aDrop.GetChars() = 1;
520 
521 		pCSS1Parser->FillDropCap( aDrop, rItemSet );
522 
523 		// Nur wenn das Initial auch ueber mehrere Zeilen geht, wird das
524 		// DropCap-Attribut gesetzt. Sonst setzten wir die Attribute hart.
525 		if( aDrop.GetLines() > 1 )
526 		{
527 			NewAttr( &aAttrTab.pDropCap, aDrop );
528 
529 			_HTMLAttrs &rAttrs = pContext->GetAttrs();
530 			rAttrs.Insert( aAttrTab.pDropCap, rAttrs.Count() );
531 
532 			return;
533 		}
534 	}
535 
536 // Feature: PrintExt
537 	if( !bCharLvl )
538 		pCSS1Parser->SetFmtBreak( rItemSet, rPropInfo );
539 // /Feature: PrintExt
540 
541 	ASSERT( aContexts.Count() <= nContextStAttrMin ||
542 			aContexts[aContexts.Count()-1] != pContext,
543 			"SwHTMLParser::InsertAttrs: Kontext doch schon auf dem Stack" );
544 
545 	SfxItemIter aIter( rItemSet );
546 
547 	const SfxPoolItem *pItem = aIter.FirstItem();
548 	while( pItem )
549 	{
550 		_HTMLAttr **ppAttr = 0;
551 
552 		switch( pItem->Which() )
553 		{
554 		case RES_LR_SPACE:
555 			{
556 				// Absatz-Einzuege muessen addiert werden und werden immer
557 				// nur absatzweise gesetzt (fuer den ersten Absatz hier,
558 				// fuer alle folgenden in SetTxtCollAttrs)
559 
560 				const SvxLRSpaceItem *pLRItem =
561 					(const SvxLRSpaceItem *)pItem;
562 
563 				// die bisherigen Absatz-Abstaende holen (ohne die vom
564 				// obersten Kontext, denn den veraendern wir ja gerade) ...
565 				sal_uInt16 nOldLeft = 0, nOldRight = 0;
566 				short nOldIndent = 0;
567 				sal_Bool bIgnoreTop = aContexts.Count() > nContextStMin &&
568 								  aContexts[aContexts.Count()-1] == pContext;
569 				GetMarginsFromContext( nOldLeft, nOldRight, nOldIndent,
570 									   bIgnoreTop  );
571 
572 
573 				// und noch die aktuell gueltigen
574 				sal_uInt16 nLeft = nOldLeft, nRight = nOldRight;
575 				short nIndent = nOldIndent;
576 				pContext->GetMargins( nLeft, nRight, nIndent );
577 
578 				// ... und die neuen Abstaende zu den alten addieren
579 				// Hier werden nicht die aus dem Item genommen, sondern die
580 				// extra gemerkten, weil die auch negativ sein koennen. Die
581 				// Abfrage ueber das Item funktioniert aber trotzdem, denn
582 				// fuer negative Werte wird das Item (mit Wert 0) auch
583 				// eingefuegt.
584 				if( rPropInfo.bLeftMargin )
585 				{
586 					ASSERT( rPropInfo.nLeftMargin < 0 ||
587 							rPropInfo.nLeftMargin == pLRItem->GetTxtLeft(),
588 							"linker Abstand stimmt nicht mit Item ueberein" );
589 					if( rPropInfo.nLeftMargin < 0 &&
590 						-rPropInfo.nLeftMargin > nOldLeft )
591 						nLeft = 0;
592 					else
593                         nLeft = nOldLeft + static_cast< sal_uInt16 >(rPropInfo.nLeftMargin);
594 				}
595 				if( rPropInfo.bRightMargin )
596 				{
597 					ASSERT( rPropInfo.nRightMargin < 0 ||
598 							rPropInfo.nRightMargin == pLRItem->GetRight(),
599 							"rechter Abstand stimmt nicht mit Item ueberein" );
600 					if( rPropInfo.nRightMargin < 0 &&
601 						-rPropInfo.nRightMargin > nOldRight )
602 						nRight = 0;
603 					else
604                         nRight = nOldRight + static_cast< sal_uInt16 >(rPropInfo.nRightMargin);
605 				}
606 				if( rPropInfo.bTextIndent )
607 					nIndent = pLRItem->GetTxtFirstLineOfst();
608 
609 				// und die Werte fuer nachfolgende Absaetze merken
610 				pContext->SetMargins( nLeft, nRight, nIndent );
611 
612 				// das Attribut noch am aktuellen Absatz setzen
613 				SvxLRSpaceItem aLRItem( *pLRItem );
614 				aLRItem.SetTxtFirstLineOfst( nIndent );
615 				aLRItem.SetTxtLeft( nLeft );
616 				aLRItem.SetRight( nRight );
617 				NewAttr( &aAttrTab.pLRSpace, aLRItem );
618 				EndAttr( aAttrTab.pLRSpace, 0, sal_False );
619 			}
620 			break;
621 
622 		case RES_UL_SPACE:
623 			if( !rPropInfo.bTopMargin || !rPropInfo.bBottomMargin )
624 			{
625 				sal_uInt16 nUpper = 0, nLower = 0;
626 				GetULSpaceFromContext( nUpper, nLower );
627 				SvxULSpaceItem aULSpace( *((const SvxULSpaceItem *)pItem) );
628 				if( !rPropInfo.bTopMargin )
629 					aULSpace.SetUpper( nUpper );
630 				if( !rPropInfo.bBottomMargin )
631 					aULSpace.SetLower( nLower );
632 
633 				NewAttr( &aAttrTab.pULSpace, aULSpace );
634 
635 				// ... und noch die Kontext-Information speichern
636 				_HTMLAttrs &rAttrs = pContext->GetAttrs();
637 				rAttrs.Insert( aAttrTab.pULSpace, rAttrs.Count() );
638 
639 				pContext->SetULSpace( aULSpace.GetUpper(), aULSpace.GetLower() );
640 			}
641 			else
642 			{
643 				ppAttr = &aAttrTab.pULSpace;
644 			}
645 			break;
646 		case RES_CHRATR_FONTSIZE:
647 			// es werden keine Attribute mit %-Angaben gesetzt
648 			if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 )
649 				ppAttr = &aAttrTab.pFontHeight;
650 			break;
651 		case RES_CHRATR_CJK_FONTSIZE:
652 			// es werden keine Attribute mit %-Angaben gesetzt
653 			if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 )
654 				ppAttr = &aAttrTab.pFontHeightCJK;
655 			break;
656 		case RES_CHRATR_CTL_FONTSIZE:
657 			// es werden keine Attribute mit %-Angaben gesetzt
658 			if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 )
659 				ppAttr = &aAttrTab.pFontHeightCTL;
660 			break;
661 
662 		case RES_BACKGROUND:
663 			if( bCharLvl )
664 			{
665 				// das Frame-Attr ggf. in ein Char-Attr umwandeln
666 				SvxBrushItem aBrushItem( *(const SvxBrushItem *)pItem );
667 				aBrushItem.SetWhich( RES_CHRATR_BACKGROUND );
668 
669 				// Das Attribut setzen ...
670 				NewAttr( &aAttrTab.pCharBrush, aBrushItem );
671 
672 				// ... und noch die Kontext-Information speichern
673 				_HTMLAttrs &rAttrs = pContext->GetAttrs();
674 				rAttrs.Insert( aAttrTab.pCharBrush, rAttrs.Count() );
675 			}
676 			else if( pContext->GetToken() != HTML_TABLEHEADER_ON &&
677 					 pContext->GetToken() != HTML_TABLEDATA_ON )
678 			{
679 				ppAttr = &aAttrTab.pBrush;
680 			}
681 			break;
682 
683 		default:
684 			// den zu dem Item gehoehrenden Tabellen-Eintrag ermitteln ...
685 			ppAttr = GetAttrTabEntry( pItem->Which() );
686 			break;
687 		}
688 
689 		if( ppAttr )
690 		{
691 			// Das Attribut setzen ...
692 			NewAttr( ppAttr, *pItem );
693 
694 			// ... und noch die Kontext-Information speichern
695 			_HTMLAttrs &rAttrs = pContext->GetAttrs();
696 			rAttrs.Insert( *ppAttr, rAttrs.Count() );
697 		}
698 
699 		// auf zum naechsten Item
700 		pItem = aIter.NextItem();
701 	}
702 
703 	if( rPropInfo.aId.Len() )
704 		InsertBookmark( rPropInfo.aId );
705 }
706 
InsertAttr(_HTMLAttr ** ppAttr,const SfxPoolItem & rItem,_HTMLAttrContext * pCntxt)707 void SwHTMLParser::InsertAttr( _HTMLAttr **ppAttr, const SfxPoolItem & rItem,
708 							   _HTMLAttrContext *pCntxt )
709 {
710 	if( !ppAttr )
711 	{
712 		ppAttr = GetAttrTabEntry( rItem.Which() );
713 		if( !ppAttr )
714 			return;
715 	}
716 
717 	// das Attribut setzen
718 	NewAttr( ppAttr, rItem );
719 
720 	// und im Kontext merken
721 	_HTMLAttrs &rAttrs = pCntxt->GetAttrs();
722 	rAttrs.Insert( *ppAttr, rAttrs.Count() );
723 }
724 
SplitPREListingXMP(_HTMLAttrContext * pCntxt)725 void SwHTMLParser::SplitPREListingXMP( _HTMLAttrContext *pCntxt )
726 {
727 	// PRE/Listing/XMP soll beim beenden des Kontexts beendet werden.
728 	pCntxt->SetFinishPREListingXMP( sal_True );
729 
730 	// Und die jetzt gueltigen Flags sollen wieder gesetzt werden.
731 	if( IsReadPRE() )
732 		pCntxt->SetRestartPRE( sal_True );
733 	if( IsReadXMP() )
734 		pCntxt->SetRestartXMP( sal_True );
735 	if( IsReadListing() )
736 		pCntxt->SetRestartListing( sal_True );
737 
738 	// PRE/Listing/XMP wird auuserdem sofort beendet
739 	FinishPREListingXMP();
740 }
741 
GetFrmItemSet(SwDoc * pCreateDoc)742 SfxItemSet *_HTMLAttrContext::GetFrmItemSet( SwDoc *pCreateDoc )
743 {
744 	if( !pFrmItemSet && pCreateDoc )
745 		pFrmItemSet = new SfxItemSet( pCreateDoc->GetAttrPool(),
746 						RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
747 	return pFrmItemSet;
748 }
749