xref: /aoo41x/main/sw/source/filter/html/swhtml.cxx (revision dec99bbd)
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 <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
29 #include <com/sun/star/document/XDocumentProperties.hpp>
30 #include <com/sun/star/i18n/ScriptType.hpp>
31 #include <sfx2/sfx.hrc>
32 #include <svx/svxids.hrc>
33 #ifdef DBG_UTIL
34 #include <stdlib.h>
35 #endif
36 #include <hintids.hxx>
37 
38 #define _SVSTDARR_STRINGS
39 #include <svl/svstdarr.hxx>
40 #include <svl/stritem.hxx>
41 #include <svtools/imap.hxx>
42 #include <svtools/htmltokn.h>
43 #include <svtools/htmlkywd.hxx>
44 #include <svtools/ctrltool.hxx>
45 #include <unotools/pathoptions.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/wrkwin.hxx>
48 #include <sfx2/fcontnr.hxx>
49 #include <sfx2/docfile.hxx>
50 
51 #include <svtools/htmlcfg.hxx>
52 #include <sfx2/linkmgr.hxx>
53 #include <editeng/kernitem.hxx>
54 #include <editeng/boxitem.hxx>
55 #include <editeng/fhgtitem.hxx>
56 #include <editeng/brkitem.hxx>
57 #include <editeng/postitem.hxx>
58 #include <editeng/wghtitem.hxx>
59 #include <editeng/crsditem.hxx>
60 #include <editeng/udlnitem.hxx>
61 #include <editeng/escpitem.hxx>
62 #include <editeng/blnkitem.hxx>
63 #include <editeng/ulspitem.hxx>
64 #include <editeng/colritem.hxx>
65 #include <editeng/fontitem.hxx>
66 #include <editeng/adjitem.hxx>
67 #include <editeng/lrspitem.hxx>
68 #include <editeng/protitem.hxx>
69 #include <editeng/flstitem.hxx>
70 
71 
72 #include <frmatr.hxx>
73 #include <charatr.hxx>
74 #include <fmtfld.hxx>
75 #include <fmtpdsc.hxx>
76 #include <txtfld.hxx>
77 #include <fmtanchr.hxx>
78 #include <fmtsrnd.hxx>
79 #include <fmtfsize.hxx>
80 #include <fmtclds.hxx>
81 #include <fchrfmt.hxx>
82 #include <fmtinfmt.hxx>
83 #include <docary.hxx>
84 #include <docstat.hxx>
85 #include <doc.hxx>
86 #include <IDocumentUndoRedo.hxx>
87 #include <pam.hxx>
88 #include <ndtxt.hxx>
89 #include <mdiexp.hxx>           // ...Percent()
90 #include <expfld.hxx>
91 #include <poolfmt.hxx>
92 #include <pagedesc.hxx>
93 #include <IMark.hxx>		// fuer SwBookmark ...
94 #include <docsh.hxx>
95 #include <editsh.hxx>		// fuer Start/EndAction
96 #include <docufld.hxx>
97 #include <swcss1.hxx>
98 #include <htmlvsh.hxx>
99 #include <fltini.hxx>
100 #include <htmltbl.hxx>
101 #include <htmlnum.hxx>
102 #include <swhtml.hxx>
103 #include <linkenum.hxx>
104 #include <breakit.hxx>
105 #include <SwAppletImpl.hxx>
106 
107 #include <sfx2/viewfrm.hxx>
108 
109 #include <statstr.hrc>          // ResId fuer Statusleiste
110 #include <swerror.h>
111 
112 #define FONTSIZE_MASK 			7
113 #define FONTCOLOR_MASK			(1<<15)
114 #define FONT_MASK				(1<<14)
115 
116 #define HTML_ESC_PROP 80
117 #define HTML_ESC_SUPER DFLT_ESC_SUPER
118 #define HTML_ESC_SUB DFLT_ESC_SUB
119 
120 #define HTML_SPTYPE_NONE 0
121 #define HTML_SPTYPE_BLOCK 1
122 #define HTML_SPTYPE_HORI 2
123 #define HTML_SPTYPE_VERT 3
124 
125 #ifndef TOOLS_CONSTASCII_STRINGPARAM
126 #define TOOLS_CONSTASCII_STRINGPARAM( constAsciiStr ) constAsciiStr, sizeof( constAsciiStr )-1
127 #endif
128 
129 using namespace ::com::sun::star;
130 
131 // <P ALIGN=xxx>, <Hn ALIGN=xxx>, <TD ALIGN=xxx> usw.
132 HTMLOptionEnum __FAR_DATA aHTMLPAlignTable[] =
133 {
134 	{ OOO_STRING_SVTOOLS_HTML_AL_left,	SVX_ADJUST_LEFT		},
135 	{ OOO_STRING_SVTOOLS_HTML_AL_center,	SVX_ADJUST_CENTER	},
136 	{ OOO_STRING_SVTOOLS_HTML_AL_middle,	SVX_ADJUST_CENTER	}, // Netscape
137 	{ OOO_STRING_SVTOOLS_HTML_AL_right,	SVX_ADJUST_RIGHT	},
138 	{ OOO_STRING_SVTOOLS_HTML_AL_justify,	SVX_ADJUST_BLOCK	},
139 	{ OOO_STRING_SVTOOLS_HTML_AL_char,	SVX_ADJUST_LEFT		},
140 	{ 0,				0					}
141 };
142 
143 // <SPACER TYPE=...>
144 static HTMLOptionEnum __FAR_DATA aHTMLSpacerTypeTable[] =
145 {
146 	{ OOO_STRING_SVTOOLS_HTML_SPTYPE_block,		HTML_SPTYPE_BLOCK		},
147 	{ OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal,	HTML_SPTYPE_HORI		},
148 	{ OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical,	HTML_SPTYPE_VERT		},
149 	{ 0,					0						}
150 };
151 
SV_IMPL_PTRARR(_HTMLAttrs,_HTMLAttrPtr)152 SV_IMPL_PTRARR( _HTMLAttrs, _HTMLAttrPtr )
153 
154 HTMLReader::HTMLReader()
155 {
156 	bTmplBrowseMode = sal_True;
157 }
158 
GetTemplateName() const159 String HTMLReader::GetTemplateName() const
160 {
161 	String sTemplate(
162 			String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("internal")) );
163 	sTemplate += INET_PATH_TOKEN;
164 	sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("html") );
165 	String sTemplateWithoutExt( sTemplate );
166 #ifndef MAC_WITHOUT_EXT
167     // --> OD 2005-01-26 - first search for OpenDocument Writer/Web template
168     sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".oth") );
169     // <--
170 #endif
171 
172 	SvtPathOptions aPathOpt;
173     // OpenDocument Writer/Web template (extension .oth)
174 	sal_Bool bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
175 
176 #ifndef MAC_WITHOUT_EXT
177 	if( !bSet )
178 	{
179         // 6.0 (extension .stw)
180 		sTemplate = sTemplateWithoutExt;
181         // --> OD 2005-01-26 - no OpenDocument Writer/Web template found.
182         // search for OpenOffice.org Writer/Web template
183         sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".stw") );
184         // <--
185 		bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
186 	}
187 #endif
188 
189 	if( !bSet )
190 	{
191 		sTemplate.Erase();
192 		ASSERT( !this,
193 			"Die html.vor befindet sich nicht mehr im definierten Directory!");
194 	}
195 
196 	return sTemplate;
197 }
198 
SetStrmStgPtr()199 int HTMLReader::SetStrmStgPtr()
200 {
201 	ASSERT( pMedium, "Wo ist das Medium??" );
202 
203 	if( pMedium->IsRemote() || !pMedium->IsStorage() )
204 	{
205 		pStrm = pMedium->GetInStream();
206 		return sal_True;
207 	}
208 	return sal_False;
209 
210 }
211 
212 	// Aufruf fuer die allg. Reader-Schnittstelle
Read(SwDoc & rDoc,const String & rBaseURL,SwPaM & rPam,const String & rName)213 sal_uLong HTMLReader::Read( SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & rName )
214 {
215 	if( !pStrm )
216 	{
217 		ASSERT( pStrm, "HTML-Read ohne Stream" );
218 		return ERR_SWG_READ_ERROR;
219 	}
220 
221 	if( !bInsertMode )
222 	{
223 		Reader::SetNoOutlineNum( rDoc );
224 		Reader::ResetFrmFmts( rDoc );
225 
226 		// Die HTML-Seitenvorlage setzen, wenn des kein HTML-Dokument ist,
227 		// sonst ist sie schon gesetzt.
228 		if( !rDoc.get(IDocumentSettingAccess::HTML_MODE) )
229 		{
230             rDoc.InsertPoolItem( rPam, SwFmtPageDesc(
231                 rDoc.GetPageDescFromPool( RES_POOLPAGE_HTML, false )), 0 );
232 		}
233 	}
234 
235 	// damit keiner das Doc klaut!
236 	rDoc.acquire();
237 	sal_uLong nRet = 0;
238 	SvParserRef xParser = new SwHTMLParser( &rDoc, rPam, *pStrm,
239                                             rName, rBaseURL, !bInsertMode, pMedium,
240 											IsReadUTF8(),
241                                             bIgnoreHTMLComments );
242 
243 	SvParserState eState = xParser->CallParser();
244 
245 	if( SVPAR_PENDING == eState )
246 		pStrm->ResetError();
247 	else if( SVPAR_ACCEPTED != eState )
248 	{
249 		String sErr( String::CreateFromInt32((sal_Int32)xParser->GetLineNr()));
250 		sErr += ',';
251 		sErr += String::CreateFromInt32((sal_Int32)xParser->GetLinePos());
252 
253 		// den Stream als Fehlernummer Transporter benutzen
254 		nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr,
255 									ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR );
256 	}
257 
258 
259 	return nRet;
260 }
261 
262 
263 /*  */
264 
SwHTMLParser(SwDoc * pD,const SwPaM & rCrsr,SvStream & rIn,const String & rPath,const String & rBaseURL,int bReadNewDoc,SfxMedium * pMed,sal_Bool bReadUTF8,sal_Bool bNoHTMLComments)265 SwHTMLParser::SwHTMLParser( SwDoc* pD, const SwPaM& rCrsr, SvStream& rIn,
266                             const String& rPath,
267                             const String& rBaseURL,
268                             int bReadNewDoc,
269 							SfxMedium* pMed, sal_Bool bReadUTF8,
270                             sal_Bool bNoHTMLComments )
271     : SfxHTMLParser( rIn, static_cast< sal_Bool >(bReadNewDoc), pMed ),
272 	SwClient( 0 ),
273 	aPathToFile( rPath ),
274 	sBaseURL( rBaseURL ),
275 	pAppletImpl( 0 ),
276 	pCSS1Parser( 0 ),
277 	pNumRuleInfo( new SwHTMLNumRuleInfo ),
278 	pPendStack( 0 ),
279 	pDoc( pD ),
280 	pActionViewShell( 0 ),
281 	pSttNdIdx( 0 ),
282 	pTable(0),
283 	pFormImpl( 0 ),
284 	pMarquee( 0 ),
285 	pField( 0 ),
286 	pImageMap( 0 ),
287 	pImageMaps( 0 ),
288 	pFootEndNoteImpl( 0 ),
289 	nScriptStartLineNr( 0 ),
290 	nBaseFontStMin( 0 ),
291 	nFontStMin( 0 ),
292 	nDefListDeep( 0 ),
293 	nFontStHeadStart( 0 ),
294 	nSBModuleCnt( 0 ),
295 	nMissingImgMaps( 0 ),
296 	nParaCnt( 5 ),
297     // --> OD 2007-10-26 #i83625#
298     nContextStMin( 0 ),
299     nContextStAttrMin( 0 ),
300     // <--
301 	nOpenParaToken( 0 ),
302 	eJumpTo( JUMPTO_NONE ),
303 #ifdef DBG_UTIL
304 	nContinue( 0 ),
305 #endif
306 	eParaAdjust( SVX_ADJUST_END ),
307 	bDocInitalized( sal_False ),
308 	bSetModEnabled( sal_False ),
309 	bInFloatingFrame( sal_False ),
310 	bInField( sal_False ),
311 	bCallNextToken( sal_False ),
312 	bIgnoreRawData( sal_False ),
313 	bNoParSpace( sal_False ),
314 	bInNoEmbed( sal_False ),
315 	bInTitle( sal_False ),
316 	bUpdateDocStat( sal_False ),
317 	bFixSelectWidth( sal_False ),
318 	bFixSelectHeight( sal_False ),
319 	bTextArea( sal_False ),
320 	bSelect( sal_False ),
321 	bInFootEndNoteAnchor( sal_False ),
322 	bInFootEndNoteSymbol( sal_False ),
323 //    bIgnoreHTMLComments( bNoHTMLComments )
324 	bIgnoreHTMLComments( bNoHTMLComments ),
325     bRemoveHidden( sal_False ),
326     pTempViewFrame(0)
327 {
328 	nEventId = 0;
329 	bUpperSpace = bViewCreated = bChkJumpMark =
330 	bSetCrsr = sal_False;
331 
332 	eScriptLang = HTML_SL_UNKNOWN;
333 	bAnyStarBasic = sal_True;
334 
335 	pPam = new SwPaM( *rCrsr.GetPoint() );
336 	memset( &aAttrTab, 0, sizeof( _HTMLAttrTable ));
337 
338 	// Die Font-Groessen 1-7 aus der INI-Datei lesen
339 	SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get();
340 	aFontHeights[0] = pHtmlOptions->GetFontSize( 0 ) * 20;
341 	aFontHeights[1] = pHtmlOptions->GetFontSize( 1 ) * 20;
342 	aFontHeights[2] = pHtmlOptions->GetFontSize( 2 ) * 20;
343 	aFontHeights[3] = pHtmlOptions->GetFontSize( 3 ) * 20;
344 	aFontHeights[4] = pHtmlOptions->GetFontSize( 4 ) * 20;
345 	aFontHeights[5] = pHtmlOptions->GetFontSize( 5 ) * 20;
346 	aFontHeights[6] = pHtmlOptions->GetFontSize( 6 ) * 20;
347 
348 	bKeepUnknown = pHtmlOptions->IsImportUnknown();
349 
350     if(bReadNewDoc)
351     {
352         SvxFontHeightItem aFontHeight(aFontHeights[2], 100, RES_CHRATR_FONTSIZE);
353         pDoc->SetDefault( aFontHeight );
354         aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
355         pDoc->SetDefault( aFontHeight );
356         aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
357         pDoc->SetDefault( aFontHeight );
358     }
359 
360 	// Waehrend des Imports in den HTML-Modus schalten, damit die
361 	// richrigen Vorlagen angelegt werden
362 	bOldIsHTMLMode = pDoc->get(IDocumentSettingAccess::HTML_MODE);
363 	pDoc->set(IDocumentSettingAccess::HTML_MODE, true);
364 
365     pCSS1Parser = new SwCSS1Parser( pDoc, aFontHeights, sBaseURL, IsNewDoc() );
366 	pCSS1Parser->SetIgnoreFontFamily( pHtmlOptions->IsIgnoreFontFamily() );
367 
368 	if( bReadUTF8 )
369 	{
370 		SetSrcEncoding( RTL_TEXTENCODING_UTF8 );
371 	}
372 	else
373 	{
374 		SwDocShell *pDocSh = pDoc->GetDocShell();
375 		SvKeyValueIterator *pHeaderAttrs =
376 			pDocSh->GetHeaderAttributes();
377 		if( pHeaderAttrs )
378 			SetEncodingByHTTPHeader( pHeaderAttrs );
379 	}
380 	pCSS1Parser->SetDfltEncoding( gsl_getSystemTextEncoding() );
381 
382 	// Timer nur bei ganz normalen Dokumenten aufsetzen!
383 	SwDocShell* pDocSh = pDoc->GetDocShell();
384 	if( pDocSh )
385 	{
386 		bViewCreated = sal_True;			// nicht, synchron laden
387 
388 		// es ist ein Sprungziel vorgegeben.
389 
390 		if( pMed )
391 		{
392 			sJmpMark = pMed->GetURLObject().GetMark();
393 			if( sJmpMark.Len() )
394 			{
395 				eJumpTo = JUMPTO_MARK;
396 				String sCmp;
397 				xub_StrLen nLastPos, nPos = 0;
398 				while( STRING_NOTFOUND != ( nLastPos =
399 						sJmpMark.Search( cMarkSeperator, nPos + 1 )) )
400 					nPos = nLastPos;
401 
402 				if( nPos && ( sCmp = sJmpMark.Copy( nPos + 1 ) ).
403 												EraseAllChars().Len() )
404 				{
405 					sCmp.ToLowerAscii();
406 					if( sCmp.EqualsAscii( pMarkToRegion ) )
407 						eJumpTo = JUMPTO_REGION;
408 					else if( sCmp.EqualsAscii( pMarkToTable ) )
409 						eJumpTo = JUMPTO_TABLE;
410 					else if( sCmp.EqualsAscii( pMarkToGraphic ) )
411 						eJumpTo = JUMPTO_GRAPHIC;
412 					else if( sCmp.EqualsAscii( pMarkToOutline ) ||
413 							sCmp.EqualsAscii( pMarkToText ) ||
414 							sCmp.EqualsAscii( pMarkToFrame ) )
415 						eJumpTo = JUMPTO_NONE;	// das ist nichts gueltiges!
416 					else
417 						// ansonsten ist das ein normaler (Book)Mark
418 						nPos = STRING_LEN;
419 				}
420 				else
421 					nPos = STRING_LEN;
422 
423 				sJmpMark.Erase( nPos );
424 				if( !sJmpMark.Len() )
425 					eJumpTo = JUMPTO_NONE;
426 			}
427 		}
428 	}
429 }
430 
~SwHTMLParser()431 __EXPORT SwHTMLParser::~SwHTMLParser()
432 {
433 #ifdef DBG_UTIL
434 	ASSERT( !nContinue, "DTOR im Continue - Das geht schief!!!" );
435 #endif
436 	sal_Bool bAsync = pDoc->IsInLoadAsynchron();
437 	pDoc->SetInLoadAsynchron( sal_False );
438 	pDoc->set(IDocumentSettingAccess::HTML_MODE, bOldIsHTMLMode);
439 
440 	if( pDoc->GetDocShell() && nEventId )
441 		Application::RemoveUserEvent( nEventId );
442 
443 	// das DocumentDetected kann ggfs. die DocShells loeschen, darum nochmals
444 	// abfragen
445 	if( pDoc->GetDocShell() )
446 	{
447 		// Gelinkte Bereiche updaten
448         sal_uInt16 nLinkMode = pDoc->getLinkUpdateMode( true );
449 		if( nLinkMode != NEVER && bAsync &&
450 			SFX_CREATE_MODE_INTERNAL!=pDoc->GetDocShell()->GetCreateMode() )
451 			pDoc->GetLinkManager().UpdateAllLinks( nLinkMode == MANUAL,
452 												   sal_True, sal_False );
453 
454         if ( pDoc->GetDocShell()->IsLoading() )
455         {
456             // --> OD 2006-11-07 #i59688#
457             pDoc->GetDocShell()->LoadingFinished();
458         }
459 	}
460 
461 	delete pSttNdIdx;
462 
463 	if( aSetAttrTab.Count() )
464 	{
465 		ASSERT( !aSetAttrTab.Count(),"Es stehen noch Attribute auf dem Stack" );
466 		aSetAttrTab.DeleteAndDestroy( 0, aSetAttrTab.Count() );
467 	}
468 
469 	delete pPam;
470 	delete pCSS1Parser;
471 	delete pNumRuleInfo;
472 	DeleteFormImpl();
473 	DeleteFootEndNoteImpl();
474 
475 	ASSERT( !pTable, "Es existiert noch eine offene Tabelle" );
476 	delete pImageMaps;
477 	//delete pTable;
478 
479 	ASSERT( !pPendStack,
480 			"SwHTMLParser::~SwHTMLParser: Hier sollte es keinen Pending-Stack mehr geben" );
481 	while( pPendStack )
482 	{
483 		SwPendingStack* pTmp = pPendStack;
484 		pPendStack = pPendStack->pNext;
485 		delete pTmp->pData;
486 		delete pTmp;
487 	}
488 
489 	if( !pDoc->release() )
490 	{
491 		// keiner will mehr das Doc haben, also weg damit
492 		delete pDoc;
493         pDoc = NULL;
494 	}
495 
496 	if ( pTempViewFrame )
497     {
498 		pTempViewFrame->DoClose();
499 
500         // the temporary view frame is hidden, so the hidden flag might need to be removed
501         if ( bRemoveHidden && pDoc && pDoc->GetDocShell() && pDoc->GetDocShell()->GetMedium() )
502             pDoc->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN );
503     }
504 }
505 
506 IMPL_LINK( SwHTMLParser, AsyncCallback, void*, /*pVoid*/ )
507 {
508 	nEventId=0;
509 
510     // --> FME 2005-08-18 #i47907# If the document has already been destructed,
511     // the parser should be aware of this:
512     if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
513         || 1 == pDoc->getReferenceCount() )
514     {
515         // wurde der Import vom SFX abgebrochen?
516         eState = SVPAR_ERROR;
517     }
518     // <--
519 
520 	GetAsynchCallLink().Call(0);
521 	return 0;
522 }
523 
CallParser()524 SvParserState __EXPORT SwHTMLParser::CallParser()
525 {
526 	// einen temporaeren Index anlegen, auf Pos 0 so wird er nicht bewegt!
527 	pSttNdIdx = new SwNodeIndex( pDoc->GetNodes() );
528 	if( !IsNewDoc() )		// in ein Dokument einfuegen ?
529 	{
530 		const SwPosition* pPos = pPam->GetPoint();
531 
532 		pDoc->SplitNode( *pPos, false );
533 
534 		*pSttNdIdx = pPos->nNode.GetIndex()-1;
535 		pDoc->SplitNode( *pPos, false );
536 
537 		SwPaM aInsertionRangePam( *pPos );
538 
539 		pPam->Move( fnMoveBackward );
540 
541 		// #106634# split any redline over the insertion point
542 		aInsertionRangePam.SetMark();
543 		*aInsertionRangePam.GetPoint() = *pPam->GetPoint();
544 		aInsertionRangePam.Move( fnMoveBackward );
545 		pDoc->SplitRedline( aInsertionRangePam );
546 
547 		pDoc->SetTxtFmtColl( *pPam,
548 				pCSS1Parser->GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
549 	}
550 
551 	if( GetMedium() )
552 	{
553 		if( !bViewCreated )
554 		{
555             nEventId = Application::PostUserEvent( LINK( this, SwHTMLParser, AsyncCallback ), 0 );
556 		}
557 		else
558 		{
559 			bViewCreated = sal_True;
560 			nEventId = 0;
561 		}
562 	}
563 
564 	// Laufbalken anzeigen
565 	else if( !GetMedium() || !GetMedium()->IsRemote() )
566 	{
567 		rInput.Seek(STREAM_SEEK_TO_END);
568 		rInput.ResetError();
569 		::StartProgress( STR_STATSTR_W4WREAD, 0, rInput.Tell(),
570 						 pDoc->GetDocShell() );
571 		rInput.Seek(STREAM_SEEK_TO_BEGIN);
572 		rInput.ResetError();
573 	}
574 
575 	SwPageDesc& rDesc = pDoc->_GetPageDesc( 0 );
576 	rDesc.Add( this );
577 
578 	SvParserState eRet = HTMLParser::CallParser();
579 	return eRet;
580 }
581 
Continue(int nToken)582 void __EXPORT SwHTMLParser::Continue( int nToken )
583 {
584 #ifdef DBG_UTIL
585 	ASSERT( !nContinue, "Continue im Continue - Das sollte doch nicht sein, oder?" );
586 	nContinue++;
587 #endif
588 
589 	// Wenn der Import (vom SFX) abgebrochen wurde, wird ein Fehler
590 	// gesetzt aber trotzdem noch weiter gemacht, damit vernuenftig
591 	// aufgeraeumt wird.
592 	ASSERT( SVPAR_ERROR!=eState,
593 			"SwHTMLParser::Continue: bereits ein Fehler gesetzt" );
594 	if( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
595 		eState = SVPAR_ERROR;
596 
597 	// Die ViewShell vom Dokument holen, merken und als aktuelle setzen.
598 	ViewShell *pInitVSh = CallStartAction();
599 
600 	if( SVPAR_ERROR != eState && GetMedium() && !bViewCreated )
601 	{
602 		// Beim ersten Aufruf erstmal returnen, Doc anzeigen
603 		// und auf Timer Callback warten.
604 		// An dieser Stelle wurde im CallParser gerade mal ein Zeichen
605 		// gelesen und ein SaveState(0) gerufen.
606 		eState = SVPAR_PENDING;
607 		bViewCreated = sal_True;
608 		pDoc->SetInLoadAsynchron( sal_True );
609 
610 #ifdef DBG_UTIL
611 		nContinue--;
612 #endif
613 
614 		return;
615 	}
616 
617 	bSetModEnabled = sal_False;
618 	if( pDoc->GetDocShell() &&
619 		0 != (bSetModEnabled = pDoc->GetDocShell()->IsEnableSetModified()) )
620 	{
621 		pDoc->GetDocShell()->EnableSetModified( sal_False );
622 	}
623 
624 	// waehrend des einlesens kein OLE-Modified rufen
625 	Link aOLELink( pDoc->GetOle2Link() );
626 	pDoc->SetOle2Link( Link() );
627 
628 	sal_Bool bModified = pDoc->IsModified();
629     bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
630     pDoc->GetIDocumentUndoRedo().DoUndo(false);
631 
632 	// Wenn der Import abgebrochen wird, kein Continue mehr rufen.
633 	// Falls ein Pending-Stack existiert aber durch einen Aufruf
634 	// von NextToken dafuer sorgen, dass der Pending-Stack noch
635 	// beendet wird.
636 	if( SVPAR_ERROR == eState )
637 	{
638 		ASSERT( !pPendStack || pPendStack->nToken,
639 				"SwHTMLParser::Continue: Pending-Stack ohne Token" );
640 		if( pPendStack && pPendStack->nToken )
641 			NextToken( pPendStack->nToken );
642 		ASSERT( !pPendStack,
643 				"SwHTMLParser::Continue: Es gibt wieder einen Pend-Stack" );
644 	}
645 	else
646 	{
647 		HTMLParser::Continue( pPendStack ? pPendStack->nToken : nToken );
648 	}
649 
650 	// Laufbalken wieder abschalten
651 	EndProgress( pDoc->GetDocShell() );
652 
653 	sal_Bool bLFStripped = sal_False;
654 	if( SVPAR_PENDING != GetStatus() )
655 	{
656 		// noch die letzten Attribute setzen
657 		{
658 			if( aScriptSource.Len() )
659 			{
660 				SwScriptFieldType *pType =
661 					(SwScriptFieldType*)pDoc->GetSysFldType( RES_SCRIPTFLD );
662 
663 				SwScriptField aFld( pType, aScriptType, aScriptSource,
664 									sal_False );
665 				InsertAttr( SwFmtFld( aFld ) );
666 			}
667 
668 			if( pAppletImpl )
669 			{
670                 if( pAppletImpl->GetApplet().is() )
671 					EndApplet();
672 				else
673 					EndObject();
674 			}
675 
676 			// ggf. ein noch vorhandes LF hinter dem letzen Absatz entfernen
677 			if( IsNewDoc() )
678 				bLFStripped = StripTrailingLF() > 0;
679 
680 			// noch offene Nummerierungen beenden.
681 			while( GetNumInfo().GetNumRule() )
682 				EndNumBulList();
683 
684 			ASSERT( !nContextStMin, "Es gibt geschuetzte Kontexte" );
685 			nContextStMin = 0;
686 			while( aContexts.Count() )
687 			{
688 				_HTMLAttrContext *pCntxt = PopContext();
689 				if( pCntxt )
690 				{
691 					EndContext( pCntxt );
692 					delete pCntxt;
693 				}
694 			}
695 
696 			if( aParaAttrs.Count() )
697 				aParaAttrs.Remove( 0, aParaAttrs.Count() );
698 
699 			SetAttr( sal_False );
700 
701 			// Noch die erst verzoegert gesetzten Styles setzen
702 			pCSS1Parser->SetDelayedStyles();
703 		}
704 
705 		// den Start wieder korrigieren
706 		if( !IsNewDoc() && pSttNdIdx->GetIndex() )
707 		{
708 			SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode();
709 			SwNodeIndex aNxtIdx( *pSttNdIdx );
710 			if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx ))
711 			{
712 				xub_StrLen nStt = pTxtNode->GetTxt().Len();
713 				// wenn der Cursor noch in dem Node steht, dann setze in an das Ende
714 				if( pPam->GetPoint()->nNode == aNxtIdx )
715 				{
716 					pPam->GetPoint()->nNode = *pSttNdIdx;
717 					pPam->GetPoint()->nContent.Assign( pTxtNode, nStt );
718 				}
719 
720 #ifdef DBG_UTIL
721 // !!! sollte nicht moeglich sein, oder ??
722 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( sal_True ).nNode.GetIndex(),
723 			"Pam.Bound1 steht noch im Node" );
724 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( sal_False ).nNode.GetIndex(),
725 			"Pam.Bound2 steht noch im Node" );
726 
727 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( sal_True ).nNode.GetIndex() )
728 {
729 	xub_StrLen nCntPos = pPam->GetBound( sal_True ).nContent.GetIndex();
730 	pPam->GetBound( sal_True ).nContent.Assign( pTxtNode,
731 					pTxtNode->GetTxt().Len() + nCntPos );
732 }
733 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( sal_False ).nNode.GetIndex() )
734 {
735 	xub_StrLen nCntPos = pPam->GetBound( sal_False ).nContent.GetIndex();
736 	pPam->GetBound( sal_False ).nContent.Assign( pTxtNode,
737 					pTxtNode->GetTxt().Len() + nCntPos );
738 }
739 #endif
740 				// Zeichen Attribute beibehalten!
741 				SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode();
742 				if( pTxtNode->GetTxt().Len() )
743 					pDelNd->FmtToTxtAttr( pTxtNode );
744 				else
745 					pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() );
746 				pTxtNode->JoinNext();
747 			}
748 		}
749 	}
750 
751 	if( SVPAR_ACCEPTED == eState )
752 	{
753 		if( nMissingImgMaps )
754 		{
755 			// es fehlen noch ein paar Image-Map zuordungen.
756 			// vielleicht sind die Image-Maps ja jetzt da?
757 			ConnectImageMaps();
758 		}
759 
760 		// jetzt noch den letzten ueberfluessigen Absatz loeschen
761 		SwPosition* pPos = pPam->GetPoint();
762 		if( !pPos->nContent.GetIndex() && !bLFStripped )
763 		{
764 			SwTxtNode* pAktNd;
765 			sal_uLong nNodeIdx = pPos->nNode.GetIndex();
766 
767 			sal_Bool bHasFlysOrMarks =
768 				HasCurrentParaFlys() || HasCurrentParaBookmarks( sal_True );
769 
770 			if( IsNewDoc() )
771 			{
772 				const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
773 				if( !pPam->GetPoint()->nContent.GetIndex() &&
774 					( pPrev->IsCntntNode() ||
775 					  (pPrev->IsEndNode() &&
776 					  pPrev->StartOfSectionNode()->IsSectionNode()) ) )
777 				{
778 					SwCntntNode* pCNd = pPam->GetCntntNode();
779 					if( pCNd && pCNd->StartOfSectionIndex()+2 <
780 						pCNd->EndOfSectionIndex() && !bHasFlysOrMarks )
781 					{
782 						ViewShell *pVSh = CheckActionViewShell();
783 						SwCrsrShell *pCrsrSh = pVSh && pVSh->ISA(SwCrsrShell)
784 										? static_cast < SwCrsrShell * >( pVSh )
785 										: 0;
786 						if( pCrsrSh &&
787 							pCrsrSh->GetCrsr()->GetPoint()
788 								   ->nNode.GetIndex() == nNodeIdx )
789 						{
790 							pCrsrSh->MovePara(fnParaPrev, fnParaEnd );
791 							pCrsrSh->SetMark();
792 							pCrsrSh->ClearMark();
793 						}
794 						pPam->GetBound(sal_True).nContent.Assign( 0, 0 );
795 						pPam->GetBound(sal_False).nContent.Assign( 0, 0 );
796 						pDoc->GetNodes().Delete( pPam->GetPoint()->nNode );
797 					}
798 				}
799 			}
800 			else if( 0 != ( pAktNd = pDoc->GetNodes()[ nNodeIdx ]->GetTxtNode()) && !bHasFlysOrMarks )
801 			{
802 				if( pAktNd->CanJoinNext( &pPos->nNode ))
803 				{
804 					SwTxtNode* pNextNd = pPos->nNode.GetNode().GetTxtNode();
805 					pPos->nContent.Assign( pNextNd, 0 );
806 					pPam->SetMark(); pPam->DeleteMark();
807 					pNextNd->JoinPrev();
808 				}
809 				else if( !pAktNd->GetTxt().Len() )
810 				{
811 					pPos->nContent.Assign( 0, 0 );
812 					pPam->SetMark(); pPam->DeleteMark();
813 					pDoc->GetNodes().Delete( pPos->nNode, 1 );
814 					pPam->Move( fnMoveBackward );
815 				}
816 			}
817 		}
818 
819 		// nun noch das SplitNode vom Anfang aufheben
820 		else if( !IsNewDoc() )
821 		{
822 			if( pPos->nContent.GetIndex() ) 	// dann gabs am Ende kein <P>,
823 				pPam->Move( fnMoveForward, fnGoNode ); 	// als zum naechsten Node
824 			SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
825 			SwNodeIndex aPrvIdx( pPos->nNode );
826 			if( pTxtNode && pTxtNode->CanJoinPrev( &aPrvIdx ) &&
827 				*pSttNdIdx <= aPrvIdx )
828 			{
829 				// eigentlich muss hier ein JoinNext erfolgen, aber alle Cursor
830 				// usw. sind im pTxtNode angemeldet, so dass der bestehen
831 				// bleiben MUSS.
832 
833 				// Absatz in Zeichen-Attribute umwandeln, aus dem Prev die
834 				// Absatzattribute und die Vorlage uebernehmen!
835 				SwTxtNode* pPrev = aPrvIdx.GetNode().GetTxtNode();
836 				pTxtNode->ChgFmtColl( pPrev->GetTxtColl() );
837 				pTxtNode->FmtToTxtAttr( pPrev );
838                 pTxtNode->ResetAllAttr();
839 
840                 if( pPrev->HasSwAttrSet() )
841                     pTxtNode->SetAttr( *pPrev->GetpSwAttrSet() );
842 
843 				if( &pPam->GetBound(sal_True).nNode.GetNode() == pPrev )
844 					pPam->GetBound(sal_True).nContent.Assign( pTxtNode, 0 );
845 				if( &pPam->GetBound(sal_False).nNode.GetNode() == pPrev )
846 					pPam->GetBound(sal_False).nContent.Assign( pTxtNode, 0 );
847 
848 				pTxtNode->JoinPrev();
849 			}
850 		}
851 
852 		// und noch die DocumentInfo aufbereiten
853 		if( IsNewDoc() )
854 		{
855             SwDocShell *pDocShell(pDoc->GetDocShell());
856             DBG_ASSERT(pDocShell, "no SwDocShell");
857             if (pDocShell) {
858                 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
859                     pDocShell->GetModel(), uno::UNO_QUERY_THROW);
860                 uno::Reference<document::XDocumentProperties> xDocProps(
861                     xDPS->getDocumentProperties());
862                 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
863                 if ( xDocProps.is() && (xDocProps->getAutoloadSecs() > 0) &&
864                      xDocProps->getAutoloadURL().equalsAscii("") )
865                 {
866                     xDocProps->setAutoloadURL(aPathToFile);
867                 }
868             }
869 		}
870 
871 		if( bUpdateDocStat )
872 		{
873 			SwDocStat aStat( pDoc->GetDocStat() );
874 			pDoc->UpdateDocStat( aStat );
875 		}
876 	}
877 
878 	if( SVPAR_PENDING != GetStatus() )
879 		delete pSttNdIdx, pSttNdIdx = 0;
880 
881 	// sollte der Parser der Letzte sein, der das Doc haelt, dann braucht
882 	// man hier auch nichts mehr tun, Doc wird gleich zerstoert!
883 	if( 1 < pDoc->getReferenceCount() )
884 	{
885 		if( bWasUndo )
886         {
887             pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
888             pDoc->GetIDocumentUndoRedo().DoUndo(true);
889         }
890 		else if( !pInitVSh )
891 		{
892 			// Wenn zu Beginn des Continue keine Shell vorhanden war,
893 			// kann trotzdem mitlerweile eine angelegt worden sein.
894 			// In dieses Fall stimmt das bWasUndo-Flag nicht und
895 			// wir muessen das Undo noch anschalten.
896 			ViewShell *pTmpVSh = CheckActionViewShell();
897 			if( pTmpVSh )
898             {
899                 pDoc->GetIDocumentUndoRedo().DoUndo(true);
900             }
901         }
902 
903 		pDoc->SetOle2Link( aOLELink );
904 		if( !bModified )
905 			pDoc->ResetModified();
906 		if( bSetModEnabled && pDoc->GetDocShell() )
907 		{
908 			pDoc->GetDocShell()->EnableSetModified( sal_True );
909 			bSetModEnabled = sal_False; // this is unnecessary here
910 		}
911 	}
912 
913 
914 	// Wenn die Dokuemnt-ViewShell noch existiert und eine Action
915 	// offen ist (muss bei Abbruch nicht sein), die Action beenden,
916 	// uns von der Shell abmelden und schliesslich die alte Shell
917 	// wieder rekonstruieren.
918 	CallEndAction( sal_True );
919 
920 #ifdef DBG_UTIL
921 	nContinue--;
922 #endif
923 }
924 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)925 void SwHTMLParser::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
926 {
927 	switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
928 	{
929 	case RES_OBJECTDYING:
930 		if( ((SwPtrMsgPoolItem *)pOld)->pObject == GetRegisteredIn() )
931 		{
932 			// dann uns selbst beenden
933 			GetRegisteredInNonConst()->Remove( this );
934 			ReleaseRef();					// ansonsten sind wir fertig!
935 		}
936 		break;
937 	}
938 }
939 
DocumentDetected()940 void SwHTMLParser::DocumentDetected()
941 {
942 	ASSERT( !bDocInitalized, "DocumentDetected mehrfach aufgerufen" );
943 	bDocInitalized = sal_True;
944 	if( IsNewDoc() )
945 	{
946 		if( IsInHeader() )
947 			FinishHeader( sal_True );
948 
949 		CallEndAction( sal_True, sal_True );
950 
951         pDoc->GetIDocumentUndoRedo().DoUndo(false);
952 		// Durch das DocumentDetected wurde im allgemeinen eine
953 		// ViewShell angelegt. Es kann aber auch sein, dass sie
954 		// erst spaeter angelegt wird, naemlich dann, wenn die UI
955 		// gecaptured ist.
956 		CallStartAction();
957 	}
958 }
959 
960 // wird fuer jedes Token gerufen, das in CallParser erkannt wird
NextToken(int nToken)961 void __EXPORT SwHTMLParser::NextToken( int nToken )
962 {
963 	if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
964 		|| 1 == pDoc->getReferenceCount() )
965 	{
966 		// wurde der Import vom SFX abgebrochen? Wenn ein Pending-Stack
967 		// existiert den noch aufraumen
968 		eState = SVPAR_ERROR;
969 		ASSERT( !pPendStack || pPendStack->nToken,
970 				"SwHTMLParser::NextToken: Pending-Stack ohne Token" );
971 		if( 1 == pDoc->getReferenceCount() || !pPendStack )
972 			return ;
973 	}
974 
975 #ifdef DBG_UTIL
976 	if( pPendStack )
977 	{
978 		switch( nToken )
979 		{
980 			// Tabellen werden ueber rekusive Methodenaufrufe gelesen
981 		case HTML_TABLE_ON:
982 			// Bei CSS-Deklarationen muss evtl. noch auf das
983 			// Ende eines File-Downloads gewartet werden.
984 		case HTML_LINK:
985 			// Bei Controls muss evtl. noch die Groesse gesetzt werden.
986 		case HTML_INPUT:
987 		case HTML_TEXTAREA_ON:
988 		case HTML_SELECT_ON:
989 		case HTML_SELECT_OFF:
990 			break;
991 		default:
992 			ASSERT( !pPendStack, "Unbekanntes Token fuer Pending-Stack" );
993 			break;
994 		}
995 	}
996 #endif
997 
998 	// Die folgeneden Spezialfaelle muessen vor der Filter-Detection behandelt
999 	// werden, denn der Inhalt des Titels, etc. wird auch in Netcape nicht
1000 	// zur Filter-Detection herangezogen.
1001 	if( !pPendStack )
1002 	{
1003 		if( bInTitle )
1004 		{
1005 			switch( nToken )
1006 			{
1007 			case HTML_TITLE_OFF:
1008 				if( IsNewDoc() && sTitle.Len() )
1009 				{
1010                     if( pDoc->GetDocShell() ) {
1011                         uno::Reference<document::XDocumentPropertiesSupplier>
1012                             xDPS(pDoc->GetDocShell()->GetModel(),
1013                             uno::UNO_QUERY_THROW);
1014                         uno::Reference<document::XDocumentProperties> xDocProps(
1015                             xDPS->getDocumentProperties());
1016                         DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
1017                         if (xDocProps.is()) {
1018                             xDocProps->setTitle(sTitle);
1019                         }
1020 
1021 						pDoc->GetDocShell()->SetTitle( sTitle );
1022                     }
1023 				}
1024 				bInTitle = sal_False;
1025 				sTitle.Erase();
1026 				break;
1027 
1028 			case HTML_NONBREAKSPACE:
1029 				sTitle += ' ';
1030 				break;
1031 
1032 			case HTML_SOFTHYPH:
1033 				sTitle += '-';
1034 				break;
1035 
1036 			case HTML_TEXTTOKEN:
1037 				sTitle += aToken;
1038 				break;
1039 
1040 			default:
1041 				sTitle += '<';
1042 				if( (HTML_TOKEN_ONOFF & nToken) && (1 & nToken) )
1043 					sTitle += '/';
1044 				sTitle += sSaveToken;
1045 				if( aToken.Len() )
1046 				{
1047 					sTitle += ' ';
1048 					sTitle += aToken;
1049 				}
1050 				sTitle += '>';
1051 				break;
1052 			}
1053 
1054 			return;
1055 		}
1056 	}
1057 
1058 	// Wenn wir noch nicht wissen, was fuer ein Dokument wir vor uns haben,
1059 	// versuchen wir das erstmal rauszufinden. Das muss fuer Controls in
1060 	// Fall vor dem Einfuegen des Controls passieren, weil beim Einfuegen
1061 	// bereits eine View benoetigt wird.
1062 	if( !bDocInitalized )
1063 		DocumentDetected();
1064 
1065 	sal_Bool bGetIDOption = sal_False, bInsertUnknown = sal_False;
1066 	sal_Bool bUpperSpaceSave = bUpperSpace;
1067 	bUpperSpace = sal_False;
1068 
1069 	// Die folgenden Speziallfaelle muessen oder koennen nach der
1070 	// Filter-Detection erfolgen.
1071 	if( !pPendStack )
1072 	{
1073 		if( bInFloatingFrame )
1074 		{
1075 			// <SCRIPT> wird hier (von uns) ignoriert, weil es auch in
1076 			// Applets ignoriert wird!
1077 			if( HTML_IFRAME_OFF == nToken )
1078 			{
1079 				bCallNextToken = sal_False;
1080 				EndFloatingFrame();
1081 			}
1082 
1083 			return;
1084 		}
1085 		else if( bInNoEmbed )
1086 		{
1087 			switch( nToken )
1088 			{
1089 			case HTML_NOEMBED_OFF:
1090 				aContents.ConvertLineEnd();
1091 				InsertComment( aContents, OOO_STRING_SVTOOLS_HTML_noembed );
1092 				aContents.Erase();
1093 				bCallNextToken = sal_False;
1094 				bInNoEmbed = sal_False;
1095 				break;
1096 
1097 			case HTML_RAWDATA:
1098 				InsertCommentText( OOO_STRING_SVTOOLS_HTML_noembed );
1099 				break;
1100 
1101 			default:
1102 				ASSERT( !this, "SwHTMLParser::NextToken: ungueltiges Tag" );
1103 				break;
1104 			}
1105 
1106 			return;
1107 		}
1108 		else if( pAppletImpl )
1109 		{
1110 			// in einem Applet interessieren uns (erstmal) nur <PARAM>-Tags
1111 			// und das </APPLET>.
1112 			// <SCRIPT> wird hier (von Netscape) ignoriert!
1113 
1114 			switch( nToken )
1115 			{
1116 			case HTML_APPLET_OFF:
1117 				bCallNextToken = sal_False;
1118 				EndApplet();
1119 				break;
1120 			case HTML_OBJECT_OFF:
1121 				bCallNextToken = sal_False;
1122 				EndObject();
1123 				break;
1124 
1125 			case HTML_PARAM:
1126 				InsertParam();
1127 				break;
1128 			}
1129 
1130 			return;
1131 		}
1132 		else if( bTextArea )
1133 		{
1134 			// in einer TextArea wird alles bis zum </TEXTAREA> als Text
1135 			// eingefuegt
1136 			// <SCRIPT> wird hier (von Netscape) ignoriert!
1137 
1138 			switch( nToken )
1139 			{
1140 			case HTML_TEXTAREA_OFF:
1141 				bCallNextToken = sal_False;
1142 				EndTextArea();
1143 				break;
1144 
1145 			default:
1146                 InsertTextAreaText( static_cast< sal_uInt16 >(nToken) );
1147 				break;
1148 			}
1149 
1150 			return;
1151 		}
1152 		else if( bSelect )
1153 		{
1154 			// MUSS nach bNoScript kommen!
1155 			switch( nToken )
1156 			{
1157 			case HTML_SELECT_OFF:
1158 				bCallNextToken = sal_False;
1159 				EndSelect();
1160 				return;
1161 
1162 			case HTML_OPTION:
1163 				InsertSelectOption();
1164 				return;
1165 
1166 			case HTML_TEXTTOKEN:
1167 				InsertSelectText();
1168 				return;
1169 
1170 			case HTML_INPUT:
1171 			case HTML_SCRIPT_ON:
1172 			case HTML_SCRIPT_OFF:
1173 			case HTML_NOSCRIPT_ON:
1174 			case HTML_NOSCRIPT_OFF:
1175 			case HTML_RAWDATA:
1176 				// im normalen switch bahandeln
1177 				break;
1178 
1179 			default:
1180 				// ignorieren
1181 				return;
1182 			}
1183 		}
1184 		else if( pMarquee )
1185 		{
1186 			// in einer TextArea wird alles bis zum </TEXTAREA> als Text
1187 			// eingefuegt
1188 			// Die <SCRIPT>-Tags werden vom MS-IE ignoriert, von uns das
1189 			// geasmte Script
1190 			switch( nToken )
1191 			{
1192 			case HTML_MARQUEE_OFF:
1193 				bCallNextToken = sal_False;
1194 				EndMarquee();
1195 				break;
1196 
1197 			case HTML_TEXTTOKEN:
1198 				InsertMarqueeText();
1199 				break;
1200 			}
1201 
1202 			return;
1203 		}
1204 		else if( bInField )
1205 		{
1206 			switch( nToken )
1207 			{
1208 			case HTML_SDFIELD_OFF:
1209 				bCallNextToken = sal_False;
1210 				EndField();
1211 				break;
1212 
1213 			case HTML_TEXTTOKEN:
1214 				InsertFieldText();
1215 				break;
1216 			}
1217 
1218 			return;
1219 		}
1220 		else if( bInFootEndNoteAnchor || bInFootEndNoteSymbol )
1221 		{
1222 			switch( nToken )
1223 			{
1224 			case HTML_ANCHOR_OFF:
1225 				EndAnchor();
1226 				bCallNextToken = sal_False;
1227 				break;
1228 
1229 			case HTML_TEXTTOKEN:
1230 				InsertFootEndNoteText();
1231 				break;
1232 			}
1233 			return;
1234 		}
1235 		else if( aUnknownToken.Len() )
1236 		{
1237 			// Unbekannte Token im Header werden nur durch ein passendes
1238 			// End-Token, </HEAD> oder <BODY> wieder beendet. Darin wird Text
1239 			// ignoriert.
1240 			switch( nToken )
1241 			{
1242 			case HTML_UNKNOWNCONTROL_OFF:
1243 				if( aUnknownToken.CompareTo(sSaveToken) != COMPARE_EQUAL )
1244 					return;
1245 			case HTML_FRAMESET_ON:
1246 			case HTML_HEAD_OFF:
1247 			case HTML_BODY_ON:
1248 			case HTML_IMAGE:		// Warum auch immer Netscape das tut.
1249 				aUnknownToken.Erase();
1250 				break;
1251 			case HTML_TEXTTOKEN:
1252 				return;
1253 			default:
1254 				break;
1255 			}
1256 		}
1257 	}
1258 
1259 	switch( nToken )
1260 	{
1261 	case HTML_BODY_ON:
1262 		if( aStyleSource.Len() )
1263 		{
1264 			pCSS1Parser->ParseStyleSheet( aStyleSource );
1265 			aStyleSource.Erase();
1266 		}
1267 		if( IsNewDoc() )
1268 		{
1269 			InsertBodyOptions();
1270 			// Falls es eine Vorlage fuer die erste oder rechte Seite gibt,
1271 			// setzen wir die hier.
1272 			const SwPageDesc *pPageDesc = 0;
1273 			if( pCSS1Parser->IsSetFirstPageDesc() )
1274 				pPageDesc = pCSS1Parser->GetFirstPageDesc();
1275 			else if( pCSS1Parser->IsSetRightPageDesc() )
1276 				pPageDesc = pCSS1Parser->GetRightPageDesc();
1277 
1278 			if( pPageDesc )
1279             {
1280                 pDoc->InsertPoolItem( *pPam, SwFmtPageDesc( pPageDesc ), 0 );
1281             }
1282 		}
1283 		break;
1284 
1285 	case HTML_LINK:
1286 		InsertLink();
1287 		break;
1288 
1289 	case HTML_BASE:
1290 		{
1291 			const HTMLOptions *pHTMLOptions = GetOptions();
1292 			for( sal_uInt16 i = pHTMLOptions->Count(); i; )
1293 			{
1294 				const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1295 				switch( pOption->GetToken() )
1296 				{
1297 				case HTML_O_HREF:
1298 					sBaseURL = pOption->GetString();
1299 					break;
1300 				case HTML_O_TARGET:
1301 					if( IsNewDoc() )
1302 					{
1303                         SwDocShell *pDocShell(pDoc->GetDocShell());
1304                         DBG_ASSERT(pDocShell, "no SwDocShell");
1305                         if (pDocShell) {
1306                             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1307                                 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1308                             uno::Reference<document::XDocumentProperties>
1309                                 xDocProps(xDPS->getDocumentProperties());
1310                             DBG_ASSERT(xDocProps.is(),"no DocumentProperties");
1311                             if (xDocProps.is()) {
1312                                 xDocProps->setDefaultTarget(
1313                                     pOption->GetString());
1314                             }
1315                         }
1316 					}
1317 					break;
1318 				}
1319 			}
1320 		}
1321 		break;
1322 
1323 	case HTML_META:
1324 		{
1325 			SvKeyValueIterator *pHTTPHeader = 0;
1326 			if( IsNewDoc() )
1327 			{
1328 				SwDocShell *pDocSh = pDoc->GetDocShell();
1329 				if( pDocSh )
1330 					pHTTPHeader = pDocSh->GetHeaderAttributes();
1331 			}
1332             SwDocShell *pDocShell(pDoc->GetDocShell());
1333             DBG_ASSERT(pDocShell, "no SwDocShell");
1334             if (pDocShell)
1335             {
1336                 uno::Reference<document::XDocumentProperties> xDocProps;
1337                 if (IsNewDoc())
1338                 {
1339                     const uno::Reference<document::XDocumentPropertiesSupplier>
1340                         xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW );
1341                     xDocProps = xDPS->getDocumentProperties();
1342                     DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
1343                 }
1344                 ParseMetaOptions( xDocProps, pHTTPHeader );
1345 			}
1346 		}
1347 		break;
1348 
1349 	case HTML_TITLE_ON:
1350 		bInTitle = sal_True;
1351 		break;
1352 
1353 	case HTML_SCRIPT_ON:
1354 		NewScript();
1355 		break;
1356 
1357 	case HTML_SCRIPT_OFF:
1358 		EndScript();
1359 		break;
1360 
1361 	case HTML_NOSCRIPT_ON:
1362 	case HTML_NOSCRIPT_OFF:
1363 		bInsertUnknown = sal_True;
1364 		break;
1365 
1366 	case HTML_STYLE_ON:
1367 		NewStyle();
1368 		break;
1369 
1370 	case HTML_STYLE_OFF:
1371 		EndStyle();
1372 		break;
1373 
1374 	case HTML_RAWDATA:
1375 		if( !bIgnoreRawData )
1376 		{
1377 			if( IsReadScript() )
1378 			{
1379 				AddScriptSource();
1380 			}
1381 			else if( IsReadStyle() )
1382 			{
1383 				if( aStyleSource.Len() )
1384 					aStyleSource += '\n';
1385 				aStyleSource += aToken;
1386 			}
1387 		}
1388 		break;
1389 
1390 	case HTML_OBJECT_ON:
1391 #ifdef SOLAR_JAVA
1392 		NewObject();
1393 		bCallNextToken = pAppletImpl!=0 && pTable!=0;
1394 #endif
1395 		break;
1396 
1397 	case HTML_APPLET_ON:
1398 #ifdef SOLAR_JAVA
1399 		InsertApplet();
1400 		bCallNextToken = pAppletImpl!=0 && pTable!=0;
1401 #endif
1402 		break;
1403 
1404 	case HTML_IFRAME_ON:
1405 		InsertFloatingFrame();
1406 		bCallNextToken = bInFloatingFrame && pTable!=0;
1407 		break;
1408 
1409 	case HTML_LINEBREAK:
1410 		if( !IsReadPRE() )
1411 		{
1412 			InsertLineBreak();
1413 			break;
1414 		}
1415 		else
1416 			bGetIDOption = sal_True;
1417 			// <BR>s in <PRE> aehneln echten LFs, deshalb kein break
1418 
1419 	case HTML_NEWPARA:
1420 		// CR in PRE/LISTING/XMP
1421 		{
1422 			if( HTML_NEWPARA==nToken ||
1423 				pPam->GetPoint()->nContent.GetIndex() )
1424 			{
1425 				AppendTxtNode(); // lf gibts hier nicht, deshalb unkritisch
1426 				SetTxtCollAttrs();
1427 			}
1428 			// Laufbalkenanzeige
1429 			if( !GetMedium() || !GetMedium()->IsRemote() )
1430 				::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
1431 		}
1432 		break;
1433 
1434 	case HTML_NONBREAKSPACE:
1435         pDoc->InsertString( *pPam, CHAR_HARDBLANK );
1436 		break;
1437 
1438 	case HTML_SOFTHYPH:
1439         pDoc->InsertString( *pPam, CHAR_SOFTHYPHEN );
1440 		break;
1441 
1442 	case HTML_LINEFEEDCHAR:
1443 		if( pPam->GetPoint()->nContent.GetIndex() )
1444 			AppendTxtNode();
1445 		if( !pTable && !pDoc->IsInHeaderFooter( pPam->GetPoint()->nNode ) )
1446 		{
1447             NewAttr( &aAttrTab.pBreak, SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
1448 			EndAttr( aAttrTab.pBreak, 0, sal_False );
1449 		}
1450 		break;
1451 
1452 	case HTML_TEXTTOKEN:
1453 		// dann fuege den String ein, ohne das Attribute am Ende
1454 		// aufgespannt werden.
1455 		if( aToken.Len() && ' '==aToken.GetChar(0) && !IsReadPRE() )
1456 		{
1457 			xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
1458 			if( nPos )
1459 			{
1460 				const String& rText =
1461                     pPam->GetPoint()->nNode.GetNode().GetTxtNode()->GetTxt();
1462 				sal_Unicode cLast = rText.GetChar(--nPos);
1463 				if( ' ' == cLast || '\x0a' == cLast)
1464 					aToken.Erase(0,1);
1465 			}
1466 			else
1467 				aToken.Erase(0,1);
1468 
1469 			if( !aToken.Len() )
1470 			{
1471 				bUpperSpace = bUpperSpaceSave;
1472 				break;
1473 			}
1474 		}
1475 
1476 		if( aToken.Len() )
1477 		{
1478 			if( !bDocInitalized )
1479 				DocumentDetected();
1480             pDoc->InsertString( *pPam, aToken );
1481 
1482 			// wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber
1483 			// nicht leer ist, dann sind die Absatz-Attribute entgueltig.
1484 			if( aParaAttrs.Count() )
1485 				aParaAttrs.Remove( 0, aParaAttrs.Count() );
1486 
1487 			SetAttr();
1488 		}
1489 		break;
1490 
1491 	case HTML_HORZRULE:
1492 		InsertHorzRule();
1493 		break;
1494 
1495 	case HTML_IMAGE:
1496 		InsertImage();
1497 		// sollte der Parser der Letzte sein, der das Doc haelt, dann kann
1498 		// man hier abbrechen und einen Fehler setzen.
1499 		if( 1 == pDoc->getReferenceCount() )
1500 		{
1501 			eState = SVPAR_ERROR;
1502 		}
1503 		break;
1504 
1505 	case HTML_SPACER:
1506 		InsertSpacer();
1507 		break;
1508 
1509 	case HTML_EMBED:
1510 		InsertEmbed();
1511 		break;
1512 
1513 	case HTML_NOEMBED_ON:
1514 		bInNoEmbed = sal_True;
1515 		bCallNextToken = pTable!=0;
1516 		ReadRawData( OOO_STRING_SVTOOLS_HTML_noembed );
1517 		break;
1518 
1519 	case HTML_DEFLIST_ON:
1520 		if( nOpenParaToken )
1521 			EndPara();
1522 		NewDefList();
1523 		break;
1524 	case HTML_DEFLIST_OFF:
1525 		if( nOpenParaToken )
1526 			EndPara();
1527 		EndDefListItem( 0, sal_False, 1==nDefListDeep );
1528 		EndDefList();
1529 		break;
1530 
1531 	case HTML_DD_ON:
1532 	case HTML_DT_ON:
1533 		if( nOpenParaToken )
1534 			EndPara();
1535 		EndDefListItem( 0, sal_False );// <DD>/<DT> beenden und keine Vorl. setzen
1536 		NewDefListItem( nToken );
1537 		break;
1538 
1539 	case HTML_DD_OFF:
1540 	case HTML_DT_OFF:
1541 		// siehe HTML_LI_OFF
1542 		// eigentlich muesste man ein DD/DT jetzt beenden. Da aber sowhl
1543 		// Netscape als auch Microsoft das nicht tun, machen wir das eben
1544 		// auch nicht.
1545 		EndDefListItem( nToken, sal_False );
1546 		break;
1547 
1548 	// Bereiche
1549 	case HTML_DIVISION_ON:
1550 	case HTML_CENTER_ON:
1551 		if( nOpenParaToken )
1552 		{
1553 			if( IsReadPRE() )
1554 				nOpenParaToken = 0;
1555 			else
1556 				EndPara();
1557 		}
1558 		NewDivision( nToken );
1559 		break;
1560 
1561 	case HTML_DIVISION_OFF:
1562 	case HTML_CENTER_OFF:
1563 		if( nOpenParaToken )
1564 		{
1565 			if( IsReadPRE() )
1566 				nOpenParaToken = 0;
1567 			else
1568 				EndPara();
1569 		}
1570 		EndDivision( nToken );
1571 		break;
1572 
1573 	case HTML_MULTICOL_ON:
1574 		if( nOpenParaToken )
1575 			EndPara();
1576 		NewMultiCol();
1577 		break;
1578 
1579 	case HTML_MULTICOL_OFF:
1580 		if( nOpenParaToken )
1581 			EndPara();
1582 		EndTag( HTML_MULTICOL_ON );
1583 		break;
1584 
1585 	case HTML_MARQUEE_ON:
1586 		NewMarquee();
1587 		bCallNextToken = pMarquee!=0 && pTable!=0;
1588 		break;
1589 
1590 	case HTML_FORM_ON:
1591 		NewForm();
1592 		break;
1593 	case HTML_FORM_OFF:
1594 		EndForm();
1595 		break;
1596 
1597 	// Vorlagen:
1598 	case HTML_PARABREAK_ON:
1599 		if( nOpenParaToken )
1600 			EndPara( sal_True );
1601 		NewPara();
1602 		break;
1603 
1604 	case HTML_PARABREAK_OFF:
1605 		EndPara( sal_True );
1606 		break;
1607 
1608 	case HTML_ADDRESS_ON:
1609 		if( nOpenParaToken )
1610 			EndPara();
1611 		NewTxtFmtColl( HTML_ADDRESS_ON, RES_POOLCOLL_SENDADRESS );
1612 		break;
1613 
1614 	case HTML_ADDRESS_OFF:
1615 		if( nOpenParaToken )
1616 			EndPara();
1617 		EndTxtFmtColl( HTML_ADDRESS_OFF );
1618 		break;
1619 
1620 	case HTML_BLOCKQUOTE_ON:
1621 	case HTML_BLOCKQUOTE30_ON:
1622 		if( nOpenParaToken )
1623 			EndPara();
1624 		NewTxtFmtColl( HTML_BLOCKQUOTE_ON, RES_POOLCOLL_HTML_BLOCKQUOTE );
1625 		break;
1626 
1627 	case HTML_BLOCKQUOTE_OFF:
1628 	case HTML_BLOCKQUOTE30_OFF:
1629 		if( nOpenParaToken )
1630 			EndPara();
1631 		EndTxtFmtColl( HTML_BLOCKQUOTE_ON );
1632 		break;
1633 
1634 	case HTML_PREFORMTXT_ON:
1635 	case HTML_LISTING_ON:
1636 	case HTML_XMP_ON:
1637 		if( nOpenParaToken )
1638 			EndPara();
1639 		NewTxtFmtColl( nToken, RES_POOLCOLL_HTML_PRE );
1640 		break;
1641 
1642 	case HTML_PREFORMTXT_OFF:
1643 		bNoParSpace = sal_True; // der letzte PRE-Absatz muss einen Zeilenabstand bekommen
1644 		EndTxtFmtColl( HTML_PREFORMTXT_OFF );
1645 		break;
1646 
1647 	case HTML_LISTING_OFF:
1648 	case HTML_XMP_OFF:
1649 		EndTxtFmtColl( nToken );
1650 		break;
1651 
1652 	case HTML_HEAD1_ON:
1653 	case HTML_HEAD2_ON:
1654 	case HTML_HEAD3_ON:
1655 	case HTML_HEAD4_ON:
1656 	case HTML_HEAD5_ON:
1657 	case HTML_HEAD6_ON:
1658 		if( nOpenParaToken )
1659 		{
1660 			if( IsReadPRE() )
1661 				nOpenParaToken = 0;
1662 			else
1663 				EndPara();
1664 		}
1665 		NewHeading( nToken );
1666 		break;
1667 
1668 	case HTML_HEAD1_OFF:
1669 	case HTML_HEAD2_OFF:
1670 	case HTML_HEAD3_OFF:
1671 	case HTML_HEAD4_OFF:
1672 	case HTML_HEAD5_OFF:
1673 	case HTML_HEAD6_OFF:
1674 		EndHeading();
1675 		break;
1676 
1677 	case HTML_TABLE_ON:
1678 		if( pPendStack )
1679 			BuildTable( SVX_ADJUST_END );
1680 		else
1681 		{
1682 			if( nOpenParaToken )
1683 				EndPara();
1684 			ASSERT( !pTable, "Tabelle in Tabelle darf hier nicht vorkommen" );
1685 			if( !pTable && (IsNewDoc() || !pPam->GetNode()->FindTableNode()) &&
1686 				(pPam->GetPoint()->nNode.GetIndex() >
1687 							pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
1688 				!pPam->GetNode()->FindFootnoteStartNode() ) )
1689 			{
1690 				if ( nParaCnt < 5 )
1691 					Show();		// bis hierhin schon mal anzeigen
1692 
1693 				SvxAdjust eAdjust = aAttrTab.pAdjust
1694 					? ((const SvxAdjustItem&)aAttrTab.pAdjust->GetItem()).
1695 											 GetAdjust()
1696 					: SVX_ADJUST_END;
1697 				BuildTable( eAdjust );
1698 			}
1699 			else
1700 				bInsertUnknown = bKeepUnknown;
1701 		}
1702 		break;
1703 
1704 	// Listen
1705 	case HTML_DIRLIST_ON:
1706 	case HTML_MENULIST_ON:
1707 	case HTML_ORDERLIST_ON:
1708 	case HTML_UNORDERLIST_ON:
1709 		if( nOpenParaToken )
1710 			EndPara();
1711 		NewNumBulList( nToken );
1712 		break;
1713 
1714 	case HTML_DIRLIST_OFF:
1715 	case HTML_MENULIST_OFF:
1716 	case HTML_ORDERLIST_OFF:
1717 	case HTML_UNORDERLIST_OFF:
1718 		if( nOpenParaToken )
1719 			EndPara();
1720 		EndNumBulListItem( 0, sal_True, GetNumInfo().GetDepth()==1 );
1721 		EndNumBulList( nToken );
1722 		break;
1723 
1724 	case HTML_LI_ON:
1725 	case HTML_LISTHEADER_ON:
1726 		if( nOpenParaToken &&
1727 			(pPam->GetPoint()->nContent.GetIndex()
1728 			|| HTML_PARABREAK_ON==nOpenParaToken) )
1729 		{
1730 			// nure bei <P><LI> den Absatz beenden, aber nicht bei <DD><LI>
1731 			EndPara();
1732 		}
1733 
1734 		EndNumBulListItem( 0, sal_False );// <LI>/<LH> beenden und keine Vorl. setzen
1735 		NewNumBulListItem( nToken );
1736 		break;
1737 
1738 	case HTML_LI_OFF:
1739 	case HTML_LISTHEADER_OFF:
1740 		EndNumBulListItem( nToken, sal_False );
1741 		break;
1742 
1743 	// Attribute :
1744 	case HTML_ITALIC_ON:
1745 		{
1746             SvxPostureItem aPosture( ITALIC_NORMAL, RES_CHRATR_POSTURE );
1747 			SvxPostureItem aPostureCJK( ITALIC_NORMAL, RES_CHRATR_CJK_POSTURE );
1748 			SvxPostureItem aPostureCTL( ITALIC_NORMAL, RES_CHRATR_CTL_POSTURE );
1749 			NewStdAttr( HTML_ITALIC_ON,
1750 				   		&aAttrTab.pItalic, aPosture,
1751 				   		&aAttrTab.pItalicCJK, &aPostureCJK,
1752 				   		&aAttrTab.pItalicCTL, &aPostureCTL );
1753 		}
1754 		break;
1755 
1756 	case HTML_BOLD_ON:
1757 		{
1758             SvxWeightItem aWeight( WEIGHT_BOLD, RES_CHRATR_WEIGHT );
1759 			SvxWeightItem aWeightCJK( WEIGHT_BOLD, RES_CHRATR_CJK_WEIGHT );
1760 			SvxWeightItem aWeightCTL( WEIGHT_BOLD, RES_CHRATR_CTL_WEIGHT );
1761 			NewStdAttr( HTML_BOLD_ON,
1762 						&aAttrTab.pBold, aWeight,
1763 						&aAttrTab.pBoldCJK, &aWeightCJK,
1764 						&aAttrTab.pBoldCTL, &aWeightCTL );
1765 		}
1766 		break;
1767 
1768 
1769 	case HTML_STRIKE_ON:
1770 	case HTML_STRIKETHROUGH_ON:
1771 		{
1772 			NewStdAttr( HTML_STRIKE_ON, &aAttrTab.pStrike,
1773                         SvxCrossedOutItem(STRIKEOUT_SINGLE, RES_CHRATR_CROSSEDOUT) );
1774 		}
1775 		break;
1776 
1777 	case HTML_UNDERLINE_ON:
1778 		{
1779 			NewStdAttr( HTML_UNDERLINE_ON, &aAttrTab.pUnderline,
1780                         SvxUnderlineItem(UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE) );
1781 		}
1782 		break;
1783 
1784 	case HTML_SUPERSCRIPT_ON:
1785 		{
1786 			NewStdAttr( HTML_SUPERSCRIPT_ON, &aAttrTab.pEscapement,
1787                         SvxEscapementItem(HTML_ESC_SUPER,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1788 		}
1789 		break;
1790 
1791 	case HTML_SUBSCRIPT_ON:
1792 		{
1793 			NewStdAttr( HTML_SUBSCRIPT_ON, &aAttrTab.pEscapement,
1794                         SvxEscapementItem(HTML_ESC_SUB,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1795 		}
1796 		break;
1797 
1798 	case HTML_BLINK_ON:
1799 		{
1800 			NewStdAttr( HTML_BLINK_ON, &aAttrTab.pBlink,
1801                         SvxBlinkItem( sal_True, RES_CHRATR_BLINK ) );
1802 		}
1803 		break;
1804 
1805 	case HTML_SPAN_ON:
1806 		NewStdAttr( HTML_SPAN_ON );
1807 		break;
1808 
1809 
1810 	case HTML_ITALIC_OFF:
1811 	case HTML_BOLD_OFF:
1812 	case HTML_STRIKE_OFF:
1813 	case HTML_UNDERLINE_OFF:
1814 	case HTML_SUPERSCRIPT_OFF:
1815 	case HTML_SUBSCRIPT_OFF:
1816 	case HTML_BLINK_OFF:
1817 	case HTML_SPAN_OFF:
1818 		EndTag( nToken );
1819 		break;
1820 
1821 	case HTML_STRIKETHROUGH_OFF:
1822 		EndTag( HTML_STRIKE_OFF );
1823 		break;
1824 
1825 	case HTML_BASEFONT_ON:
1826 		NewBasefontAttr();
1827 		break;
1828 	case HTML_BASEFONT_OFF:
1829 		EndBasefontAttr();
1830 		break;
1831 	case HTML_FONT_ON:
1832 	case HTML_BIGPRINT_ON:
1833 	case HTML_SMALLPRINT_ON:
1834 		NewFontAttr( nToken );
1835 		break;
1836 	case HTML_FONT_OFF:
1837 	case HTML_BIGPRINT_OFF:
1838 	case HTML_SMALLPRINT_OFF:
1839 		EndFontAttr( nToken );
1840 		break;
1841 
1842 	case HTML_EMPHASIS_ON:
1843 	case HTML_CITIATION_ON:
1844 	case HTML_STRONG_ON:
1845 	case HTML_CODE_ON:
1846 	case HTML_SAMPLE_ON:
1847 	case HTML_KEYBOARD_ON:
1848 	case HTML_VARIABLE_ON:
1849 	case HTML_DEFINSTANCE_ON:
1850 	case HTML_SHORTQUOTE_ON:
1851 	case HTML_LANGUAGE_ON:
1852 	case HTML_AUTHOR_ON:
1853 	case HTML_PERSON_ON:
1854 	case HTML_ACRONYM_ON:
1855 	case HTML_ABBREVIATION_ON:
1856 	case HTML_INSERTEDTEXT_ON:
1857 	case HTML_DELETEDTEXT_ON:
1858 
1859 	case HTML_TELETYPE_ON:
1860 		NewCharFmt( nToken );
1861 		break;
1862 
1863 	case HTML_SDFIELD_ON:
1864 		NewField();
1865 		bCallNextToken = bInField && pTable!=0;
1866 		break;
1867 
1868 	case HTML_EMPHASIS_OFF:
1869 	case HTML_CITIATION_OFF:
1870 	case HTML_STRONG_OFF:
1871 	case HTML_CODE_OFF:
1872 	case HTML_SAMPLE_OFF:
1873 	case HTML_KEYBOARD_OFF:
1874 	case HTML_VARIABLE_OFF:
1875 	case HTML_DEFINSTANCE_OFF:
1876 	case HTML_SHORTQUOTE_OFF:
1877 	case HTML_LANGUAGE_OFF:
1878 	case HTML_AUTHOR_OFF:
1879 	case HTML_PERSON_OFF:
1880 	case HTML_ACRONYM_OFF:
1881 	case HTML_ABBREVIATION_OFF:
1882 	case HTML_INSERTEDTEXT_OFF:
1883 	case HTML_DELETEDTEXT_OFF:
1884 
1885 	case HTML_TELETYPE_OFF:
1886 		EndTag( nToken );
1887 		break;
1888 
1889 	case HTML_HEAD_OFF:
1890 		if( aStyleSource.Len() )
1891 		{
1892 			pCSS1Parser->ParseStyleSheet( aStyleSource );
1893 			aStyleSource.Erase();
1894 		}
1895 		break;
1896 
1897 	case HTML_DOCTYPE:
1898 	case HTML_BODY_OFF:
1899 	case HTML_HTML_OFF:
1900 	case HTML_HEAD_ON:
1901 	case HTML_TITLE_OFF:
1902 		break;		// nicht weiter auswerten, oder???
1903 	case HTML_HTML_ON:
1904 		{
1905 			const HTMLOptions *pHTMLOptions = GetOptions();
1906 			for( sal_uInt16 i = pHTMLOptions->Count(); i; )
1907 			{
1908 				const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1909 				if( HTML_O_DIR == pOption->GetToken() )
1910 				{
1911 					const String& rDir = pOption->GetString();
1912 					SfxItemSet aItemSet( pDoc->GetAttrPool(),
1913 										 pCSS1Parser->GetWhichMap() );
1914 					SvxCSS1PropertyInfo aPropInfo;
1915 					String aDummy;
1916 					ParseStyleOptions( aDummy, aDummy, aDummy, aItemSet,
1917 									   aPropInfo, 0, &rDir );
1918 
1919 					pCSS1Parser->SetPageDescAttrs( 0, &aItemSet );
1920 					break;
1921 				}
1922 			}
1923 		}
1924 		break;
1925 
1926 	case HTML_INPUT:
1927 		InsertInput();
1928 		break;
1929 
1930 	case HTML_TEXTAREA_ON:
1931 		NewTextArea();
1932 		bCallNextToken = bTextArea && pTable!=0;
1933 		break;
1934 
1935 	case HTML_SELECT_ON:
1936 		NewSelect();
1937 		bCallNextToken = bSelect && pTable!=0;
1938 		break;
1939 
1940 	case HTML_ANCHOR_ON:
1941 		NewAnchor();
1942 		break;
1943 
1944 	case HTML_ANCHOR_OFF:
1945 		EndAnchor();
1946 		break;
1947 
1948 	case HTML_COMMENT:
1949 		if( ( aToken.Len() > 5 ) && ( ! bIgnoreHTMLComments ) )
1950 		{
1951 			// als Post-It einfuegen
1952 			// MIB 8.12.2000: If there are no space characters right behind
1953 			// the <!-- and on front of the -->, leave the comment untouched.
1954 			if( ' ' == aToken.GetChar( 3 ) &&
1955 				' ' == aToken.GetChar( aToken.Len()-3 ) )
1956 			{
1957 				String aComment( aToken.Copy( 3, aToken.Len()-5 ) );
1958 				aComment.EraseLeadingChars().EraseTrailingChars();
1959 				InsertComment( aComment );
1960 			}
1961 			else
1962 			{
1963 				String aComment( '<' );
1964 				(aComment += aToken) += '>';
1965 				InsertComment( aComment );
1966 			}
1967 		}
1968 		break;
1969 
1970 	case HTML_MAP_ON:
1971 		// Image Maps werden asynchron gelesen: Zunaechst wird nur eine
1972 		// ImageMap angelegt. Die Bereiche kommen spaeter. Trozdem wird
1973 		// die ImageMap schon in das IMap-Array eingetragen, denn sie
1974 		// koennte ja schon verwendet werden.
1975 		pImageMap = new ImageMap;
1976 		if( ParseMapOptions( pImageMap) )
1977 		{
1978 			if( !pImageMaps )
1979 				pImageMaps = new ImageMaps;
1980 			pImageMaps->Insert( pImageMap, pImageMaps->Count() );
1981 		}
1982 		else
1983 		{
1984 			delete pImageMap;
1985 			pImageMap = 0;
1986 		}
1987 		break;
1988 
1989 	case HTML_MAP_OFF:
1990 		// jetzt gibt es keine ImageMap mehr (IMap nicht Loeschen, denn
1991 		// die stckt ja schon in dem Array!)
1992 		pImageMap = 0;
1993 		break;
1994 
1995 	case HTML_AREA:
1996 		if( pImageMap )
1997             ParseAreaOptions( pImageMap, sBaseURL, SFX_EVENT_MOUSEOVER_OBJECT,
1998 										 SFX_EVENT_MOUSEOUT_OBJECT );
1999 		break;
2000 
2001 	case HTML_FRAMESET_ON:
2002 		bInsertUnknown = bKeepUnknown;
2003 		break;
2004 
2005 	case HTML_NOFRAMES_ON:
2006 		if( IsInHeader() )
2007 			FinishHeader( sal_True );
2008 		bInsertUnknown = bKeepUnknown;
2009 		break;
2010 
2011 	case HTML_UNKNOWNCONTROL_ON:
2012 		// Im Header muss der Inhalt von unbekannten Token ignoriert werden,
2013 		// es sei denn, das Token faengt mit einem '!' an.
2014 		if( IsInHeader() && !IsReadPRE() && !aUnknownToken.Len() &&
2015 			sSaveToken.Len() && '!' != sSaveToken.GetChar(0) &&
2016 			'%' != sSaveToken.GetChar(0) )
2017 			aUnknownToken = sSaveToken;
2018 		// kein break
2019 
2020 	default:
2021 		bInsertUnknown = bKeepUnknown;
2022 		break;
2023 	}
2024 
2025 	if( bGetIDOption )
2026 		InsertIDOption();
2027 
2028 	if( bInsertUnknown )
2029 	{
2030 		String aComment(
2031 			String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
2032 		if( (HTML_TOKEN_ONOFF & nToken) != 0 && (1 & nToken) != 0 )
2033 			aComment += '/';
2034 		aComment += sSaveToken;
2035 		if( aToken.Len() )
2036 		{
2037 			UnescapeToken();
2038 			(aComment += ' ') += aToken;
2039 		}
2040 		aComment += '>';
2041 		InsertComment( aComment );
2042 	}
2043 
2044 	// wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber
2045 	// nicht leer ist, dann sind die Absatz-Attribute entgueltig.
2046 	if( aParaAttrs.Count() && pPam->GetPoint()->nContent.GetIndex() )
2047 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
2048 }
2049 
2050 /*  */
2051 
2052 extern sal_Bool lcl_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 );
2053 
lcl_swhtml_getItemInfo(const _HTMLAttr & rAttr,sal_Bool & rScriptDependent,sal_Bool & rFont,sal_uInt16 & rScriptType)2054 void lcl_swhtml_getItemInfo( const _HTMLAttr& rAttr,
2055 								 sal_Bool& rScriptDependent, sal_Bool& rFont,
2056 								 sal_uInt16& rScriptType )
2057 {
2058 	sal_uInt16 nWhich = rAttr.GetItem().Which();
2059 	switch( nWhich )
2060 	{
2061 	case RES_CHRATR_FONT:
2062 		rFont = sal_True;
2063 	case RES_CHRATR_FONTSIZE:
2064 	case RES_CHRATR_LANGUAGE:
2065 	case RES_CHRATR_POSTURE:
2066 	case RES_CHRATR_WEIGHT:
2067         rScriptType = i18n::ScriptType::LATIN;
2068 		rScriptDependent = sal_True;
2069 		break;
2070 	case RES_CHRATR_CJK_FONT:
2071 		rFont = sal_True;
2072 	case RES_CHRATR_CJK_FONTSIZE:
2073 	case RES_CHRATR_CJK_LANGUAGE:
2074 	case RES_CHRATR_CJK_POSTURE:
2075 	case RES_CHRATR_CJK_WEIGHT:
2076         rScriptType = i18n::ScriptType::ASIAN;
2077 		rScriptDependent = sal_True;
2078 		break;
2079 	case RES_CHRATR_CTL_FONT:
2080 		rFont = sal_True;
2081 	case RES_CHRATR_CTL_FONTSIZE:
2082 	case RES_CHRATR_CTL_LANGUAGE:
2083 	case RES_CHRATR_CTL_POSTURE:
2084 	case RES_CHRATR_CTL_WEIGHT:
2085         rScriptType = i18n::ScriptType::COMPLEX;
2086 		rScriptDependent = sal_True;
2087 		break;
2088 	default:
2089 		rScriptDependent = sal_False;
2090 		rFont = sal_False;
2091 		break;
2092 	}
2093 }
2094 
AppendTxtNode(SwHTMLAppendMode eMode,sal_Bool bUpdateNum)2095 sal_Bool SwHTMLParser::AppendTxtNode( SwHTMLAppendMode eMode, sal_Bool bUpdateNum )
2096 {
2097 	// Ein harter Zeilen-Umbruch am Ende muss immer entfernt werden.
2098 	// Einen zweiten ersetzen wir durch einen Absatz-Abstand.
2099 	xub_StrLen nLFStripped = StripTrailingLF();
2100 	if( (AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode) && nLFStripped > 1 )
2101 		eMode = AM_SPACE;
2102 
2103 	// die harten Attribute an diesem Absatz werden nie mehr ungueltig
2104 	if( aParaAttrs.Count() )
2105 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
2106 
2107 	if( AM_SPACE==eMode || AM_NOSPACE==eMode )
2108 	{
2109 		SwTxtNode *pTxtNode =
2110             pPam->GetPoint()->nNode.GetNode().GetTxtNode();
2111 
2112 		const SvxULSpaceItem& rULSpace =
2113 			(const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2114 
2115 		sal_Bool bChange = AM_NOSPACE==eMode ? rULSpace.GetLower() > 0
2116 										 : rULSpace.GetLower() == 0;
2117 
2118 		if( bChange )
2119 		{
2120 			const SvxULSpaceItem& rCollULSpace =
2121 				pTxtNode->GetAnyFmtColl().GetULSpace();
2122 
2123 			sal_Bool bMayReset = AM_NOSPACE==eMode ? rCollULSpace.GetLower() == 0
2124 											   : rCollULSpace.GetLower() > 0;
2125 
2126 			if( bMayReset &&
2127 				rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2128 			{
2129 				pTxtNode->ResetAttr( RES_UL_SPACE );
2130 			}
2131 			else
2132 			{
2133                 pTxtNode->SetAttr(
2134 					SvxULSpaceItem( rULSpace.GetUpper(),
2135                          AM_NOSPACE==eMode ? 0 : HTML_PARSPACE, RES_UL_SPACE ) );
2136 			}
2137 		}
2138 	}
2139 	bNoParSpace = AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode;
2140 
2141 	SwPosition aOldPos( *pPam->GetPoint() );
2142 
2143 	sal_Bool bRet = pDoc->AppendTxtNode( *pPam->GetPoint() );
2144 
2145 	// Zeichen-Attribute aufspalten und ggf keine setzen, die ueber den
2146 	// ganzen Absatz gesetzt sind
2147 	const SwNodeIndex& rEndIdx = aOldPos.nNode;
2148 	xub_StrLen nEndCnt = aOldPos.nContent.GetIndex();
2149 	const SwPosition& rPos = *pPam->GetPoint();
2150 
2151 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
2152 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
2153 		 nCnt--; ++pTbl )
2154 	{
2155 		_HTMLAttr *pAttr = *pTbl;
2156 		if( pAttr && pAttr->GetItem().Which() < RES_PARATR_BEGIN )
2157 		{
2158 			sal_Bool bWholePara = sal_False;
2159 
2160 			while( pAttr )
2161 			{
2162 				_HTMLAttr *pNext = pAttr->GetNext();
2163 				if( pAttr->GetSttParaIdx() < rEndIdx.GetIndex() ||
2164 					(!bWholePara &&
2165 					 pAttr->GetSttPara() == rEndIdx &&
2166 					 pAttr->GetSttCnt() != nEndCnt) )
2167 				{
2168 					bWholePara =
2169 						pAttr->GetSttPara() == rEndIdx &&
2170 						pAttr->GetSttCnt() == 0;
2171 
2172 					xub_StrLen nStt = pAttr->nSttCntnt;
2173 					sal_Bool bScript = sal_False, bFont = sal_False;
2174 					sal_uInt16 nScriptItem;
2175 					sal_Bool bInsert = sal_True;
2176 				   	lcl_swhtml_getItemInfo( *pAttr, bScript, bFont,
2177 											nScriptItem );
2178 						// den besehrigen Teil setzen
2179 					if( bInsert && bScript )
2180 					{
2181 						const SwTxtNode *pTxtNd =
2182 							pAttr->GetSttPara().GetNode().GetTxtNode();
2183 						ASSERT( pTxtNd, "No text node" );
2184 						if( pTxtNd )
2185 						{
2186 							const String& rText = pTxtNd->GetTxt();
2187 							sal_uInt16 nScriptTxt =
2188 								pBreakIt->GetBreakIter()->getScriptType(
2189 											rText, pAttr->GetSttCnt() );
2190 							xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2191 									->endOfScript( rText, nStt, nScriptTxt );
2192 							while( nScriptEnd < nEndCnt )
2193 							{
2194 								if( nScriptItem == nScriptTxt )
2195 								{
2196 									_HTMLAttr *pSetAttr =
2197 										pAttr->Clone( rEndIdx, nScriptEnd );
2198 									pSetAttr->nSttCntnt = nStt;
2199 									pSetAttr->ClearPrev();
2200 									if( !pNext || bWholePara )
2201 									{
2202 										sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
2203 														: aSetAttrTab.Count();
2204 										aSetAttrTab.Insert( pSetAttr, nTmp );
2205 									}
2206 									else
2207 										pNext->InsertPrev( pSetAttr );
2208 								}
2209 								nStt = nScriptEnd;
2210 								nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
2211 												rText, nStt );
2212 								nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2213 									->endOfScript( rText, nStt, nScriptTxt );
2214 							}
2215 							bInsert = nScriptItem == nScriptTxt;
2216 						}
2217 					}
2218 					if( bInsert )
2219 					{
2220 						_HTMLAttr *pSetAttr =
2221 							pAttr->Clone( rEndIdx, nEndCnt );
2222 						pSetAttr->nSttCntnt = nStt;
2223 
2224 						// Wenn das Attribut den gesamten Absatz umspannt, werden
2225 						// alle auesseren Attribute nicht mehr beachtet. Deshalb
2226 						// darf es auch nicht in die Prev-Liste eines ausseren
2227 						// Attributs eingetragen werden, denn dieses wird ja
2228 						// erstmal nicht gesetzt. Das fuehrt zu verschiebenungen,
2229 						// wenn Felder ins Rennen kommen (siehe #51020#)
2230 						if( !pNext || bWholePara )
2231 						{
2232 							sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
2233 															 : aSetAttrTab.Count();
2234 							aSetAttrTab.Insert( pSetAttr, nTmp );
2235 						}
2236 						else
2237 							pNext->InsertPrev( pSetAttr );
2238 					}
2239 					else
2240 					{
2241 						_HTMLAttr *pPrev = pAttr->GetPrev();
2242 						if( pPrev )
2243 						{
2244 							// Die Previous-Attribute muessen trotzdem gesetzt werden.
2245 							if( !pNext || bWholePara )
2246 							{
2247 								sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
2248 								aSetAttrTab.Insert( pPrev, nTmp );
2249 							}
2250 							else
2251 								pNext->InsertPrev( pPrev );
2252 						}
2253 					}
2254 					pAttr->ClearPrev();
2255 				}
2256 
2257 				pAttr->SetStart( rPos );
2258 				pAttr = pNext;
2259 			}
2260 		}
2261 	}
2262 
2263     if( bUpdateNum )
2264     {
2265         if( GetNumInfo().GetDepth() )
2266         {
2267             sal_uInt8 nLvl = GetNumInfo().GetLevel();
2268             SetNodeNum( nLvl, false );
2269         }
2270         else
2271             pPam->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE );
2272     }
2273 
2274     // Attrubute im Absatz davor sollte man jetzt setzen (wegen JavaScript)
2275     SetAttr();
2276 
2277 	// Now it is time to get rid of all script dependent hints that are
2278 	// equal to the settings in the style
2279 	SwTxtNode *pTxtNd = rEndIdx.GetNode().GetTxtNode();
2280 	ASSERT( pTxtNd, "There is the txt node" );
2281 	sal_uInt16 nCntAttr = (pTxtNd  && pTxtNd->GetpSwpHints())
2282 							? pTxtNd->GetSwpHints().Count() : 0;
2283 	if( nCntAttr )
2284 	{
2285 		// These are the end position of all script depenent hints.
2286 		// If we find a hint that starts before the current end position,
2287 		// we have to set it. If we finf a hint that start behind or at
2288 		// that position, we have to take the hint's value into account.
2289 		// If it is equal to the style, or in fact the paragarph's value
2290 		// for that hint, the hint is removed. Otherwise it's end position
2291 		// is remembered.
2292 		xub_StrLen aEndPos[15] =
2293 			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2294 		SwpHints& rHints = pTxtNd->GetSwpHints();
2295 		for( sal_uInt16 i=0; i < nCntAttr; i++ )
2296 		{
2297             SwTxtAttr *pHt = rHints.GetTextHint( i );
2298 			sal_uInt16 nWhich = pHt->Which();
2299 			sal_Int16 nIdx = -1;
2300 			if( RES_CHRATR_CJK_FONT <= nWhich &&
2301 					nWhich <= RES_CHRATR_CTL_WEIGHT )
2302 			{
2303                 nIdx = static_cast< sal_uInt16 >(nWhich - RES_CHRATR_CJK_FONT + 5);
2304 			}
2305 			else switch( nWhich )
2306 			{
2307 			case RES_CHRATR_FONT:		nIdx = 0;	break;
2308 			case RES_CHRATR_FONTSIZE:	nIdx = 1;	break;
2309 			case RES_CHRATR_LANGUAGE:	nIdx = 2;	break;
2310 			case RES_CHRATR_POSTURE:	nIdx = 3;	break;
2311 			case RES_CHRATR_WEIGHT:		nIdx = 4;	break;
2312 			}
2313 			if( nIdx != -1 )
2314 			{
2315 				xub_StrLen nStt = *pHt->GetStart();
2316 				if( nStt >= aEndPos[nIdx] )
2317 				{
2318 					sal_Bool bFont = (nIdx % 5) == 0;
2319 					const SfxPoolItem& rItem =
2320 						((const SwCntntNode *)pTxtNd)->GetAttr( nWhich );
2321 					if( bFont ? lcl_css1atr_equalFontItems(rItem,pHt->GetAttr())
2322 							  : rItem == pHt->GetAttr() )
2323 					{
2324 						// The hint is the same as set in the paragraph and
2325 						// therfor, it can be deleted
2326 						// CAUTION!!! This WILL delete the hint and it MAY
2327 						// also delete the SwpHints!!! To avoid any trouble
2328 						// we leave the loop immediately if this is the last
2329 						// hint.
2330                         pTxtNd->DeleteAttribute( pHt );
2331 						if( 1 == nCntAttr )
2332 							break;
2333 						i--;
2334 						nCntAttr--;
2335 					}
2336 					else
2337 					{
2338 						// The hint is deifferent. Therfor all hints within that
2339 						// hint have to be ignored.
2340 						aEndPos[nIdx] = pHt->GetEnd() ? *pHt->GetEnd() : nStt;
2341 					}
2342 				}
2343 				else
2344 				{
2345 					// The hint starts before another one ends.
2346 					// The hint in this case is not deleted
2347 					ASSERT( pHt->GetEnd() && *pHt->GetEnd() <= aEndPos[nIdx],
2348 							"hints aren't nested properly!" );
2349 				}
2350 			}
2351 		}
2352 	}
2353 
2354 
2355 	if( !pTable && !--nParaCnt )
2356 		Show();
2357 
2358 	return bRet;
2359 }
2360 
AddParSpace()2361 void SwHTMLParser::AddParSpace()
2362 {
2363 	if( !bNoParSpace )
2364 		return;
2365 
2366 	bNoParSpace = sal_False;
2367 
2368 	sal_uLong nNdIdx = pPam->GetPoint()->nNode.GetIndex() - 1;
2369 
2370 	SwTxtNode *pTxtNode = pDoc->GetNodes()[nNdIdx]->GetTxtNode();
2371 	if( !pTxtNode )
2372 		return;
2373 
2374 	SvxULSpaceItem rULSpace =
2375 		(const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2376 	if( !rULSpace.GetLower() )
2377 	{
2378 		const SvxULSpaceItem& rCollULSpace =
2379 			pTxtNode->GetAnyFmtColl().GetULSpace();
2380 		if( rCollULSpace.GetLower() &&
2381 			rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2382 		{
2383 			pTxtNode->ResetAttr( RES_UL_SPACE );
2384 		}
2385 		else
2386 		{
2387             pTxtNode->SetAttr(
2388                 SvxULSpaceItem( rULSpace.GetUpper(), HTML_PARSPACE, RES_UL_SPACE )  );
2389 		}
2390 	}
2391 }
2392 
2393 
Show()2394 void SwHTMLParser::Show()
2395 {
2396 	// Hier wird
2397 	// - ein EndAction gerufen, damit formatiert wird
2398 	// - ein Reschedule gerufen,
2399 	// - die eiegen View-Shell wieder gesetzt
2400 	// - und Start-Action gerufen
2401 
2402 	ASSERT( SVPAR_WORKING==eState, "Show nicht im Working-State - Das kann ins Auge gehen" );
2403 	ViewShell *pOldVSh = CallEndAction();
2404 
2405 	GetpApp()->Reschedule();
2406 
2407 	if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2408 		|| 1 == pDoc->getReferenceCount() )
2409 	{
2410 		// wurde der Import vom SFX abgebrochen?
2411 		eState = SVPAR_ERROR;
2412 	}
2413 
2414 	// Die ViewShell nochmal holen, denn sie koennte im Reschedule
2415 	// zerstoert wirden sein.
2416 	ViewShell *pVSh = CallStartAction( pOldVSh );
2417 
2418 	// ist der aktuelle Node nicht mehr sichtbar, dann benutzen wir
2419 	// eine groessere Schrittweite
2420 	if( pVSh )
2421     {
2422         nParaCnt = (pPam->GetPoint()->nNode.GetNode().IsInVisibleArea(pVSh))
2423             ? 5 : 50;
2424     }
2425 }
2426 
ShowStatline()2427 void SwHTMLParser::ShowStatline()
2428 {
2429 	// Hier wird
2430 	// - ein Reschedule gerufen, damit gescrollt werden kann
2431 	// - die eiegen View-Shell wieder gesetzt
2432 	// - ein Start/End-Action gerufen, wenn gescrollt wurde.
2433 
2434 	ASSERT( SVPAR_WORKING==eState, "ShowStatLine nicht im Working-State - Das kann ins Auge gehen" );
2435 
2436 	// Laufbalkenanzeige
2437 	if( !GetMedium() || !GetMedium()->IsRemote() )
2438 	{
2439 		::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
2440 		CheckActionViewShell();
2441 	}
2442 	else
2443 	{
2444 		GetpApp()->Reschedule();
2445 
2446 		if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2447 			|| 1 == pDoc->getReferenceCount() )
2448 			// wurde der Import vom SFX abgebrochen?
2449 			eState = SVPAR_ERROR;
2450 
2451 		ViewShell *pVSh = CheckActionViewShell();
2452 		if( pVSh && pVSh->HasInvalidRect() )
2453 		{
2454 			CallEndAction( sal_False, sal_False );
2455 			CallStartAction( pVSh, sal_False );
2456 		}
2457 	}
2458 }
2459 
CallStartAction(ViewShell * pVSh,sal_Bool bChkPtr)2460 ViewShell *SwHTMLParser::CallStartAction( ViewShell *pVSh, sal_Bool bChkPtr )
2461 {
2462 	ASSERT( !pActionViewShell, "CallStartAction: ViewShell schon gesetzt" );
2463 
2464 	if( !pVSh || bChkPtr )
2465 	{
2466 #ifdef DBG_UTIL
2467 		ViewShell *pOldVSh = pVSh;
2468 #endif
2469 		pDoc->GetEditShell( &pVSh );
2470 		ASSERT( !pVSh || !pOldVSh || pOldVSh == pVSh, "CallStartAction: Wer hat die ViewShell ausgetauscht?" );
2471 #ifdef DBG_UTIL
2472 		if( pOldVSh && !pVSh )
2473 			pVSh = 0;
2474 #endif
2475 	}
2476 	pActionViewShell = pVSh;
2477 
2478 	if( pActionViewShell )
2479 	{
2480 		if( pActionViewShell->ISA( SwEditShell ) )
2481 			((SwEditShell*)pActionViewShell)->StartAction();
2482 		else
2483 			pActionViewShell->StartAction();
2484 	}
2485 
2486 	return pActionViewShell;
2487 }
2488 
CallEndAction(sal_Bool bChkAction,sal_Bool bChkPtr)2489 ViewShell *SwHTMLParser::CallEndAction( sal_Bool bChkAction, sal_Bool bChkPtr )
2490 {
2491 	if( bChkPtr )
2492 	{
2493 		ViewShell *pVSh = 0;
2494 		pDoc->GetEditShell( &pVSh );
2495 		ASSERT( !pVSh || pActionViewShell == pVSh,
2496 				"CallEndAction: Wer hat die ViewShell ausgetauscht?" );
2497 #if OSL_DEBUG_LEVEL > 1
2498 		if( pActionViewShell && !pVSh )
2499 			pVSh = 0;
2500 #endif
2501 		if( pVSh != pActionViewShell )
2502 			pActionViewShell = 0;
2503 	}
2504 
2505 	if( !pActionViewShell || (bChkAction && !pActionViewShell->ActionPend()) )
2506 		return pActionViewShell;
2507 
2508 	if( bSetCrsr )
2509 	{
2510 		// an allen CrsrEditShells die Cursor auf den Doc-Anfang setzen
2511 		ViewShell *pSh = pActionViewShell;
2512 		do {
2513 			if( pSh->IsA( TYPE( SwCrsrShell ) ) )
2514 				((SwCrsrShell*)pSh)->SttEndDoc(sal_True);
2515 			pSh = (ViewShell *)pSh->GetNext();
2516 		} while( pSh != pActionViewShell );
2517 
2518 		bSetCrsr = sal_False;
2519 	}
2520 	if( pActionViewShell->ISA( SwEditShell ) )
2521 	{
2522 		//Schon gescrollt?, dann dafuer sorgen, dass die View sich nicht bewegt!
2523 		const sal_Bool bOldLock = pActionViewShell->IsViewLocked();
2524 		pActionViewShell->LockView( sal_True );
2525 		const sal_Bool bOldEndActionByVirDev = pActionViewShell->IsEndActionByVirDev();
2526 		pActionViewShell->SetEndActionByVirDev( sal_True );;
2527 		((SwEditShell*)pActionViewShell)->EndAction();
2528 		pActionViewShell->SetEndActionByVirDev( bOldEndActionByVirDev );
2529 		pActionViewShell->LockView( bOldLock );
2530 
2531 		// bChkJumpMark ist nur gesetzt, wenn das Object auch gefunden wurde
2532 		if( bChkJumpMark )
2533 		{
2534 			const Point aVisSttPos( DOCUMENTBORDER, DOCUMENTBORDER );
2535 			if( GetMedium() && aVisSttPos == pActionViewShell->VisArea().Pos() )
2536 				::JumpToSwMark( pActionViewShell,
2537 								GetMedium()->GetURLObject().GetMark() );
2538 			bChkJumpMark = sal_False;
2539 		}
2540 	}
2541 	else
2542 		pActionViewShell->EndAction();
2543 
2544 	// sollte der Parser der Letzte sein, der das Doc haelt, dann kann
2545 	// man hier abbrechen und einen Fehler setzen.
2546 	if( 1 == pDoc->getReferenceCount() )
2547 	{
2548 		eState = SVPAR_ERROR;
2549 	}
2550 
2551 	ViewShell *pVSh = pActionViewShell;
2552 	pActionViewShell = 0;
2553 
2554 	return pVSh;
2555 }
2556 
CheckActionViewShell()2557 ViewShell *SwHTMLParser::CheckActionViewShell()
2558 {
2559 	ViewShell *pVSh = 0;
2560 	pDoc->GetEditShell( &pVSh );
2561 	ASSERT( !pVSh || pActionViewShell == pVSh,
2562 			"CheckActionViewShell: Wer hat die ViewShell ausgetauscht?" );
2563 #if OSL_DEBUG_LEVEL > 1
2564 	if( pActionViewShell && !pVSh )
2565 		pVSh = 0;
2566 #endif
2567 	if( pVSh != pActionViewShell )
2568 		pActionViewShell = 0;
2569 
2570 	return pActionViewShell;
2571 }
2572 
2573 /*  */
2574 
_SetAttr(sal_Bool bChkEnd,sal_Bool bBeforeTable,_HTMLAttrs * pPostIts)2575 void SwHTMLParser::_SetAttr( sal_Bool bChkEnd, sal_Bool bBeforeTable,
2576 							 _HTMLAttrs *pPostIts )
2577 {
2578 	SwPaM* pAttrPam = new SwPaM( *pPam->GetPoint() );
2579 	const SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
2580 	xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2581 	_HTMLAttr* pAttr;
2582 	SwCntntNode* pCNd;
2583 	sal_uInt16 n;
2584 
2585 	_HTMLAttrs aFields( 5, 5 );
2586 
2587 	for( n = aSetAttrTab.Count(); n; )
2588 	{
2589 		pAttr = aSetAttrTab[ --n ];
2590 		sal_uInt16 nWhich = pAttr->pItem->Which();
2591 
2592 		sal_uLong nEndParaIdx = pAttr->GetEndParaIdx();
2593 		sal_Bool bSetAttr;
2594 		if( bChkEnd )
2595 		{
2596 			// fix #42192#: Zechen-Attribute mit Ende moeglich frueh,
2597 			// also noch im aktuellen Absatz setzen (wegen JavaScript
2598 			// und diversen Chats). das darf man aber nicht fuer Attribute,
2599 			// die ueber den ganzen Absatz aufgspannt werden sollen, weil
2600 			// sie aus Absatzvorlgen stammen, die nicht gesetzt werden
2601 			// koennen. Weil die Attribute mit SETATTR_DONTREPLACE
2602 			// eingefuegt werden, sollte man sie auch anchtraeglich
2603 			// noch setzen koennen.
2604 			bSetAttr = ( nEndParaIdx < rEndIdx.GetIndex() &&
2605 						 (RES_LR_SPACE != nWhich || !GetNumInfo().GetNumRule()) ) ||
2606 					   ( !pAttr->IsLikePara() &&
2607 						 nEndParaIdx == rEndIdx.GetIndex() &&
2608 						 pAttr->GetEndCnt() < nEndCnt &&
2609                          (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)) ) ||
2610 					   ( bBeforeTable &&
2611 						 nEndParaIdx == rEndIdx.GetIndex() &&
2612 						 !pAttr->GetEndCnt() );
2613 		}
2614 		else
2615 		{
2616 			// Attribiute im Content-Bereich duerfen nicht gesetzt
2617 			// werden, wenn wir in einem Sonderbereich stehen, aber
2618 			// umgekekehrt schon.
2619 			sal_uLong nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2620 			bSetAttr = nEndParaIdx < rEndIdx.GetIndex() ||
2621 					   rEndIdx.GetIndex() > nEndOfIcons ||
2622 					   nEndParaIdx <= nEndOfIcons;
2623 		}
2624 
2625 		if( bSetAttr )
2626 		{
2627 			// Das Attribute darf nicht in der liste der vorlaeufigen
2628 			// Absatz-Attribute stehen, weil es sonst geloescht wurde.
2629 			sal_uInt16 ii = aParaAttrs.Count();
2630 			while( ii-- )
2631 			{
2632 				ASSERT( pAttr != aParaAttrs[ii],
2633 						"SetAttr: Attribut duerfte noch nicht gesetzt werden" );
2634 				aParaAttrs.Remove( ii );
2635 			}
2636 
2637 
2638 			// dann also setzen
2639 			aSetAttrTab.Remove( n, 1 );
2640 
2641 			while( pAttr )
2642 			{
2643 				_HTMLAttr *pPrev = pAttr->GetPrev();
2644 				if( !pAttr->bValid )
2645 				{
2646 					// ungueltige Attribute koennen gloescht werden
2647 					delete pAttr;
2648 					pAttr = pPrev;
2649 					continue; //break;
2650 				}
2651 
2652 
2653                 pCNd = pAttr->nSttPara.GetNode().GetCntntNode();
2654 				if( !pCNd )
2655 				{
2656 					// durch die elende Loescherei von Nodes kann auch mal
2657 					// ein Index auf einen End-Node zeigen :-(
2658                     if ( (pAttr->GetSttPara() == pAttr->GetEndPara()) &&
2659                          !isTXTATR_NOEND(nWhich) )
2660 					{
2661 						// wenn der End-Index auch auf den Node zeigt
2662 						// brauchen wir auch kein Attribut mehr zu setzen,
2663 						// es sei denn, es ist ein Text-Attribut.
2664 						delete pAttr;
2665 						pAttr = pPrev;
2666 						continue; //break;
2667 					}
2668 					pCNd = pDoc->GetNodes().GoNext( &(pAttr->nSttPara) );
2669 					if( pCNd )
2670 						pAttr->nSttCntnt = 0;
2671 					else
2672 					{
2673 						ASSERT( !this, "SetAttr: GoNext() failed!" );
2674 						delete pAttr;
2675 						pAttr = pPrev;
2676 						continue; // break;
2677 					}
2678 				}
2679 				pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2680 
2681 
2682 
2683 				// durch das Loeschen von BRs kann der Start-Index
2684 				// auch mal hinter das Ende des Textes zeigen
2685 				if( pAttr->nSttCntnt > pCNd->Len() )
2686 					pAttr->nSttCntnt = pCNd->Len();
2687 				pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2688 
2689 				pAttrPam->SetMark();
2690                 if ( (pAttr->GetSttPara() != pAttr->GetEndPara()) &&
2691                          !isTXTATR_NOEND(nWhich) )
2692                 {
2693                     pCNd = pAttr->nEndPara.GetNode().GetCntntNode();
2694 					if( !pCNd )
2695 					{
2696 						pCNd = pDoc->GetNodes().GoPrevious( &(pAttr->nEndPara) );
2697 						if( pCNd )
2698 							pAttr->nEndCntnt = pCNd->Len();
2699 						else
2700 						{
2701 							ASSERT( !this, "SetAttr: GoPrevious() failed!" );
2702 							pAttrPam->DeleteMark();
2703 							delete pAttr;
2704 							pAttr = pPrev;
2705 							continue; // break;
2706 						}
2707 					}
2708 
2709 					pAttrPam->GetPoint()->nNode = pAttr->nEndPara;
2710 				}
2711 				else if( pAttr->IsLikePara() )
2712 				{
2713 					pAttr->nEndCntnt = pCNd->Len();
2714 				}
2715 
2716 				// durch das Loeschen von BRs kann der End-Index
2717 				// auch mal hinter das Ende des Textes zeigen
2718 				if( pAttr->nEndCntnt > pCNd->Len() )
2719 					pAttr->nEndCntnt = pCNd->Len();
2720 
2721 				pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nEndCntnt );
2722 				if( bBeforeTable &&
2723 					pAttrPam->GetPoint()->nNode.GetIndex() ==
2724 						rEndIdx.GetIndex() )
2725 				{
2726 					// wenn wir vor dem Einfuegen einer Tabelle stehen
2727 					// und das Attribut im aktuellen Node beendet wird,
2728 					// muessen wir es im Node davor beenden oder wegschmeissen,
2729 					// wenn es erst in dem Node beginnt
2730 					if( nWhich != RES_BREAK && nWhich != RES_PAGEDESC &&
2731                          !isTXTATR_NOEND(nWhich) )
2732 					{
2733 						if( pAttrPam->GetMark()->nNode.GetIndex() !=
2734 							rEndIdx.GetIndex() )
2735 						{
2736 							ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2737 									"Content-Position vor Tabelle nicht 0???" );
2738 							pAttrPam->Move( fnMoveBackward );
2739 						}
2740 						else
2741 						{
2742 							pAttrPam->DeleteMark();
2743 							delete pAttr;
2744 							pAttr = pPrev;
2745 							continue;
2746 						}
2747 					}
2748 				}
2749 
2750 				switch( nWhich )
2751 				{
2752                 case RES_FLTR_BOOKMARK: // insert bookmark
2753                     {
2754                         const String sName( ((SfxStringItem*)pAttr->pItem)->GetValue() );
2755                         IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
2756                         IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark( sName );
2757                         if( ppBkmk != pMarkAccess->getAllMarksEnd() &&
2758                             ppBkmk->get()->GetMarkStart() == *pAttrPam->GetPoint() )
2759                             break; // do not generate duplicates on this position
2760                         pAttrPam->DeleteMark();
2761                         const ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
2762                             *pAttrPam,
2763                             sName,
2764                             IDocumentMarkAccess::BOOKMARK );
2765 
2766                         // jump to bookmark
2767                         if( JUMPTO_MARK == eJumpTo && pNewMark->GetName() == ::rtl::OUString(sJmpMark) )
2768                         {
2769                             bChkJumpMark = sal_True;
2770                             eJumpTo = JUMPTO_NONE;
2771                         }
2772                     }
2773                     break;
2774                 case RES_TXTATR_FIELD:
2775                 case RES_TXTATR_ANNOTATION:
2776                 case RES_TXTATR_INPUTFIELD:
2777                     {
2778                         sal_uInt16 nFldWhich =
2779                             pPostIts
2780                             ? ((const SwFmtFld *)pAttr->pItem)->GetField()->GetTyp()->Which()
2781                             : 0;
2782                         if( pPostIts && (RES_POSTITFLD == nFldWhich ||
2783                                          RES_SCRIPTFLD == nFldWhich) )
2784                         {
2785                             pPostIts->Insert( pAttr, 0 );
2786                         }
2787                         else
2788                         {
2789                             aFields.Insert( pAttr, aFields.Count() );
2790                         }
2791                     }
2792                     pAttrPam->DeleteMark();
2793                     pAttr = pPrev;
2794                     continue;
2795 
2796 				case RES_LR_SPACE:
2797 					if( pAttrPam->GetPoint()->nNode.GetIndex() ==
2798 						pAttrPam->GetMark()->nNode.GetIndex() &&
2799 						pCNd )
2800 					{
2801 						// wegen Numerierungen dieses Attribut direkt
2802 						// am Node setzen
2803 						pCNd->SetAttr( *pAttr->pItem );
2804 						break;
2805 					}
2806 					ASSERT(	!this,
2807 							"LRSpace ueber mehrere Absaetze gesetzt!" );
2808 					// kein break (hier sollen wir trotzdem nie hinkommen;
2809 				default:
2810 
2811 					// ggfs. ein Bookmark anspringen
2812 					if( RES_TXTATR_INETFMT == nWhich &&
2813 						JUMPTO_MARK == eJumpTo &&
2814 						sJmpMark == ((SwFmtINetFmt*)pAttr->pItem)->GetName() )
2815 					{
2816 						bChkJumpMark = sal_True;
2817 						eJumpTo = JUMPTO_NONE;
2818 					}
2819 
2820                     pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, nsSetAttrMode::SETATTR_DONTREPLACE );
2821 				}
2822 				pAttrPam->DeleteMark();
2823 
2824 				delete pAttr;
2825 				pAttr = pPrev;
2826 			}
2827 		}
2828 	}
2829 
2830 	for( n = aMoveFlyFrms.Count(); n; )
2831 	{
2832 		SwFrmFmt *pFrmFmt = aMoveFlyFrms[ --n ];
2833 
2834 		const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
2835         ASSERT( FLY_AT_PARA == rAnchor.GetAnchorId(),
2836 				"Nur Auto-Rahmen brauchen eine Spezialbehandlung" );
2837 		const SwPosition *pFlyPos = rAnchor.GetCntntAnchor();
2838 		sal_uLong nFlyParaIdx = pFlyPos->nNode.GetIndex();
2839 		sal_Bool bMoveFly;
2840 		if( bChkEnd )
2841 		{
2842 			bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2843 					   ( nFlyParaIdx == rEndIdx.GetIndex() &&
2844 						 aMoveFlyCnts[n] < nEndCnt );
2845 		}
2846 		else
2847 		{
2848 			sal_uLong nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2849 			bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2850 					   rEndIdx.GetIndex() > nEndOfIcons ||
2851 					   nFlyParaIdx <= nEndOfIcons;
2852 		}
2853 		if( bMoveFly )
2854 		{
2855 			pFrmFmt->DelFrms();
2856 			*pAttrPam->GetPoint() = *pFlyPos;
2857 			pAttrPam->GetPoint()->nContent.Assign( pAttrPam->GetCntntNode(),
2858 												   aMoveFlyCnts[n] );
2859 			SwFmtAnchor aAnchor( rAnchor );
2860             aAnchor.SetType( FLY_AT_CHAR );
2861 			aAnchor.SetAnchor( pAttrPam->GetPoint() );
2862             pFrmFmt->SetFmtAttr( aAnchor );
2863 
2864 			const SwFmtHoriOrient& rHoriOri = pFrmFmt->GetHoriOrient();
2865             if( text::HoriOrientation::LEFT == rHoriOri.GetHoriOrient() )
2866 			{
2867 				SwFmtHoriOrient aHoriOri( rHoriOri );
2868                 aHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2869                 pFrmFmt->SetFmtAttr( aHoriOri );
2870 			}
2871 			const SwFmtVertOrient& rVertOri = pFrmFmt->GetVertOrient();
2872             if( text::VertOrientation::TOP == rVertOri.GetVertOrient() )
2873 			{
2874 				SwFmtVertOrient aVertOri( rVertOri );
2875                 aVertOri.SetRelationOrient( text::RelOrientation::CHAR );
2876                 pFrmFmt->SetFmtAttr( aVertOri );
2877 			}
2878 
2879 			pFrmFmt->MakeFrms();
2880 			aMoveFlyFrms.Remove( n, 1 );
2881 			aMoveFlyCnts.erase( aMoveFlyCnts.begin() + n );
2882 		}
2883 	}
2884 	while( aFields.Count() )
2885 	{
2886 		pAttr = aFields[0];
2887 
2888         pCNd = pAttr->nSttPara.GetNode().GetCntntNode();
2889 		pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2890 		pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2891 
2892 		if( bBeforeTable &&
2893 			pAttrPam->GetPoint()->nNode.GetIndex() == rEndIdx.GetIndex() )
2894 		{
2895 			ASSERT( !bBeforeTable, "Aha, der Fall tritt also doch ein" );
2896 			ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2897 					"Content-Position vor Tabelle nicht 0???" );
2898 			// !!!
2899 			pAttrPam->Move( fnMoveBackward );
2900 		}
2901 
2902         pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, 0 );
2903 
2904 		aFields.Remove( 0, 1 );
2905 		delete pAttr;
2906 	}
2907 
2908 	delete pAttrPam;
2909 }
2910 
NewAttr(_HTMLAttr ** ppAttr,const SfxPoolItem & rItem)2911 void SwHTMLParser::NewAttr( _HTMLAttr **ppAttr, const SfxPoolItem& rItem )
2912 {
2913 	// Font-Hoehen und -Farben- sowie Escapement-Attribute duerfen nicht
2914 	// zusammengefasst werden. Sie werden deshalb in einer Liste gespeichert,
2915 	// in der das zuletzt aufgespannte Attribut vorne steht und der Count
2916 	// immer 1 ist. Fuer alle anderen Attribute wird der Count einfach
2917 	// hochgezaehlt.
2918 	if( *ppAttr )
2919 	{
2920 		_HTMLAttr *pAttr = new _HTMLAttr( *pPam->GetPoint(), rItem,
2921 											ppAttr );
2922 		pAttr->InsertNext( *ppAttr );
2923 		(*ppAttr) = pAttr;
2924 	}
2925 	else
2926 		(*ppAttr) = new _HTMLAttr( *pPam->GetPoint(), rItem, ppAttr );
2927 }
2928 
2929 
EndAttr(_HTMLAttr * pAttr,_HTMLAttr ** ppDepAttr,sal_Bool bChkEmpty)2930 void SwHTMLParser::EndAttr( _HTMLAttr* pAttr, _HTMLAttr **ppDepAttr,
2931 							sal_Bool bChkEmpty )
2932 {
2933 	ASSERT( !ppDepAttr, "SwHTMLParser::EndAttr: ppDepAttr-Feature ungetestet?" );
2934 	// Der Listenkopf ist im Attribut gespeichert
2935 	_HTMLAttr **ppHead = pAttr->ppHead;
2936 
2937 	ASSERT( ppHead, "keinen Attributs-Listenkopf gefunden!" );
2938 
2939 	// die aktuelle Psoition als Ende-Position merken
2940 	const SwNodeIndex* pEndIdx = &pPam->GetPoint()->nNode;
2941 	xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2942 
2943 	// WIrd das zueltzt gestartete oder ein frueher gestartetes Attribut
2944 	// beendet?
2945 	_HTMLAttr *pLast = 0;
2946 	if( ppHead && pAttr != *ppHead )
2947 	{
2948 		// Es wird nicht das zuletzt gestartete Attribut beendet
2949 
2950 		// Dann suche wir das unmittelbar danach gestartete Attribut, das
2951 		// ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
2952 		// mehr in der Liste
2953 		pLast = *ppHead;
2954 		while( pLast && pLast->GetNext() != pAttr )
2955 			pLast = pLast->GetNext();
2956 
2957 		ASSERT( pLast, "Attribut nicht in eigener Liste gefunden!" );
2958 
2959 		// das Attribut nicht an der PaM-Psoition beenden, sondern da,
2960 		// wo das danch gestartete Attribut anfing???
2961 		//pEndIdx = &pPrev->GetSttPara();
2962 		//nEndCnt = pPrev->GetSttCnt();
2963 	}
2964 
2965 	sal_Bool bMoveBack = sal_False;
2966 	sal_uInt16 nWhich = pAttr->pItem->Which();
2967 	if( /*!pLast &&*/ !nEndCnt && RES_PARATR_BEGIN <= nWhich &&
2968 		*pEndIdx != pAttr->GetSttPara() )
2969 	{
2970 		// dann eine Cntntnt Position zurueck!
2971 		bMoveBack = pPam->Move( fnMoveBackward );
2972 		nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2973 	}
2974 
2975 	// nun das Attrubut beenden
2976 	_HTMLAttr *pNext = pAttr->GetNext();
2977 
2978 
2979 	sal_Bool bInsert;
2980     sal_uInt16 nScriptItem = 0;
2981 	sal_Bool bScript = sal_False, bFont = sal_False;
2982 	// ein Bereich ??
2983 	if( !bChkEmpty || (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
2984 		RES_PAGEDESC == nWhich || RES_BREAK == nWhich ||
2985 		*pEndIdx != pAttr->GetSttPara() ||
2986 		nEndCnt != pAttr->GetSttCnt() )
2987 	{
2988 		bInsert = sal_True;
2989 		// We do some optimization for script depenedent attribtes here.
2990 		if( *pEndIdx == pAttr->GetSttPara() )
2991 		{
2992 			lcl_swhtml_getItemInfo( *pAttr, bScript, bFont, nScriptItem );
2993 		}
2994 	}
2995 	else
2996 	{
2997 		bInsert = sal_False;
2998 	}
2999 
3000 	if( bInsert && bScript )
3001 	{
3002 		const SwTxtNode *pTxtNd = pAttr->GetSttPara().GetNode()
3003 											.GetTxtNode();
3004 		ASSERT( pTxtNd, "No text node" );
3005 		const String& rText = pTxtNd->GetTxt();
3006 		sal_uInt16 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
3007 						rText, pAttr->GetSttCnt() );
3008 		xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
3009 					->endOfScript( rText, pAttr->GetSttCnt(), nScriptTxt );
3010 		while( nScriptEnd < nEndCnt )
3011 		{
3012 			if( nScriptItem == nScriptTxt )
3013 			{
3014 				_HTMLAttr *pSetAttr = pAttr->Clone( *pEndIdx, nScriptEnd );
3015 				pSetAttr->ClearPrev();
3016 				if( pNext )
3017 					pNext->InsertPrev( pSetAttr );
3018 				else
3019 				{
3020 					sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
3021 														: aSetAttrTab.Count();
3022 					aSetAttrTab.Insert( pSetAttr, nTmp );
3023 				}
3024 			}
3025 			pAttr->nSttCntnt = nScriptEnd;
3026 			nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
3027 							rText, nScriptEnd );
3028 			nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
3029 					->endOfScript( rText, nScriptEnd, nScriptTxt );
3030 		}
3031 		bInsert = nScriptItem == nScriptTxt;
3032 	}
3033 	if( bInsert )
3034 	{
3035 		pAttr->nEndPara = *pEndIdx;
3036 		pAttr->nEndCntnt = nEndCnt;
3037 		pAttr->bInsAtStart = RES_TXTATR_INETFMT != nWhich &&
3038 							 RES_TXTATR_CHARFMT != nWhich;
3039 
3040 		if( !pNext )
3041 		{
3042 			// keine offenen Attribute dieses Typs mehr da,
3043 			// dann koennen alle gesetzt werden, es sei denn
3044 			// sie haengen noch von einem anderen Attribut ab,
3045 			// dann werden sie dort angehaengt
3046 			if( ppDepAttr && *ppDepAttr )
3047 				(*ppDepAttr)->InsertPrev( pAttr );
3048 			else
3049 			{
3050 				sal_uInt16 nTmp = pAttr->bInsAtStart ? 0 : aSetAttrTab.Count();
3051 				aSetAttrTab.Insert( pAttr, nTmp );
3052 			}
3053 		}
3054 		else
3055 		{
3056 			// es gibt noch andere offene Attribute des Typs,
3057 			// daher muss das Setzen zurueckgestellt werden.
3058 			// das aktuelle Attribut wird deshalb hinten an die
3059 			// Previous-Liste des Nachfolgers angehaengt
3060 			pNext->InsertPrev( pAttr );
3061 		}
3062 	}
3063 	else
3064 	{
3065 		// dann nicht einfuegen, sondern Loeschen. Durch das "tuerken" von
3066 		// Vorlagen durch harte Attributierung koennen sich auch mal andere
3067 		// leere Attribute in der Prev-Liste befinden, die dann trotzdem
3068 		// gesetzt werden muessen
3069 		_HTMLAttr *pPrev = pAttr->GetPrev();
3070 		delete pAttr;
3071 
3072 		if( pPrev )
3073 		{
3074 			// Die Previous-Attribute muessen trotzdem gesetzt werden.
3075 			if( pNext )
3076 				pNext->InsertPrev( pPrev );
3077 			else
3078 			{
3079 				sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3080 				aSetAttrTab.Insert( pPrev, nTmp );
3081 			}
3082 		}
3083 
3084 	}
3085 
3086 	// wenn das erste Attribut der Liste gesetzt wurde muss noch der
3087 	// Listenkopf korrigiert werden.
3088 	if( pLast )
3089 		pLast->pNext = pNext;
3090 	else if( ppHead )
3091 		*ppHead = pNext;
3092 
3093 	if( bMoveBack )
3094 		pPam->Move( fnMoveForward );
3095 }
3096 
DeleteAttr(_HTMLAttr * pAttr)3097 void SwHTMLParser::DeleteAttr( _HTMLAttr* pAttr )
3098 {
3099 	// Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3100 	// koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3101 	ASSERT( !aParaAttrs.Count(),
3102 			"Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3103 	if( aParaAttrs.Count() )
3104 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3105 
3106 	// Der Listenkopf ist im Attribut gespeichert
3107 	_HTMLAttr **ppHead = pAttr->ppHead;
3108 
3109 	ASSERT( ppHead, "keinen Attributs-Listenkopf gefunden!" );
3110 
3111 	// Wird das zueltzt gestartete oder ein frueher gestartetes Attribut
3112 	// entfernt?
3113 	_HTMLAttr *pLast = 0;
3114 	if( ppHead && pAttr != *ppHead )
3115 	{
3116 		// Es wird nicht das zuletzt gestartete Attribut beendet
3117 
3118 		// Dann suche wir das unmittelbar danach gestartete Attribut, das
3119 		// ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
3120 		// mehr in der Liste
3121 		pLast = *ppHead;
3122 		while( pLast && pLast->GetNext() != pAttr )
3123 			pLast = pLast->GetNext();
3124 
3125 		ASSERT( pLast, "Attribut nicht in eigener Liste gefunden!" );
3126 	}
3127 
3128 	// nun das Attrubut entfernen
3129 	_HTMLAttr *pNext = pAttr->GetNext();
3130 	_HTMLAttr *pPrev = pAttr->GetPrev();
3131 	delete pAttr;
3132 
3133 	if( pPrev )
3134 	{
3135 		// Die Previous-Attribute muessen trotzdem gesetzt werden.
3136 		if( pNext )
3137 			pNext->InsertPrev( pPrev );
3138 		else
3139 		{
3140 			sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3141 			aSetAttrTab.Insert( pPrev, nTmp );
3142 		}
3143 	}
3144 
3145 	// wenn das erste Attribut der Liste entfernt wurde muss noch der
3146 	// Listenkopf korrigiert werden.
3147 	if( pLast )
3148 		pLast->pNext = pNext;
3149 	else if( ppHead )
3150 		*ppHead = pNext;
3151 }
3152 
SaveAttrTab(_HTMLAttrTable & rNewAttrTab)3153 void SwHTMLParser::SaveAttrTab( _HTMLAttrTable& rNewAttrTab )
3154 {
3155 	// Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3156 	// koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3157 	ASSERT( !aParaAttrs.Count(),
3158 			"Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3159 	if( aParaAttrs.Count() )
3160 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3161 
3162 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3163 	_HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3164 
3165 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3166 		 nCnt--; (++pTbl, ++pSaveTbl) )
3167 	{
3168 		*pSaveTbl = *pTbl;
3169 
3170 		_HTMLAttr *pAttr = *pSaveTbl;
3171 		while( pAttr )
3172 		{
3173 			pAttr->SetHead( pSaveTbl );
3174 			pAttr = pAttr->GetNext();
3175 		}
3176 
3177 		*pTbl = 0;
3178 	}
3179 }
3180 
SplitAttrTab(_HTMLAttrTable & rNewAttrTab,sal_Bool bMoveEndBack)3181 void SwHTMLParser::SplitAttrTab( _HTMLAttrTable& rNewAttrTab,
3182 								 sal_Bool bMoveEndBack )
3183 {
3184 	// Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3185 	// koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3186 	ASSERT( !aParaAttrs.Count(),
3187 			"Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3188 	if( aParaAttrs.Count() )
3189 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3190 
3191 	const SwNodeIndex& nSttIdx = pPam->GetPoint()->nNode;
3192 	SwNodeIndex nEndIdx( nSttIdx );
3193 
3194 	// alle noch offenen Attribute beenden und hinter der Tabelle
3195 	// neu aufspannen
3196 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3197 	_HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3198 	sal_Bool bSetAttr = sal_True;
3199 	xub_StrLen nSttCnt = pPam->GetPoint()->nContent.GetIndex();
3200 	xub_StrLen nEndCnt = nSttCnt;
3201 
3202 	if( bMoveEndBack )
3203 	{
3204 		sal_uLong nOldEnd = nEndIdx.GetIndex();
3205 		sal_uLong nTmpIdx;
3206 		if(	( nTmpIdx = pDoc->GetNodes().GetEndOfExtras().GetIndex()) >= nOldEnd ||
3207 			( nTmpIdx = pDoc->GetNodes().GetEndOfAutotext().GetIndex()) >= nOldEnd )
3208 		{
3209 			nTmpIdx = pDoc->GetNodes().GetEndOfInserts().GetIndex();
3210 		}
3211 		SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious(&nEndIdx);
3212 
3213 		// keine Attribute setzen, wenn der PaM aus dem Content-Bereich
3214 		// herausgeschoben wurde.
3215 		bSetAttr = pCNd && nTmpIdx < nEndIdx.GetIndex();
3216 
3217 		nEndCnt = (bSetAttr ? pCNd->Len() : 0);
3218 	}
3219 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3220 		 nCnt--; (++pTbl, ++pSaveTbl) )
3221 	{
3222 		_HTMLAttr *pAttr = *pTbl;
3223 		*pSaveTbl = 0;
3224 		while( pAttr )
3225 		{
3226 			_HTMLAttr *pNext = pAttr->GetNext();
3227 			_HTMLAttr *pPrev = pAttr->GetPrev();
3228 
3229 			if( bSetAttr &&
3230 				( pAttr->GetSttParaIdx() < nEndIdx.GetIndex() ||
3231 				  (pAttr->GetSttPara() == nEndIdx &&
3232 				   pAttr->GetSttCnt() != nEndCnt) ) )
3233 			{
3234 				// das Attribut muss vor der Liste gesetzt werden. Da wir
3235 				// das Original noch brauchen, weil Zeiger auf das Attribut
3236 				// noch in den Kontexten existieren, muessen wir es clonen.
3237 				// Die Next-Liste geht dabei verloren, aber die
3238 				// Previous-Liste bleibt erhalten
3239 				_HTMLAttr *pSetAttr = pAttr->Clone( nEndIdx, nEndCnt );
3240 
3241 				if( pNext )
3242 					pNext->InsertPrev( pSetAttr );
3243 				else
3244 				{
3245 					sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
3246 														: aSetAttrTab.Count();
3247 					aSetAttrTab.Insert( pSetAttr, nTmp );
3248 				}
3249 			}
3250 			else if( pPrev )
3251 			{
3252 				// Wenn das Attribut nicht gesetzt vor der Tabelle
3253 				// gesetzt werden muss, muessen der Previous-Attribute
3254 				// trotzdem gesetzt werden.
3255 				if( pNext )
3256 					pNext->InsertPrev( pPrev );
3257 				else
3258 				{
3259 					sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3260 					aSetAttrTab.Insert( pPrev, nTmp );
3261 				}
3262 			}
3263 
3264 			// den Start des Attributs neu setzen und die Verkettungen
3265 			// aufbrechen
3266 			pAttr->Reset( nSttIdx, nSttCnt, pSaveTbl );
3267 
3268 			if( *pSaveTbl )
3269 			{
3270 				_HTMLAttr *pSAttr = *pSaveTbl;
3271 				while( pSAttr->GetNext() )
3272 					pSAttr = pSAttr->GetNext();
3273 				pSAttr->InsertNext( pAttr );
3274 			}
3275 			else
3276 				*pSaveTbl = pAttr;
3277 
3278 			pAttr = pNext;
3279 		}
3280 
3281 		*pTbl = 0;
3282 	}
3283 }
3284 
RestoreAttrTab(const _HTMLAttrTable & rNewAttrTab,sal_Bool bSetNewStart)3285 void SwHTMLParser::RestoreAttrTab( const _HTMLAttrTable& rNewAttrTab,
3286 								   sal_Bool bSetNewStart )
3287 {
3288 	// Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3289 	// koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3290 	ASSERT( !aParaAttrs.Count(),
3291 			"Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3292 	if( aParaAttrs.Count() )
3293 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3294 
3295 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3296 	_HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3297 
3298 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3299 		nCnt--; (++pTbl, ++pSaveTbl) )
3300 	{
3301 		ASSERT( !*pTbl, "Die Attribut-Tabelle ist nicht leer!" );
3302 
3303 		const SwPosition *pPos = pPam->GetPoint();
3304 		const SwNodeIndex& rSttPara = pPos->nNode;
3305 		xub_StrLen nSttCnt = pPos->nContent.GetIndex();
3306 
3307 		*pTbl = *pSaveTbl;
3308 
3309 		_HTMLAttr *pAttr = *pTbl;
3310 		while( pAttr )
3311 		{
3312 			ASSERT( !pAttr->GetPrev() || !pAttr->GetPrev()->ppHead,
3313 					"Previous-Attribut hat noch einen Header" );
3314 			pAttr->SetHead( pTbl );
3315 			if( bSetNewStart )
3316 			{
3317 				pAttr->nSttPara = rSttPara;
3318 				pAttr->nEndPara = rSttPara;
3319 				pAttr->nSttCntnt = nSttCnt;
3320 				pAttr->nEndCntnt = nSttCnt;
3321 			}
3322 			pAttr = pAttr->GetNext();
3323 		}
3324 
3325 		*pSaveTbl = 0;
3326 	}
3327 }
3328 
InsertAttr(const SfxPoolItem & rItem,sal_Bool bLikePara,sal_Bool bInsAtStart)3329 void SwHTMLParser::InsertAttr( const SfxPoolItem& rItem, sal_Bool bLikePara,
3330 							   sal_Bool bInsAtStart )
3331 {
3332 	_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(),
3333 									 rItem );
3334 	if( bLikePara )
3335 		pTmp->SetLikePara();
3336 	sal_uInt16 nTmp = bInsAtStart ? 0 : aSetAttrTab.Count();
3337 	aSetAttrTab.Insert( pTmp, nTmp );
3338 }
3339 
InsertAttrs(_HTMLAttrs & rAttrs)3340 void SwHTMLParser::InsertAttrs( _HTMLAttrs& rAttrs )
3341 {
3342 	while( rAttrs.Count() )
3343 	{
3344 		_HTMLAttr *pAttr = rAttrs[0];
3345 		InsertAttr( pAttr->GetItem() );
3346 		rAttrs.Remove( 0, 1 );
3347 		delete pAttr;
3348 	}
3349 }
3350 
3351 /*  */
3352 
NewStdAttr(int nToken)3353 void SwHTMLParser::NewStdAttr( int nToken )
3354 {
3355 	String aId, aStyle, aClass, aLang, aDir;
3356 
3357 	const HTMLOptions *pHTMLOptions = GetOptions();
3358 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3359 	{
3360 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3361 		switch( pOption->GetToken() )
3362 		{
3363 		case HTML_O_ID:
3364 			aId = pOption->GetString();
3365 			break;
3366 		case HTML_O_STYLE:
3367 			aStyle = pOption->GetString();
3368 			break;
3369 		case HTML_O_CLASS:
3370 			aClass = pOption->GetString();
3371 			break;
3372 		case HTML_O_LANG:
3373 			aLang = pOption->GetString();
3374 			break;
3375 		case HTML_O_DIR:
3376 			aDir = pOption->GetString();
3377 			break;
3378 		}
3379 	}
3380 
3381 	// einen neuen Kontext anlegen
3382     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3383 
3384 	// Styles parsen
3385 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3386 	{
3387 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3388 		SvxCSS1PropertyInfo aPropInfo;
3389 
3390 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3391 		{
3392 			if( HTML_SPAN_ON != nToken || !aClass.Len() ||
3393 				!CreateContainer( aClass, aItemSet, aPropInfo, pCntxt ) )
3394 				DoPositioning( aItemSet, aPropInfo, pCntxt );
3395 			InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3396 		}
3397 	}
3398 
3399 	// den Kontext merken
3400 	PushContext( pCntxt );
3401 }
3402 
NewStdAttr(int nToken,_HTMLAttr ** ppAttr,const SfxPoolItem & rItem,_HTMLAttr ** ppAttr2,const SfxPoolItem * pItem2,_HTMLAttr ** ppAttr3,const SfxPoolItem * pItem3)3403 void SwHTMLParser::NewStdAttr( int nToken,
3404 							   _HTMLAttr **ppAttr, const SfxPoolItem & rItem,
3405 							   _HTMLAttr **ppAttr2, const SfxPoolItem *pItem2,
3406 							   _HTMLAttr **ppAttr3, const SfxPoolItem *pItem3 )
3407 {
3408 	String aId, aStyle, aClass, aLang, aDir;
3409 
3410 	const HTMLOptions *pHTMLOptions = GetOptions();
3411 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3412 	{
3413 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3414 		switch( pOption->GetToken() )
3415 		{
3416 		case HTML_O_ID:
3417 			aId = pOption->GetString();
3418 			break;
3419 		case HTML_O_STYLE:
3420 			aStyle = pOption->GetString();
3421 			break;
3422 		case HTML_O_CLASS:
3423 			aClass = pOption->GetString();
3424 			break;
3425 		case HTML_O_LANG:
3426 			aLang = pOption->GetString();
3427 			break;
3428 		case HTML_O_DIR:
3429 			aDir = pOption->GetString();
3430 			break;
3431 		}
3432 	}
3433 
3434 	// einen neuen Kontext anlegen
3435     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3436 
3437 	// Styles parsen
3438 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3439 	{
3440 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3441 		SvxCSS1PropertyInfo aPropInfo;
3442 
3443 		aItemSet.Put( rItem );
3444 		if( pItem2 )
3445 			aItemSet.Put( *pItem2 );
3446 		if( pItem3 )
3447 			aItemSet.Put( *pItem3 );
3448 
3449 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3450 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3451 
3452 		InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3453 	}
3454 	else
3455 	{
3456 		InsertAttr( ppAttr ,rItem, pCntxt );
3457 		if( pItem2 )
3458 		{
3459 			ASSERT( ppAttr2, "missing table entry for item2" );
3460 			InsertAttr( ppAttr2, *pItem2, pCntxt );
3461 		}
3462 		if( pItem3 )
3463 		{
3464 			ASSERT( ppAttr3, "missing table entry for item3" );
3465 			InsertAttr( ppAttr3, *pItem3, pCntxt );
3466 		}
3467 	}
3468 
3469 	// den Kontext merken
3470 	PushContext( pCntxt );
3471 }
3472 
EndTag(int nToken)3473 void SwHTMLParser::EndTag( int nToken )
3474 {
3475 	// den Kontext holen
3476     _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
3477 	if( pCntxt )
3478 	{
3479 		// und ggf. die Attribute beenden
3480 		EndContext( pCntxt );
3481 		delete pCntxt;
3482 	}
3483 }
3484 
3485 
NewBasefontAttr()3486 void SwHTMLParser::NewBasefontAttr()
3487 {
3488 	String aId, aStyle, aClass, aLang, aDir;
3489 	sal_uInt16 nSize = 3;
3490 
3491 	const HTMLOptions *pHTMLOptions = GetOptions();
3492 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3493 	{
3494 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3495 		switch( pOption->GetToken() )
3496 		{
3497 		case HTML_O_SIZE:
3498 			nSize = (sal_uInt16)pOption->GetNumber();
3499 			break;
3500 		case HTML_O_ID:
3501 			aId = pOption->GetString();
3502 			break;
3503 		case HTML_O_STYLE:
3504 			aStyle = pOption->GetString();
3505 			break;
3506 		case HTML_O_CLASS:
3507 			aClass = pOption->GetString();
3508 			break;
3509 		case HTML_O_LANG:
3510 			aLang = pOption->GetString();
3511 			break;
3512 		case HTML_O_DIR:
3513 			aDir = pOption->GetString();
3514 			break;
3515 		}
3516 	}
3517 
3518 	if( nSize < 1 )
3519 		nSize = 1;
3520 
3521 	if( nSize > 7 )
3522 		nSize = 7;
3523 
3524 	// einen neuen Kontext anlegen
3525 	_HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_BASEFONT_ON );
3526 
3527 	// Styles parsen
3528 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3529 	{
3530 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3531 		SvxCSS1PropertyInfo aPropInfo;
3532 
3533         SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3534 		aItemSet.Put( aFontHeight );
3535 		aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3536 		aItemSet.Put( aFontHeight );
3537 		aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3538 		aItemSet.Put( aFontHeight );
3539 
3540 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3541 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3542 
3543 		InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3544 	}
3545 	else
3546 	{
3547         SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3548 		InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3549 		aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3550 		InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3551 		aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3552 		InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3553 	}
3554 
3555 	// den Kontext merken
3556 	PushContext( pCntxt );
3557 
3558 	// die Font-Size merken
3559 	aBaseFontStack.Insert( nSize, aBaseFontStack.Count() );
3560 }
3561 
EndBasefontAttr()3562 void SwHTMLParser::EndBasefontAttr()
3563 {
3564 	EndTag( HTML_BASEFONT_ON );
3565 
3566 	// Stack-Unterlauf in Tabellen vermeiden
3567 	if( aBaseFontStack.Count() > nBaseFontStMin )
3568 		aBaseFontStack.Remove( aBaseFontStack.Count()-1, 1 );
3569 }
3570 
NewFontAttr(int nToken)3571 void SwHTMLParser::NewFontAttr( int nToken )
3572 {
3573 	sal_uInt16 nBaseSize =
3574 		( aBaseFontStack.Count() > nBaseFontStMin
3575 			? (aBaseFontStack[aBaseFontStack.Count()-1] & FONTSIZE_MASK)
3576 			: 3 );
3577 	sal_uInt16 nFontSize =
3578 		( aFontStack.Count() > nFontStMin
3579 			? (aFontStack[aFontStack.Count()-1] & FONTSIZE_MASK)
3580 			: nBaseSize );
3581 
3582 	String aFace, aId, aStyle, aClass, aLang, aDir;
3583 	Color aColor;
3584 	sal_uLong nFontHeight = 0;	// tatsaechlich einzustellende Font-Hoehe
3585 	sal_uInt16 nSize = 0;		// Fontgroesse in Netscape-Notation (1-7)
3586 	sal_Bool bColor = sal_False;
3587 
3588 	const HTMLOptions *pHTMLOptions = GetOptions();
3589 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3590 	{
3591 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3592 		switch( pOption->GetToken() )
3593 		{
3594 		case HTML_O_SIZE:
3595 			if( HTML_FONT_ON==nToken && pOption->GetString().Len() )
3596 			{
3597 				sal_Int32 nSSize;
3598 				if( '+' == pOption->GetString().GetChar(0) ||
3599 					'-' == pOption->GetString().GetChar(0) )
3600 					nSSize = nBaseSize + pOption->GetSNumber();
3601 				else
3602 					nSSize = (sal_Int32)pOption->GetNumber();
3603 
3604 				if( nSSize < 1 )
3605 					nSSize = 1;
3606 				else if( nSSize > 7 )
3607 					nSSize = 7;
3608 
3609 				nSize = (sal_uInt16)nSSize;
3610 				nFontHeight = aFontHeights[nSize-1];
3611 			}
3612 			break;
3613 		case HTML_O_COLOR:
3614 			if( HTML_FONT_ON==nToken )
3615 			{
3616 				pOption->GetColor( aColor );
3617 				bColor = sal_True;
3618 			}
3619 			break;
3620 		case HTML_O_FACE:
3621 			if( HTML_FONT_ON==nToken )
3622 				aFace = pOption->GetString();
3623 			break;
3624 		case HTML_O_ID:
3625 			aId = pOption->GetString();
3626 			break;
3627 		case HTML_O_STYLE:
3628 			aStyle = pOption->GetString();
3629 			break;
3630 		case HTML_O_CLASS:
3631 			aClass = pOption->GetString();
3632 			break;
3633 		case HTML_O_LANG:
3634 			aLang = pOption->GetString();
3635 			break;
3636 		case HTML_O_DIR:
3637 			aDir = pOption->GetString();
3638 			break;
3639 		}
3640 	}
3641 
3642 	if( HTML_FONT_ON != nToken )
3643 	{
3644 		// HTML_BIGPRINT_ON oder HTML_SMALLPRINT_ON
3645 
3646 		// in Ueberschriften bestimmt die aktuelle Ueberschrift
3647 		// die Font-Hoehe und nicht BASEFONT
3648 		sal_uInt16 nPoolId = GetCurrFmtColl()->GetPoolFmtId();
3649 		if( (nPoolId>=RES_POOLCOLL_HEADLINE1 &&
3650 			 nPoolId<=RES_POOLCOLL_HEADLINE6) )
3651 		{
3652 			// wenn die Schriftgroesse in der Ueberschrift noch
3653 			// nicht veraendert ist, die aus der Vorlage nehmen
3654 			if( nFontStHeadStart==aFontStack.Count() )
3655                 nFontSize = static_cast< sal_uInt16 >(6 - (nPoolId - RES_POOLCOLL_HEADLINE1));
3656 		}
3657 		else
3658 			nPoolId = 0;
3659 
3660 		if( HTML_BIGPRINT_ON == nToken )
3661 			nSize = ( nFontSize<7 ? nFontSize+1 : 7 );
3662 		else
3663 			nSize = ( nFontSize>1 ? nFontSize-1 : 1 );
3664 
3665 		// in Ueberschriften wird die neue Fonthoehe wenn moeglich aus
3666 		// den Vorlagen geholt.
3667 		if( nPoolId && nSize>=1 && nSize <=6 )
3668 			nFontHeight =
3669 				pCSS1Parser->GetTxtCollFromPool(
3670 					RES_POOLCOLL_HEADLINE1+6-nSize )->GetSize().GetHeight();
3671 		else
3672 			nFontHeight = aFontHeights[nSize-1];
3673 	}
3674 
3675 	ASSERT( !nSize == !nFontHeight, "HTML-Font-Size != Font-Height" );
3676 
3677 	String aFontName, aStyleName;
3678 	FontFamily eFamily = FAMILY_DONTKNOW;	// Family und Pitch,
3679 	FontPitch ePitch = PITCH_DONTKNOW;		// falls nicht gefunden
3680 	rtl_TextEncoding eEnc = gsl_getSystemTextEncoding();
3681 
3682 	if( aFace.Len() && !pCSS1Parser->IsIgnoreFontFamily() )
3683 	{
3684 		const FontList *pFList = 0;
3685 		SwDocShell *pDocSh = pDoc->GetDocShell();
3686 		if( pDocSh )
3687 		{
3688 			const SvxFontListItem *pFListItem =
3689 			   (const SvxFontListItem *)pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST);
3690 			if( pFListItem )
3691 				pFList = pFListItem->GetFontList();
3692 		}
3693 
3694 		sal_Bool bFound = sal_False;
3695 		xub_StrLen nStrPos = 0;
3696 		while( nStrPos!=STRING_NOTFOUND )
3697 		{
3698 			String aFName = aFace.GetToken( 0, ',', nStrPos );
3699 			aFName.EraseTrailingChars().EraseLeadingChars();
3700 			if( aFName.Len() )
3701 			{
3702 				if( !bFound && pFList )
3703 				{
3704 					sal_Handle hFont = pFList->GetFirstFontInfo( aFName );
3705 					if( 0 != hFont )
3706 					{
3707 						const FontInfo& rFInfo = pFList->GetFontInfo( hFont );
3708 						if( RTL_TEXTENCODING_DONTKNOW != rFInfo.GetCharSet() )
3709 						{
3710 							bFound = sal_True;
3711 							if( RTL_TEXTENCODING_SYMBOL == rFInfo.GetCharSet() )
3712 								eEnc = RTL_TEXTENCODING_SYMBOL;
3713 						}
3714 					}
3715 				}
3716 				if( aFontName.Len() )
3717 					aFontName += ';';
3718 				aFontName += aFName;
3719 			}
3720 		}
3721 	}
3722 
3723 
3724 	// einen neuen Kontext anlegen
3725     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3726 
3727 	// Styles parsen
3728 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3729 	{
3730 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3731 		SvxCSS1PropertyInfo aPropInfo;
3732 
3733 		if( nFontHeight )
3734 		{
3735             SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3736 			aItemSet.Put( aFontHeight );
3737 			aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3738 			aItemSet.Put( aFontHeight );
3739 			aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3740 			aItemSet.Put( aFontHeight );
3741 		}
3742 		if( bColor )
3743             aItemSet.Put( SvxColorItem(aColor, RES_CHRATR_COLOR) );
3744 		if( aFontName.Len() )
3745 		{
3746             SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3747 			aItemSet.Put( aFont );
3748 			aFont.SetWhich( RES_CHRATR_CJK_FONT );
3749 			aItemSet.Put( aFont );
3750 			aFont.SetWhich( RES_CHRATR_CTL_FONT );
3751 			aItemSet.Put( aFont );
3752 		}
3753 
3754 
3755 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3756 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3757 
3758 		InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3759 	}
3760 	else
3761 	{
3762 		if( nFontHeight )
3763 		{
3764             SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3765 			InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3766 			aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3767 			InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3768 			aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3769 			InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3770 		}
3771 		if( bColor )
3772             InsertAttr( &aAttrTab.pFontColor, SvxColorItem(aColor, RES_CHRATR_COLOR), pCntxt );
3773 		if( aFontName.Len() )
3774 		{
3775             SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3776 			InsertAttr( &aAttrTab.pFont, aFont, pCntxt );
3777 			aFont.SetWhich( RES_CHRATR_CJK_FONT );
3778 			InsertAttr( &aAttrTab.pFontCJK, aFont, pCntxt );
3779 			aFont.SetWhich( RES_CHRATR_CTL_FONT );
3780 			InsertAttr( &aAttrTab.pFontCTL, aFont, pCntxt );
3781 		}
3782 	}
3783 
3784 	// den Kontext merken
3785 	PushContext( pCntxt );
3786 
3787 	aFontStack.Insert( nSize, aFontStack.Count() );
3788 }
3789 
EndFontAttr(int nToken)3790 void SwHTMLParser::EndFontAttr( int nToken )
3791 {
3792 	EndTag( nToken );
3793 
3794 	// Stack-Unterlauf in Tabellen vermeiden
3795 	if( aFontStack.Count() > nFontStMin )
3796 		aFontStack.Remove( aFontStack.Count()-1, 1 );
3797 }
3798 
3799 /*  */
3800 
NewPara()3801 void SwHTMLParser::NewPara()
3802 {
3803 	if( pPam->GetPoint()->nContent.GetIndex() )
3804 		AppendTxtNode( AM_SPACE );
3805 	else
3806 		AddParSpace();
3807 
3808 	eParaAdjust = SVX_ADJUST_END;
3809 	String aId, aStyle, aClass, aLang, aDir;
3810 
3811 	const HTMLOptions *pHTMLOptions = GetOptions();
3812 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3813 	{
3814 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3815 		switch( pOption->GetToken() )
3816 		{
3817 			case HTML_O_ID:
3818 				aId = pOption->GetString();
3819 				break;
3820 			case HTML_O_ALIGN:
3821                 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3822 				break;
3823 			case HTML_O_STYLE:
3824 				aStyle = pOption->GetString();
3825 				break;
3826 			case HTML_O_CLASS:
3827 				aClass = pOption->GetString();
3828 				break;
3829 			case HTML_O_LANG:
3830 				aLang = pOption->GetString();
3831 				break;
3832 			case HTML_O_DIR:
3833 				aDir = pOption->GetString();
3834 				break;
3835 		}
3836 	}
3837 
3838 	// einen neuen Kontext anlegen
3839 	_HTMLAttrContext *pCntxt =
3840 		aClass.Len() ? new _HTMLAttrContext( HTML_PARABREAK_ON,
3841 											 RES_POOLCOLL_TEXT, aClass )
3842 					 : new _HTMLAttrContext( HTML_PARABREAK_ON );
3843 
3844 	// Styles parsen (Class nicht beruecksichtigen. Das geht nur, solange
3845 	// keine der CSS1-Properties der Klasse hart formatiert werden muss!!!)
3846 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
3847 	{
3848 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3849 		SvxCSS1PropertyInfo aPropInfo;
3850 
3851 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
3852 		{
3853 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
3854 					"Class wird nicht beruecksichtigt" );
3855 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3856 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
3857 		}
3858 	}
3859 
3860 	if( SVX_ADJUST_END != eParaAdjust )
3861         InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
3862 
3863 	// und auf den Stack packen
3864 	PushContext( pCntxt );
3865 
3866 	// die aktuelle Vorlage oder deren Attribute setzen
3867 	SetTxtCollAttrs( aClass.Len() ? pCntxt : 0 );
3868 
3869 	// Laufbalkenanzeige
3870 	ShowStatline();
3871 
3872 	ASSERT( !nOpenParaToken, "Jetzt geht ein offenes Absatz-Element verloren" );
3873 	nOpenParaToken = HTML_PARABREAK_ON;
3874 }
3875 
EndPara(sal_Bool bReal)3876 void SwHTMLParser::EndPara( sal_Bool bReal )
3877 {
3878 	if( HTML_LI_ON==nOpenParaToken && pTable )
3879 	{
3880 #ifdef DBG_UTIL
3881 		const SwNumRule *pNumRule = pPam->GetNode()->GetTxtNode()->GetNumRule();
3882 #endif
3883 		ASSERT( pNumRule, "Wo ist die Numrule geblieben" );
3884 	}
3885 
3886 	// leere Absaetze werden von Netscape uebersprungen, von uns jetzt auch
3887 	if( bReal )
3888 	{
3889 		if( pPam->GetPoint()->nContent.GetIndex() )
3890 			AppendTxtNode( AM_SPACE );
3891 		else
3892 			AddParSpace();
3893 	}
3894 
3895 	// wenn ein DD oder DT offen war, handelt es sich um eine
3896 	// implizite Def-Liste, die jetzt beendet werden muss
3897 	if( (nOpenParaToken==HTML_DT_ON || nOpenParaToken==HTML_DD_ON) &&
3898 		nDefListDeep)
3899 	{
3900 		nDefListDeep--;
3901 	}
3902 
3903 	// den Kontext vom Stack holen. Er kann auch von einer implizit
3904 	// geoeffneten Definitionsliste kommen
3905 	_HTMLAttrContext *pCntxt =
3906         PopContext( static_cast< sal_uInt16 >(nOpenParaToken ? (nOpenParaToken & ~1)
3907                                    : HTML_PARABREAK_ON) );
3908 
3909 	// Attribute beenden
3910 	if( pCntxt )
3911 	{
3912 		EndContext( pCntxt );
3913 		SetAttr();	// Absatz-Atts wegen JavaScript moeglichst schnell setzen
3914 		delete pCntxt;
3915 	}
3916 
3917 	// und die bisherige Vorlage neu setzen
3918 	if( bReal )
3919 		SetTxtCollAttrs();
3920 
3921 	nOpenParaToken = 0;
3922 }
3923 
3924 
NewHeading(int nToken)3925 void SwHTMLParser::NewHeading( int nToken )
3926 {
3927 	eParaAdjust = SVX_ADJUST_END;
3928 
3929 	String aId, aStyle, aClass, aLang, aDir;
3930 
3931 	const HTMLOptions *pHTMLOptions = GetOptions();
3932 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3933 	{
3934 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3935 		switch( pOption->GetToken() )
3936 		{
3937 			case HTML_O_ID:
3938 				aId = pOption->GetString();
3939 				break;
3940 			case HTML_O_ALIGN:
3941                 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3942 				break;
3943 			case HTML_O_STYLE:
3944 				aStyle = pOption->GetString();
3945 				break;
3946 			case HTML_O_CLASS:
3947 				aClass = pOption->GetString();
3948 				break;
3949 			case HTML_O_LANG:
3950 				aLang = pOption->GetString();
3951 				break;
3952 			case HTML_O_DIR:
3953 				aDir = pOption->GetString();
3954 				break;
3955 		}
3956 	}
3957 
3958 	// einen neuen Absatz aufmachen
3959 	if( pPam->GetPoint()->nContent.GetIndex() )
3960 		AppendTxtNode( AM_SPACE );
3961 	else
3962 		AddParSpace();
3963 
3964 	// die passende Vorlage suchen
3965 	sal_uInt16 nTxtColl;
3966 	switch( nToken )
3967 	{
3968 	case HTML_HEAD1_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE1;	break;
3969 	case HTML_HEAD2_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE2;	break;
3970 	case HTML_HEAD3_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE3;	break;
3971 	case HTML_HEAD4_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE4;	break;
3972 	case HTML_HEAD5_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE5;	break;
3973 	case HTML_HEAD6_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE6;	break;
3974 	default:					nTxtColl = RES_POOLCOLL_STANDARD;	break;
3975 	}
3976 
3977 	// den Kontext anlegen
3978     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nTxtColl, aClass );
3979 
3980 	// Styles parsen (zu Class siehe auch NewPara)
3981 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
3982 	{
3983 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3984 		SvxCSS1PropertyInfo aPropInfo;
3985 
3986 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
3987 		{
3988 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
3989 					"Class wird nicht beruecksichtigt" );
3990 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3991 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
3992 		}
3993 	}
3994 
3995 	if( SVX_ADJUST_END != eParaAdjust )
3996         InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
3997 
3998 	// udn auf den Stack packen
3999 	PushContext( pCntxt );
4000 
4001 	// und die Vorlage oder deren Attribute setzen
4002 	SetTxtCollAttrs( pCntxt );
4003 
4004 	nFontStHeadStart = aFontStack.Count();
4005 
4006 	// Laufbalkenanzeige
4007 	ShowStatline();
4008 }
4009 
EndHeading()4010 void SwHTMLParser::EndHeading()
4011 {
4012 	// einen neuen Absatz aufmachen
4013 	if( pPam->GetPoint()->nContent.GetIndex() )
4014 		AppendTxtNode( AM_SPACE );
4015 	else
4016 		AddParSpace();
4017 
4018 	// Kontext zu dem Token suchen und vom Stack holen
4019 	_HTMLAttrContext *pCntxt = 0;
4020 	sal_uInt16 nPos = aContexts.Count();
4021 	while( !pCntxt && nPos>nContextStMin )
4022 	{
4023 		switch( aContexts[--nPos]->GetToken() )
4024 		{
4025 		case HTML_HEAD1_ON:
4026 		case HTML_HEAD2_ON:
4027 		case HTML_HEAD3_ON:
4028 		case HTML_HEAD4_ON:
4029 		case HTML_HEAD5_ON:
4030 		case HTML_HEAD6_ON:
4031 			pCntxt = aContexts[nPos];
4032 			aContexts.Remove( nPos, 1 );
4033 			break;
4034 		}
4035 	}
4036 
4037 	// und noch Attribute beenden
4038 	if( pCntxt )
4039 	{
4040 		EndContext( pCntxt );
4041 		SetAttr();	// Absatz-Atts wegen JavaScript moeglichst schnell setzen
4042 		delete pCntxt;
4043 	}
4044 
4045 	// die bisherige Vorlage neu setzen
4046 	SetTxtCollAttrs();
4047 
4048 	nFontStHeadStart = nFontStMin;
4049 }
4050 
4051 /*  */
4052 
NewTxtFmtColl(int nToken,sal_uInt16 nColl)4053 void SwHTMLParser::NewTxtFmtColl( int nToken, sal_uInt16 nColl )
4054 {
4055 	String aId, aStyle, aClass, aLang, aDir;
4056 
4057 	const HTMLOptions *pHTMLOptions = GetOptions();
4058 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4059 	{
4060 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4061 		switch( pOption->GetToken() )
4062 		{
4063 			case HTML_O_ID:
4064 				aId = pOption->GetString();
4065 				break;
4066 			case HTML_O_STYLE:
4067 				aStyle = pOption->GetString();
4068 				break;
4069 			case HTML_O_CLASS:
4070 				aClass = pOption->GetString();
4071 				break;
4072 			case HTML_O_LANG:
4073 				aLang = pOption->GetString();
4074 				break;
4075 			case HTML_O_DIR:
4076 				aDir = pOption->GetString();
4077 				break;
4078 		}
4079 	}
4080 
4081 	// einen neuen Absatz aufmachen
4082 	SwHTMLAppendMode eMode = AM_NORMAL;
4083 	switch( nToken )
4084 	{
4085 	case HTML_LISTING_ON:
4086 	case HTML_XMP_ON:
4087 		// Diese beiden Tags werden jetzt auf die PRE-Vorlage gemappt.
4088 		// Fuer dem Fall, dass ein CLASS angegeben ist, loeschen wir
4089 		// es damit wir nicht die CLASS der PRE-Vorlage bekommen.
4090 		aClass = aEmptyStr;
4091 	case HTML_BLOCKQUOTE_ON:
4092 	case HTML_BLOCKQUOTE30_ON:
4093 	case HTML_PREFORMTXT_ON:
4094 		eMode = AM_SPACE;
4095 		break;
4096 	case HTML_ADDRESS_ON:
4097 		eMode = AM_NOSPACE;	// ADDRESS kann auf einen <P> ohne </P> folgen
4098 		break;
4099 	case HTML_DT_ON:
4100 	case HTML_DD_ON:
4101 		eMode = AM_SOFTNOSPACE;
4102 		break;
4103 	default:
4104 		ASSERT( !this, "unbekannte Vorlage" );
4105 		break;
4106 	}
4107 	if( pPam->GetPoint()->nContent.GetIndex() )
4108 		AppendTxtNode( eMode );
4109 	else if( AM_SPACE==eMode )
4110 		AddParSpace();
4111 
4112 	// ... und in einem Kontext merken
4113     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nColl, aClass );
4114 
4115 	// Styles parsen (zu Class siehe auch NewPara)
4116 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4117 	{
4118 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4119 		SvxCSS1PropertyInfo aPropInfo;
4120 
4121 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4122 		{
4123 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4124 					"Class wird nicht beruecksichtigt" );
4125 			DoPositioning( aItemSet, aPropInfo, pCntxt );
4126 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
4127 		}
4128 	}
4129 
4130 	PushContext( pCntxt );
4131 
4132 	// die neue Vorlage setzen
4133 	SetTxtCollAttrs( pCntxt );
4134 
4135 	// Laufbalkenanzeige aktualisieren
4136 	ShowStatline();
4137 }
4138 
EndTxtFmtColl(int nToken)4139 void SwHTMLParser::EndTxtFmtColl( int nToken )
4140 {
4141 	SwHTMLAppendMode eMode = AM_NORMAL;
4142 	switch( nToken & ~1 )
4143 	{
4144 	case HTML_BLOCKQUOTE_ON:
4145 	case HTML_BLOCKQUOTE30_ON:
4146 	case HTML_PREFORMTXT_ON:
4147 	case HTML_LISTING_ON:
4148 	case HTML_XMP_ON:
4149 		eMode = AM_SPACE;
4150 		break;
4151 	case HTML_ADDRESS_ON:
4152 	case HTML_DT_ON:
4153 	case HTML_DD_ON:
4154 		eMode = AM_SOFTNOSPACE;
4155 		break;
4156 	default:
4157 		ASSERT( !this, "unbekannte Vorlage" );
4158 		break;
4159 	}
4160 	if( pPam->GetPoint()->nContent.GetIndex() )
4161 		AppendTxtNode( eMode );
4162 	else if( AM_SPACE==eMode )
4163 		AddParSpace();
4164 
4165 	// den aktuellen Kontext vom Stack holen
4166     _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
4167 
4168 	// und noch Attribute beenden
4169 	if( pCntxt )
4170 	{
4171 		EndContext( pCntxt );
4172 		SetAttr();	// Absatz-Atts wegen JavaScript moeglichst schnell setzen
4173 		delete pCntxt;
4174 	}
4175 
4176 	// und die bisherige Vorlage setzen
4177 	SetTxtCollAttrs();
4178 }
4179 
4180 /*  */
4181 
NewDefList()4182 void SwHTMLParser::NewDefList()
4183 {
4184 	String aId, aStyle, aClass, aLang, aDir;
4185 
4186 	const HTMLOptions *pHTMLOptions = GetOptions();
4187 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4188 	{
4189 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4190 		switch( pOption->GetToken() )
4191 		{
4192 			case HTML_O_ID:
4193 				aId = pOption->GetString();
4194 				break;
4195 			case HTML_O_STYLE:
4196 				aStyle = pOption->GetString();
4197 				break;
4198 			case HTML_O_CLASS:
4199 				aClass = pOption->GetString();
4200 				break;
4201 			case HTML_O_LANG:
4202 				aLang = pOption->GetString();
4203 				break;
4204 			case HTML_O_DIR:
4205 				aDir = pOption->GetString();
4206 				break;
4207 		}
4208 	}
4209 
4210 	// einen neuen Absatz aufmachen
4211 	sal_Bool bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 0;
4212 	if( pPam->GetPoint()->nContent.GetIndex() )
4213 		AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4214 	else if( bSpace )
4215 		AddParSpace();
4216 
4217 	// ein Level mehr
4218 	nDefListDeep++;
4219 
4220 
4221 	sal_Bool bInDD = sal_False, bNotInDD = sal_False;
4222 	sal_uInt16 nPos = aContexts.Count();
4223 	while( !bInDD && !bNotInDD && nPos>nContextStMin )
4224 	{
4225 		sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
4226 		switch( nCntxtToken )
4227 		{
4228 		case HTML_DEFLIST_ON:
4229 		case HTML_DIRLIST_ON:
4230 		case HTML_MENULIST_ON:
4231 		case HTML_ORDERLIST_ON:
4232 		case HTML_UNORDERLIST_ON:
4233 			bNotInDD = sal_True;
4234 			break;
4235 		case HTML_DD_ON:
4236 			bInDD = sal_True;
4237 			break;
4238 		}
4239 	}
4240 
4241 
4242 	// ... und in einem Kontext merken
4243 	_HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_DEFLIST_ON );
4244 
4245 	// darin auch die Raender merken
4246 	sal_uInt16 nLeft=0, nRight=0;
4247 	short nIndent=0;
4248 	GetMarginsFromContext( nLeft, nRight, nIndent );
4249 
4250 	// Die Einrueckung, die sich schon aus einem DL-ergibt, entspricht der
4251 	// eines DT auf dem aktuellen Level, und die entspricht der eines
4252 	// DD auf dem Level davor. Fue einen Level >=2 muss also ein DD-Abstand
4253 	// hinzugefuegt werden
4254 	if( !bInDD && nDefListDeep > 1 )
4255 	{
4256 
4257 		// und den der DT-Vorlage des aktuellen Levels
4258 		SvxLRSpaceItem rLRSpace =
4259 			pCSS1Parser->GetTxtFmtColl( RES_POOLCOLL_HTML_DD, aEmptyStr )
4260 					   ->GetLRSpace();
4261         nLeft = nLeft + static_cast< sal_uInt16 >(rLRSpace.GetTxtLeft());
4262 	}
4263 
4264 	pCntxt->SetMargins( nLeft, nRight, nIndent );
4265 
4266 	// Styles parsen
4267 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
4268 	{
4269 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4270 		SvxCSS1PropertyInfo aPropInfo;
4271 
4272 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
4273 		{
4274 			DoPositioning( aItemSet, aPropInfo, pCntxt );
4275 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
4276 		}
4277 	}
4278 
4279 	PushContext( pCntxt );
4280 
4281 	// die Attribute der neuen Vorlage setzen
4282 	if( nDefListDeep > 1 )
4283 		SetTxtCollAttrs( pCntxt );
4284 }
4285 
EndDefList()4286 void SwHTMLParser::EndDefList()
4287 {
4288 	sal_Bool bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 1;
4289 	if( pPam->GetPoint()->nContent.GetIndex() )
4290 		AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4291 	else if( bSpace )
4292 		AddParSpace();
4293 
4294 	// ein Level weniger
4295 	if( nDefListDeep > 0 )
4296 		nDefListDeep--;
4297 
4298 	// den aktuellen Kontext vom Stack holen
4299 	_HTMLAttrContext *pCntxt = PopContext( HTML_DEFLIST_ON );
4300 
4301 	// und noch Attribute beenden
4302 	if( pCntxt )
4303 	{
4304 		EndContext( pCntxt );
4305 		SetAttr();	// Absatz-Atts wegen JavaScript moeglichst schnell setzen
4306 		delete pCntxt;
4307 	}
4308 
4309 	// und Vorlage setzen
4310 	SetTxtCollAttrs();
4311 }
4312 
NewDefListItem(int nToken)4313 void SwHTMLParser::NewDefListItem( int nToken )
4314 {
4315 	// festellen, ob das DD/DT in einer DL vorkommt
4316 	sal_Bool bInDefList = sal_False, bNotInDefList = sal_False;
4317 	sal_uInt16 nPos = aContexts.Count();
4318 	while( !bInDefList && !bNotInDefList && nPos>nContextStMin )
4319 	{
4320 		sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
4321 		switch( nCntxtToken )
4322 		{
4323 		case HTML_DEFLIST_ON:
4324 			bInDefList = sal_True;
4325 			break;
4326 		case HTML_DIRLIST_ON:
4327 		case HTML_MENULIST_ON:
4328 		case HTML_ORDERLIST_ON:
4329 		case HTML_UNORDERLIST_ON:
4330 			bNotInDefList = sal_True;
4331 			break;
4332 		}
4333 	}
4334 
4335 	// wenn nicht, implizit eine neue DL aufmachen
4336 	if( !bInDefList )
4337 	{
4338 		nDefListDeep++;
4339 		ASSERT( !nOpenParaToken,
4340 				"Jetzt geht ein offenes Absatz-Element verloren" );
4341         nOpenParaToken = static_cast< sal_uInt16 >(nToken);
4342 	}
4343 
4344     NewTxtFmtColl( nToken, static_cast< sal_uInt16 >(nToken==HTML_DD_ON ? RES_POOLCOLL_HTML_DD
4345                                               : RES_POOLCOLL_HTML_DT) );
4346 }
4347 
EndDefListItem(int nToken,sal_Bool bSetColl,sal_Bool)4348 void SwHTMLParser::EndDefListItem( int nToken, sal_Bool bSetColl,
4349 								   sal_Bool /*bLastPara*/ )
4350 {
4351 	// einen neuen Absatz aufmachen
4352 	if( !nToken && pPam->GetPoint()->nContent.GetIndex() )
4353 		AppendTxtNode( AM_SOFTNOSPACE );
4354 
4355 	// Kontext zu dem Token suchen und vom Stack holen
4356 	nToken &= ~1;
4357 	_HTMLAttrContext *pCntxt = 0;
4358 	sal_uInt16 nPos = aContexts.Count();
4359 	while( !pCntxt && nPos>nContextStMin )
4360 	{
4361 		sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
4362 		switch( nCntxtToken )
4363 		{
4364 		case HTML_DD_ON:
4365 		case HTML_DT_ON:
4366 			if( !nToken || nToken == nCntxtToken  )
4367 			{
4368 				pCntxt = aContexts[nPos];
4369 				aContexts.Remove( nPos, 1 );
4370 			}
4371 			break;
4372 		case HTML_DEFLIST_ON:
4373 			// keine DD/DT ausserhalb der aktuelen DefListe betrachten
4374 		case HTML_DIRLIST_ON:
4375 		case HTML_MENULIST_ON:
4376 		case HTML_ORDERLIST_ON:
4377 		case HTML_UNORDERLIST_ON:
4378 			// und auch nicht ausserhalb einer anderen Liste
4379 			nPos = nContextStMin;
4380 			break;
4381 		}
4382 	}
4383 
4384 	// und noch Attribute beenden
4385 	if( pCntxt )
4386 	{
4387 		EndContext( pCntxt );
4388 		SetAttr();	// Absatz-Atts wegen JavaScript moeglichst schnell setzen
4389 		delete pCntxt;
4390 	}
4391 
4392 	// und die bisherige Vorlage setzen
4393 	if( bSetColl )
4394 		SetTxtCollAttrs();
4395 }
4396 
4397 /*  */
4398 
HasCurrentParaFlys(sal_Bool bNoSurroundOnly,sal_Bool bSurroundOnly) const4399 sal_Bool SwHTMLParser::HasCurrentParaFlys( sal_Bool bNoSurroundOnly,
4400 									   sal_Bool bSurroundOnly ) const
4401 {
4402 	// bNoSurroundOnly:		Der Absatz enthaelt mindestens einen Rahmen
4403 	//						ohne Umlauf
4404 	// bSurroundOnly:		Der Absatz enthaelt mindestens einen Rahmen
4405 	//						mit Umlauf aber keinen ohne Umlauf
4406 	// sonst:				Der Absatz enthaelt irgendeinen Rahmen
4407 	SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
4408 
4409 	const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
4410 
4411 	sal_Bool bFound = sal_False;
4412     for ( sal_uInt16 i=0; i<rFrmFmtTbl.Count(); i++ )
4413     {
4414         SwFrmFmt *const pFmt = rFrmFmtTbl[i];
4415         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
4416 		// Ein Rahmen wurde gefunden, wenn
4417 		// - er absatzgebunden ist, und
4418 		// - im aktuellen Absatz verankert ist, und
4419 		//   - jeder absatzgebunene Rahmen zaehlt, oder
4420 		//   - (nur Rahmen oder umlauf zaehlen und ) der Rahmen keinen
4421 		//     Umlauf besitzt
4422         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
4423         if (pAPos &&
4424             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
4425              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
4426 			pAPos->nNode == rNodeIdx )
4427 		{
4428 			if( !(bNoSurroundOnly || bSurroundOnly) )
4429 			{
4430 				bFound = sal_True;
4431 				break;
4432 			}
4433 			else
4434 			{
4435 				// fix #42282#: Wenn Rahmen mit Umlauf gesucht sind,
4436 				// auch keine mit Durchlauf beachten. Dabei handelt es
4437 				// sich (noch) um HIDDEN-Controls, und denen weicht man
4438 				// besser auch nicht aus.
4439 				SwSurround eSurround = pFmt->GetSurround().GetSurround();
4440 				if( bNoSurroundOnly )
4441 				{
4442 					if( SURROUND_NONE==eSurround )
4443 					{
4444 						bFound = sal_True;
4445 						break;
4446 					}
4447 				}
4448 				if( bSurroundOnly )
4449 				{
4450 					if( SURROUND_NONE==eSurround )
4451 					{
4452 						bFound = sal_False;
4453 						break;
4454 					}
4455 					else if( SURROUND_THROUGHT!=eSurround )
4456 					{
4457 						bFound = sal_True;
4458 						// weitersuchen: Es koennten ja noch welche ohne
4459 						// Umlauf kommen ...
4460 					}
4461 				}
4462 			}
4463 		}
4464 	}
4465 
4466 	return bFound;
4467 }
4468 
4469 /*  */
4470 
4471 // die speziellen Methoden zum Einfuegen von Objecten
4472 
GetCurrFmtColl() const4473 const SwFmtColl *SwHTMLParser::GetCurrFmtColl() const
4474 {
4475 	const SwCntntNode* pCNd = pPam->GetCntntNode();
4476 	return &pCNd->GetAnyFmtColl();
4477 }
4478 
4479 
SetTxtCollAttrs(_HTMLAttrContext * pContext)4480 void SwHTMLParser::SetTxtCollAttrs( _HTMLAttrContext *pContext )
4481 {
4482 	SwTxtFmtColl *pCollToSet = 0;	// die zu setzende Vorlage
4483 	SfxItemSet *pItemSet = 0;		// der Set fuer harte Attrs
4484 	sal_uInt16 nTopColl = pContext ? pContext->GetTxtFmtColl() : 0;
4485 	const String& rTopClass = pContext ? pContext->GetClass() : (const String&) aEmptyStr;
4486 	sal_uInt16 nDfltColl = RES_POOLCOLL_TEXT;
4487 
4488 	sal_Bool bInPRE=sal_False;							// etwas Kontext Info
4489 
4490 	sal_uInt16 nLeftMargin = 0, nRightMargin = 0;	// die Einzuege und
4491 	short nFirstLineIndent = 0;					// Abstaende
4492 	sal_uInt16 i;
4493 
4494 	for( i = nContextStAttrMin; i < aContexts.Count(); i++ )
4495 	{
4496 		const _HTMLAttrContext *pCntxt = aContexts[i];
4497 
4498 		sal_uInt16 nColl = pCntxt->GetTxtFmtColl();
4499 		if( nColl )
4500 		{
4501 			// Es gibt eine Vorlage, die zu setzen ist. Dann
4502 			// muss zunaechst einmal entschieden werden,
4503 			// ob die Vorlage auch gesetzt werden kann
4504 			sal_Bool bSetThis = sal_True;
4505 			switch( nColl )
4506 			{
4507 			case sal_uInt16(RES_POOLCOLL_HTML_PRE):
4508 				bInPRE = sal_True;
4509 				break;
4510 			case sal_uInt16(RES_POOLCOLL_TEXT):
4511 				// <TD><P CLASS=xxx> muss TD.xxx werden
4512 				if( nDfltColl==RES_POOLCOLL_TABLE ||
4513 					nDfltColl==RES_POOLCOLL_TABLE_HDLN )
4514 					nColl = nDfltColl;
4515 				break;
4516 			case sal_uInt16(RES_POOLCOLL_HTML_HR):
4517 				// <HR> auch in <PRE> als Vorlage setzen, sonst kann man sie
4518 				// nicht mehr exportieren
4519 				break;
4520 			default:
4521 				if( bInPRE )
4522 					bSetThis = sal_False;
4523 				break;
4524 			}
4525 
4526 			SwTxtFmtColl *pNewColl =
4527 				pCSS1Parser->GetTxtFmtColl( nColl, pCntxt->GetClass() );
4528 
4529 			if( bSetThis )
4530 			{
4531 				// wenn jetzt eine andere Vorlage gesetzt werden soll als
4532 				// bisher, muss die bishere Vorlage durch harte Attributierung
4533 				// ersetzt werden
4534 
4535 				if( pCollToSet )
4536 				{
4537 					// die Attribute, die die bisherige Vorlage setzt
4538 					// hart einfuegen
4539 					if( !pItemSet )
4540 						pItemSet = new SfxItemSet( pCollToSet->GetAttrSet() );
4541 					else
4542 					{
4543 						const SfxItemSet& rCollSet = pCollToSet->GetAttrSet();
4544 						SfxItemSet aItemSet( *rCollSet.GetPool(),
4545 											 rCollSet.GetRanges() );
4546 						aItemSet.Set( rCollSet );
4547 						pItemSet->Put( aItemSet );
4548 					}
4549 					// aber die Attribute, die aktuelle Vorlage setzt
4550 					// entfernen, weil sie sonst spaeter ueberschrieben
4551 					// werden
4552 					pItemSet->Differentiate( pNewColl->GetAttrSet() );
4553 				}
4554 
4555 				pCollToSet = pNewColl;
4556 			}
4557 			else
4558 			{
4559 				// hart Attributieren
4560 				if( !pItemSet )
4561 					pItemSet = new SfxItemSet( pNewColl->GetAttrSet() );
4562 				else
4563 				{
4564 					const SfxItemSet& rCollSet = pNewColl->GetAttrSet();
4565 					SfxItemSet aItemSet( *rCollSet.GetPool(),
4566 										 rCollSet.GetRanges() );
4567 					aItemSet.Set( rCollSet );
4568 					pItemSet->Put( aItemSet );
4569 				}
4570 			}
4571 		}
4572 		else
4573 		{
4574 			// vielliecht gibt es ja eine Default-Vorlage?
4575 			nColl = pCntxt->GetDfltTxtFmtColl();
4576 			if( nColl )
4577 				nDfltColl = nColl;
4578 		}
4579 
4580 		// ggf. neue Absatz-Einzuege holen
4581 		if( pCntxt->IsLRSpaceChanged() )
4582 		{
4583 			sal_uInt16 nLeft=0, nRight=0;
4584 
4585 			pCntxt->GetMargins( nLeft, nRight, nFirstLineIndent );
4586 			nLeftMargin = nLeft;
4587 			nRightMargin = nRight;
4588 		}
4589 	}
4590 
4591 	// wenn im aktuellen Kontext eine neue Vorlage gesetzt werden soll,
4592 	// muessen deren Absatz-Abstaende noch in den Kontext eingetragen werden
4593 	if( pContext && nTopColl )
4594 	{
4595 		// <TD><P CLASS=xxx> muss TD.xxx werden
4596 		if( nTopColl==RES_POOLCOLL_TEXT &&
4597 			(nDfltColl==RES_POOLCOLL_TABLE ||
4598 			 nDfltColl==RES_POOLCOLL_TABLE_HDLN) )
4599 			nTopColl = nDfltColl;
4600 
4601 		const SwTxtFmtColl *pTopColl =
4602 			pCSS1Parser->GetTxtFmtColl( nTopColl, rTopClass );
4603 		const SfxItemSet& rItemSet = pTopColl->GetAttrSet();
4604 		const SfxPoolItem *pItem;
4605 		if( SFX_ITEM_SET == rItemSet.GetItemState(RES_LR_SPACE,sal_True, &pItem) )
4606 		{
4607 			const SvxLRSpaceItem *pLRItem =
4608 				(const SvxLRSpaceItem *)pItem;
4609 
4610 			sal_Int32 nLeft = pLRItem->GetTxtLeft();
4611 			sal_Int32 nRight = pLRItem->GetRight();
4612 			nFirstLineIndent = pLRItem->GetTxtFirstLineOfst();
4613 
4614 			// In Definitions-Listen enthalten die Abstaende auch die der
4615 			// vorhergehenden Level
4616 			if( RES_POOLCOLL_HTML_DD == nTopColl )
4617 			{
4618 				const SvxLRSpaceItem& rDTLRSpace = pCSS1Parser
4619 					->GetTxtFmtColl( RES_POOLCOLL_HTML_DT, aEmptyStr )
4620 					->GetLRSpace();
4621 				nLeft -= rDTLRSpace.GetTxtLeft();
4622 				nRight -= rDTLRSpace.GetRight();
4623 			}
4624 			else if( RES_POOLCOLL_HTML_DT == nTopColl )
4625 			{
4626 				nLeft = 0;
4627 				nRight = 0;
4628 			}
4629 
4630 			// die Absatz-Abstaende addieren sich
4631             nLeftMargin = nLeftMargin + static_cast< sal_uInt16 >(nLeft);
4632             nRightMargin = nRightMargin + static_cast< sal_uInt16 >(nRight);
4633 
4634 			pContext->SetMargins( nLeftMargin, nRightMargin,
4635 								  nFirstLineIndent );
4636 		}
4637 		if( SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,sal_True, &pItem) )
4638 		{
4639 			const SvxULSpaceItem *pULItem =
4640 				(const SvxULSpaceItem *)pItem;
4641 			pContext->SetULSpace( pULItem->GetUpper(), pULItem->GetLower() );
4642 		}
4643 	}
4644 
4645 	// wenn gar keine Vorlage im Kontext gesetzt ist, Textkoerper nehmen
4646 	if( !pCollToSet )
4647 	{
4648 		pCollToSet = pCSS1Parser->GetTxtCollFromPool( nDfltColl );
4649 		const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4650 		if( !nLeftMargin )
4651             nLeftMargin = static_cast< sal_uInt16 >(rLRItem.GetTxtLeft());
4652 		if( !nRightMargin )
4653             nRightMargin = static_cast< sal_uInt16 >(rLRItem.GetRight());
4654 		if( !nFirstLineIndent )
4655 			nFirstLineIndent = rLRItem.GetTxtFirstLineOfst();
4656 	}
4657 
4658 	// bisherige harte Attributierung des Absatzes entfernen
4659 	if( aParaAttrs.Count() )
4660 	{
4661 		for( i=0; i<aParaAttrs.Count(); i++ )
4662 			aParaAttrs[i]->Invalidate();
4663 
4664 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
4665 	}
4666 
4667 	// Die Vorlage setzen
4668 	pDoc->SetTxtFmtColl( *pPam, pCollToSet );
4669 
4670 	// ggf. noch den Absatz-Einzug korrigieren
4671 	const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4672 	sal_Bool bSetLRSpace;
4673 
4674        	bSetLRSpace = nLeftMargin != rLRItem.GetTxtLeft() ||
4675 					  nFirstLineIndent != rLRItem.GetTxtFirstLineOfst() ||
4676 					  nRightMargin != rLRItem.GetRight();
4677 
4678 	if( bSetLRSpace )
4679 	{
4680 		SvxLRSpaceItem aLRItem( rLRItem );
4681 		aLRItem.SetTxtLeft( nLeftMargin );
4682 		aLRItem.SetRight( nRightMargin );
4683 		aLRItem.SetTxtFirstLineOfst( nFirstLineIndent );
4684 		if( pItemSet )
4685 			pItemSet->Put( aLRItem );
4686 		else
4687 		{
4688 			NewAttr( &aAttrTab.pLRSpace, aLRItem );
4689 			aAttrTab.pLRSpace->SetLikePara();
4690 			aParaAttrs.Insert( aAttrTab.pLRSpace, aParaAttrs.Count() );
4691 			EndAttr( aAttrTab.pLRSpace, 0, sal_False );
4692 		}
4693 	}
4694 
4695 	// und nun noch die Attribute setzen
4696 	if( pItemSet )
4697 	{
4698 		InsertParaAttrs( *pItemSet );
4699 		delete pItemSet;
4700 	}
4701 }
4702 
4703 /*  */
4704 
NewCharFmt(int nToken)4705 void SwHTMLParser::NewCharFmt( int nToken )
4706 {
4707 	String aId, aStyle, aClass, aLang, aDir;
4708 
4709 	const HTMLOptions *pHTMLOptions = GetOptions();
4710 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4711 	{
4712 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4713 		switch( pOption->GetToken() )
4714 		{
4715 		case HTML_O_ID:
4716 			aId = pOption->GetString();
4717 			break;
4718 		case HTML_O_STYLE:
4719 			aStyle = pOption->GetString();
4720 			break;
4721 		case HTML_O_CLASS:
4722 			aClass = pOption->GetString();
4723 			break;
4724 		case HTML_O_LANG:
4725 			aLang = pOption->GetString();
4726 			break;
4727 		case HTML_O_DIR:
4728 			aDir = pOption->GetString();
4729 			break;
4730 		}
4731 	}
4732 
4733 	// einen neuen Kontext anlegen
4734     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
4735 
4736 	// die Vorlage setzen und im Kontext merken
4737     SwCharFmt* pCFmt = pCSS1Parser->GetChrFmt( static_cast< sal_uInt16 >(nToken), aClass );
4738 	ASSERT( pCFmt, "keine Zeichenvorlage zu Token gefunden" );
4739 
4740 
4741 	// Styles parsen (zu Class siehe auch NewPara)
4742 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4743 	{
4744 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4745 		SvxCSS1PropertyInfo aPropInfo;
4746 
4747 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4748 		{
4749 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4750 					"Class wird nicht beruecksichtigt" );
4751 			DoPositioning( aItemSet, aPropInfo, pCntxt );
4752 			InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
4753 		}
4754 	}
4755 
4756 	// Zeichen-Vorlagen werden in einem eigenen Stack gehalten und
4757 	// koennen nie durch Styles eingefuegt werden. Das Attribut ist deshalb
4758 	// auch gar nicht im CSS1-Which-Range enthalten
4759 	if( pCFmt )
4760 		InsertAttr( &aAttrTab.pCharFmts, SwFmtCharFmt( pCFmt ), pCntxt );
4761 
4762 	// den Kontext merken
4763 	PushContext( pCntxt );
4764 }
4765 
4766 
4767 /*  */
4768 
InsertSpacer()4769 void SwHTMLParser::InsertSpacer()
4770 {
4771 	// und es ggf. durch die Optionen veraendern
4772 	String aId;
4773     sal_Int16 eVertOri = text::VertOrientation::TOP;
4774     sal_Int16 eHoriOri = text::HoriOrientation::NONE;
4775 	Size aSize( 0, 0);
4776 	long nSize = 0;
4777 	sal_Bool bPrcWidth = sal_False;
4778 	sal_Bool bPrcHeight = sal_False;
4779 	sal_uInt16 nType = HTML_SPTYPE_HORI;
4780 
4781 	const HTMLOptions *pHTMLOptions = GetOptions();
4782 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4783 	{
4784 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4785 		switch( pOption->GetToken() )
4786 		{
4787 		case HTML_O_ID:
4788 			aId = pOption->GetString();
4789 			break;
4790 		case HTML_O_TYPE:
4791 			pOption->GetEnum( nType, aHTMLSpacerTypeTable );
4792 			break;
4793 		case HTML_O_ALIGN:
4794 			eVertOri =
4795                 pOption->GetEnum( aHTMLImgVAlignTable,
4796                                   eVertOri );
4797 			eHoriOri =
4798                 pOption->GetEnum( aHTMLImgHAlignTable,
4799                                   eHoriOri );
4800 			break;
4801 		case HTML_O_WIDTH:
4802 			// erstmal nur als Pixelwerte merken!
4803 			bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4804 			aSize.Width() = (long)pOption->GetNumber();
4805 			break;
4806 		case HTML_O_HEIGHT:
4807 			// erstmal nur als Pixelwerte merken!
4808 			bPrcHeight = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4809 			aSize.Height() = (long)pOption->GetNumber();
4810 			break;
4811 		case HTML_O_SIZE:
4812 			// erstmal nur als Pixelwerte merken!
4813 			nSize = pOption->GetNumber();
4814 			break;
4815 		}
4816 	}
4817 
4818 	switch( nType )
4819 	{
4820 	case HTML_SPTYPE_BLOCK:
4821 		{
4822 			// einen leeren Textrahmen anlegen
4823 
4824 			// den Itemset holen
4825 			SfxItemSet aFrmSet( pDoc->GetAttrPool(),
4826 								RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
4827 			if( !IsNewDoc() )
4828 				Reader::ResetFrmFmtAttrs( aFrmSet );
4829 
4830 			// den Anker und die Ausrichtung setzen
4831 			SetAnchorAndAdjustment( eVertOri, eHoriOri, aFrmSet );
4832 
4833 			// und noch die Groesse des Rahmens
4834 			Size aDfltSz( MINFLY, MINFLY );
4835 			Size aSpace( 0, 0 );
4836 			SfxItemSet aDummyItemSet( pDoc->GetAttrPool(),
4837 								 pCSS1Parser->GetWhichMap() );
4838 			SvxCSS1PropertyInfo aDummyPropInfo;
4839 
4840 			SetFixSize( aSize, aDfltSz, bPrcWidth, bPrcHeight,
4841 						aDummyItemSet, aDummyPropInfo, aFrmSet );
4842 			SetSpace( aSpace, aDummyItemSet, aDummyPropInfo, aFrmSet );
4843 
4844 			// den Inhalt schuetzen
4845             SvxProtectItem aProtectItem( RES_PROTECT) ;
4846 			aProtectItem.SetCntntProtect( sal_True );
4847 			aFrmSet.Put( aProtectItem );
4848 
4849 			// der Rahmen anlegen
4850 			RndStdIds eAnchorId =
4851 				((const SwFmtAnchor &)aFrmSet.Get(RES_ANCHOR)).GetAnchorId();
4852 			SwFrmFmt *pFlyFmt = pDoc->MakeFlySection( eAnchorId,
4853 											pPam->GetPoint(), &aFrmSet );
4854 			// Ggf Frames anlegen und auto-geb. Rahmen registrieren
4855 			RegisterFlyFrm( pFlyFmt );
4856 		}
4857 		break;
4858 	case HTML_SPTYPE_VERT:
4859 		if( nSize > 0 )
4860 		{
4861 			if( nSize && Application::GetDefaultDevice() )
4862 			{
4863 				nSize = Application::GetDefaultDevice()
4864 							->PixelToLogic( Size(0,nSize),
4865 											MapMode(MAP_TWIP) ).Height();
4866 			}
4867 
4868 			// einen Absatz-Abstand setzen
4869 			SwTxtNode *pTxtNode = 0;
4870 			if( !pPam->GetPoint()->nContent.GetIndex() )
4871 			{
4872 				// den unteren Absatz-Abstand des vorherigen Nodes aendern,
4873 				// wenn moeglich
4874 
4875 				SetAttr();	// noch offene Absatz-Attribute setzen
4876 
4877 				pTxtNode = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()-1]
4878 							   ->GetTxtNode();
4879 
4880 				// Wenn der Abstz davor kein Txtenode ist, dann wird jetzt
4881 				// ein leere Absatz angelegt, der eh schon eine Zeilenhoehe
4882 				// Abstand erzeugt.
4883 				if( !pTxtNode )
4884 					nSize = nSize>HTML_PARSPACE ? nSize-HTML_PARSPACE : 0;
4885 			}
4886 
4887 			if( pTxtNode )
4888 			{
4889 				SvxULSpaceItem aULSpace( (const SvxULSpaceItem&)pTxtNode
4890 					->SwCntntNode::GetAttr( RES_UL_SPACE ) );
4891 				aULSpace.SetLower( aULSpace.GetLower() + (sal_uInt16)nSize );
4892                 pTxtNode->SetAttr( aULSpace );
4893 			}
4894 			else
4895 			{
4896                 NewAttr( &aAttrTab.pULSpace, SvxULSpaceItem( 0, (sal_uInt16)nSize, RES_UL_SPACE ) );
4897 				EndAttr( aAttrTab.pULSpace, 0, sal_False );
4898 
4899 				AppendTxtNode();	// nicht am Abstand drehen!
4900 			}
4901 		}
4902 		break;
4903 	case HTML_SPTYPE_HORI:
4904 		if( nSize > 0 )
4905 		{
4906 			// wenn der Absatz noch leer ist, einen Erstzeilen-Einzug
4907 			// setzen, sondern Sperrschrift ueber einem Space aufspannen
4908 
4909 			if( nSize && Application::GetDefaultDevice() )
4910 			{
4911 				nSize = Application::GetDefaultDevice()
4912 							->PixelToLogic( Size(nSize,0),
4913 											MapMode(MAP_TWIP) ).Width();
4914 			}
4915 
4916 			if( !pPam->GetPoint()->nContent.GetIndex() )
4917 			{
4918 				sal_uInt16 nLeft=0, nRight=0;
4919 				short nIndent = 0;
4920 
4921 				GetMarginsFromContextWithNumBul( nLeft, nRight, nIndent );
4922                 nIndent = nIndent + (short)nSize;
4923 
4924                 SvxLRSpaceItem aLRItem( RES_LR_SPACE );
4925 				aLRItem.SetTxtLeft( nLeft );
4926 				aLRItem.SetRight( nRight );
4927 				aLRItem.SetTxtFirstLineOfst( nIndent );
4928 
4929 				NewAttr( &aAttrTab.pLRSpace, aLRItem );
4930 				EndAttr( aAttrTab.pLRSpace, 0, sal_False );
4931 			}
4932 			else
4933 			{
4934                 NewAttr( &aAttrTab.pKerning, SvxKerningItem( (short)nSize, RES_CHRATR_KERNING ) );
4935 				String aTmp( ' ' );
4936                 pDoc->InsertString( *pPam, aTmp );
4937 				EndAttr( aAttrTab.pKerning );
4938 			}
4939 		}
4940 	}
4941 }
4942 
ToTwips(sal_uInt16 nPixel) const4943 sal_uInt16 SwHTMLParser::ToTwips( sal_uInt16 nPixel ) const
4944 {
4945 	if( nPixel && Application::GetDefaultDevice() )
4946 	{
4947 		long nTwips = Application::GetDefaultDevice()->PixelToLogic(
4948 					Size( nPixel, nPixel ), MapMode( MAP_TWIP ) ).Width();
4949 		return nTwips <= USHRT_MAX ? (sal_uInt16)nTwips : USHRT_MAX;
4950 	}
4951 	else
4952 		return nPixel;
4953 }
4954 
GetCurrentBrowseWidth()4955 SwTwips SwHTMLParser::GetCurrentBrowseWidth()
4956 {
4957     const SwTwips nWidth = SwHTMLTableLayout::GetBrowseWidth( *pDoc );
4958 	if( nWidth )
4959 		return nWidth;
4960 
4961 	if( !aHTMLPageSize.Width() )
4962 	{
4963 		const SwFrmFmt& rPgFmt = pCSS1Parser->GetMasterPageDesc()->GetMaster();
4964 
4965 		const SwFmtFrmSize& rSz   = rPgFmt.GetFrmSize();
4966 		const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace();
4967 		const SvxULSpaceItem& rUL = rPgFmt.GetULSpace();
4968 		const SwFmtCol& rCol = rPgFmt.GetCol();
4969 
4970 		aHTMLPageSize.Width() = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight();
4971 		aHTMLPageSize.Height() = rSz.GetHeight() - rUL.GetUpper() - rUL.GetLower();
4972 
4973 		if( 1 < rCol.GetNumCols() )
4974 			aHTMLPageSize.Width() /= rCol.GetNumCols();
4975 	}
4976 
4977 	return aHTMLPageSize.Width();
4978 }
4979 
4980 
4981 /*  */
4982 
InsertIDOption()4983 void SwHTMLParser::InsertIDOption()
4984 {
4985 	String aId;
4986 	const HTMLOptions *pHTMLOptions = GetOptions();
4987 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4988 	{
4989 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4990 		if( HTML_O_ID==pOption->GetToken() )
4991 		{
4992 			aId = pOption->GetString();
4993 			break;
4994 		}
4995 	}
4996 
4997 	if( aId.Len() )
4998 		InsertBookmark( aId );
4999 }
5000 
5001 
5002 /*  */
5003 
5004 
InsertLineBreak()5005 void SwHTMLParser::InsertLineBreak()
5006 {
5007 	// <BR CLEAR=xxx> wird wie folgt behandelt:
5008 	// 1.) Es werden nur nur absatzgebundene Rahmen betrachtet, die
5009 	//     im aktuellen Absatz verankert sind.
5010 	// 2.) Fuer linksbuendig ausgerichtete Rahmen wird bei CLEAR=LEFT
5011 	//     oder ALL und auf rechtsbuendige ausgerichtete Rahmen bei
5012 	//     CLEAR=RIGHT oder ALL der Durchlauf wie folgt geaendert:
5013 	// 3.) Wenn der Absatz keinen Text enthaelt, bekommt der Rahmen keinen
5014 	//     Umlauf
5015 	// 4.) sonst erhaelt ein links ausgerichteter Rahmen eine rechten
5016 	//     "nur Anker" Umlauf und recht rechst ausg. Rahmen einen linken
5017 	//     "nur Anker" Umlauf.
5018 	// 5.) wenn in einem nicht-leeren Absatz der Umlauf eines Rahmens
5019 	//     geaendert wird, wird ein neuer Absatz aufgemacht
5020 	// 6.) Wenn von keinem Rahmen der Umlauf geaendert wird, wird ein
5021 	//     harter Zeilenumbruch eingefuegt
5022 
5023 	String aId, aStyle, aClass;			  	// die ID der Bookmark
5024 	sal_Bool bClearLeft = sal_False, bClearRight = sal_False;
5025 	sal_Bool bCleared = sal_False;	// wurde ein CLEAR ausgefuehrt?
5026 
5027 	// dann holen wir mal die Optionen
5028 	const HTMLOptions *pHTMLOptions = GetOptions();
5029 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
5030 	{
5031 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
5032 		switch( pOption->GetToken() )
5033 		{
5034 			case HTML_O_CLEAR:
5035 				{
5036 					const String &aClear = pOption->GetString();
5037 					if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_all ) )
5038 					{
5039 						bClearLeft = sal_True;
5040 						bClearRight = sal_True;
5041 					}
5042 					else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) )
5043 						bClearLeft = sal_True;
5044 					else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) )
5045 						bClearRight = sal_True;
5046 				}
5047 				break;
5048 			case HTML_O_ID:
5049 				aId = pOption->GetString();
5050 				break;
5051 			case HTML_O_STYLE:
5052 				aStyle = pOption->GetString();
5053 				break;
5054 			case HTML_O_CLASS:
5055 				aClass = pOption->GetString();
5056 				break;
5057 		}
5058 	}
5059 
5060 	// CLEAR wird nur fuer den aktuellen Absaetz unterstuetzt
5061 	if( bClearLeft || bClearRight )
5062 	{
5063 		SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
5064 		SwTxtNode* pTxtNd = rNodeIdx.GetNode().GetTxtNode();
5065 		if( pTxtNd )
5066 		{
5067 			const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
5068 
5069 			for( sal_uInt16 i=0; i<rFrmFmtTbl.Count(); i++ )
5070 			{
5071                 SwFrmFmt *const pFmt = rFrmFmtTbl[i];
5072                 SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
5073                 SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
5074                 if (pAPos &&
5075                     ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
5076                      (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
5077 					pAPos->nNode == rNodeIdx &&
5078 					pFmt->GetSurround().GetSurround() != SURROUND_NONE )
5079 				{
5080                     sal_Int16 eHori = RES_DRAWFRMFMT == pFmt->Which()
5081                         ? text::HoriOrientation::LEFT
5082 						: pFmt->GetHoriOrient().GetHoriOrient();
5083 
5084 					SwSurround eSurround = SURROUND_PARALLEL;
5085 					if( pPam->GetPoint()->nContent.GetIndex() )
5086 					{
5087                         if( bClearLeft && text::HoriOrientation::LEFT==eHori )
5088 							eSurround = SURROUND_RIGHT;
5089                         else if( bClearRight && text::HoriOrientation::RIGHT==eHori )
5090 							eSurround = SURROUND_LEFT;
5091 					}
5092                     else if( (bClearLeft && text::HoriOrientation::LEFT==eHori) ||
5093                              (bClearRight && text::HoriOrientation::RIGHT==eHori) )
5094 					{
5095 						eSurround = SURROUND_NONE;
5096 					}
5097 
5098 					if( SURROUND_PARALLEL != eSurround )
5099 					{
5100 						SwFmtSurround aSurround( eSurround );
5101 						if( SURROUND_NONE != eSurround )
5102 							aSurround.SetAnchorOnly( sal_True );
5103                         pFmt->SetFmtAttr( aSurround );
5104 						bCleared = sal_True;
5105 					}
5106 				} // Anker ist nicht im Node
5107 			} // Schleife ueber Fly-Frames
5108 		} // kein Text-Node
5109 	} // kein CLEAR
5110 
5111 	// Styles parsen
5112     SvxFmtBreakItem aBreakItem( SVX_BREAK_NONE, RES_BREAK );
5113 	sal_Bool bBreakItem = sal_False;
5114 	if( HasStyleOptions( aStyle, aId, aClass ) )
5115 	{
5116 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
5117 		SvxCSS1PropertyInfo aPropInfo;
5118 
5119 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) )
5120 		{
5121 			if( pCSS1Parser->SetFmtBreak( aItemSet, aPropInfo ) )
5122 			{
5123 				aBreakItem = (const SvxFmtBreakItem &)aItemSet.Get( RES_BREAK );
5124 				bBreakItem = sal_True;
5125 			}
5126 			if( aPropInfo.aId.Len() )
5127 				InsertBookmark( aPropInfo.aId );
5128 		}
5129 	}
5130 
5131 	if( bBreakItem && SVX_BREAK_PAGE_AFTER==aBreakItem.GetBreak() )
5132 	{
5133 		NewAttr( &aAttrTab.pBreak, aBreakItem );
5134 		EndAttr( aAttrTab.pBreak, 0, sal_False );
5135 	}
5136 
5137 	if( !bCleared && !bBreakItem )
5138 	{
5139 		// wenn kein CLEAR ausgefuehrt werden sollte oder konnte, wird
5140 		// ein Zeilenumbruch eingef?gt
5141 		String sTmp( (sal_Unicode)0x0a );	// make the Mac happy :-)
5142         pDoc->InsertString( *pPam, sTmp );
5143 	}
5144 	else if( pPam->GetPoint()->nContent.GetIndex() )
5145 	{
5146 		// wenn ein Claer in einem nicht-leeren Absatz ausgefuehrt wurde,
5147 		// muss anschliessen ein neuer Absatz aufgemacht werden
5148 		// MIB 21.02.97: Eigentlich muesste man hier den unteren Absatz-
5149 		// Absatnd auf 0 drehen. Das geht aber bei sowas wie <BR ..><P>
5150 		// schief (>Netacpe). Deshalb lassen wir das erstmal.
5151 		AppendTxtNode( AM_NOSPACE );
5152 	}
5153 	if( bBreakItem && SVX_BREAK_PAGE_BEFORE==aBreakItem.GetBreak() )
5154 	{
5155 		NewAttr( &aAttrTab.pBreak, aBreakItem );
5156 		EndAttr( aAttrTab.pBreak, 0, sal_False );
5157 	}
5158 }
5159 
InsertHorzRule()5160 void SwHTMLParser::InsertHorzRule()
5161 {
5162 	sal_uInt16 nSize = 0;
5163 	sal_uInt16 nWidth = 0;
5164 
5165 	SvxAdjust eAdjust = SVX_ADJUST_END;
5166 
5167 	sal_Bool bPrcWidth = sal_False;
5168 	sal_Bool bNoShade = sal_False;
5169 	sal_Bool bColor = sal_False;
5170 
5171 	Color aColor;
5172 	String aId;
5173 
5174 	// dann holen wir mal die Optionen
5175 	const HTMLOptions *pHTMLOptions = GetOptions();
5176 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
5177 	{
5178 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
5179 		switch( pOption->GetToken() )
5180 		{
5181 		case HTML_O_ID:
5182 			aId = pOption->GetString();
5183 			break;
5184 		case HTML_O_SIZE:
5185 			nSize = (sal_uInt16)pOption->GetNumber();
5186 			break;
5187 		case HTML_O_WIDTH:
5188 			bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
5189 			nWidth = (sal_uInt16)pOption->GetNumber();
5190 			if( bPrcWidth && nWidth>=100 )
5191 			{
5192 				// 100%-Linien sind der default-Fall (keine Attrs neotig)
5193 				nWidth = 0;
5194 				bPrcWidth = sal_False;
5195 			}
5196 			break;
5197 		case HTML_O_ALIGN:
5198 			eAdjust =
5199                 (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eAdjust) );
5200 			break;
5201 		case HTML_O_NOSHADE:
5202 			bNoShade = sal_True;
5203 			break;
5204 		case HTML_O_COLOR:
5205 			pOption->GetColor( aColor );
5206 			bColor = sal_True;
5207 			break;
5208 		}
5209 	}
5210 
5211 	if( pPam->GetPoint()->nContent.GetIndex() )
5212 		AppendTxtNode( AM_NOSPACE );
5213 	if( nOpenParaToken )
5214 		EndPara();
5215 	AppendTxtNode();
5216 	pPam->Move( fnMoveBackward );
5217 
5218 	// ... und in einem Kontext merken
5219 	_HTMLAttrContext *pCntxt =
5220 		new _HTMLAttrContext( HTML_HORZRULE, RES_POOLCOLL_HTML_HR, aEmptyStr );
5221 
5222 	PushContext( pCntxt );
5223 
5224 	// die neue Vorlage setzen
5225 	SetTxtCollAttrs( pCntxt );
5226 
5227 	// die harten Attribute an diesem Absatz werden nie mehr ungueltig
5228 	if( aParaAttrs.Count() )
5229 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
5230 
5231 	if( nSize>0 || bColor || bNoShade )
5232 	{
5233 		// Farbe und/oder Breite der Linie setzen
5234 		if( !bColor )
5235 			aColor.SetColor( COL_GRAY );
5236 
5237 		SvxBorderLine aBorderLine( &aColor );
5238 		if( nSize )
5239 		{
5240 			long nPWidth = 0;
5241 			long nPHeight = (long)nSize;
5242 			SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
5243 			SvxCSS1Parser::SetBorderWidth( aBorderLine, (sal_uInt16)nPHeight,
5244 										   !bNoShade );
5245 		}
5246 		else if( bNoShade )
5247 		{
5248 			aBorderLine.SetOutWidth( DEF_LINE_WIDTH_2 );
5249 		}
5250 		else
5251 		{
5252 			aBorderLine.SetOutWidth( DEF_DOUBLE_LINE0_OUT );
5253 			aBorderLine.SetInWidth( DEF_DOUBLE_LINE0_IN );
5254 			aBorderLine.SetDistance( DEF_DOUBLE_LINE0_DIST );
5255 		}
5256 
5257         SvxBoxItem aBoxItem(RES_BOX);
5258 		aBoxItem.SetLine( &aBorderLine, BOX_LINE_BOTTOM );
5259 		_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aBoxItem );
5260 		aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5261 	}
5262 	if( nWidth )
5263 	{
5264 		// Wenn wir in keiner Tabelle sind, wird die Breitenangabe durch
5265 		// Absatz-Einzuege "getuerkt". In einer Tabelle macht das wenig
5266 		// Sinn. Um zu Vermeiden, dass die Linie bei der Breitenberechnung
5267 		// beruecksichtigt wird, bekommt sie aber trotzdem entsprechendes
5268 		// LRSpace-Item verpasst.
5269 #ifdef FIX41370
5270 		const SwFmtColl *pColl = GetCurrFmtColl();
5271 		SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5272 #endif
5273 		if( !pTable )
5274 		{
5275 			// Laenge und Ausrichtung der Linie ueber Absatz-Einzuege "tuerken"
5276 			long nBrowseWidth = GetCurrentBrowseWidth();
5277 			nWidth = bPrcWidth ? (sal_uInt16)((nWidth*nBrowseWidth) / 100)
5278 							   : ToTwips( (sal_uInt16)nBrowseWidth );
5279 			if( nWidth < MINLAY )
5280 				nWidth = MINLAY;
5281 
5282 			if( (long)nWidth < nBrowseWidth )
5283 			{
5284 #ifndef FIX41370
5285 				const SwFmtColl *pColl = GetCurrFmtColl();
5286 				SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5287 #endif
5288 				long nDist = nBrowseWidth - nWidth;
5289 
5290 				switch( eAdjust )
5291 				{
5292 				case SVX_ADJUST_RIGHT:
5293 					aLRItem.SetTxtLeft( (sal_uInt16)nDist );
5294 					break;
5295 				case SVX_ADJUST_LEFT:
5296 					aLRItem.SetRight( (sal_uInt16)nDist );
5297 					break;
5298 				case SVX_ADJUST_CENTER:
5299 				default:
5300 					nDist /= 2;
5301 					aLRItem.SetTxtLeft( (sal_uInt16)nDist );
5302 					aLRItem.SetRight( (sal_uInt16)nDist );
5303 					break;
5304 				}
5305 
5306 #ifndef FIX41370
5307 				_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5308 				aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5309 #endif
5310 			}
5311 		}
5312 
5313 #ifdef FIX41370
5314 		_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5315 		aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5316 #endif
5317 	}
5318 
5319 	// Bookmarks koennen nicht in Hyperlinks eingefueht werden
5320 	if( aId.Len() )
5321 		InsertBookmark( aId );
5322 
5323 	// den aktuellen Kontext vom Stack holen
5324 	_HTMLAttrContext *pPoppedContext = PopContext( HTML_HORZRULE );
5325 	ASSERT( pPoppedContext==pCntxt, "wo kommt denn da ein HR-Kontext her?" );
5326 	delete pPoppedContext;
5327 
5328 	pPam->Move( fnMoveForward );
5329 
5330 	// und im Absatz danach die dort aktuelle Vorlage setzen
5331 	SetTxtCollAttrs();
5332 }
5333 
ParseMoreMetaOptions()5334 void SwHTMLParser::ParseMoreMetaOptions()
5335 {
5336     String aName, aContent;
5337     sal_Bool bHTTPEquiv = sal_False;
5338 
5339     const HTMLOptions *pHTMLOptions = GetOptions();
5340     for( sal_uInt16 i = pHTMLOptions->Count(); i; )
5341     {
5342         const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
5343         switch( pOption->GetToken() )
5344         {
5345         case HTML_O_NAME:
5346             aName = pOption->GetString();
5347             bHTTPEquiv = sal_False;
5348             break;
5349         case HTML_O_HTTPEQUIV:
5350             aName = pOption->GetString();
5351             bHTTPEquiv = sal_True;
5352             break;
5353         case HTML_O_CONTENT:
5354             aContent = pOption->GetString();
5355             break;
5356         }
5357     }
5358 
5359     // Hier wird es etwas tricky: Wir wissen genau, da? die Dok-Info
5360     // nicht geaendert wurde. Deshalb genuegt es, auf Generator und
5361     // auf refresh abzufragen, um noch nicht verarbeitete Token zu finden,
5362     // denn das sind die einzigen, die die Dok-Info nicht modifizieren.
5363     if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_generator ) ||
5364         aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_refresh ) ||
5365         aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_type ) ||
5366         aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_script_type ) )
5367         return;
5368 
5369     aContent.EraseAllChars( _CR );
5370     aContent.EraseAllChars( _LF );
5371 
5372     if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdendnote ) )
5373     {
5374         FillEndNoteInfo( aContent );
5375         return;
5376     }
5377 
5378     if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdfootnote ) )
5379     {
5380         FillFootNoteInfo( aContent );
5381         return;
5382     }
5383 
5384     String sText( String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
5385     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_meta) );
5386     sText.Append( ' ' );
5387     if( bHTTPEquiv  )
5388         sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_httpequiv) );
5389     else
5390         sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_name) );
5391     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5392     sText.Append( aName );
5393     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\" ") );
5394     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_content) );
5395     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5396     sText.Append( aContent );
5397     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\">") );
5398 
5399     SwPostItField aPostItFld(
5400         (SwPostItFieldType*)pDoc->GetSysFldType( RES_POSTITFLD ),
5401         sText,
5402         aEmptyStr,
5403         aEmptyStr,
5404         aEmptyStr,
5405         DateTime() );
5406     SwFmtFld aFmtFld( aPostItFld );
5407     InsertAttr( aFmtFld );
5408 }
5409 
5410 /*  */
5411 
_HTMLAttr(const SwPosition & rPos,const SfxPoolItem & rItem,_HTMLAttr ** ppHd)5412 _HTMLAttr::_HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem,
5413 					  _HTMLAttr **ppHd ) :
5414 	nSttPara( rPos.nNode ),
5415 	nEndPara( rPos.nNode ),
5416 	nSttCntnt( rPos.nContent.GetIndex() ),
5417 	nEndCntnt(rPos.nContent.GetIndex() ),
5418 	bInsAtStart( sal_True ),
5419 	bLikePara( sal_False ),
5420 	bValid( sal_True ),
5421 	nCount( 1 ),
5422 	pNext( 0 ),
5423 	pPrev( 0 ),
5424 	ppHead( ppHd )
5425 {
5426 	pItem = rItem.Clone();
5427 }
5428 
_HTMLAttr(const _HTMLAttr & rAttr,const SwNodeIndex & rEndPara,sal_uInt16 nEndCnt,_HTMLAttr ** ppHd)5429 _HTMLAttr::_HTMLAttr( const _HTMLAttr &rAttr, const SwNodeIndex &rEndPara,
5430 					  sal_uInt16 nEndCnt, _HTMLAttr **ppHd ) :
5431 	nSttPara( rAttr.nSttPara ),
5432 	nEndPara( rEndPara ),
5433 	nSttCntnt( rAttr.nSttCntnt ),
5434 	nEndCntnt( nEndCnt ),
5435 	bInsAtStart( rAttr.bInsAtStart ),
5436 	bLikePara( rAttr.bLikePara ),
5437 	bValid( rAttr.bValid ),
5438 	nCount( rAttr.nCount ),
5439 	pNext( 0 ),
5440 	pPrev( 0 ),
5441 	ppHead( ppHd )
5442 {
5443 	pItem = rAttr.pItem->Clone();
5444 }
5445 
~_HTMLAttr()5446 _HTMLAttr::~_HTMLAttr()
5447 {
5448 	delete pItem;
5449 }
5450 
Clone(const SwNodeIndex & rEndPara,sal_uInt16 nEndCnt) const5451 _HTMLAttr *_HTMLAttr::Clone( const SwNodeIndex& rEndPara, sal_uInt16 nEndCnt ) const
5452 {
5453 	// das Attribut mit der alten Start-Position neu anlegen
5454 	_HTMLAttr *pNew = new _HTMLAttr( *this, rEndPara, nEndCnt, ppHead );
5455 
5456 	// die Previous-Liste muss uebernommen werden, die Next-Liste nicht!
5457 	pNew->pPrev = pPrev;
5458 
5459 	return pNew;
5460 }
5461 
Reset(const SwNodeIndex & rSttPara,sal_uInt16 nSttCnt,_HTMLAttr ** ppHd)5462 void _HTMLAttr::Reset( const SwNodeIndex& rSttPara, sal_uInt16 nSttCnt,
5463 					   _HTMLAttr **ppHd )
5464 {
5465 	// den Anfang (und das Ende) neu setzen
5466 	nSttPara = rSttPara;
5467 	nSttCntnt = nSttCnt;
5468 	nEndPara = rSttPara;
5469 	nEndCntnt = nSttCnt;
5470 
5471 	// den Head korrigieren und die Verkettungen aufheben
5472 	pNext = 0;
5473 	pPrev = 0;
5474 	ppHead = ppHd;
5475 }
5476 
InsertPrev(_HTMLAttr * pPrv)5477 void _HTMLAttr::InsertPrev( _HTMLAttr *pPrv )
5478 {
5479 	ASSERT( !pPrv->pNext || pPrv->pNext == this,
5480 			"_HTMLAttr::InsertPrev: pNext falsch" );
5481 	pPrv->pNext = 0;
5482 
5483 	ASSERT( 0 == pPrv->ppHead || ppHead == pPrv->ppHead,
5484 			"_HTMLAttr::InsertPrev: ppHead falsch" );
5485 	pPrv->ppHead = 0;
5486 
5487 	_HTMLAttr *pAttr = this;
5488 	while( pAttr->GetPrev() )
5489 		pAttr = pAttr->GetPrev();
5490 
5491 	pAttr->pPrev = pPrv;
5492 }
5493 
ParseMetaOptions(const uno::Reference<document::XDocumentProperties> & i_xDocProps,SvKeyValueIterator * i_pHeader)5494 bool SwHTMLParser::ParseMetaOptions(
5495         const uno::Reference<document::XDocumentProperties> & i_xDocProps,
5496         SvKeyValueIterator *i_pHeader )
5497 {
5498     // always call base ParseMetaOptions, it sets the encoding (#i96700#)
5499     bool ret( HTMLParser::ParseMetaOptions(i_xDocProps, i_pHeader) );
5500     if (!ret && IsNewDoc())
5501     {
5502         ParseMoreMetaOptions();
5503     }
5504     return ret;
5505 }
5506 
5507 // override so we can parse DOCINFO field subtypes INFO[1-4]
AddMetaUserDefined(::rtl::OUString const & i_rMetaName)5508 void SwHTMLParser::AddMetaUserDefined( ::rtl::OUString const & i_rMetaName )
5509 {
5510     // unless we already have 4 names, append the argument to m_InfoNames
5511     ::rtl::OUString* pName // the first empty string in m_InfoNames
5512          (!m_InfoNames[0].getLength() ? &m_InfoNames[0] :
5513          (!m_InfoNames[1].getLength() ? &m_InfoNames[1] :
5514          (!m_InfoNames[2].getLength() ? &m_InfoNames[2] :
5515          (!m_InfoNames[3].getLength() ? &m_InfoNames[3] : 0 ))));
5516     if (pName)
5517     {
5518         (*pName) = i_rMetaName;
5519     }
5520 }
5521 
5522