xref: /trunk/main/sw/source/filter/html/swhtml.cxx (revision 6494b7d7)
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>		// for SwBookmark ...
94 #include <docsh.hxx>
95 #include <editsh.hxx>		// for 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 for Statusbar
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( sal_False,
193 			"The html.vor is no longer in the defined directory!");
194 	}
195 
196 	return sTemplate;
197 }
198 
SetStrmStgPtr()199 int HTMLReader::SetStrmStgPtr()
200 {
201 	ASSERT( pMedium, "Where is the 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 	// Call of generic Read Interface
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 without Stream" );
218 		return ERR_SWG_READ_ERROR;
219 	}
220 
221 	if( !bInsertMode )
222 	{
223 		Reader::SetNoOutlineNum( rDoc );
224 		Reader::ResetFrmFmts( rDoc );
225 
226 		// set HTML-template, if the document is not html,
227 		// else it is set.
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 	// lock to prevent stealing of the Doc!
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 		// use Stream to carry the error number
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 	bDocInitialized( 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 	// read Font-size 1-7 from INI-file
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 	// during import switch to HTML-Mode, in order
361 	// to set correct templates
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 	// use Timer only with normal Documents!
383 	SwDocShell* pDocSh = pDoc->GetDocShell();
384 	if( pDocSh )
385 	{
386 		bViewCreated = sal_True;			// do not load synchron
387 
388 		// a jumppoint is set.
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;	// this is not valid!
416 					else
417 						// else it is a normal (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 in Continue - This will not work!!!" );
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 	// DocumentDetected may delete DocShells,
444 	// so requst it again
445 	if( pDoc->GetDocShell() )
446 	{
447 		// update linked areas
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(),"There are still attributes on the 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, "There is still one open table" );
476 	delete pImageMaps;
477 	//delete pTable;
478 
479 	ASSERT( !pPendStack,
480 			"SwHTMLParser::~SwHTMLParser: There should be no more pending stack here" );
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 		// no more use for Doc, delete it
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         // Import of SFX aborted?
516         eState = SVPAR_ERROR;
517     }
518     // <--
519 
520 	GetAsynchCallLink().Call(0);
521 	return 0;
522 }
523 
CallParser()524 SvParserState __EXPORT SwHTMLParser::CallParser()
525 {
526 	// set tempory Index, on Pos 0 in order avoid moving!
527 	pSttNdIdx = new SwNodeIndex( pDoc->GetNodes() );
528 	if( !IsNewDoc() )		// insert to a new document ?
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 	// show progress bar
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 - That should not be, shouldn't it?" );
586 	nContinue++;
587 #endif
588 
589 	// if Import (vom SFX) has been aborted, an error is set
590 	// in order to clean up, the process continues
591 	ASSERT( SVPAR_ERROR!=eState,
592 			"SwHTMLParser::Continue: already set an error" );
593 	if( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
594 		eState = SVPAR_ERROR;
595 
596 	// get ViewShell from Document, memorize and set as current.
597 	ViewShell *pInitVSh = CallStartAction();
598 
599 	if( SVPAR_ERROR != eState && GetMedium() && !bViewCreated )
600 	{
601 		// Return at first call, show Doc and wait for timer callback.
602 		// At this point, CallParser read only one character and called
603 		// SaveState(0)
604 		eState = SVPAR_PENDING;
605 		bViewCreated = sal_True;
606 		pDoc->SetInLoadAsynchron( sal_True );
607 
608 #ifdef DBG_UTIL
609 		nContinue--;
610 #endif
611 
612 		return;
613 	}
614 
615 	bSetModEnabled = sal_False;
616 	if( pDoc->GetDocShell() &&
617 		0 != (bSetModEnabled = pDoc->GetDocShell()->IsEnableSetModified()) )
618 	{
619 		pDoc->GetDocShell()->EnableSetModified( sal_False );
620 	}
621 
622 	// during read. do not call OLE-Modify
623 	Link aOLELink( pDoc->GetOle2Link() );
624 	pDoc->SetOle2Link( Link() );
625 
626 	sal_Bool bModified = pDoc->IsModified();
627     bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
628     pDoc->GetIDocumentUndoRedo().DoUndo(false);
629 
630 	// If Import aborts, do not call Continue.
631 	// if a Pending-Stack exists, call NextToken.
632 	// NextToken will take care of clean up.
633 	if( SVPAR_ERROR == eState )
634 	{
635 		ASSERT( !pPendStack || pPendStack->nToken,
636 				"SwHTMLParser::Continue: Pending-Stack without Token" );
637 		if( pPendStack && pPendStack->nToken )
638 			NextToken( pPendStack->nToken );
639 		ASSERT( !pPendStack,
640 				"SwHTMLParser::Continue: there is still a Pend-Stack" );
641 	}
642 	else
643 	{
644 		HTMLParser::Continue( pPendStack ? pPendStack->nToken : nToken );
645 	}
646 
647 	// switch progress bar off
648 	EndProgress( pDoc->GetDocShell() );
649 
650 	sal_Bool bLFStripped = sal_False;
651 	if( SVPAR_PENDING != GetStatus() )
652 	{
653 		// set last Attributes
654 		{
655 			if( aScriptSource.Len() )
656 			{
657 				SwScriptFieldType *pType =
658 					(SwScriptFieldType*)pDoc->GetSysFldType( RES_SCRIPTFLD );
659 
660 				SwScriptField aFld( pType, aScriptType, aScriptSource,
661 									sal_False );
662 				InsertAttr( SwFmtFld( aFld ) );
663 			}
664 
665 			if( pAppletImpl )
666 			{
667                 if( pAppletImpl->GetApplet().is() )
668 					EndApplet();
669 				else
670 					EndObject();
671 			}
672 
673 			// remove LF behind last paragaf if exists
674 			if( IsNewDoc() )
675 				bLFStripped = StripTrailingLF() > 0;
676 
677 			// end open nummerations.
678 			while( GetNumInfo().GetNumRule() )
679 				EndNumBulList();
680 
681 			ASSERT( !nContextStMin, "There are protected contexts" );
682 			nContextStMin = 0;
683 			while( aContexts.Count() )
684 			{
685 				_HTMLAttrContext *pCntxt = PopContext();
686 				if( pCntxt )
687 				{
688 					EndContext( pCntxt );
689 					delete pCntxt;
690 				}
691 			}
692 
693 			if( aParaAttrs.Count() )
694 				aParaAttrs.Remove( 0, aParaAttrs.Count() );
695 
696 			SetAttr( sal_False );
697 
698 			// set deferred Styles
699 			pCSS1Parser->SetDelayedStyles();
700 		}
701 
702 		// fix again Start
703 		if( !IsNewDoc() && pSttNdIdx->GetIndex() )
704 		{
705 			SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode();
706 			SwNodeIndex aNxtIdx( *pSttNdIdx );
707 			if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx ))
708 			{
709 				xub_StrLen nStt = pTxtNode->GetTxt().Len();
710 				// if Cursor is in Node, set it to the end
711 				if( pPam->GetPoint()->nNode == aNxtIdx )
712 				{
713 					pPam->GetPoint()->nNode = *pSttNdIdx;
714 					pPam->GetPoint()->nContent.Assign( pTxtNode, nStt );
715 				}
716 
717 #ifdef DBG_UTIL
718 // !!! should not be possible, should it ??
719 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( sal_True ).nNode.GetIndex(),
720 			"Pam.Bound1 is in Node" );
721 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( sal_False ).nNode.GetIndex(),
722 			"Pam.Bound2 is in Node" );
723 
724 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( sal_True ).nNode.GetIndex() )
725 {
726 	xub_StrLen nCntPos = pPam->GetBound( sal_True ).nContent.GetIndex();
727 	pPam->GetBound( sal_True ).nContent.Assign( pTxtNode,
728 					pTxtNode->GetTxt().Len() + nCntPos );
729 }
730 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( sal_False ).nNode.GetIndex() )
731 {
732 	xub_StrLen nCntPos = pPam->GetBound( sal_False ).nContent.GetIndex();
733 	pPam->GetBound( sal_False ).nContent.Assign( pTxtNode,
734 					pTxtNode->GetTxt().Len() + nCntPos );
735 }
736 #endif
737 				// keep character Attribute!
738 				SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode();
739 				if( pTxtNode->GetTxt().Len() )
740 					pDelNd->FmtToTxtAttr( pTxtNode );
741 				else
742 					pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() );
743 				pTxtNode->JoinNext();
744 			}
745 		}
746 	}
747 
748 	if( SVPAR_ACCEPTED == eState )
749 	{
750 		if( nMissingImgMaps )
751 		{
752 			// some image maps were not assigned.
753 			// Maybe their Image-Maps are already there?
754 			ConnectImageMaps();
755 		}
756 
757 		// now delete the last needless paragraph
758 		SwPosition* pPos = pPam->GetPoint();
759 		if( !pPos->nContent.GetIndex() && !bLFStripped )
760 		{
761 			SwTxtNode* pAktNd;
762 			sal_uLong nNodeIdx = pPos->nNode.GetIndex();
763 
764 			sal_Bool bHasFlysOrMarks =
765 				HasCurrentParaFlys() || HasCurrentParaBookmarks( sal_True );
766 
767 			if( IsNewDoc() )
768 			{
769 				const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
770 				if( !pPam->GetPoint()->nContent.GetIndex() &&
771 					( pPrev->IsCntntNode() ||
772 					  (pPrev->IsEndNode() &&
773 					  pPrev->StartOfSectionNode()->IsSectionNode()) ) )
774 				{
775 					SwCntntNode* pCNd = pPam->GetCntntNode();
776 					if( pCNd && pCNd->StartOfSectionIndex()+2 <
777 						pCNd->EndOfSectionIndex() && !bHasFlysOrMarks )
778 					{
779 						ViewShell *pVSh = CheckActionViewShell();
780 						SwCrsrShell *pCrsrSh = pVSh && pVSh->ISA(SwCrsrShell)
781 										? static_cast < SwCrsrShell * >( pVSh )
782 										: 0;
783 						if( pCrsrSh &&
784 							pCrsrSh->GetCrsr()->GetPoint()
785 								   ->nNode.GetIndex() == nNodeIdx )
786 						{
787 							pCrsrSh->MovePara(fnParaPrev, fnParaEnd );
788 							pCrsrSh->SetMark();
789 							pCrsrSh->ClearMark();
790 						}
791 						pPam->GetBound(sal_True).nContent.Assign( 0, 0 );
792 						pPam->GetBound(sal_False).nContent.Assign( 0, 0 );
793 						pDoc->GetNodes().Delete( pPam->GetPoint()->nNode );
794 					}
795 				}
796 			}
797 			else if( 0 != ( pAktNd = pDoc->GetNodes()[ nNodeIdx ]->GetTxtNode()) && !bHasFlysOrMarks )
798 			{
799 				if( pAktNd->CanJoinNext( &pPos->nNode ))
800 				{
801 					SwTxtNode* pNextNd = pPos->nNode.GetNode().GetTxtNode();
802 					pPos->nContent.Assign( pNextNd, 0 );
803 					pPam->SetMark(); pPam->DeleteMark();
804 					pNextNd->JoinPrev();
805 				}
806 				else if( !pAktNd->GetTxt().Len() )
807 				{
808 					pPos->nContent.Assign( 0, 0 );
809 					pPam->SetMark(); pPam->DeleteMark();
810 					pDoc->GetNodes().Delete( pPos->nNode, 1 );
811 					pPam->Move( fnMoveBackward );
812 				}
813 			}
814 		}
815 
816 		// now cancel the SplitNode from the start
817 		else if( !IsNewDoc() )
818 		{
819 			if( pPos->nContent.GetIndex() ) 	// then there was no <P> at the end
820 				pPam->Move( fnMoveForward, fnGoNode ); 	// to the next node
821 			SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
822 			SwNodeIndex aPrvIdx( pPos->nNode );
823 			if( pTxtNode && pTxtNode->CanJoinPrev( &aPrvIdx ) &&
824 				*pSttNdIdx <= aPrvIdx )
825 			{
826 				// actually a JoinNext must be done here, but all cursors
827 				// etc. are registered in the pTxtNode,
828 				// which MUST remain
829 
830 
831 				// Convert paragraph to character attributes,
832 				// take over the paragraph attributes and the template from the Prev!
833 				SwTxtNode* pPrev = aPrvIdx.GetNode().GetTxtNode();
834 				pTxtNode->ChgFmtColl( pPrev->GetTxtColl() );
835 				pTxtNode->FmtToTxtAttr( pPrev );
836                 pTxtNode->ResetAllAttr();
837 
838                 if( pPrev->HasSwAttrSet() )
839                     pTxtNode->SetAttr( *pPrev->GetpSwAttrSet() );
840 
841 				if( &pPam->GetBound(sal_True).nNode.GetNode() == pPrev )
842 					pPam->GetBound(sal_True).nContent.Assign( pTxtNode, 0 );
843 				if( &pPam->GetBound(sal_False).nNode.GetNode() == pPrev )
844 					pPam->GetBound(sal_False).nContent.Assign( pTxtNode, 0 );
845 
846 				pTxtNode->JoinPrev();
847 			}
848 		}
849 
850 		// and prepare DocumentInfo
851 		if( IsNewDoc() )
852 		{
853             SwDocShell *pDocShell(pDoc->GetDocShell());
854             DBG_ASSERT(pDocShell, "no SwDocShell");
855             if (pDocShell) {
856                 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
857                     pDocShell->GetModel(), uno::UNO_QUERY_THROW);
858                 uno::Reference<document::XDocumentProperties> xDocProps(
859                     xDPS->getDocumentProperties());
860                 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
861                 if ( xDocProps.is() && (xDocProps->getAutoloadSecs() > 0) &&
862                      xDocProps->getAutoloadURL().equalsAscii("") )
863                 {
864                     xDocProps->setAutoloadURL(aPathToFile);
865                 }
866             }
867 		}
868 
869 		if( bUpdateDocStat )
870 		{
871 			SwDocStat aStat( pDoc->GetDocStat() );
872 			pDoc->UpdateDocStat( aStat );
873 		}
874 	}
875 
876 	if( SVPAR_PENDING != GetStatus() )
877 		delete pSttNdIdx, pSttNdIdx = 0;
878 
879 	// should the parser be the last one to hold the doc,
880 	// no need to do anything here either, doc is about to be destroyed!
881 	if( 1 < pDoc->getReferenceCount() )
882 	{
883 		if( bWasUndo )
884         {
885             pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
886             pDoc->GetIDocumentUndoRedo().DoUndo(true);
887         }
888 		else if( !pInitVSh )
889 		{
890 			// If there was no shell at the beginning of the Continue,
891 			// nevertheless one may have been created in the meantime.
892 			// In this case the bWasUndo flag is not correct and
893 			// a switch on the undo is necessary.
894 			ViewShell *pTmpVSh = CheckActionViewShell();
895 			if( pTmpVSh )
896             {
897                 pDoc->GetIDocumentUndoRedo().DoUndo(true);
898             }
899         }
900 
901 		pDoc->SetOle2Link( aOLELink );
902 		if( !bModified )
903 			pDoc->ResetModified();
904 		if( bSetModEnabled && pDoc->GetDocShell() )
905 		{
906 			pDoc->GetDocShell()->EnableSetModified( sal_True );
907 			bSetModEnabled = sal_False; // this is unnecessary here
908 		}
909 	}
910 
911 
912 	// If the Dokuemnt-ViewShell still exists and an Action
913 	// is open (doesn't have to be on abort), terminate the action,
914 	// log out of the shell and finally reconstruct the old shell
915 	// again.
916 
917 	CallEndAction( sal_True );
918 
919 #ifdef DBG_UTIL
920 	nContinue--;
921 #endif
922 }
923 
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)924 void SwHTMLParser::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
925 {
926 	switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
927 	{
928 	case RES_OBJECTDYING:
929 		if( ((SwPtrMsgPoolItem *)pOld)->pObject == GetRegisteredIn() )
930 		{
931 			// then finish ourselves
932 			GetRegisteredInNonConst()->Remove( this );
933 			ReleaseRef();					// otherwise we are done!
934 		}
935 		break;
936 	}
937 }
938 
DocumentDetected()939 void SwHTMLParser::DocumentDetected()
940 {
941 	ASSERT( !bDocInitialized, "DocumentDetected called multiple times" );
942 	bDocInitialized = sal_True;
943 	if( IsNewDoc() )
944 	{
945 		if( IsInHeader() )
946 			FinishHeader( sal_True );
947 
948 		CallEndAction( sal_True, sal_True );
949 
950         pDoc->GetIDocumentUndoRedo().DoUndo(false);
951 		// By DocumentDetected a ViewShell has been created.
952 		// But it can also be that it is created later,
953 		// namely when the UI is is captured.
954 		CallStartAction();
955 	}
956 }
957 
958 // is called for each token that is recognized in CallParser
NextToken(int nToken)959 void __EXPORT SwHTMLParser::NextToken( int nToken )
960 {
961 	if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
962 		|| 1 == pDoc->getReferenceCount() )
963 	{
964 		// was the import aborted by the SFX? If a pending stack
965 		// still exists to clean it up
966 		eState = SVPAR_ERROR;
967 		ASSERT( !pPendStack || pPendStack->nToken,
968 				"SwHTMLParser::NextToken: pending stack without token" );
969 		if( 1 == pDoc->getReferenceCount() || !pPendStack )
970 			return ;
971 	}
972 
973 #ifdef DBG_UTIL
974 	if( pPendStack )
975 	{
976 		switch( nToken )
977 		{
978 			// tables are read via recusive method calls
979 		case HTML_TABLE_ON:
980 			// For CSS declarations you may have to wait for the
981 			// end of a file download.
982 		case HTML_LINK:
983 			// For controls, the size may still have to be set.
984 		case HTML_INPUT:
985 		case HTML_TEXTAREA_ON:
986 		case HTML_SELECT_ON:
987 		case HTML_SELECT_OFF:
988 			break;
989 		default:
990 			ASSERT( !pPendStack, "Unknown token for pending stack" );
991 			break;
992 		}
993 	}
994 #endif
995 
996 	// The following special cases have to be handled before the filter detection
997 	// because the content of the title, etc. is not used for filter even in Netcape.
998 	if( !pPendStack )
999 	{
1000 		if( bInTitle )
1001 		{
1002 			switch( nToken )
1003 			{
1004 			case HTML_TITLE_OFF:
1005 				if( IsNewDoc() && sTitle.Len() )
1006 				{
1007                     if( pDoc->GetDocShell() ) {
1008                         uno::Reference<document::XDocumentPropertiesSupplier>
1009                             xDPS(pDoc->GetDocShell()->GetModel(),
1010                             uno::UNO_QUERY_THROW);
1011                         uno::Reference<document::XDocumentProperties> xDocProps(
1012                             xDPS->getDocumentProperties());
1013                         DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
1014                         if (xDocProps.is()) {
1015                             xDocProps->setTitle(sTitle);
1016                         }
1017 
1018 						pDoc->GetDocShell()->SetTitle( sTitle );
1019                     }
1020 				}
1021 				bInTitle = sal_False;
1022 				sTitle.Erase();
1023 				break;
1024 
1025 			case HTML_NONBREAKSPACE:
1026 				sTitle += ' ';
1027 				break;
1028 
1029 			case HTML_SOFTHYPH:
1030 				sTitle += '-';
1031 				break;
1032 
1033 			case HTML_TEXTTOKEN:
1034 				sTitle += aToken;
1035 				break;
1036 
1037 			default:
1038 				sTitle += '<';
1039 				if( (HTML_TOKEN_ONOFF & nToken) && (1 & nToken) )
1040 					sTitle += '/';
1041 				sTitle += sSaveToken;
1042 				if( aToken.Len() )
1043 				{
1044 					sTitle += ' ';
1045 					sTitle += aToken;
1046 				}
1047 				sTitle += '>';
1048 				break;
1049 			}
1050 
1051 			return;
1052 		}
1053 	}
1054 
1055 	// If we don't know yet, what kind of document we have in front of us,
1056 	// let's try to find out first. This must be done for controls in
1057 	// case before inserting the control, because when inserting the control
1058 	// a view is already needed.
1059 	if( !bDocInitialized )
1060 		DocumentDetected();
1061 
1062 	sal_Bool bGetIDOption = sal_False, bInsertUnknown = sal_False;
1063 	sal_Bool bUpperSpaceSave = bUpperSpace;
1064 	bUpperSpace = sal_False;
1065 
1066 	// The following special cases must or can be made after the
1067 	// filter detection.
1068 	if( !pPendStack )
1069 	{
1070 		if( bInFloatingFrame )
1071 		{
1072 			// <SCRIPT> is ignored here (by us), because it is also ignored in applets!
1073 			if( HTML_IFRAME_OFF == nToken )
1074 			{
1075 				bCallNextToken = sal_False;
1076 				EndFloatingFrame();
1077 			}
1078 
1079 			return;
1080 		}
1081 		else if( bInNoEmbed )
1082 		{
1083 			switch( nToken )
1084 			{
1085 			case HTML_NOEMBED_OFF:
1086 				aContents.ConvertLineEnd();
1087 				InsertComment( aContents, OOO_STRING_SVTOOLS_HTML_noembed );
1088 				aContents.Erase();
1089 				bCallNextToken = sal_False;
1090 				bInNoEmbed = sal_False;
1091 				break;
1092 
1093 			case HTML_RAWDATA:
1094 				InsertCommentText( OOO_STRING_SVTOOLS_HTML_noembed );
1095 				break;
1096 
1097 			default:
1098 				ASSERT( sal_False, "SwHTMLParser::NextToken: invalid day" );
1099 				break;
1100 			}
1101 
1102 			return;
1103 		}
1104 		else if( pAppletImpl )
1105 		{
1106 			// in an applet we are (for now) only interested in <PARAM> tags.
1107 			// and the </APPLET>.
1108 			// <SCRIPT> is ignored here (by Netscape)!
1109 
1110 			switch( nToken )
1111 			{
1112 			case HTML_APPLET_OFF:
1113 				bCallNextToken = sal_False;
1114 				EndApplet();
1115 				break;
1116 			case HTML_OBJECT_OFF:
1117 				bCallNextToken = sal_False;
1118 				EndObject();
1119 				break;
1120 
1121 			case HTML_PARAM:
1122 				InsertParam();
1123 				break;
1124 			}
1125 
1126 			return;
1127 		}
1128 		else if( bTextArea )
1129 		{
1130 			// in a TextArea everything up to </TEXTAREA> is inserted as text.
1131 			// <SCRIPT> is ignored here (by Netscape)!
1132 
1133 			switch( nToken )
1134 			{
1135 			case HTML_TEXTAREA_OFF:
1136 				bCallNextToken = sal_False;
1137 				EndTextArea();
1138 				break;
1139 
1140 			default:
1141                 InsertTextAreaText( static_cast< sal_uInt16 >(nToken) );
1142 				break;
1143 			}
1144 
1145 			return;
1146 		}
1147 		else if( bSelect )
1148 		{
1149 			// MUST come after bNoScript!
1150 			switch( nToken )
1151 			{
1152 			case HTML_SELECT_OFF:
1153 				bCallNextToken = sal_False;
1154 				EndSelect();
1155 				return;
1156 
1157 			case HTML_OPTION:
1158 				InsertSelectOption();
1159 				return;
1160 
1161 			case HTML_TEXTTOKEN:
1162 				InsertSelectText();
1163 				return;
1164 
1165 			case HTML_INPUT:
1166 			case HTML_SCRIPT_ON:
1167 			case HTML_SCRIPT_OFF:
1168 			case HTML_NOSCRIPT_ON:
1169 			case HTML_NOSCRIPT_OFF:
1170 			case HTML_RAWDATA:
1171 				// handle in the normal switch
1172 				break;
1173 
1174 			default:
1175 				// ignore
1176 				return;
1177 			}
1178 		}
1179 		else if( pMarquee )
1180 		{
1181 			// in a TextArea everything up to </TEXTAREA> is inserted as text.
1182 			// The <SCRIPT> tags will be ignored by MS-IE, by us the
1183 			// whole script
1184 			switch( nToken )
1185 			{
1186 			case HTML_MARQUEE_OFF:
1187 				bCallNextToken = sal_False;
1188 				EndMarquee();
1189 				break;
1190 
1191 			case HTML_TEXTTOKEN:
1192 				InsertMarqueeText();
1193 				break;
1194 			}
1195 
1196 			return;
1197 		}
1198 		else if( bInField )
1199 		{
1200 			switch( nToken )
1201 			{
1202 			case HTML_SDFIELD_OFF:
1203 				bCallNextToken = sal_False;
1204 				EndField();
1205 				break;
1206 
1207 			case HTML_TEXTTOKEN:
1208 				InsertFieldText();
1209 				break;
1210 			}
1211 
1212 			return;
1213 		}
1214 		else if( bInFootEndNoteAnchor || bInFootEndNoteSymbol )
1215 		{
1216 			switch( nToken )
1217 			{
1218 			case HTML_ANCHOR_OFF:
1219 				EndAnchor();
1220 				bCallNextToken = sal_False;
1221 				break;
1222 
1223 			case HTML_TEXTTOKEN:
1224 				InsertFootEndNoteText();
1225 				break;
1226 			}
1227 			return;
1228 		}
1229 		else if( aUnknownToken.Len() )
1230 		{
1231 			// Unknown tokens in the header are only terminated by a matching
1232 			// end token, </HEAD> or <BODY> again. In this text
1233 			// is ignored.
1234 			switch( nToken )
1235 			{
1236 			case HTML_UNKNOWNCONTROL_OFF:
1237 				if( aUnknownToken.CompareTo(sSaveToken) != COMPARE_EQUAL )
1238 					return;
1239 			case HTML_FRAMESET_ON:
1240 			case HTML_HEAD_OFF:
1241 			case HTML_BODY_ON:
1242 			case HTML_IMAGE:		// For whatever reason Netscape does this.
1243 				aUnknownToken.Erase();
1244 				break;
1245 			case HTML_TEXTTOKEN:
1246 				return;
1247 			default:
1248 				break;
1249 			}
1250 		}
1251 	}
1252 
1253 	switch( nToken )
1254 	{
1255 	case HTML_BODY_ON:
1256 		if( aStyleSource.Len() )
1257 		{
1258 			pCSS1Parser->ParseStyleSheet( aStyleSource );
1259 			aStyleSource.Erase();
1260 		}
1261 		if( IsNewDoc() )
1262 		{
1263 			InsertBodyOptions();
1264 			// If there is a template for the first or right page,
1265 			// we set it here.
1266 			const SwPageDesc *pPageDesc = 0;
1267 			if( pCSS1Parser->IsSetFirstPageDesc() )
1268 				pPageDesc = pCSS1Parser->GetFirstPageDesc();
1269 			else if( pCSS1Parser->IsSetRightPageDesc() )
1270 				pPageDesc = pCSS1Parser->GetRightPageDesc();
1271 
1272 			if( pPageDesc )
1273             {
1274                 pDoc->InsertPoolItem( *pPam, SwFmtPageDesc( pPageDesc ), 0 );
1275             }
1276 		}
1277 		break;
1278 
1279 	case HTML_LINK:
1280 		InsertLink();
1281 		break;
1282 
1283 	case HTML_BASE:
1284 		{
1285 			const HTMLOptions *pHTMLOptions = GetOptions();
1286 			for( sal_uInt16 i = pHTMLOptions->Count(); i; )
1287 			{
1288 				const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1289 				switch( pOption->GetToken() )
1290 				{
1291 				case HTML_O_HREF:
1292 					sBaseURL = pOption->GetString();
1293 					break;
1294 				case HTML_O_TARGET:
1295 					if( IsNewDoc() )
1296 					{
1297                         SwDocShell *pDocShell(pDoc->GetDocShell());
1298                         DBG_ASSERT(pDocShell, "no SwDocShell");
1299                         if (pDocShell) {
1300                             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1301                                 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1302                             uno::Reference<document::XDocumentProperties>
1303                                 xDocProps(xDPS->getDocumentProperties());
1304                             DBG_ASSERT(xDocProps.is(),"no DocumentProperties");
1305                             if (xDocProps.is()) {
1306                                 xDocProps->setDefaultTarget(
1307                                     pOption->GetString());
1308                             }
1309                         }
1310 					}
1311 					break;
1312 				}
1313 			}
1314 		}
1315 		break;
1316 
1317 	case HTML_META:
1318 		{
1319 			SvKeyValueIterator *pHTTPHeader = 0;
1320 			if( IsNewDoc() )
1321 			{
1322 				SwDocShell *pDocSh = pDoc->GetDocShell();
1323 				if( pDocSh )
1324 					pHTTPHeader = pDocSh->GetHeaderAttributes();
1325 			}
1326             SwDocShell *pDocShell(pDoc->GetDocShell());
1327             DBG_ASSERT(pDocShell, "no SwDocShell");
1328             if (pDocShell)
1329             {
1330                 uno::Reference<document::XDocumentProperties> xDocProps;
1331                 if (IsNewDoc())
1332                 {
1333                     const uno::Reference<document::XDocumentPropertiesSupplier>
1334                         xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW );
1335                     xDocProps = xDPS->getDocumentProperties();
1336                     DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
1337                 }
1338                 ParseMetaOptions( xDocProps, pHTTPHeader );
1339 			}
1340 		}
1341 		break;
1342 
1343 	case HTML_TITLE_ON:
1344 		bInTitle = sal_True;
1345 		break;
1346 
1347 	case HTML_SCRIPT_ON:
1348 		NewScript();
1349 		break;
1350 
1351 	case HTML_SCRIPT_OFF:
1352 		EndScript();
1353 		break;
1354 
1355 	case HTML_NOSCRIPT_ON:
1356 	case HTML_NOSCRIPT_OFF:
1357 		bInsertUnknown = sal_True;
1358 		break;
1359 
1360 	case HTML_STYLE_ON:
1361 		NewStyle();
1362 		break;
1363 
1364 	case HTML_STYLE_OFF:
1365 		EndStyle();
1366 		break;
1367 
1368 	case HTML_RAWDATA:
1369 		if( !bIgnoreRawData )
1370 		{
1371 			if( IsReadScript() )
1372 			{
1373 				AddScriptSource();
1374 			}
1375 			else if( IsReadStyle() )
1376 			{
1377 				if( aStyleSource.Len() )
1378 					aStyleSource += '\n';
1379 				aStyleSource += aToken;
1380 			}
1381 		}
1382 		break;
1383 
1384 	case HTML_OBJECT_ON:
1385 #ifdef SOLAR_JAVA
1386 		NewObject();
1387 		bCallNextToken = pAppletImpl!=0 && pTable!=0;
1388 #endif
1389 		break;
1390 
1391 	case HTML_APPLET_ON:
1392 #ifdef SOLAR_JAVA
1393 		InsertApplet();
1394 		bCallNextToken = pAppletImpl!=0 && pTable!=0;
1395 #endif
1396 		break;
1397 
1398 	case HTML_IFRAME_ON:
1399 		InsertFloatingFrame();
1400 		bCallNextToken = bInFloatingFrame && pTable!=0;
1401 		break;
1402 
1403 	case HTML_LINEBREAK:
1404 		if( !IsReadPRE() )
1405 		{
1406 			InsertLineBreak();
1407 			break;
1408 		}
1409 		else
1410 			bGetIDOption = sal_True;
1411 			// <BR>s in <PRE> resemble real LFs, therefore no break
1412 
1413 	case HTML_NEWPARA:
1414 		// CR in PRE/LISTING/XMP
1415 		{
1416 			if( HTML_NEWPARA==nToken ||
1417 				pPam->GetPoint()->nContent.GetIndex() )
1418 			{
1419 				AppendTxtNode(); // lf does not exist here, therefore uncritical
1420 				SetTxtCollAttrs();
1421 			}
1422 			// progress bar
1423 			if( !GetMedium() || !GetMedium()->IsRemote() )
1424 				::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
1425 		}
1426 		break;
1427 
1428 	case HTML_NONBREAKSPACE:
1429         pDoc->InsertString( *pPam, CHAR_HARDBLANK );
1430 		break;
1431 
1432 	case HTML_SOFTHYPH:
1433         pDoc->InsertString( *pPam, CHAR_SOFTHYPHEN );
1434 		break;
1435 
1436 	case HTML_LINEFEEDCHAR:
1437 		if( pPam->GetPoint()->nContent.GetIndex() )
1438 			AppendTxtNode();
1439 		if( !pTable && !pDoc->IsInHeaderFooter( pPam->GetPoint()->nNode ) )
1440 		{
1441             NewAttr( &aAttrTab.pBreak, SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
1442 			EndAttr( aAttrTab.pBreak, 0, sal_False );
1443 		}
1444 		break;
1445 
1446 	case HTML_TEXTTOKEN:
1447         // then insert the string without adding any attributes to the end
1448 		if( aToken.Len() && ' '==aToken.GetChar(0) && !IsReadPRE() )
1449 		{
1450 			xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
1451 			if( nPos )
1452 			{
1453 				const String& rText =
1454                     pPam->GetPoint()->nNode.GetNode().GetTxtNode()->GetTxt();
1455 				sal_Unicode cLast = rText.GetChar(--nPos);
1456 				if( ' ' == cLast || '\x0a' == cLast)
1457 					aToken.Erase(0,1);
1458 			}
1459 			else
1460 				aToken.Erase(0,1);
1461 
1462 			if( !aToken.Len() )
1463 			{
1464 				bUpperSpace = bUpperSpaceSave;
1465 				break;
1466 			}
1467 		}
1468 
1469 		if( aToken.Len() )
1470 		{
1471 			if( !bDocInitialized )
1472 				DocumentDetected();
1473             pDoc->InsertString( *pPam, aToken );
1474 
1475             // if there are still preliminary paragraph attributes, but the paragraph
1476 			// is not empty, then the paragraph attributes are invalid.
1477 			if( aParaAttrs.Count() )
1478 				aParaAttrs.Remove( 0, aParaAttrs.Count() );
1479 
1480 			SetAttr();
1481 		}
1482 		break;
1483 
1484 	case HTML_HORZRULE:
1485 		InsertHorzRule();
1486 		break;
1487 
1488 	case HTML_IMAGE:
1489 		InsertImage();
1490 		// If the parser should be the last one to hold the doc, then abort here and set an error.
1491 		if( 1 == pDoc->getReferenceCount() )
1492 		{
1493 			eState = SVPAR_ERROR;
1494 		}
1495 		break;
1496 
1497 	case HTML_SPACER:
1498 		InsertSpacer();
1499 		break;
1500 
1501 	case HTML_EMBED:
1502 		InsertEmbed();
1503 		break;
1504 
1505 	case HTML_NOEMBED_ON:
1506 		bInNoEmbed = sal_True;
1507 		bCallNextToken = pTable!=0;
1508 		ReadRawData( OOO_STRING_SVTOOLS_HTML_noembed );
1509 		break;
1510 
1511 	case HTML_DEFLIST_ON:
1512 		if( nOpenParaToken )
1513 			EndPara();
1514 		NewDefList();
1515 		break;
1516 	case HTML_DEFLIST_OFF:
1517 		if( nOpenParaToken )
1518 			EndPara();
1519 		EndDefListItem( 0, sal_False, 1==nDefListDeep );
1520 		EndDefList();
1521 		break;
1522 
1523 	case HTML_DD_ON:
1524 	case HTML_DT_ON:
1525 		if( nOpenParaToken )
1526 			EndPara();
1527 		EndDefListItem( 0, sal_False );// <DD>/<DT> quit and set no template
1528 		NewDefListItem( nToken );
1529 		break;
1530 
1531 	case HTML_DD_OFF:
1532 	case HTML_DT_OFF:
1533 		// see HTML_LI_OFF
1534 		// actually a DD/DT should be terminated now. But since both
1535 		// Netscape and Microsoft don't do that, we don't do that either.
1536 		EndDefListItem( nToken, sal_False );
1537 		break;
1538 
1539 	// Areas
1540 	case HTML_DIVISION_ON:
1541 	case HTML_CENTER_ON:
1542 		if( nOpenParaToken )
1543 		{
1544 			if( IsReadPRE() )
1545 				nOpenParaToken = 0;
1546 			else
1547 				EndPara();
1548 		}
1549 		NewDivision( nToken );
1550 		break;
1551 
1552 	case HTML_DIVISION_OFF:
1553 	case HTML_CENTER_OFF:
1554 		if( nOpenParaToken )
1555 		{
1556 			if( IsReadPRE() )
1557 				nOpenParaToken = 0;
1558 			else
1559 				EndPara();
1560 		}
1561 		EndDivision( nToken );
1562 		break;
1563 
1564 	case HTML_MULTICOL_ON:
1565 		if( nOpenParaToken )
1566 			EndPara();
1567 		NewMultiCol();
1568 		break;
1569 
1570 	case HTML_MULTICOL_OFF:
1571 		if( nOpenParaToken )
1572 			EndPara();
1573 		EndTag( HTML_MULTICOL_ON );
1574 		break;
1575 
1576 	case HTML_MARQUEE_ON:
1577 		NewMarquee();
1578 		bCallNextToken = pMarquee!=0 && pTable!=0;
1579 		break;
1580 
1581 	case HTML_FORM_ON:
1582 		NewForm();
1583 		break;
1584 	case HTML_FORM_OFF:
1585 		EndForm();
1586 		break;
1587 
1588 	// Templates:
1589 	case HTML_PARABREAK_ON:
1590 		if( nOpenParaToken )
1591 			EndPara( sal_True );
1592 		NewPara();
1593 		break;
1594 
1595 	case HTML_PARABREAK_OFF:
1596 		EndPara( sal_True );
1597 		break;
1598 
1599 	case HTML_ADDRESS_ON:
1600 		if( nOpenParaToken )
1601 			EndPara();
1602 		NewTxtFmtColl( HTML_ADDRESS_ON, RES_POOLCOLL_SENDADRESS );
1603 		break;
1604 
1605 	case HTML_ADDRESS_OFF:
1606 		if( nOpenParaToken )
1607 			EndPara();
1608 		EndTxtFmtColl( HTML_ADDRESS_OFF );
1609 		break;
1610 
1611 	case HTML_BLOCKQUOTE_ON:
1612 	case HTML_BLOCKQUOTE30_ON:
1613 		if( nOpenParaToken )
1614 			EndPara();
1615 		NewTxtFmtColl( HTML_BLOCKQUOTE_ON, RES_POOLCOLL_HTML_BLOCKQUOTE );
1616 		break;
1617 
1618 	case HTML_BLOCKQUOTE_OFF:
1619 	case HTML_BLOCKQUOTE30_OFF:
1620 		if( nOpenParaToken )
1621 			EndPara();
1622 		EndTxtFmtColl( HTML_BLOCKQUOTE_ON );
1623 		break;
1624 
1625 	case HTML_PREFORMTXT_ON:
1626 	case HTML_LISTING_ON:
1627 	case HTML_XMP_ON:
1628 		if( nOpenParaToken )
1629 			EndPara();
1630 		NewTxtFmtColl( nToken, RES_POOLCOLL_HTML_PRE );
1631 		break;
1632 
1633 	case HTML_PREFORMTXT_OFF:
1634 		bNoParSpace = sal_True; // the last PRE paragraph must get a line spacing
1635 		EndTxtFmtColl( HTML_PREFORMTXT_OFF );
1636 		break;
1637 
1638 	case HTML_LISTING_OFF:
1639 	case HTML_XMP_OFF:
1640 		EndTxtFmtColl( nToken );
1641 		break;
1642 
1643 	case HTML_HEAD1_ON:
1644 	case HTML_HEAD2_ON:
1645 	case HTML_HEAD3_ON:
1646 	case HTML_HEAD4_ON:
1647 	case HTML_HEAD5_ON:
1648 	case HTML_HEAD6_ON:
1649 		if( nOpenParaToken )
1650 		{
1651 			if( IsReadPRE() )
1652 				nOpenParaToken = 0;
1653 			else
1654 				EndPara();
1655 		}
1656 		NewHeading( nToken );
1657 		break;
1658 
1659 	case HTML_HEAD1_OFF:
1660 	case HTML_HEAD2_OFF:
1661 	case HTML_HEAD3_OFF:
1662 	case HTML_HEAD4_OFF:
1663 	case HTML_HEAD5_OFF:
1664 	case HTML_HEAD6_OFF:
1665 		EndHeading();
1666 		break;
1667 
1668 	case HTML_TABLE_ON:
1669 		if( pPendStack )
1670 			BuildTable( SVX_ADJUST_END );
1671 		else
1672 		{
1673 			if( nOpenParaToken )
1674 				EndPara();
1675 			ASSERT( !pTable, "Table in table must not occur here" );
1676 			if( !pTable && (IsNewDoc() || !pPam->GetNode()->FindTableNode()) &&
1677 				(pPam->GetPoint()->nNode.GetIndex() >
1678 							pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
1679 				!pPam->GetNode()->FindFootnoteStartNode() ) )
1680 			{
1681 				if ( nParaCnt < 5 )
1682 					Show();		// show up to this point
1683 
1684 				SvxAdjust eAdjust = aAttrTab.pAdjust
1685 					? ((const SvxAdjustItem&)aAttrTab.pAdjust->GetItem()).
1686 											 GetAdjust()
1687 					: SVX_ADJUST_END;
1688 				BuildTable( eAdjust );
1689 			}
1690 			else
1691 				bInsertUnknown = bKeepUnknown;
1692 		}
1693 		break;
1694 
1695 	// Lists
1696 	case HTML_DIRLIST_ON:
1697 	case HTML_MENULIST_ON:
1698 	case HTML_ORDERLIST_ON:
1699 	case HTML_UNORDERLIST_ON:
1700 		if( nOpenParaToken )
1701 			EndPara();
1702 		NewNumBulList( nToken );
1703 		break;
1704 
1705 	case HTML_DIRLIST_OFF:
1706 	case HTML_MENULIST_OFF:
1707 	case HTML_ORDERLIST_OFF:
1708 	case HTML_UNORDERLIST_OFF:
1709 		if( nOpenParaToken )
1710 			EndPara();
1711 		EndNumBulListItem( 0, sal_True, GetNumInfo().GetDepth()==1 );
1712 		EndNumBulList( nToken );
1713 		break;
1714 
1715 	case HTML_LI_ON:
1716 	case HTML_LISTHEADER_ON:
1717 		if( nOpenParaToken &&
1718 			(pPam->GetPoint()->nContent.GetIndex()
1719 			|| HTML_PARABREAK_ON==nOpenParaToken) )
1720 		{
1721 			// only <P><LI> end paragraph, not with <DD><LI>
1722 			EndPara();
1723 		}
1724 
1725 		EndNumBulListItem( 0, sal_False );// <LI>/<LH> quit and set no template
1726 		NewNumBulListItem( nToken );
1727 		break;
1728 
1729 	case HTML_LI_OFF:
1730 	case HTML_LISTHEADER_OFF:
1731 		EndNumBulListItem( nToken, sal_False );
1732 		break;
1733 
1734 	// Attributes :
1735 	case HTML_ITALIC_ON:
1736 		{
1737             SvxPostureItem aPosture( ITALIC_NORMAL, RES_CHRATR_POSTURE );
1738 			SvxPostureItem aPostureCJK( ITALIC_NORMAL, RES_CHRATR_CJK_POSTURE );
1739 			SvxPostureItem aPostureCTL( ITALIC_NORMAL, RES_CHRATR_CTL_POSTURE );
1740 			NewStdAttr( HTML_ITALIC_ON,
1741 				   		&aAttrTab.pItalic, aPosture,
1742 				   		&aAttrTab.pItalicCJK, &aPostureCJK,
1743 				   		&aAttrTab.pItalicCTL, &aPostureCTL );
1744 		}
1745 		break;
1746 
1747 	case HTML_BOLD_ON:
1748 		{
1749             SvxWeightItem aWeight( WEIGHT_BOLD, RES_CHRATR_WEIGHT );
1750 			SvxWeightItem aWeightCJK( WEIGHT_BOLD, RES_CHRATR_CJK_WEIGHT );
1751 			SvxWeightItem aWeightCTL( WEIGHT_BOLD, RES_CHRATR_CTL_WEIGHT );
1752 			NewStdAttr( HTML_BOLD_ON,
1753 						&aAttrTab.pBold, aWeight,
1754 						&aAttrTab.pBoldCJK, &aWeightCJK,
1755 						&aAttrTab.pBoldCTL, &aWeightCTL );
1756 		}
1757 		break;
1758 
1759 
1760 	case HTML_STRIKE_ON:
1761 	case HTML_STRIKETHROUGH_ON:
1762 		{
1763 			NewStdAttr( HTML_STRIKE_ON, &aAttrTab.pStrike,
1764                         SvxCrossedOutItem(STRIKEOUT_SINGLE, RES_CHRATR_CROSSEDOUT) );
1765 		}
1766 		break;
1767 
1768 	case HTML_UNDERLINE_ON:
1769 		{
1770 			NewStdAttr( HTML_UNDERLINE_ON, &aAttrTab.pUnderline,
1771                         SvxUnderlineItem(UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE) );
1772 		}
1773 		break;
1774 
1775 	case HTML_SUPERSCRIPT_ON:
1776 		{
1777 			NewStdAttr( HTML_SUPERSCRIPT_ON, &aAttrTab.pEscapement,
1778                         SvxEscapementItem(HTML_ESC_SUPER,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1779 		}
1780 		break;
1781 
1782 	case HTML_SUBSCRIPT_ON:
1783 		{
1784 			NewStdAttr( HTML_SUBSCRIPT_ON, &aAttrTab.pEscapement,
1785                         SvxEscapementItem(HTML_ESC_SUB,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1786 		}
1787 		break;
1788 
1789 	case HTML_BLINK_ON:
1790 		{
1791 			NewStdAttr( HTML_BLINK_ON, &aAttrTab.pBlink,
1792                         SvxBlinkItem( sal_True, RES_CHRATR_BLINK ) );
1793 		}
1794 		break;
1795 
1796 	case HTML_SPAN_ON:
1797 		NewStdAttr( HTML_SPAN_ON );
1798 		break;
1799 
1800 
1801 	case HTML_ITALIC_OFF:
1802 	case HTML_BOLD_OFF:
1803 	case HTML_STRIKE_OFF:
1804 	case HTML_UNDERLINE_OFF:
1805 	case HTML_SUPERSCRIPT_OFF:
1806 	case HTML_SUBSCRIPT_OFF:
1807 	case HTML_BLINK_OFF:
1808 	case HTML_SPAN_OFF:
1809 		EndTag( nToken );
1810 		break;
1811 
1812 	case HTML_STRIKETHROUGH_OFF:
1813 		EndTag( HTML_STRIKE_OFF );
1814 		break;
1815 
1816 	case HTML_BASEFONT_ON:
1817 		NewBasefontAttr();
1818 		break;
1819 	case HTML_BASEFONT_OFF:
1820 		EndBasefontAttr();
1821 		break;
1822 	case HTML_FONT_ON:
1823 	case HTML_BIGPRINT_ON:
1824 	case HTML_SMALLPRINT_ON:
1825 		NewFontAttr( nToken );
1826 		break;
1827 	case HTML_FONT_OFF:
1828 	case HTML_BIGPRINT_OFF:
1829 	case HTML_SMALLPRINT_OFF:
1830 		EndFontAttr( nToken );
1831 		break;
1832 
1833 	case HTML_EMPHASIS_ON:
1834 	case HTML_CITIATION_ON:
1835 	case HTML_STRONG_ON:
1836 	case HTML_CODE_ON:
1837 	case HTML_SAMPLE_ON:
1838 	case HTML_KEYBOARD_ON:
1839 	case HTML_VARIABLE_ON:
1840 	case HTML_DEFINSTANCE_ON:
1841 	case HTML_SHORTQUOTE_ON:
1842 	case HTML_LANGUAGE_ON:
1843 	case HTML_AUTHOR_ON:
1844 	case HTML_PERSON_ON:
1845 	case HTML_ACRONYM_ON:
1846 	case HTML_ABBREVIATION_ON:
1847 	case HTML_INSERTEDTEXT_ON:
1848 	case HTML_DELETEDTEXT_ON:
1849 
1850 	case HTML_TELETYPE_ON:
1851 		NewCharFmt( nToken );
1852 		break;
1853 
1854 	case HTML_SDFIELD_ON:
1855 		NewField();
1856 		bCallNextToken = bInField && pTable!=0;
1857 		break;
1858 
1859 	case HTML_EMPHASIS_OFF:
1860 	case HTML_CITIATION_OFF:
1861 	case HTML_STRONG_OFF:
1862 	case HTML_CODE_OFF:
1863 	case HTML_SAMPLE_OFF:
1864 	case HTML_KEYBOARD_OFF:
1865 	case HTML_VARIABLE_OFF:
1866 	case HTML_DEFINSTANCE_OFF:
1867 	case HTML_SHORTQUOTE_OFF:
1868 	case HTML_LANGUAGE_OFF:
1869 	case HTML_AUTHOR_OFF:
1870 	case HTML_PERSON_OFF:
1871 	case HTML_ACRONYM_OFF:
1872 	case HTML_ABBREVIATION_OFF:
1873 	case HTML_INSERTEDTEXT_OFF:
1874 	case HTML_DELETEDTEXT_OFF:
1875 
1876 	case HTML_TELETYPE_OFF:
1877 		EndTag( nToken );
1878 		break;
1879 
1880 	case HTML_HEAD_OFF:
1881 		if( aStyleSource.Len() )
1882 		{
1883 			pCSS1Parser->ParseStyleSheet( aStyleSource );
1884 			aStyleSource.Erase();
1885 		}
1886 		break;
1887 
1888 	case HTML_DOCTYPE:
1889 	case HTML_BODY_OFF:
1890 	case HTML_HTML_OFF:
1891 	case HTML_HEAD_ON:
1892 	case HTML_TITLE_OFF:
1893 		break;		// do not go on, right???
1894 	case HTML_HTML_ON:
1895 		{
1896 			const HTMLOptions *pHTMLOptions = GetOptions();
1897 			for( sal_uInt16 i = pHTMLOptions->Count(); i; )
1898 			{
1899 				const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1900 				if( HTML_O_DIR == pOption->GetToken() )
1901 				{
1902 					const String& rDir = pOption->GetString();
1903 					SfxItemSet aItemSet( pDoc->GetAttrPool(),
1904 										 pCSS1Parser->GetWhichMap() );
1905 					SvxCSS1PropertyInfo aPropInfo;
1906 					String aDummy;
1907 					ParseStyleOptions( aDummy, aDummy, aDummy, aItemSet,
1908 									   aPropInfo, 0, &rDir );
1909 
1910 					pCSS1Parser->SetPageDescAttrs( 0, &aItemSet );
1911 					break;
1912 				}
1913 			}
1914 		}
1915 		break;
1916 
1917 	case HTML_INPUT:
1918 		InsertInput();
1919 		break;
1920 
1921 	case HTML_TEXTAREA_ON:
1922 		NewTextArea();
1923 		bCallNextToken = bTextArea && pTable!=0;
1924 		break;
1925 
1926 	case HTML_SELECT_ON:
1927 		NewSelect();
1928 		bCallNextToken = bSelect && pTable!=0;
1929 		break;
1930 
1931 	case HTML_ANCHOR_ON:
1932 		NewAnchor();
1933 		break;
1934 
1935 	case HTML_ANCHOR_OFF:
1936 		EndAnchor();
1937 		break;
1938 
1939 	case HTML_COMMENT:
1940 		if( ( aToken.Len() > 5 ) && ( ! bIgnoreHTMLComments ) )
1941 		{
1942 			// insert as Post-It
1943 			// MIB 8.12.2000: If there are no space characters right behind
1944 			// the <!-- and on front of the -->, leave the comment untouched.
1945 			if( ' ' == aToken.GetChar( 3 ) &&
1946 				' ' == aToken.GetChar( aToken.Len()-3 ) )
1947 			{
1948 				String aComment( aToken.Copy( 3, aToken.Len()-5 ) );
1949 				aComment.EraseLeadingChars().EraseTrailingChars();
1950 				InsertComment( aComment );
1951 			}
1952 			else
1953 			{
1954 				String aComment( '<' );
1955 				(aComment += aToken) += '>';
1956 				InsertComment( aComment );
1957 			}
1958 		}
1959 		break;
1960 
1961 	case HTML_MAP_ON:
1962 		// Image Maps are read asynchron: At first setup only an
1963 		// ImageMap. The Areas are added later. Never the less add
1964 		// the ImageMap to the IMap-Array, because it could be used
1965 		pImageMap = new ImageMap;
1966 		if( ParseMapOptions( pImageMap) )
1967 		{
1968 			if( !pImageMaps )
1969 				pImageMaps = new ImageMaps;
1970 			pImageMaps->Insert( pImageMap, pImageMaps->Count() );
1971 		}
1972 		else
1973 		{
1974 			delete pImageMap;
1975 			pImageMap = 0;
1976 		}
1977 		break;
1978 
1979 	case HTML_MAP_OFF:
1980 		// the ImageMap does not exist anymore
1981 		// but do not delete it, since it has been added to the array
1982 		pImageMap = 0;
1983 		break;
1984 
1985 	case HTML_AREA:
1986 		if( pImageMap )
1987             ParseAreaOptions( pImageMap, sBaseURL, SFX_EVENT_MOUSEOVER_OBJECT,
1988 										 SFX_EVENT_MOUSEOUT_OBJECT );
1989 		break;
1990 
1991 	case HTML_FRAMESET_ON:
1992 		bInsertUnknown = bKeepUnknown;
1993 		break;
1994 
1995 	case HTML_NOFRAMES_ON:
1996 		if( IsInHeader() )
1997 			FinishHeader( sal_True );
1998 		bInsertUnknown = bKeepUnknown;
1999 		break;
2000 
2001 	case HTML_UNKNOWNCONTROL_ON:
2002 	        // In the header we must ignore the content of unknown tokens,
2003 		// except for those starting with '!"
2004 		if( IsInHeader() && !IsReadPRE() && !aUnknownToken.Len() &&
2005 			sSaveToken.Len() && '!' != sSaveToken.GetChar(0) &&
2006 			'%' != sSaveToken.GetChar(0) )
2007 			aUnknownToken = sSaveToken;
2008 		// no break
2009 
2010 	default:
2011 		bInsertUnknown = bKeepUnknown;
2012 		break;
2013 	}
2014 
2015 	if( bGetIDOption )
2016 		InsertIDOption();
2017 
2018 	if( bInsertUnknown )
2019 	{
2020 		String aComment(
2021 			String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
2022 		if( (HTML_TOKEN_ONOFF & nToken) != 0 && (1 & nToken) != 0 )
2023 			aComment += '/';
2024 		aComment += sSaveToken;
2025 		if( aToken.Len() )
2026 		{
2027 			UnescapeToken();
2028 			(aComment += ' ') += aToken;
2029 		}
2030 		aComment += '>';
2031 		InsertComment( aComment );
2032 	}
2033 
2034     // if temporary paragraph attributes exists and the paragraph is
2035 	// not empty, then paragraph attributes are final
2036 	if( aParaAttrs.Count() && pPam->GetPoint()->nContent.GetIndex() )
2037 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
2038 }
2039 
2040 /*  */
2041 
2042 extern sal_Bool lcl_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 );
2043 
lcl_swhtml_getItemInfo(const _HTMLAttr & rAttr,sal_Bool & rScriptDependent,sal_Bool & rFont,sal_uInt16 & rScriptType)2044 void lcl_swhtml_getItemInfo( const _HTMLAttr& rAttr,
2045 								 sal_Bool& rScriptDependent, sal_Bool& rFont,
2046 								 sal_uInt16& rScriptType )
2047 {
2048 	sal_uInt16 nWhich = rAttr.GetItem().Which();
2049 	switch( nWhich )
2050 	{
2051 	case RES_CHRATR_FONT:
2052 		rFont = sal_True;
2053 	case RES_CHRATR_FONTSIZE:
2054 	case RES_CHRATR_LANGUAGE:
2055 	case RES_CHRATR_POSTURE:
2056 	case RES_CHRATR_WEIGHT:
2057         rScriptType = i18n::ScriptType::LATIN;
2058 		rScriptDependent = sal_True;
2059 		break;
2060 	case RES_CHRATR_CJK_FONT:
2061 		rFont = sal_True;
2062 	case RES_CHRATR_CJK_FONTSIZE:
2063 	case RES_CHRATR_CJK_LANGUAGE:
2064 	case RES_CHRATR_CJK_POSTURE:
2065 	case RES_CHRATR_CJK_WEIGHT:
2066         rScriptType = i18n::ScriptType::ASIAN;
2067 		rScriptDependent = sal_True;
2068 		break;
2069 	case RES_CHRATR_CTL_FONT:
2070 		rFont = sal_True;
2071 	case RES_CHRATR_CTL_FONTSIZE:
2072 	case RES_CHRATR_CTL_LANGUAGE:
2073 	case RES_CHRATR_CTL_POSTURE:
2074 	case RES_CHRATR_CTL_WEIGHT:
2075         rScriptType = i18n::ScriptType::COMPLEX;
2076 		rScriptDependent = sal_True;
2077 		break;
2078 	default:
2079 		rScriptDependent = sal_False;
2080 		rFont = sal_False;
2081 		break;
2082 	}
2083 }
2084 
AppendTxtNode(SwHTMLAppendMode eMode,sal_Bool bUpdateNum)2085 sal_Bool SwHTMLParser::AppendTxtNode( SwHTMLAppendMode eMode, sal_Bool bUpdateNum )
2086 {
2087 	// A hard line feed has to be always removed.
2088 	// A second line feed is replaced by a paragraph spacing
2089 	xub_StrLen nLFStripped = StripTrailingLF();
2090 	if( (AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode) && nLFStripped > 1 )
2091 		eMode = AM_SPACE;
2092 
2093 	// hard attributes in this paragraph can not become invalid
2094 	if( aParaAttrs.Count() )
2095 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
2096 
2097 	if( AM_SPACE==eMode || AM_NOSPACE==eMode )
2098 	{
2099 		SwTxtNode *pTxtNode =
2100             pPam->GetPoint()->nNode.GetNode().GetTxtNode();
2101 
2102 		const SvxULSpaceItem& rULSpace =
2103 			(const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2104 
2105 		sal_Bool bChange = AM_NOSPACE==eMode ? rULSpace.GetLower() > 0
2106 										 : rULSpace.GetLower() == 0;
2107 
2108 		if( bChange )
2109 		{
2110 			const SvxULSpaceItem& rCollULSpace =
2111 				pTxtNode->GetAnyFmtColl().GetULSpace();
2112 
2113 			sal_Bool bMayReset = AM_NOSPACE==eMode ? rCollULSpace.GetLower() == 0
2114 											   : rCollULSpace.GetLower() > 0;
2115 
2116 			if( bMayReset &&
2117 				rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2118 			{
2119 				pTxtNode->ResetAttr( RES_UL_SPACE );
2120 			}
2121 			else
2122 			{
2123                 pTxtNode->SetAttr(
2124 					SvxULSpaceItem( rULSpace.GetUpper(),
2125                          AM_NOSPACE==eMode ? 0 : HTML_PARSPACE, RES_UL_SPACE ) );
2126 			}
2127 		}
2128 	}
2129 	bNoParSpace = AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode;
2130 
2131 	SwPosition aOldPos( *pPam->GetPoint() );
2132 
2133 	sal_Bool bRet = pDoc->AppendTxtNode( *pPam->GetPoint() );
2134 
2135 	// split character attributes  and unset if they range over the
2136 	// complete paragraph
2137 	const SwNodeIndex& rEndIdx = aOldPos.nNode;
2138 	xub_StrLen nEndCnt = aOldPos.nContent.GetIndex();
2139 	const SwPosition& rPos = *pPam->GetPoint();
2140 
2141 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
2142 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
2143 		 nCnt--; ++pTbl )
2144 	{
2145 		_HTMLAttr *pAttr = *pTbl;
2146 		if( pAttr && pAttr->GetItem().Which() < RES_PARATR_BEGIN )
2147 		{
2148 			sal_Bool bWholePara = sal_False;
2149 
2150 			while( pAttr )
2151 			{
2152 				_HTMLAttr *pNext = pAttr->GetNext();
2153 				if( pAttr->GetSttParaIdx() < rEndIdx.GetIndex() ||
2154 					(!bWholePara &&
2155 					 pAttr->GetSttPara() == rEndIdx &&
2156 					 pAttr->GetSttCnt() != nEndCnt) )
2157 				{
2158 					bWholePara =
2159 						pAttr->GetSttPara() == rEndIdx &&
2160 						pAttr->GetSttCnt() == 0;
2161 
2162 					xub_StrLen nStt = pAttr->nSttCntnt;
2163 					sal_Bool bScript = sal_False, bFont = sal_False;
2164 					sal_uInt16 nScriptItem;
2165 					sal_Bool bInsert = sal_True;
2166 				   	lcl_swhtml_getItemInfo( *pAttr, bScript, bFont,
2167 											nScriptItem );
2168 					// set parts which we have so far
2169 					if( bInsert && bScript )
2170 					{
2171 						const SwTxtNode *pTxtNd =
2172 							pAttr->GetSttPara().GetNode().GetTxtNode();
2173 						ASSERT( pTxtNd, "No text node" );
2174 						if( pTxtNd )
2175 						{
2176 							const String& rText = pTxtNd->GetTxt();
2177 							sal_uInt16 nScriptTxt =
2178 								pBreakIt->GetBreakIter()->getScriptType(
2179 											rText, pAttr->GetSttCnt() );
2180 							xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2181 									->endOfScript( rText, nStt, nScriptTxt );
2182 							while( nScriptEnd < nEndCnt )
2183 							{
2184 								if( nScriptItem == nScriptTxt )
2185 								{
2186 									_HTMLAttr *pSetAttr =
2187 										pAttr->Clone( rEndIdx, nScriptEnd );
2188 									pSetAttr->nSttCntnt = nStt;
2189 									pSetAttr->ClearPrev();
2190 									if( !pNext || bWholePara )
2191 									{
2192 										sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
2193 														: aSetAttrTab.Count();
2194 										aSetAttrTab.Insert( pSetAttr, nTmp );
2195 									}
2196 									else
2197 										pNext->InsertPrev( pSetAttr );
2198 								}
2199 								nStt = nScriptEnd;
2200 								nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
2201 												rText, nStt );
2202 								nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2203 									->endOfScript( rText, nStt, nScriptTxt );
2204 							}
2205 							bInsert = nScriptItem == nScriptTxt;
2206 						}
2207 					}
2208 					if( bInsert )
2209 					{
2210 						_HTMLAttr *pSetAttr =
2211 							pAttr->Clone( rEndIdx, nEndCnt );
2212 						pSetAttr->nSttCntnt = nStt;
2213 
2214 						// If the attribute spans the entire paragraph, then
2215 						// all other attributes are ignored. Therefore
2216 						// it must not be added to the prev list of an outer
2217 						// attribute, because this attribute is
2218 						// not set for the time being. This leads to shifts,
2219 						// when fields are added to the race (see #51020#).
2220 						if( !pNext || bWholePara )
2221 						{
2222 							sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
2223 															 : aSetAttrTab.Count();
2224 							aSetAttrTab.Insert( pSetAttr, nTmp );
2225 						}
2226 						else
2227 							pNext->InsertPrev( pSetAttr );
2228 					}
2229 					else
2230 					{
2231 						_HTMLAttr *pPrev = pAttr->GetPrev();
2232 						if( pPrev )
2233 						{
2234 							// The Previous attributes must be set anyway.
2235 							if( !pNext || bWholePara )
2236 							{
2237 								sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
2238 								aSetAttrTab.Insert( pPrev, nTmp );
2239 							}
2240 							else
2241 								pNext->InsertPrev( pPrev );
2242 						}
2243 					}
2244 					pAttr->ClearPrev();
2245 				}
2246 
2247 				pAttr->SetStart( rPos );
2248 				pAttr = pNext;
2249 			}
2250 		}
2251 	}
2252 
2253     if( bUpdateNum )
2254     {
2255         if( GetNumInfo().GetDepth() )
2256         {
2257             sal_uInt8 nLvl = GetNumInfo().GetLevel();
2258             SetNodeNum( nLvl, false );
2259         }
2260         else
2261             pPam->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE );
2262     }
2263 
2264     // because of JavaScript, Attributes in the paragraph should be set now
2265     SetAttr();
2266 
2267 	// Now it is time to get rid of all script dependent hints that are
2268 	// equal to the settings in the style
2269 	SwTxtNode *pTxtNd = rEndIdx.GetNode().GetTxtNode();
2270 	ASSERT( pTxtNd, "There is the txt node" );
2271 	sal_uInt16 nCntAttr = (pTxtNd  && pTxtNd->GetpSwpHints())
2272 							? pTxtNd->GetSwpHints().Count() : 0;
2273 	if( nCntAttr )
2274 	{
2275 		// These are the end position of all script depenent hints.
2276 		// If we find a hint that starts before the current end position,
2277 		// we have to set it. If we finf a hint that start behind or at
2278 		// that position, we have to take the hint's value into account.
2279 		// If it is equal to the style, or in fact the paragarph's value
2280 		// for that hint, the hint is removed. Otherwise it's end position
2281 		// is remembered.
2282 		xub_StrLen aEndPos[15] =
2283 			{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2284 		SwpHints& rHints = pTxtNd->GetSwpHints();
2285 		for( sal_uInt16 i=0; i < nCntAttr; i++ )
2286 		{
2287             SwTxtAttr *pHt = rHints.GetTextHint( i );
2288 			sal_uInt16 nWhich = pHt->Which();
2289 			sal_Int16 nIdx = -1;
2290 			if( RES_CHRATR_CJK_FONT <= nWhich &&
2291 					nWhich <= RES_CHRATR_CTL_WEIGHT )
2292 			{
2293                 nIdx = static_cast< sal_uInt16 >(nWhich - RES_CHRATR_CJK_FONT + 5);
2294 			}
2295 			else switch( nWhich )
2296 			{
2297 			case RES_CHRATR_FONT:		nIdx = 0;	break;
2298 			case RES_CHRATR_FONTSIZE:	nIdx = 1;	break;
2299 			case RES_CHRATR_LANGUAGE:	nIdx = 2;	break;
2300 			case RES_CHRATR_POSTURE:	nIdx = 3;	break;
2301 			case RES_CHRATR_WEIGHT:		nIdx = 4;	break;
2302 			}
2303 			if( nIdx != -1 )
2304 			{
2305 				xub_StrLen nStt = *pHt->GetStart();
2306 				if( nStt >= aEndPos[nIdx] )
2307 				{
2308 					sal_Bool bFont = (nIdx % 5) == 0;
2309 					const SfxPoolItem& rItem =
2310 						((const SwCntntNode *)pTxtNd)->GetAttr( nWhich );
2311 					if( bFont ? lcl_css1atr_equalFontItems(rItem,pHt->GetAttr())
2312 							  : rItem == pHt->GetAttr() )
2313 					{
2314 						// The hint is the same as set in the paragraph and
2315 						// therfor, it can be deleted
2316 						// CAUTION!!! This WILL delete the hint and it MAY
2317 						// also delete the SwpHints!!! To avoid any trouble
2318 						// we leave the loop immediately if this is the last
2319 						// hint.
2320                         pTxtNd->DeleteAttribute( pHt );
2321 						if( 1 == nCntAttr )
2322 							break;
2323 						i--;
2324 						nCntAttr--;
2325 					}
2326 					else
2327 					{
2328 						// The hint is deifferent. Therfor all hints within that
2329 						// hint have to be ignored.
2330 						aEndPos[nIdx] = pHt->GetEnd() ? *pHt->GetEnd() : nStt;
2331 					}
2332 				}
2333 				else
2334 				{
2335 					// The hint starts before another one ends.
2336 					// The hint in this case is not deleted
2337 					ASSERT( pHt->GetEnd() && *pHt->GetEnd() <= aEndPos[nIdx],
2338 							"hints aren't nested properly!" );
2339 				}
2340 			}
2341 		}
2342 	}
2343 
2344 
2345 	if( !pTable && !--nParaCnt )
2346 		Show();
2347 
2348 	return bRet;
2349 }
2350 
AddParSpace()2351 void SwHTMLParser::AddParSpace()
2352 {
2353 	if( !bNoParSpace )
2354 		return;
2355 
2356 	bNoParSpace = sal_False;
2357 
2358 	sal_uLong nNdIdx = pPam->GetPoint()->nNode.GetIndex() - 1;
2359 
2360 	SwTxtNode *pTxtNode = pDoc->GetNodes()[nNdIdx]->GetTxtNode();
2361 	if( !pTxtNode )
2362 		return;
2363 
2364 	SvxULSpaceItem rULSpace =
2365 		(const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2366 	if( !rULSpace.GetLower() )
2367 	{
2368 		const SvxULSpaceItem& rCollULSpace =
2369 			pTxtNode->GetAnyFmtColl().GetULSpace();
2370 		if( rCollULSpace.GetLower() &&
2371 			rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2372 		{
2373 			pTxtNode->ResetAttr( RES_UL_SPACE );
2374 		}
2375 		else
2376 		{
2377             pTxtNode->SetAttr(
2378                 SvxULSpaceItem( rULSpace.GetUpper(), HTML_PARSPACE, RES_UL_SPACE )  );
2379 		}
2380 	}
2381 }
2382 
2383 
Show()2384 void SwHTMLParser::Show()
2385 {
2386 	// Here
2387 	// - an EndAction is called, which is formatted
2388 	// - a Reschedule is called,
2389 	// - the current view shell is set again
2390 	// - and start action is called
2391 
2392 	ASSERT( SVPAR_WORKING==eState, "Show not in working state - This can backfire" );
2393 	ViewShell *pOldVSh = CallEndAction();
2394 
2395 	GetpApp()->Reschedule();
2396 
2397 	if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2398 		|| 1 == pDoc->getReferenceCount() )
2399 	{
2400 		// was the import aborted by SFX?
2401 		eState = SVPAR_ERROR;
2402 	}
2403 
2404 	// Get the ViewShell again, because it could be destroyed during reschedule
2405 	ViewShell *pVSh = CallStartAction( pOldVSh );
2406 
2407 	// if the current node is no longer visible, then we use
2408 	// a larger step size
2409 	if( pVSh )
2410     {
2411         nParaCnt = (pPam->GetPoint()->nNode.GetNode().IsInVisibleArea(pVSh))
2412             ? 5 : 50;
2413     }
2414 }
2415 
ShowStatline()2416 void SwHTMLParser::ShowStatline()
2417 {
2418 	// Here
2419 	// - a reschedule is called, so that scrolling is possible
2420 	// - the current view shell is set again
2421 	// - a start/end action is called if scrolling was done.
2422 
2423 	ASSERT( SVPAR_WORKING==eState, "ShowStatLine not in working state - This can go to the eye" );
2424 
2425 	// progress bar
2426 	if( !GetMedium() || !GetMedium()->IsRemote() )
2427 	{
2428 		::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
2429 		CheckActionViewShell();
2430 	}
2431 	else
2432 	{
2433 		GetpApp()->Reschedule();
2434 
2435 		if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2436 			|| 1 == pDoc->getReferenceCount() )
2437 		// was the import aborted by SFX?
2438 			eState = SVPAR_ERROR;
2439 
2440 		ViewShell *pVSh = CheckActionViewShell();
2441 		if( pVSh && pVSh->HasInvalidRect() )
2442 		{
2443 			CallEndAction( sal_False, sal_False );
2444 			CallStartAction( pVSh, sal_False );
2445 		}
2446 	}
2447 }
2448 
CallStartAction(ViewShell * pVSh,sal_Bool bChkPtr)2449 ViewShell *SwHTMLParser::CallStartAction( ViewShell *pVSh, sal_Bool bChkPtr )
2450 {
2451 	ASSERT( !pActionViewShell, "CallStartAction: ViewShell already set" );
2452 
2453 	if( !pVSh || bChkPtr )
2454 	{
2455 #ifdef DBG_UTIL
2456 		ViewShell *pOldVSh = pVSh;
2457 #endif
2458 		pDoc->GetEditShell( &pVSh );
2459 		ASSERT( !pVSh || !pOldVSh || pOldVSh == pVSh, "CallStartAction: Who replaced the ViewShell?" );
2460 #ifdef DBG_UTIL
2461 		if( pOldVSh && !pVSh )
2462 			pVSh = 0;
2463 #endif
2464 	}
2465 	pActionViewShell = pVSh;
2466 
2467 	if( pActionViewShell )
2468 	{
2469 		if( pActionViewShell->ISA( SwEditShell ) )
2470 			((SwEditShell*)pActionViewShell)->StartAction();
2471 		else
2472 			pActionViewShell->StartAction();
2473 	}
2474 
2475 	return pActionViewShell;
2476 }
2477 
CallEndAction(sal_Bool bChkAction,sal_Bool bChkPtr)2478 ViewShell *SwHTMLParser::CallEndAction( sal_Bool bChkAction, sal_Bool bChkPtr )
2479 {
2480 	if( bChkPtr )
2481 	{
2482 		ViewShell *pVSh = 0;
2483 		pDoc->GetEditShell( &pVSh );
2484 		ASSERT( !pVSh || pActionViewShell == pVSh,
2485 				"CallEndAction: Who replaced the ViewShell?" );
2486 #if OSL_DEBUG_LEVEL > 1
2487 		if( pActionViewShell && !pVSh )
2488 			pVSh = 0;
2489 #endif
2490 		if( pVSh != pActionViewShell )
2491 			pActionViewShell = 0;
2492 	}
2493 
2494 	if( !pActionViewShell || (bChkAction && !pActionViewShell->ActionPend()) )
2495 		return pActionViewShell;
2496 
2497 	if( bSetCrsr )
2498 	{
2499 		// at all CrsrEditShells set the cursors to the doc start.
2500 		ViewShell *pSh = pActionViewShell;
2501 		do {
2502 			if( pSh->IsA( TYPE( SwCrsrShell ) ) )
2503 				((SwCrsrShell*)pSh)->SttEndDoc(sal_True);
2504 			pSh = (ViewShell *)pSh->GetNext();
2505 		} while( pSh != pActionViewShell );
2506 
2507 		bSetCrsr = sal_False;
2508 	}
2509 	if( pActionViewShell->ISA( SwEditShell ) )
2510 	{
2511 		//Scrolled already?, then make sure that the view does not move!
2512 		const sal_Bool bOldLock = pActionViewShell->IsViewLocked();
2513 		pActionViewShell->LockView( sal_True );
2514 		const sal_Bool bOldEndActionByVirDev = pActionViewShell->IsEndActionByVirDev();
2515 		pActionViewShell->SetEndActionByVirDev( sal_True );;
2516 		((SwEditShell*)pActionViewShell)->EndAction();
2517 		pActionViewShell->SetEndActionByVirDev( bOldEndActionByVirDev );
2518 		pActionViewShell->LockView( bOldLock );
2519 
2520 		// bChkJumpMark is only set if the object was found.
2521 		if( bChkJumpMark )
2522 		{
2523 			const Point aVisSttPos( DOCUMENTBORDER, DOCUMENTBORDER );
2524 			if( GetMedium() && aVisSttPos == pActionViewShell->VisArea().Pos() )
2525 				::JumpToSwMark( pActionViewShell,
2526 								GetMedium()->GetURLObject().GetMark() );
2527 			bChkJumpMark = sal_False;
2528 		}
2529 	}
2530 	else
2531 		pActionViewShell->EndAction();
2532 
2533 	// If the parser should be the last one to hold the doc, then you can
2534 	// abort here and set an error.
2535 	if( 1 == pDoc->getReferenceCount() )
2536 	{
2537 		eState = SVPAR_ERROR;
2538 	}
2539 
2540 	ViewShell *pVSh = pActionViewShell;
2541 	pActionViewShell = 0;
2542 
2543 	return pVSh;
2544 }
2545 
CheckActionViewShell()2546 ViewShell *SwHTMLParser::CheckActionViewShell()
2547 {
2548 	ViewShell *pVSh = 0;
2549 	pDoc->GetEditShell( &pVSh );
2550 	ASSERT( !pVSh || pActionViewShell == pVSh,
2551 			"CheckActionViewShell: Who replaced the ViewShell?" );
2552 #if OSL_DEBUG_LEVEL > 1
2553 	if( pActionViewShell && !pVSh )
2554 		pVSh = 0;
2555 #endif
2556 	if( pVSh != pActionViewShell )
2557 		pActionViewShell = 0;
2558 
2559 	return pActionViewShell;
2560 }
2561 
2562 /*  */
2563 
_SetAttr(sal_Bool bChkEnd,sal_Bool bBeforeTable,_HTMLAttrs * pPostIts)2564 void SwHTMLParser::_SetAttr( sal_Bool bChkEnd, sal_Bool bBeforeTable,
2565 							 _HTMLAttrs *pPostIts )
2566 {
2567 	SwPaM* pAttrPam = new SwPaM( *pPam->GetPoint() );
2568 	const SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
2569 	xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2570 	_HTMLAttr* pAttr;
2571 	SwCntntNode* pCNd;
2572 	sal_uInt16 n;
2573 
2574 	_HTMLAttrs aFields( 5, 5 );
2575 
2576 	for( n = aSetAttrTab.Count(); n; )
2577 	{
2578 		pAttr = aSetAttrTab[ --n ];
2579 		sal_uInt16 nWhich = pAttr->pItem->Which();
2580 
2581 		sal_uLong nEndParaIdx = pAttr->GetEndParaIdx();
2582 		sal_Bool bSetAttr;
2583 		if( bChkEnd )
2584 		{
2585 			// fix #42192#: set character attributes in current paragraph with end
2586 			// as early as possible, because of JavaScript and various chats.
2587 			// Except attributes, which are spanned over the whole paragraph, because
2588 			// they come from paragraph occurrences that cannot be set.
2589 			// Because the attributes are inserted with SETATTR_DONTREPLACE
2590 			// they should be able to set them subsequently.
2591 			bSetAttr = ( nEndParaIdx < rEndIdx.GetIndex() &&
2592 						 (RES_LR_SPACE != nWhich || !GetNumInfo().GetNumRule()) ) ||
2593 					   ( !pAttr->IsLikePara() &&
2594 						 nEndParaIdx == rEndIdx.GetIndex() &&
2595 						 pAttr->GetEndCnt() < nEndCnt &&
2596                          (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)) ) ||
2597 					   ( bBeforeTable &&
2598 						 nEndParaIdx == rEndIdx.GetIndex() &&
2599 						 !pAttr->GetEndCnt() );
2600 		}
2601 		else
2602 		{
2603 			// Attributes in the content area may not be set in
2604 			// special areai, but if the opposite is true.
2605 			sal_uLong nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2606 			bSetAttr = nEndParaIdx < rEndIdx.GetIndex() ||
2607 					   rEndIdx.GetIndex() > nEndOfIcons ||
2608 					   nEndParaIdx <= nEndOfIcons;
2609 		}
2610 
2611 		if( bSetAttr )
2612 		{
2613 			// The attribute must not be in the list of previous
2614 			// paragraph attributes, otherwise it will be deleted.
2615 			sal_uInt16 ii = aParaAttrs.Count();
2616 			while( ii-- )
2617 			{
2618 				ASSERT( pAttr != aParaAttrs[ii],
2619 						"SetAttr: Attribute may not be set yet" );
2620 				aParaAttrs.Remove( ii );
2621 			}
2622 
2623 
2624 			// then set
2625 			aSetAttrTab.Remove( n, 1 );
2626 
2627 			while( pAttr )
2628 			{
2629 				_HTMLAttr *pPrev = pAttr->GetPrev();
2630 				if( !pAttr->bValid )
2631 				{
2632 					// invalid attributes can be deleted
2633 					delete pAttr;
2634 					pAttr = pPrev;
2635 					continue; //break;
2636 				}
2637 
2638 
2639                 pCNd = pAttr->nSttPara.GetNode().GetCntntNode();
2640 				if( !pCNd )
2641 				{
2642 					// due to the miserable deletion of nodes also sometimes
2643 					// an index can point to an end node :-(
2644                     if ( (pAttr->GetSttPara() == pAttr->GetEndPara()) &&
2645                          !isTXTATR_NOEND(nWhich) )
2646 					{
2647 						// if the end index also points to the node
2648 						// we don't need to set an attribute anymore,
2649 						// unless it is a text attribute.
2650 						delete pAttr;
2651 						pAttr = pPrev;
2652 						continue; //break;
2653 					}
2654 					pCNd = pDoc->GetNodes().GoNext( &(pAttr->nSttPara) );
2655 					if( pCNd )
2656 						pAttr->nSttCntnt = 0;
2657 					else
2658 					{
2659 						ASSERT( sal_False, "SetAttr: GoNext() failed!" );
2660 						delete pAttr;
2661 						pAttr = pPrev;
2662 						continue; // break;
2663 					}
2664 				}
2665 				pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2666 
2667 
2668 
2669 				// by deleting BRs, the start index can
2670 				// can also sometimes point behind the end of the text
2671 				if( pAttr->nSttCntnt > pCNd->Len() )
2672 					pAttr->nSttCntnt = pCNd->Len();
2673 				pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2674 
2675 				pAttrPam->SetMark();
2676                 if ( (pAttr->GetSttPara() != pAttr->GetEndPara()) &&
2677                          !isTXTATR_NOEND(nWhich) )
2678                 {
2679                     pCNd = pAttr->nEndPara.GetNode().GetCntntNode();
2680 					if( !pCNd )
2681 					{
2682 						pCNd = pDoc->GetNodes().GoPrevious( &(pAttr->nEndPara) );
2683 						if( pCNd )
2684 							pAttr->nEndCntnt = pCNd->Len();
2685 						else
2686 						{
2687 							ASSERT( sal_False, "SetAttr: GoPrevious() failed!" );
2688 							pAttrPam->DeleteMark();
2689 							delete pAttr;
2690 							pAttr = pPrev;
2691 							continue; // break;
2692 						}
2693 					}
2694 
2695 					pAttrPam->GetPoint()->nNode = pAttr->nEndPara;
2696 				}
2697 				else if( pAttr->IsLikePara() )
2698 				{
2699 					pAttr->nEndCntnt = pCNd->Len();
2700 				}
2701 
2702 				// by deleting BRs, the end index can
2703 				// can also sometimes point behind the end of the text
2704 				if( pAttr->nEndCntnt > pCNd->Len() )
2705 					pAttr->nEndCntnt = pCNd->Len();
2706 
2707 				pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nEndCntnt );
2708 				if( bBeforeTable &&
2709 					pAttrPam->GetPoint()->nNode.GetIndex() ==
2710 						rEndIdx.GetIndex() )
2711 				{
2712 					// if we are about to insert a table
2713 					// and the attribute is terminated in the current node,
2714 					// we must end it in the node before or throw it away,
2715 					// if it starts in the node before
2716 					if( nWhich != RES_BREAK && nWhich != RES_PAGEDESC &&
2717                          !isTXTATR_NOEND(nWhich) )
2718 					{
2719 						if( pAttrPam->GetMark()->nNode.GetIndex() !=
2720 							rEndIdx.GetIndex() )
2721 						{
2722 							ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2723 									"Content position before table not 0???" );
2724 							pAttrPam->Move( fnMoveBackward );
2725 						}
2726 						else
2727 						{
2728 							pAttrPam->DeleteMark();
2729 							delete pAttr;
2730 							pAttr = pPrev;
2731 							continue;
2732 						}
2733 					}
2734 				}
2735 
2736 				switch( nWhich )
2737 				{
2738                 case RES_FLTR_BOOKMARK: // insert bookmark
2739                     {
2740                         const String sName( ((SfxStringItem*)pAttr->pItem)->GetValue() );
2741                         IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
2742                         IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark( sName );
2743                         if( ppBkmk != pMarkAccess->getAllMarksEnd() &&
2744                             ppBkmk->get()->GetMarkStart() == *pAttrPam->GetPoint() )
2745                             break; // do not generate duplicates on this position
2746                         pAttrPam->DeleteMark();
2747                         const ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
2748                             *pAttrPam,
2749                             sName,
2750                             IDocumentMarkAccess::BOOKMARK );
2751 
2752                         // jump to bookmark
2753                         if( JUMPTO_MARK == eJumpTo && pNewMark->GetName() == ::rtl::OUString(sJmpMark) )
2754                         {
2755                             bChkJumpMark = sal_True;
2756                             eJumpTo = JUMPTO_NONE;
2757                         }
2758                     }
2759                     break;
2760                 case RES_TXTATR_FIELD:
2761                 case RES_TXTATR_ANNOTATION:
2762                 case RES_TXTATR_INPUTFIELD:
2763                     {
2764                         sal_uInt16 nFldWhich =
2765                             pPostIts
2766                             ? ((const SwFmtFld *)pAttr->pItem)->GetField()->GetTyp()->Which()
2767                             : 0;
2768                         if( pPostIts && (RES_POSTITFLD == nFldWhich ||
2769                                          RES_SCRIPTFLD == nFldWhich) )
2770                         {
2771                             pPostIts->Insert( pAttr, 0 );
2772                         }
2773                         else
2774                         {
2775                             aFields.Insert( pAttr, aFields.Count() );
2776                         }
2777                     }
2778                     pAttrPam->DeleteMark();
2779                     pAttr = pPrev;
2780                     continue;
2781 
2782 				case RES_LR_SPACE:
2783 					if( pAttrPam->GetPoint()->nNode.GetIndex() ==
2784 						pAttrPam->GetMark()->nNode.GetIndex() &&
2785 						pCNd )
2786 					{
2787 						// because of numbering this attribute directly
2788 						// set at the node
2789 						pCNd->SetAttr( *pAttr->pItem );
2790 						break;
2791 					}
2792 					ASSERT(	sal_False,
2793 							"LRSpace set over several paragraphs!" );
2794 					// no break (we are never supposed to get here anyway;
2795 				default:
2796 
2797 					// jump to a bookmark if necessary
2798 					if( RES_TXTATR_INETFMT == nWhich &&
2799 						JUMPTO_MARK == eJumpTo &&
2800 						sJmpMark == ((SwFmtINetFmt*)pAttr->pItem)->GetName() )
2801 					{
2802 						bChkJumpMark = sal_True;
2803 						eJumpTo = JUMPTO_NONE;
2804 					}
2805 
2806                     pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, nsSetAttrMode::SETATTR_DONTREPLACE );
2807 				}
2808 				pAttrPam->DeleteMark();
2809 
2810 				delete pAttr;
2811 				pAttr = pPrev;
2812 			}
2813 		}
2814 	}
2815 
2816 	for( n = aMoveFlyFrms.Count(); n; )
2817 	{
2818 		SwFrmFmt *pFrmFmt = aMoveFlyFrms[ --n ];
2819 
2820 		const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
2821         ASSERT( FLY_AT_PARA == rAnchor.GetAnchorId(),
2822 				"Only car frames need special treatment" );
2823 		const SwPosition *pFlyPos = rAnchor.GetCntntAnchor();
2824 		sal_uLong nFlyParaIdx = pFlyPos->nNode.GetIndex();
2825 		sal_Bool bMoveFly;
2826 		if( bChkEnd )
2827 		{
2828 			bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2829 					   ( nFlyParaIdx == rEndIdx.GetIndex() &&
2830 						 aMoveFlyCnts[n] < nEndCnt );
2831 		}
2832 		else
2833 		{
2834 			sal_uLong nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2835 			bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2836 					   rEndIdx.GetIndex() > nEndOfIcons ||
2837 					   nFlyParaIdx <= nEndOfIcons;
2838 		}
2839 		if( bMoveFly )
2840 		{
2841 			pFrmFmt->DelFrms();
2842 			*pAttrPam->GetPoint() = *pFlyPos;
2843 			pAttrPam->GetPoint()->nContent.Assign( pAttrPam->GetCntntNode(),
2844 												   aMoveFlyCnts[n] );
2845 			SwFmtAnchor aAnchor( rAnchor );
2846             aAnchor.SetType( FLY_AT_CHAR );
2847 			aAnchor.SetAnchor( pAttrPam->GetPoint() );
2848             pFrmFmt->SetFmtAttr( aAnchor );
2849 
2850 			const SwFmtHoriOrient& rHoriOri = pFrmFmt->GetHoriOrient();
2851             if( text::HoriOrientation::LEFT == rHoriOri.GetHoriOrient() )
2852 			{
2853 				SwFmtHoriOrient aHoriOri( rHoriOri );
2854                 aHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2855                 pFrmFmt->SetFmtAttr( aHoriOri );
2856 			}
2857 			const SwFmtVertOrient& rVertOri = pFrmFmt->GetVertOrient();
2858             if( text::VertOrientation::TOP == rVertOri.GetVertOrient() )
2859 			{
2860 				SwFmtVertOrient aVertOri( rVertOri );
2861                 aVertOri.SetRelationOrient( text::RelOrientation::CHAR );
2862                 pFrmFmt->SetFmtAttr( aVertOri );
2863 			}
2864 
2865 			pFrmFmt->MakeFrms();
2866 			aMoveFlyFrms.Remove( n, 1 );
2867 			aMoveFlyCnts.erase( aMoveFlyCnts.begin() + n );
2868 		}
2869 	}
2870 	while( aFields.Count() )
2871 	{
2872 		pAttr = aFields[0];
2873 
2874         pCNd = pAttr->nSttPara.GetNode().GetCntntNode();
2875 		pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2876 		pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2877 
2878 		if( bBeforeTable &&
2879 			pAttrPam->GetPoint()->nNode.GetIndex() == rEndIdx.GetIndex() )
2880 		{
2881 			ASSERT( !bBeforeTable, "Aha, the case occurs after all" );
2882 			ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2883 					"Content position before table not 0???" );
2884 			// !!!
2885 			pAttrPam->Move( fnMoveBackward );
2886 		}
2887 
2888         pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, 0 );
2889 
2890 		aFields.Remove( 0, 1 );
2891 		delete pAttr;
2892 	}
2893 
2894 	delete pAttrPam;
2895 }
2896 
NewAttr(_HTMLAttr ** ppAttr,const SfxPoolItem & rItem)2897 void SwHTMLParser::NewAttr( _HTMLAttr **ppAttr, const SfxPoolItem& rItem )
2898 {
2899 	// font-height and -color as well as escapement attributes must not be
2900 	// be combined. Therefore they are stored in a list,
2901 	// where the last expanded attribute is at the front and the count is always 1.
2902 	// For all other attributes the count is simply incremented.
2903 	if( *ppAttr )
2904 	{
2905 		_HTMLAttr *pAttr = new _HTMLAttr( *pPam->GetPoint(), rItem,
2906 											ppAttr );
2907 		pAttr->InsertNext( *ppAttr );
2908 		(*ppAttr) = pAttr;
2909 	}
2910 	else
2911 		(*ppAttr) = new _HTMLAttr( *pPam->GetPoint(), rItem, ppAttr );
2912 }
2913 
2914 
EndAttr(_HTMLAttr * pAttr,_HTMLAttr ** ppDepAttr,sal_Bool bChkEmpty)2915 void SwHTMLParser::EndAttr( _HTMLAttr* pAttr, _HTMLAttr **ppDepAttr,
2916 							sal_Bool bChkEmpty )
2917 {
2918 	ASSERT( !ppDepAttr, "SwHTMLParser::EndAttr: untested ppDepAttr-Feature?" );
2919 	// The list header is stored in the attribute
2920 	_HTMLAttr **ppHead = pAttr->ppHead;
2921 
2922 	ASSERT( ppHead, "no attribute list header found!" );
2923 
2924 	// remember the current position as the end position
2925 	const SwNodeIndex* pEndIdx = &pPam->GetPoint()->nNode;
2926 	xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2927 
2928 	// Is the last started or a previously started attribute
2929 	// finished?
2930 	_HTMLAttr *pLast = 0;
2931 	if( ppHead && pAttr != *ppHead )
2932 	{
2933 		// The last started attribute is not terminated
2934 
2935 		// Then we search for the attribute that was started immediately afterwards, which
2936 		// has not been finished yet either (otherwise it would not be
2937 		// any more in the list
2938 		pLast = *ppHead;
2939 		while( pLast && pLast->GetNext() != pAttr )
2940 			pLast = pLast->GetNext();
2941 
2942 		ASSERT( pLast, "Attribute not found in own list!" );
2943 
2944 		// Do not end the attribute at the PaM psoition, but there,
2945 		// where the attribute started???
2946 		//pEndIdx = &pPrev->GetSttPara();
2947 		//nEndCnt = pPrev->GetSttCnt();
2948 	}
2949 
2950 	sal_Bool bMoveBack = sal_False;
2951 	sal_uInt16 nWhich = pAttr->pItem->Which();
2952 	if( /*!pLast &&*/ !nEndCnt && RES_PARATR_BEGIN <= nWhich &&
2953 		*pEndIdx != pAttr->GetSttPara() )
2954 	{
2955 		// then one Cntnt position back!
2956 		bMoveBack = pPam->Move( fnMoveBackward );
2957 		nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2958 	}
2959 
2960 	// end this Attrubut
2961 	_HTMLAttr *pNext = pAttr->GetNext();
2962 
2963 
2964 	sal_Bool bInsert;
2965     sal_uInt16 nScriptItem = 0;
2966 	sal_Bool bScript = sal_False, bFont = sal_False;
2967 	// an area ??
2968 	if( !bChkEmpty || (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
2969 		RES_PAGEDESC == nWhich || RES_BREAK == nWhich ||
2970 		*pEndIdx != pAttr->GetSttPara() ||
2971 		nEndCnt != pAttr->GetSttCnt() )
2972 	{
2973 		bInsert = sal_True;
2974 		// We do some optimization for script depenedent attribtes here.
2975 		if( *pEndIdx == pAttr->GetSttPara() )
2976 		{
2977 			lcl_swhtml_getItemInfo( *pAttr, bScript, bFont, nScriptItem );
2978 		}
2979 	}
2980 	else
2981 	{
2982 		bInsert = sal_False;
2983 	}
2984 
2985 	if( bInsert && bScript )
2986 	{
2987 		const SwTxtNode *pTxtNd = pAttr->GetSttPara().GetNode()
2988 											.GetTxtNode();
2989 		ASSERT( pTxtNd, "No text node" );
2990 		const String& rText = pTxtNd->GetTxt();
2991 		sal_uInt16 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
2992 						rText, pAttr->GetSttCnt() );
2993 		xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2994 					->endOfScript( rText, pAttr->GetSttCnt(), nScriptTxt );
2995 		while( nScriptEnd < nEndCnt )
2996 		{
2997 			if( nScriptItem == nScriptTxt )
2998 			{
2999 				_HTMLAttr *pSetAttr = pAttr->Clone( *pEndIdx, nScriptEnd );
3000 				pSetAttr->ClearPrev();
3001 				if( pNext )
3002 					pNext->InsertPrev( pSetAttr );
3003 				else
3004 				{
3005 					sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
3006 														: aSetAttrTab.Count();
3007 					aSetAttrTab.Insert( pSetAttr, nTmp );
3008 				}
3009 			}
3010 			pAttr->nSttCntnt = nScriptEnd;
3011 			nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
3012 							rText, nScriptEnd );
3013 			nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
3014 					->endOfScript( rText, nScriptEnd, nScriptTxt );
3015 		}
3016 		bInsert = nScriptItem == nScriptTxt;
3017 	}
3018 	if( bInsert )
3019 	{
3020 		pAttr->nEndPara = *pEndIdx;
3021 		pAttr->nEndCntnt = nEndCnt;
3022 		pAttr->bInsAtStart = RES_TXTATR_INETFMT != nWhich &&
3023 							 RES_TXTATR_CHARFMT != nWhich;
3024 
3025 		if( !pNext )
3026 		{
3027 			// there are no more open attributes of this type,
3028 			// then all of them can be set, unless
3029 			// they still depend on another attribute,
3030 			// then they will be appended there
3031 			if( ppDepAttr && *ppDepAttr )
3032 				(*ppDepAttr)->InsertPrev( pAttr );
3033 			else
3034 			{
3035 				sal_uInt16 nTmp = pAttr->bInsAtStart ? 0 : aSetAttrTab.Count();
3036 				aSetAttrTab.Insert( pAttr, nTmp );
3037 			}
3038 		}
3039 		else
3040 		{
3041 			// there are other open attributes of the type,
3042 			// so the setting must be reset.
3043 			// the current attribute is therefore appended to the end of the
3044 			// previous list of the successor.
3045 			pNext->InsertPrev( pAttr );
3046 		}
3047 	}
3048 	else
3049 	{
3050 		// Then do not insert, but delete. Through "fakeing" of
3051 		// templates by hard attributes, there may be other empty attributes
3052 		// in the Prev list, which then must be set anyway.
3053 		_HTMLAttr *pPrev = pAttr->GetPrev();
3054 		delete pAttr;
3055 
3056 		if( pPrev )
3057 		{
3058 			// The Previous attributes must be set anyway.
3059 			if( pNext )
3060 				pNext->InsertPrev( pPrev );
3061 			else
3062 			{
3063 				sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3064 				aSetAttrTab.Insert( pPrev, nTmp );
3065 			}
3066 		}
3067 
3068 	}
3069 
3070 	// if the first attribute of the list has been set the
3071 	// list header must be corrected.
3072 	if( pLast )
3073 		pLast->pNext = pNext;
3074 	else if( ppHead )
3075 		*ppHead = pNext;
3076 
3077 	if( bMoveBack )
3078 		pPam->Move( fnMoveForward );
3079 }
3080 
DeleteAttr(_HTMLAttr * pAttr)3081 void SwHTMLParser::DeleteAttr( _HTMLAttr* pAttr )
3082 {
3083 	// There must not be any leading paragraph attributes here, because the
3084 	// could be set now and then the pointers are invalid!!!
3085 	ASSERT( !aParaAttrs.Count(),
3086 			"Highest risk: There are still non-final paragraph attributes" );
3087 	if( aParaAttrs.Count() )
3088 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3089 
3090 	// The list header is stored in the attribute
3091 	_HTMLAttr **ppHead = pAttr->ppHead;
3092 
3093 	ASSERT( ppHead, "no attributes list header found!" );
3094 
3095 	// Is the attribute that was started last or an attribute that was started earlier
3096 	// removed?
3097 	_HTMLAttr *pLast = 0;
3098 	if( ppHead && pAttr != *ppHead )
3099 	{
3100 		// The last started attribute is not terminated
3101 
3102 		// Then we search for the attribute that was started immediately afterwards, which
3103 		// has not been finished yet either (otherwise it would not be
3104 		// any more in the list
3105 		pLast = *ppHead;
3106 		while( pLast && pLast->GetNext() != pAttr )
3107 			pLast = pLast->GetNext();
3108 
3109 		ASSERT( pLast, "Attribute not found in own list!" );
3110 	}
3111 
3112 	// now remove the attribute
3113 	_HTMLAttr *pNext = pAttr->GetNext();
3114 	_HTMLAttr *pPrev = pAttr->GetPrev();
3115 	delete pAttr;
3116 
3117 	if( pPrev )
3118 	{
3119 		// The Previous attributes must be set anyway.
3120 		if( pNext )
3121 			pNext->InsertPrev( pPrev );
3122 		else
3123 		{
3124 			sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3125 			aSetAttrTab.Insert( pPrev, nTmp );
3126 		}
3127 	}
3128 
3129 	// if the first attribute of the list has been removed the
3130 	// list header must be corrected.
3131 	if( pLast )
3132 		pLast->pNext = pNext;
3133 	else if( ppHead )
3134 		*ppHead = pNext;
3135 }
3136 
SaveAttrTab(_HTMLAttrTable & rNewAttrTab)3137 void SwHTMLParser::SaveAttrTab( _HTMLAttrTable& rNewAttrTab )
3138 {
3139 	// There must not be any leading paragraph attributes here, because the
3140 	// could be set now and then the pointers are invalid!!!
3141 	ASSERT( !aParaAttrs.Count(),
3142 			"Highest risk: There are still non-final paragraph attributes" );
3143 	if( aParaAttrs.Count() )
3144 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3145 
3146 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3147 	_HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3148 
3149 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3150 		 nCnt--; (++pTbl, ++pSaveTbl) )
3151 	{
3152 		*pSaveTbl = *pTbl;
3153 
3154 		_HTMLAttr *pAttr = *pSaveTbl;
3155 		while( pAttr )
3156 		{
3157 			pAttr->SetHead( pSaveTbl );
3158 			pAttr = pAttr->GetNext();
3159 		}
3160 
3161 		*pTbl = 0;
3162 	}
3163 }
3164 
SplitAttrTab(_HTMLAttrTable & rNewAttrTab,sal_Bool bMoveEndBack)3165 void SwHTMLParser::SplitAttrTab( _HTMLAttrTable& rNewAttrTab,
3166 								 sal_Bool bMoveEndBack )
3167 {
3168 	// There must not be any leading paragraph attributes here, because the
3169 	// could be set now and then the pointers are invalid!!!
3170 	ASSERT( !aParaAttrs.Count(),
3171 			"Highest risk: There are still non-final paragraph attributes" );
3172 	if( aParaAttrs.Count() )
3173 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3174 
3175 	const SwNodeIndex& nSttIdx = pPam->GetPoint()->nNode;
3176 	SwNodeIndex nEndIdx( nSttIdx );
3177 
3178 	// terminate all attributes still open and span behind the table
3179 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3180 	_HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3181 	sal_Bool bSetAttr = sal_True;
3182 	xub_StrLen nSttCnt = pPam->GetPoint()->nContent.GetIndex();
3183 	xub_StrLen nEndCnt = nSttCnt;
3184 
3185 	if( bMoveEndBack )
3186 	{
3187 		sal_uLong nOldEnd = nEndIdx.GetIndex();
3188 		sal_uLong nTmpIdx;
3189 		if(	( nTmpIdx = pDoc->GetNodes().GetEndOfExtras().GetIndex()) >= nOldEnd ||
3190 			( nTmpIdx = pDoc->GetNodes().GetEndOfAutotext().GetIndex()) >= nOldEnd )
3191 		{
3192 			nTmpIdx = pDoc->GetNodes().GetEndOfInserts().GetIndex();
3193 		}
3194 		SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious(&nEndIdx);
3195 
3196 		// Do not set attributes if the PaM has been moved out of the content area.
3197 		// has been pushed out.
3198 		bSetAttr = pCNd && nTmpIdx < nEndIdx.GetIndex();
3199 
3200 		nEndCnt = (bSetAttr ? pCNd->Len() : 0);
3201 	}
3202 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3203 		 nCnt--; (++pTbl, ++pSaveTbl) )
3204 	{
3205 		_HTMLAttr *pAttr = *pTbl;
3206 		*pSaveTbl = 0;
3207 		while( pAttr )
3208 		{
3209 			_HTMLAttr *pNext = pAttr->GetNext();
3210 			_HTMLAttr *pPrev = pAttr->GetPrev();
3211 
3212 			if( bSetAttr &&
3213 				( pAttr->GetSttParaIdx() < nEndIdx.GetIndex() ||
3214 				  (pAttr->GetSttPara() == nEndIdx &&
3215 				   pAttr->GetSttCnt() != nEndCnt) ) )
3216 			{
3217 				// the attribute must be set before the list. Since we
3218 				// still need the original because pointers to the attribute
3219 				// still exist in the contexts, we have to clone it.
3220 				// The next list will be lost, but the
3221 				// Previous list is preserved
3222 				_HTMLAttr *pSetAttr = pAttr->Clone( nEndIdx, nEndCnt );
3223 
3224 				if( pNext )
3225 					pNext->InsertPrev( pSetAttr );
3226 				else
3227 				{
3228 					sal_uInt16 nTmp = pSetAttr->bInsAtStart ? 0
3229 														: aSetAttrTab.Count();
3230 					aSetAttrTab.Insert( pSetAttr, nTmp );
3231 				}
3232 			}
3233 			else if( pPrev )
3234 			{
3235 				// If the attribute is not set before the table
3236 				// the Previous attribute must be set anyway.
3237 				if( pNext )
3238 					pNext->InsertPrev( pPrev );
3239 				else
3240 				{
3241 					sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3242 					aSetAttrTab.Insert( pPrev, nTmp );
3243 				}
3244 			}
3245 
3246 			// reset the start of the attribute  and break the concatenations break
3247 			pAttr->Reset( nSttIdx, nSttCnt, pSaveTbl );
3248 
3249 			if( *pSaveTbl )
3250 			{
3251 				_HTMLAttr *pSAttr = *pSaveTbl;
3252 				while( pSAttr->GetNext() )
3253 					pSAttr = pSAttr->GetNext();
3254 				pSAttr->InsertNext( pAttr );
3255 			}
3256 			else
3257 				*pSaveTbl = pAttr;
3258 
3259 			pAttr = pNext;
3260 		}
3261 
3262 		*pTbl = 0;
3263 	}
3264 }
3265 
RestoreAttrTab(const _HTMLAttrTable & rNewAttrTab,sal_Bool bSetNewStart)3266 void SwHTMLParser::RestoreAttrTab( const _HTMLAttrTable& rNewAttrTab,
3267 								   sal_Bool bSetNewStart )
3268 {
3269 	// There must not be any leading paragraph attributes here, because the
3270 	// could be set now and then the pointers are invalid!!!
3271 	ASSERT( !aParaAttrs.Count(),
3272 			"Highest risk: There are still non-final paragraph attributes" );
3273 	if( aParaAttrs.Count() )
3274 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
3275 
3276 	_HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3277 	_HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3278 
3279 	for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3280 		nCnt--; (++pTbl, ++pSaveTbl) )
3281 	{
3282 		ASSERT( !*pTbl, "The attribute table is not empty!" );
3283 
3284 		const SwPosition *pPos = pPam->GetPoint();
3285 		const SwNodeIndex& rSttPara = pPos->nNode;
3286 		xub_StrLen nSttCnt = pPos->nContent.GetIndex();
3287 
3288 		*pTbl = *pSaveTbl;
3289 
3290 		_HTMLAttr *pAttr = *pTbl;
3291 		while( pAttr )
3292 		{
3293 			ASSERT( !pAttr->GetPrev() || !pAttr->GetPrev()->ppHead,
3294 					"Previous attribute still has a header" );
3295 			pAttr->SetHead( pTbl );
3296 			if( bSetNewStart )
3297 			{
3298 				pAttr->nSttPara = rSttPara;
3299 				pAttr->nEndPara = rSttPara;
3300 				pAttr->nSttCntnt = nSttCnt;
3301 				pAttr->nEndCntnt = nSttCnt;
3302 			}
3303 			pAttr = pAttr->GetNext();
3304 		}
3305 
3306 		*pSaveTbl = 0;
3307 	}
3308 }
3309 
InsertAttr(const SfxPoolItem & rItem,sal_Bool bLikePara,sal_Bool bInsAtStart)3310 void SwHTMLParser::InsertAttr( const SfxPoolItem& rItem, sal_Bool bLikePara,
3311 							   sal_Bool bInsAtStart )
3312 {
3313 	_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(),
3314 									 rItem );
3315 	if( bLikePara )
3316 		pTmp->SetLikePara();
3317 	sal_uInt16 nTmp = bInsAtStart ? 0 : aSetAttrTab.Count();
3318 	aSetAttrTab.Insert( pTmp, nTmp );
3319 }
3320 
InsertAttrs(_HTMLAttrs & rAttrs)3321 void SwHTMLParser::InsertAttrs( _HTMLAttrs& rAttrs )
3322 {
3323 	while( rAttrs.Count() )
3324 	{
3325 		_HTMLAttr *pAttr = rAttrs[0];
3326 		InsertAttr( pAttr->GetItem() );
3327 		rAttrs.Remove( 0, 1 );
3328 		delete pAttr;
3329 	}
3330 }
3331 
3332 /*  */
3333 
NewStdAttr(int nToken)3334 void SwHTMLParser::NewStdAttr( int nToken )
3335 {
3336 	String aId, aStyle, aClass, aLang, aDir;
3337 
3338 	const HTMLOptions *pHTMLOptions = GetOptions();
3339 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3340 	{
3341 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3342 		switch( pOption->GetToken() )
3343 		{
3344 		case HTML_O_ID:
3345 			aId = pOption->GetString();
3346 			break;
3347 		case HTML_O_STYLE:
3348 			aStyle = pOption->GetString();
3349 			break;
3350 		case HTML_O_CLASS:
3351 			aClass = pOption->GetString();
3352 			break;
3353 		case HTML_O_LANG:
3354 			aLang = pOption->GetString();
3355 			break;
3356 		case HTML_O_DIR:
3357 			aDir = pOption->GetString();
3358 			break;
3359 		}
3360 	}
3361 
3362 	// create a new context
3363     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3364 
3365 	// parse styles
3366 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3367 	{
3368 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3369 		SvxCSS1PropertyInfo aPropInfo;
3370 
3371 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3372 		{
3373 			if( HTML_SPAN_ON != nToken || !aClass.Len() ||
3374 				!CreateContainer( aClass, aItemSet, aPropInfo, pCntxt ) )
3375 				DoPositioning( aItemSet, aPropInfo, pCntxt );
3376 			InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3377 		}
3378 	}
3379 
3380 	// memorize context
3381 	PushContext( pCntxt );
3382 }
3383 
NewStdAttr(int nToken,_HTMLAttr ** ppAttr,const SfxPoolItem & rItem,_HTMLAttr ** ppAttr2,const SfxPoolItem * pItem2,_HTMLAttr ** ppAttr3,const SfxPoolItem * pItem3)3384 void SwHTMLParser::NewStdAttr( int nToken,
3385 							   _HTMLAttr **ppAttr, const SfxPoolItem & rItem,
3386 							   _HTMLAttr **ppAttr2, const SfxPoolItem *pItem2,
3387 							   _HTMLAttr **ppAttr3, const SfxPoolItem *pItem3 )
3388 {
3389 	String aId, aStyle, aClass, aLang, aDir;
3390 
3391 	const HTMLOptions *pHTMLOptions = GetOptions();
3392 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3393 	{
3394 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3395 		switch( pOption->GetToken() )
3396 		{
3397 		case HTML_O_ID:
3398 			aId = pOption->GetString();
3399 			break;
3400 		case HTML_O_STYLE:
3401 			aStyle = pOption->GetString();
3402 			break;
3403 		case HTML_O_CLASS:
3404 			aClass = pOption->GetString();
3405 			break;
3406 		case HTML_O_LANG:
3407 			aLang = pOption->GetString();
3408 			break;
3409 		case HTML_O_DIR:
3410 			aDir = pOption->GetString();
3411 			break;
3412 		}
3413 	}
3414 
3415 	// create new context
3416     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3417 
3418 	// parse Styles
3419 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3420 	{
3421 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3422 		SvxCSS1PropertyInfo aPropInfo;
3423 
3424 		aItemSet.Put( rItem );
3425 		if( pItem2 )
3426 			aItemSet.Put( *pItem2 );
3427 		if( pItem3 )
3428 			aItemSet.Put( *pItem3 );
3429 
3430 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3431 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3432 
3433 		InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3434 	}
3435 	else
3436 	{
3437 		InsertAttr( ppAttr ,rItem, pCntxt );
3438 		if( pItem2 )
3439 		{
3440 			ASSERT( ppAttr2, "missing table entry for item2" );
3441 			InsertAttr( ppAttr2, *pItem2, pCntxt );
3442 		}
3443 		if( pItem3 )
3444 		{
3445 			ASSERT( ppAttr3, "missing table entry for item3" );
3446 			InsertAttr( ppAttr3, *pItem3, pCntxt );
3447 		}
3448 	}
3449 
3450 	// memorize context
3451 	PushContext( pCntxt );
3452 }
3453 
EndTag(int nToken)3454 void SwHTMLParser::EndTag( int nToken )
3455 {
3456 	// get context
3457     _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
3458 	if( pCntxt )
3459 	{
3460 		// and terminate the attributes if necessary
3461 		EndContext( pCntxt );
3462 		delete pCntxt;
3463 	}
3464 }
3465 
3466 
NewBasefontAttr()3467 void SwHTMLParser::NewBasefontAttr()
3468 {
3469 	String aId, aStyle, aClass, aLang, aDir;
3470 	sal_uInt16 nSize = 3;
3471 
3472 	const HTMLOptions *pHTMLOptions = GetOptions();
3473 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3474 	{
3475 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3476 		switch( pOption->GetToken() )
3477 		{
3478 		case HTML_O_SIZE:
3479 			nSize = (sal_uInt16)pOption->GetNumber();
3480 			break;
3481 		case HTML_O_ID:
3482 			aId = pOption->GetString();
3483 			break;
3484 		case HTML_O_STYLE:
3485 			aStyle = pOption->GetString();
3486 			break;
3487 		case HTML_O_CLASS:
3488 			aClass = pOption->GetString();
3489 			break;
3490 		case HTML_O_LANG:
3491 			aLang = pOption->GetString();
3492 			break;
3493 		case HTML_O_DIR:
3494 			aDir = pOption->GetString();
3495 			break;
3496 		}
3497 	}
3498 
3499 	if( nSize < 1 )
3500 		nSize = 1;
3501 
3502 	if( nSize > 7 )
3503 		nSize = 7;
3504 
3505 	// set up a new context
3506 	_HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_BASEFONT_ON );
3507 
3508 	// parse styles
3509 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3510 	{
3511 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3512 		SvxCSS1PropertyInfo aPropInfo;
3513 
3514         SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3515 		aItemSet.Put( aFontHeight );
3516 		aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3517 		aItemSet.Put( aFontHeight );
3518 		aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3519 		aItemSet.Put( aFontHeight );
3520 
3521 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3522 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3523 
3524 		InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3525 	}
3526 	else
3527 	{
3528         SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3529 		InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3530 		aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3531 		InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3532 		aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3533 		InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3534 	}
3535 
3536 	// memorize context
3537 	PushContext( pCntxt );
3538 
3539 	// memorize Font-Size
3540 	aBaseFontStack.Insert( nSize, aBaseFontStack.Count() );
3541 }
3542 
EndBasefontAttr()3543 void SwHTMLParser::EndBasefontAttr()
3544 {
3545 	EndTag( HTML_BASEFONT_ON );
3546 
3547 	// Avoid stack underflow in tables
3548 	if( aBaseFontStack.Count() > nBaseFontStMin )
3549 		aBaseFontStack.Remove( aBaseFontStack.Count()-1, 1 );
3550 }
3551 
NewFontAttr(int nToken)3552 void SwHTMLParser::NewFontAttr( int nToken )
3553 {
3554 	sal_uInt16 nBaseSize =
3555 		( aBaseFontStack.Count() > nBaseFontStMin
3556 			? (aBaseFontStack[aBaseFontStack.Count()-1] & FONTSIZE_MASK)
3557 			: 3 );
3558 	sal_uInt16 nFontSize =
3559 		( aFontStack.Count() > nFontStMin
3560 			? (aFontStack[aFontStack.Count()-1] & FONTSIZE_MASK)
3561 			: nBaseSize );
3562 
3563 	String aFace, aId, aStyle, aClass, aLang, aDir;
3564 	Color aColor;
3565 	sal_uLong nFontHeight = 0;	// font height to be effectively set
3566 	sal_uInt16 nSize = 0;		// Font size in Netscape-Notation (1-7)
3567 	sal_Bool bColor = sal_False;
3568 
3569 	const HTMLOptions *pHTMLOptions = GetOptions();
3570 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3571 	{
3572 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3573 		switch( pOption->GetToken() )
3574 		{
3575 		case HTML_O_SIZE:
3576 			if( HTML_FONT_ON==nToken && pOption->GetString().Len() )
3577 			{
3578 				sal_Int32 nSSize;
3579 				if( '+' == pOption->GetString().GetChar(0) ||
3580 					'-' == pOption->GetString().GetChar(0) )
3581 					nSSize = nBaseSize + pOption->GetSNumber();
3582 				else
3583 					nSSize = (sal_Int32)pOption->GetNumber();
3584 
3585 				if( nSSize < 1 )
3586 					nSSize = 1;
3587 				else if( nSSize > 7 )
3588 					nSSize = 7;
3589 
3590 				nSize = (sal_uInt16)nSSize;
3591 				nFontHeight = aFontHeights[nSize-1];
3592 			}
3593 			break;
3594 		case HTML_O_COLOR:
3595 			if( HTML_FONT_ON==nToken )
3596 			{
3597 				pOption->GetColor( aColor );
3598 				bColor = sal_True;
3599 			}
3600 			break;
3601 		case HTML_O_FACE:
3602 			if( HTML_FONT_ON==nToken )
3603 				aFace = pOption->GetString();
3604 			break;
3605 		case HTML_O_ID:
3606 			aId = pOption->GetString();
3607 			break;
3608 		case HTML_O_STYLE:
3609 			aStyle = pOption->GetString();
3610 			break;
3611 		case HTML_O_CLASS:
3612 			aClass = pOption->GetString();
3613 			break;
3614 		case HTML_O_LANG:
3615 			aLang = pOption->GetString();
3616 			break;
3617 		case HTML_O_DIR:
3618 			aDir = pOption->GetString();
3619 			break;
3620 		}
3621 	}
3622 
3623 	if( HTML_FONT_ON != nToken )
3624 	{
3625 		// HTML_BIGPRINT_ON or HTML_SMALLPRINT_ON
3626 
3627 		// in headings, the current heading determines
3628 		// the font height and not BASEFONT
3629 		sal_uInt16 nPoolId = GetCurrFmtColl()->GetPoolFmtId();
3630 		if( (nPoolId>=RES_POOLCOLL_HEADLINE1 &&
3631 			 nPoolId<=RES_POOLCOLL_HEADLINE6) )
3632 		{
3633 			// if the font size in the heading is not yet changed, take the one from the template.
3634 			if( nFontStHeadStart==aFontStack.Count() )
3635                 nFontSize = static_cast< sal_uInt16 >(6 - (nPoolId - RES_POOLCOLL_HEADLINE1));
3636 		}
3637 		else
3638 			nPoolId = 0;
3639 
3640 		if( HTML_BIGPRINT_ON == nToken )
3641 			nSize = ( nFontSize<7 ? nFontSize+1 : 7 );
3642 		else
3643 			nSize = ( nFontSize>1 ? nFontSize-1 : 1 );
3644 
3645 		// in headlines, the new font height will be taken templates.
3646 		if( nPoolId && nSize>=1 && nSize <=6 )
3647 			nFontHeight =
3648 				pCSS1Parser->GetTxtCollFromPool(
3649 					RES_POOLCOLL_HEADLINE1+6-nSize )->GetSize().GetHeight();
3650 		else
3651 			nFontHeight = aFontHeights[nSize-1];
3652 	}
3653 
3654 	ASSERT( !nSize == !nFontHeight, "HTML-Font-Size != Font-Height" );
3655 
3656 	String aFontName, aStyleName;
3657 	FontFamily eFamily = FAMILY_DONTKNOW; // Family and Pitch,
3658 	FontPitch ePitch = PITCH_DONTKNOW; // in case it is not found
3659 	rtl_TextEncoding eEnc = gsl_getSystemTextEncoding();
3660 
3661 	if( aFace.Len() && !pCSS1Parser->IsIgnoreFontFamily() )
3662 	{
3663 		const FontList *pFList = 0;
3664 		SwDocShell *pDocSh = pDoc->GetDocShell();
3665 		if( pDocSh )
3666 		{
3667 			const SvxFontListItem *pFListItem =
3668 			   (const SvxFontListItem *)pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST);
3669 			if( pFListItem )
3670 				pFList = pFListItem->GetFontList();
3671 		}
3672 
3673 		sal_Bool bFound = sal_False;
3674 		xub_StrLen nStrPos = 0;
3675 		while( nStrPos!=STRING_NOTFOUND )
3676 		{
3677 			String aFName = aFace.GetToken( 0, ',', nStrPos );
3678 			aFName.EraseTrailingChars().EraseLeadingChars();
3679 			if( aFName.Len() )
3680 			{
3681 				if( !bFound && pFList )
3682 				{
3683 					sal_Handle hFont = pFList->GetFirstFontInfo( aFName );
3684 					if( 0 != hFont )
3685 					{
3686 						const FontInfo& rFInfo = pFList->GetFontInfo( hFont );
3687 						if( RTL_TEXTENCODING_DONTKNOW != rFInfo.GetCharSet() )
3688 						{
3689 							bFound = sal_True;
3690 							if( RTL_TEXTENCODING_SYMBOL == rFInfo.GetCharSet() )
3691 								eEnc = RTL_TEXTENCODING_SYMBOL;
3692 						}
3693 					}
3694 				}
3695 				if( aFontName.Len() )
3696 					aFontName += ';';
3697 				aFontName += aFName;
3698 			}
3699 		}
3700 	}
3701 
3702 
3703 	// set up a new context
3704     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3705 
3706 	// parse styles
3707 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3708 	{
3709 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3710 		SvxCSS1PropertyInfo aPropInfo;
3711 
3712 		if( nFontHeight )
3713 		{
3714             SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3715 			aItemSet.Put( aFontHeight );
3716 			aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3717 			aItemSet.Put( aFontHeight );
3718 			aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3719 			aItemSet.Put( aFontHeight );
3720 		}
3721 		if( bColor )
3722             aItemSet.Put( SvxColorItem(aColor, RES_CHRATR_COLOR) );
3723 		if( aFontName.Len() )
3724 		{
3725             SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3726 			aItemSet.Put( aFont );
3727 			aFont.SetWhich( RES_CHRATR_CJK_FONT );
3728 			aItemSet.Put( aFont );
3729 			aFont.SetWhich( RES_CHRATR_CTL_FONT );
3730 			aItemSet.Put( aFont );
3731 		}
3732 
3733 
3734 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3735 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3736 
3737 		InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
3738 	}
3739 	else
3740 	{
3741 		if( nFontHeight )
3742 		{
3743             SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3744 			InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3745 			aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3746 			InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3747 			aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3748 			InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3749 		}
3750 		if( bColor )
3751             InsertAttr( &aAttrTab.pFontColor, SvxColorItem(aColor, RES_CHRATR_COLOR), pCntxt );
3752 		if( aFontName.Len() )
3753 		{
3754             SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3755 			InsertAttr( &aAttrTab.pFont, aFont, pCntxt );
3756 			aFont.SetWhich( RES_CHRATR_CJK_FONT );
3757 			InsertAttr( &aAttrTab.pFontCJK, aFont, pCntxt );
3758 			aFont.SetWhich( RES_CHRATR_CTL_FONT );
3759 			InsertAttr( &aAttrTab.pFontCTL, aFont, pCntxt );
3760 		}
3761 	}
3762 
3763 	// memorize context
3764 	PushContext( pCntxt );
3765 
3766 	aFontStack.Insert( nSize, aFontStack.Count() );
3767 }
3768 
EndFontAttr(int nToken)3769 void SwHTMLParser::EndFontAttr( int nToken )
3770 {
3771 	EndTag( nToken );
3772 
3773 	// Avoid stack underflow in tables
3774 	if( aFontStack.Count() > nFontStMin )
3775 		aFontStack.Remove( aFontStack.Count()-1, 1 );
3776 }
3777 
3778 /*  */
3779 
NewPara()3780 void SwHTMLParser::NewPara()
3781 {
3782 	if( pPam->GetPoint()->nContent.GetIndex() )
3783 		AppendTxtNode( AM_SPACE );
3784 	else
3785 		AddParSpace();
3786 
3787 	eParaAdjust = SVX_ADJUST_END;
3788 	String aId, aStyle, aClass, aLang, aDir;
3789 
3790 	const HTMLOptions *pHTMLOptions = GetOptions();
3791 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3792 	{
3793 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3794 		switch( pOption->GetToken() )
3795 		{
3796 			case HTML_O_ID:
3797 				aId = pOption->GetString();
3798 				break;
3799 			case HTML_O_ALIGN:
3800                 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3801 				break;
3802 			case HTML_O_STYLE:
3803 				aStyle = pOption->GetString();
3804 				break;
3805 			case HTML_O_CLASS:
3806 				aClass = pOption->GetString();
3807 				break;
3808 			case HTML_O_LANG:
3809 				aLang = pOption->GetString();
3810 				break;
3811 			case HTML_O_DIR:
3812 				aDir = pOption->GetString();
3813 				break;
3814 		}
3815 	}
3816 
3817 	// set up a new context
3818 	_HTMLAttrContext *pCntxt =
3819 		aClass.Len() ? new _HTMLAttrContext( HTML_PARABREAK_ON,
3820 											 RES_POOLCOLL_TEXT, aClass )
3821 					 : new _HTMLAttrContext( HTML_PARABREAK_ON );
3822 
3823 	// parse styles (ignore Class. This only works as long as
3824 	// none of the CSS1 properties of the class need to be forcibly formatted!!!)
3825 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
3826 	{
3827 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3828 		SvxCSS1PropertyInfo aPropInfo;
3829 
3830 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
3831 		{
3832 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
3833 					"Class will not be considered" );
3834 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3835 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
3836 		}
3837 	}
3838 
3839 	if( SVX_ADJUST_END != eParaAdjust )
3840         InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
3841 
3842 	// push on stack
3843 	PushContext( pCntxt );
3844 
3845 	// set the current template or its attributes
3846 	SetTxtCollAttrs( aClass.Len() ? pCntxt : 0 );
3847 
3848 	// progress bar
3849 	ShowStatline();
3850 
3851 	ASSERT( !nOpenParaToken, "Now an open paragraph element is lost" );
3852 	nOpenParaToken = HTML_PARABREAK_ON;
3853 }
3854 
EndPara(sal_Bool bReal)3855 void SwHTMLParser::EndPara( sal_Bool bReal )
3856 {
3857 	if( HTML_LI_ON==nOpenParaToken && pTable )
3858 	{
3859 #ifdef DBG_UTIL
3860 		const SwNumRule *pNumRule = pPam->GetNode()->GetTxtNode()->GetNumRule();
3861 #endif
3862 		ASSERT( pNumRule, "Where has the Numrule gone" );
3863 	}
3864 
3865 	// empty paragraphs are skipped by Netscape, now also by us
3866 	if( bReal )
3867 	{
3868 		if( pPam->GetPoint()->nContent.GetIndex() )
3869 			AppendTxtNode( AM_SPACE );
3870 		else
3871 			AddParSpace();
3872 	}
3873 
3874 	// if a DD or DT was open, it is an
3875 	// implicit def list that must now be terminated.
3876 	if( (nOpenParaToken==HTML_DT_ON || nOpenParaToken==HTML_DD_ON) &&
3877 		nDefListDeep)
3878 	{
3879 		nDefListDeep--;
3880 	}
3881 
3882 	// get the context from the stack. It can also come from an implicitly
3883 	// open definition list.
3884 	_HTMLAttrContext *pCntxt =
3885         PopContext( static_cast< sal_uInt16 >(nOpenParaToken ? (nOpenParaToken & ~1)
3886                                    : HTML_PARABREAK_ON) );
3887 
3888 	// Attribute beenden
3889 	if( pCntxt )
3890 	{
3891 		EndContext( pCntxt );
3892 		SetAttr();	// set paragraph-atts as fast as possible because of JavaScript
3893 		delete pCntxt;
3894 	}
3895 
3896 	// and reset previous template
3897 	if( bReal )
3898 		SetTxtCollAttrs();
3899 
3900 	nOpenParaToken = 0;
3901 }
3902 
3903 
NewHeading(int nToken)3904 void SwHTMLParser::NewHeading( int nToken )
3905 {
3906 	eParaAdjust = SVX_ADJUST_END;
3907 
3908 	String aId, aStyle, aClass, aLang, aDir;
3909 
3910 	const HTMLOptions *pHTMLOptions = GetOptions();
3911 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
3912 	{
3913 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
3914 		switch( pOption->GetToken() )
3915 		{
3916 			case HTML_O_ID:
3917 				aId = pOption->GetString();
3918 				break;
3919 			case HTML_O_ALIGN:
3920                 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3921 				break;
3922 			case HTML_O_STYLE:
3923 				aStyle = pOption->GetString();
3924 				break;
3925 			case HTML_O_CLASS:
3926 				aClass = pOption->GetString();
3927 				break;
3928 			case HTML_O_LANG:
3929 				aLang = pOption->GetString();
3930 				break;
3931 			case HTML_O_DIR:
3932 				aDir = pOption->GetString();
3933 				break;
3934 		}
3935 	}
3936 
3937 	// create new paragraph
3938 	if( pPam->GetPoint()->nContent.GetIndex() )
3939 		AppendTxtNode( AM_SPACE );
3940 	else
3941 		AddParSpace();
3942 
3943 	// search matching template
3944 	sal_uInt16 nTxtColl;
3945 	switch( nToken )
3946 	{
3947 	case HTML_HEAD1_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE1;	break;
3948 	case HTML_HEAD2_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE2;	break;
3949 	case HTML_HEAD3_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE3;	break;
3950 	case HTML_HEAD4_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE4;	break;
3951 	case HTML_HEAD5_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE5;	break;
3952 	case HTML_HEAD6_ON: 		nTxtColl = RES_POOLCOLL_HEADLINE6;	break;
3953 	default:					nTxtColl = RES_POOLCOLL_STANDARD;	break;
3954 	}
3955 
3956 	// set context
3957     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nTxtColl, aClass );
3958 
3959 	// parse styles (to Class see NewPara)
3960 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
3961 	{
3962 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3963 		SvxCSS1PropertyInfo aPropInfo;
3964 
3965 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
3966 		{
3967 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
3968 					"Class will not be considered" );
3969 			DoPositioning( aItemSet, aPropInfo, pCntxt );
3970 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
3971 		}
3972 	}
3973 
3974 	if( SVX_ADJUST_END != eParaAdjust )
3975         InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
3976 
3977 	// push to Stack
3978 	PushContext( pCntxt );
3979 
3980 	// and set the template or its attributes
3981 	SetTxtCollAttrs( pCntxt );
3982 
3983 	nFontStHeadStart = aFontStack.Count();
3984 
3985 	// progress bar
3986 	ShowStatline();
3987 }
3988 
EndHeading()3989 void SwHTMLParser::EndHeading()
3990 {
3991     // create a new paragraph
3992 	if( pPam->GetPoint()->nContent.GetIndex() )
3993 		AppendTxtNode( AM_SPACE );
3994 	else
3995 		AddParSpace();
3996 
3997 	// get context of current token from stack
3998 	_HTMLAttrContext *pCntxt = 0;
3999 	sal_uInt16 nPos = aContexts.Count();
4000 	while( !pCntxt && nPos>nContextStMin )
4001 	{
4002 		switch( aContexts[--nPos]->GetToken() )
4003 		{
4004 		case HTML_HEAD1_ON:
4005 		case HTML_HEAD2_ON:
4006 		case HTML_HEAD3_ON:
4007 		case HTML_HEAD4_ON:
4008 		case HTML_HEAD5_ON:
4009 		case HTML_HEAD6_ON:
4010 			pCntxt = aContexts[nPos];
4011 			aContexts.Remove( nPos, 1 );
4012 			break;
4013 		}
4014 	}
4015 
4016 	// and set attributes end
4017 	if( pCntxt )
4018 	{
4019 		EndContext( pCntxt );
4020 		SetAttr();	// set paragraph-atts as fast as possible because of JavaScript
4021 		delete pCntxt;
4022 	}
4023 
4024 	// reset the previous template
4025 	SetTxtCollAttrs();
4026 
4027 	nFontStHeadStart = nFontStMin;
4028 }
4029 
4030 /*  */
4031 
NewTxtFmtColl(int nToken,sal_uInt16 nColl)4032 void SwHTMLParser::NewTxtFmtColl( int nToken, sal_uInt16 nColl )
4033 {
4034 	String aId, aStyle, aClass, aLang, aDir;
4035 
4036 	const HTMLOptions *pHTMLOptions = GetOptions();
4037 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4038 	{
4039 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4040 		switch( pOption->GetToken() )
4041 		{
4042 			case HTML_O_ID:
4043 				aId = pOption->GetString();
4044 				break;
4045 			case HTML_O_STYLE:
4046 				aStyle = pOption->GetString();
4047 				break;
4048 			case HTML_O_CLASS:
4049 				aClass = pOption->GetString();
4050 				break;
4051 			case HTML_O_LANG:
4052 				aLang = pOption->GetString();
4053 				break;
4054 			case HTML_O_DIR:
4055 				aDir = pOption->GetString();
4056 				break;
4057 		}
4058 	}
4059 
4060 	// create new paragraph
4061 	SwHTMLAppendMode eMode = AM_NORMAL;
4062 	switch( nToken )
4063 	{
4064 	case HTML_LISTING_ON:
4065 	case HTML_XMP_ON:
4066 		// These two tags are now mapped to the PRE template.
4067 		// In the case that a CLASS is specified, we delete
4068 		// it so we don't get the CLASS of the PRE template.
4069 		aClass = aEmptyStr;
4070 	case HTML_BLOCKQUOTE_ON:
4071 	case HTML_BLOCKQUOTE30_ON:
4072 	case HTML_PREFORMTXT_ON:
4073 		eMode = AM_SPACE;
4074 		break;
4075 	case HTML_ADDRESS_ON:
4076 		eMode = AM_NOSPACE;	// ADDRESS may follow a <P> without </P>.
4077 		break;
4078 	case HTML_DT_ON:
4079 	case HTML_DD_ON:
4080 		eMode = AM_SOFTNOSPACE;
4081 		break;
4082 	default:
4083 		ASSERT( sal_False, "unknown template" );
4084 		break;
4085 	}
4086 	if( pPam->GetPoint()->nContent.GetIndex() )
4087 		AppendTxtNode( eMode );
4088 	else if( AM_SPACE==eMode )
4089 		AddParSpace();
4090 
4091 	// ... and remember in a context
4092     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nColl, aClass );
4093 
4094 	// parse styles (to Class see NewPara)
4095 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4096 	{
4097 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4098 		SvxCSS1PropertyInfo aPropInfo;
4099 
4100 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4101 		{
4102 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4103 					"Class will not be considered" );
4104 			DoPositioning( aItemSet, aPropInfo, pCntxt );
4105 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
4106 		}
4107 	}
4108 
4109 	PushContext( pCntxt );
4110 
4111 	// set the new template
4112 	SetTxtCollAttrs( pCntxt );
4113 
4114 	// update progress bar
4115 	ShowStatline();
4116 }
4117 
EndTxtFmtColl(int nToken)4118 void SwHTMLParser::EndTxtFmtColl( int nToken )
4119 {
4120 	SwHTMLAppendMode eMode = AM_NORMAL;
4121 	switch( nToken & ~1 )
4122 	{
4123 	case HTML_BLOCKQUOTE_ON:
4124 	case HTML_BLOCKQUOTE30_ON:
4125 	case HTML_PREFORMTXT_ON:
4126 	case HTML_LISTING_ON:
4127 	case HTML_XMP_ON:
4128 		eMode = AM_SPACE;
4129 		break;
4130 	case HTML_ADDRESS_ON:
4131 	case HTML_DT_ON:
4132 	case HTML_DD_ON:
4133 		eMode = AM_SOFTNOSPACE;
4134 		break;
4135 	default:
4136 		ASSERT( sal_False, "unknown template" );
4137 		break;
4138 	}
4139 	if( pPam->GetPoint()->nContent.GetIndex() )
4140 		AppendTxtNode( eMode );
4141 	else if( AM_SPACE==eMode )
4142 		AddParSpace();
4143 
4144 	// get the current context from the stack
4145     _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
4146 
4147 	// and set end attribute
4148 	if( pCntxt )
4149 	{
4150 		EndContext( pCntxt );
4151 		SetAttr();	// set paragraph-atts as fast as possible because of JavaScript
4152 		delete pCntxt;
4153 	}
4154 
4155 	// and set the previous template
4156 	SetTxtCollAttrs();
4157 }
4158 
4159 /*  */
4160 
NewDefList()4161 void SwHTMLParser::NewDefList()
4162 {
4163 	String aId, aStyle, aClass, aLang, aDir;
4164 
4165 	const HTMLOptions *pHTMLOptions = GetOptions();
4166 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4167 	{
4168 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4169 		switch( pOption->GetToken() )
4170 		{
4171 			case HTML_O_ID:
4172 				aId = pOption->GetString();
4173 				break;
4174 			case HTML_O_STYLE:
4175 				aStyle = pOption->GetString();
4176 				break;
4177 			case HTML_O_CLASS:
4178 				aClass = pOption->GetString();
4179 				break;
4180 			case HTML_O_LANG:
4181 				aLang = pOption->GetString();
4182 				break;
4183 			case HTML_O_DIR:
4184 				aDir = pOption->GetString();
4185 				break;
4186 		}
4187 	}
4188 
4189 	// create new paragraph
4190 	sal_Bool bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 0;
4191 	if( pPam->GetPoint()->nContent.GetIndex() )
4192 		AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4193 	else if( bSpace )
4194 		AddParSpace();
4195 
4196 	// one more level
4197 	nDefListDeep++;
4198 
4199 
4200 	sal_Bool bInDD = sal_False, bNotInDD = sal_False;
4201 	sal_uInt16 nPos = aContexts.Count();
4202 	while( !bInDD && !bNotInDD && nPos>nContextStMin )
4203 	{
4204 		sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
4205 		switch( nCntxtToken )
4206 		{
4207 		case HTML_DEFLIST_ON:
4208 		case HTML_DIRLIST_ON:
4209 		case HTML_MENULIST_ON:
4210 		case HTML_ORDERLIST_ON:
4211 		case HTML_UNORDERLIST_ON:
4212 			bNotInDD = sal_True;
4213 			break;
4214 		case HTML_DD_ON:
4215 			bInDD = sal_True;
4216 			break;
4217 		}
4218 	}
4219 
4220 
4221 	// ... and remember in a context
4222 	_HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_DEFLIST_ON );
4223 
4224 	// remeber the borders, too
4225 	sal_uInt16 nLeft=0, nRight=0;
4226 	short nIndent=0;
4227 	GetMarginsFromContext( nLeft, nRight, nIndent );
4228 
4229 	// The indent, which already results from a DL-, corresponds to that
4230 	// of a DT on the current level, and that corresponds to that of a
4231 	// DD on the level before. So for a level >=2 a DD distance must be added
4232 	if( !bInDD && nDefListDeep > 1 )
4233 	{
4234 
4235 		// and that of the DT template of the current level
4236 		SvxLRSpaceItem rLRSpace =
4237 			pCSS1Parser->GetTxtFmtColl( RES_POOLCOLL_HTML_DD, aEmptyStr )
4238 					   ->GetLRSpace();
4239         nLeft = nLeft + static_cast< sal_uInt16 >(rLRSpace.GetTxtLeft());
4240 	}
4241 
4242 	pCntxt->SetMargins( nLeft, nRight, nIndent );
4243 
4244 	// parse styles
4245 	if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
4246 	{
4247 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4248 		SvxCSS1PropertyInfo aPropInfo;
4249 
4250 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
4251 		{
4252 			DoPositioning( aItemSet, aPropInfo, pCntxt );
4253 			InsertAttrs( aItemSet, aPropInfo, pCntxt );
4254 		}
4255 	}
4256 
4257 	PushContext( pCntxt );
4258 
4259 	// set the attributes of the new template
4260 	if( nDefListDeep > 1 )
4261 		SetTxtCollAttrs( pCntxt );
4262 }
4263 
EndDefList()4264 void SwHTMLParser::EndDefList()
4265 {
4266 	sal_Bool bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 1;
4267 	if( pPam->GetPoint()->nContent.GetIndex() )
4268 		AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4269 	else if( bSpace )
4270 		AddParSpace();
4271 
4272 	// reduce one level
4273 	if( nDefListDeep > 0 )
4274 		nDefListDeep--;
4275 
4276 	// get the current context from the stack
4277 	_HTMLAttrContext *pCntxt = PopContext( HTML_DEFLIST_ON );
4278 
4279 	// and set end Attribute
4280 	if( pCntxt )
4281 	{
4282 		EndContext( pCntxt );
4283 		SetAttr();	// set paragraph-atts as fast as possible because of JavaScript
4284 		delete pCntxt;
4285 	}
4286 
4287 	// and set Template
4288 	SetTxtCollAttrs();
4289 }
4290 
NewDefListItem(int nToken)4291 void SwHTMLParser::NewDefListItem( int nToken )
4292 {
4293 	// determine whether the DD/DT occurs in a DL
4294 	sal_Bool bInDefList = sal_False, bNotInDefList = sal_False;
4295 	sal_uInt16 nPos = aContexts.Count();
4296 	while( !bInDefList && !bNotInDefList && nPos>nContextStMin )
4297 	{
4298 		sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
4299 		switch( nCntxtToken )
4300 		{
4301 		case HTML_DEFLIST_ON:
4302 			bInDefList = sal_True;
4303 			break;
4304 		case HTML_DIRLIST_ON:
4305 		case HTML_MENULIST_ON:
4306 		case HTML_ORDERLIST_ON:
4307 		case HTML_UNORDERLIST_ON:
4308 			bNotInDefList = sal_True;
4309 			break;
4310 		}
4311 	}
4312 
4313 	// if not, implicitly open a new DL
4314 	if( !bInDefList )
4315 	{
4316 		nDefListDeep++;
4317 		ASSERT( !nOpenParaToken,
4318 				"Now an open paragraph element is lost" );
4319         nOpenParaToken = static_cast< sal_uInt16 >(nToken);
4320 	}
4321 
4322     NewTxtFmtColl( nToken, static_cast< sal_uInt16 >(nToken==HTML_DD_ON ? RES_POOLCOLL_HTML_DD
4323                                               : RES_POOLCOLL_HTML_DT) );
4324 }
4325 
EndDefListItem(int nToken,sal_Bool bSetColl,sal_Bool)4326 void SwHTMLParser::EndDefListItem( int nToken, sal_Bool bSetColl,
4327 								   sal_Bool /*bLastPara*/ )
4328 {
4329 	// create new paragraph
4330 	if( !nToken && pPam->GetPoint()->nContent.GetIndex() )
4331 		AppendTxtNode( AM_SOFTNOSPACE );
4332 
4333 	// Search context to the token and get it from the stack
4334 	nToken &= ~1;
4335 	_HTMLAttrContext *pCntxt = 0;
4336 	sal_uInt16 nPos = aContexts.Count();
4337 	while( !pCntxt && nPos>nContextStMin )
4338 	{
4339 		sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
4340 		switch( nCntxtToken )
4341 		{
4342 		case HTML_DD_ON:
4343 		case HTML_DT_ON:
4344 			if( !nToken || nToken == nCntxtToken  )
4345 			{
4346 				pCntxt = aContexts[nPos];
4347 				aContexts.Remove( nPos, 1 );
4348 			}
4349 			break;
4350 		case HTML_DEFLIST_ON:
4351 			// do not consider DD/DT outside the current def list
4352 		case HTML_DIRLIST_ON:
4353 		case HTML_MENULIST_ON:
4354 		case HTML_ORDERLIST_ON:
4355 		case HTML_UNORDERLIST_ON:
4356 			// and also not outside of another list
4357 			nPos = nContextStMin;
4358 			break;
4359 		}
4360 	}
4361 
4362 	// and set end Attribute
4363 	if( pCntxt )
4364 	{
4365 		EndContext( pCntxt );
4366 		SetAttr();	// set paragraph-atts as fast as possible because of JavaScript
4367 		delete pCntxt;
4368 	}
4369 
4370 	// and set the previous template
4371 	if( bSetColl )
4372 		SetTxtCollAttrs();
4373 }
4374 
4375 /*  */
4376 
HasCurrentParaFlys(sal_Bool bNoSurroundOnly,sal_Bool bSurroundOnly) const4377 sal_Bool SwHTMLParser::HasCurrentParaFlys( sal_Bool bNoSurroundOnly,
4378 									   sal_Bool bSurroundOnly ) const
4379 {
4380 	// bNoSurroundOnly: The paragraph contains at least one frame
4381 	//                  without text flow
4382 	// bSurroundOnly:   The paragraph contains at least one frame
4383 	//                  with a text flow but none without a text flow
4384 	// else:            the paragraph contains at least one frame
4385 	SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
4386 
4387 	const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
4388 
4389 	sal_Bool bFound = sal_False;
4390     for ( sal_uInt16 i=0; i<rFrmFmtTbl.Count(); i++ )
4391     {
4392         SwFrmFmt *const pFmt = rFrmFmtTbl[i];
4393         SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
4394 		// A frame has been found if
4395 		// - it is paragraph-bound, and
4396 		// - it is anchored in the current paragraph, and
4397 		//    - every paragraph-bound frame counts, or
4398 		//    - (only frames or text flow counts) the frame has no
4399 		//      text flow
4400         SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
4401         if (pAPos &&
4402             ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
4403              (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
4404 			pAPos->nNode == rNodeIdx )
4405 		{
4406 			if( !(bNoSurroundOnly || bSurroundOnly) )
4407 			{
4408 				bFound = sal_True;
4409 				break;
4410 			}
4411 			else
4412 			{
4413 				// fix #42282#: If frames with circulation are wanted,
4414 				// do not consider any with circulation either. These are
4415 				// are (still) HIDDEN controls, and it's better not to avoid them.
4416 				SwSurround eSurround = pFmt->GetSurround().GetSurround();
4417 				if( bNoSurroundOnly )
4418 				{
4419 					if( SURROUND_NONE==eSurround )
4420 					{
4421 						bFound = sal_True;
4422 						break;
4423 					}
4424 				}
4425 				if( bSurroundOnly )
4426 				{
4427 					if( SURROUND_NONE==eSurround )
4428 					{
4429 						bFound = sal_False;
4430 						break;
4431 					}
4432 					else if( SURROUND_THROUGHT!=eSurround )
4433 					{
4434 						bFound = sal_True;
4435 						// continue searching: There might still be some without
4436 						// circulation ...
4437 					}
4438 				}
4439 			}
4440 		}
4441 	}
4442 
4443 	return bFound;
4444 }
4445 
4446 /*  */
4447 
4448 // the special methods for inserting objects
4449 
GetCurrFmtColl() const4450 const SwFmtColl *SwHTMLParser::GetCurrFmtColl() const
4451 {
4452 	const SwCntntNode* pCNd = pPam->GetCntntNode();
4453 	return &pCNd->GetAnyFmtColl();
4454 }
4455 
4456 
SetTxtCollAttrs(_HTMLAttrContext * pContext)4457 void SwHTMLParser::SetTxtCollAttrs( _HTMLAttrContext *pContext )
4458 {
4459 	SwTxtFmtColl *pCollToSet = 0;	// the template to be set
4460 	SfxItemSet *pItemSet = 0;		// the set for hard attributes
4461 	sal_uInt16 nTopColl = pContext ? pContext->GetTxtFmtColl() : 0;
4462 	const String& rTopClass = pContext ? pContext->GetClass() : (const String&) aEmptyStr;
4463 	sal_uInt16 nDfltColl = RES_POOLCOLL_TEXT;
4464 
4465 	sal_Bool bInPRE=sal_False; // some context info
4466 
4467 	sal_uInt16 nLeftMargin = 0, nRightMargin = 0; // the margins and
4468 	short nFirstLineIndent = 0; // Indent
4469 	sal_uInt16 i;
4470 
4471 	for( i = nContextStAttrMin; i < aContexts.Count(); i++ )
4472 	{
4473 		const _HTMLAttrContext *pCntxt = aContexts[i];
4474 
4475 		sal_uInt16 nColl = pCntxt->GetTxtFmtColl();
4476 		if( nColl )
4477 		{
4478 			// There is a template to be set. Then
4479 			// a decision has to be made first,
4480 			// whether the template can also be set
4481 			sal_Bool bSetThis = sal_True;
4482 			switch( nColl )
4483 			{
4484 			case sal_uInt16(RES_POOLCOLL_HTML_PRE):
4485 				bInPRE = sal_True;
4486 				break;
4487 			case sal_uInt16(RES_POOLCOLL_TEXT):
4488 				// <TD><P CLASS=xxx> must become TD.xxx
4489 				if( nDfltColl==RES_POOLCOLL_TABLE ||
4490 					nDfltColl==RES_POOLCOLL_TABLE_HDLN )
4491 					nColl = nDfltColl;
4492 				break;
4493 			case sal_uInt16(RES_POOLCOLL_HTML_HR):
4494 				// <HR> also set in <PRE> as template, otherwise you can't
4495 				// no longer export
4496 				break;
4497 			default:
4498 				if( bInPRE )
4499 					bSetThis = sal_False;
4500 				break;
4501 			}
4502 
4503 			SwTxtFmtColl *pNewColl =
4504 				pCSS1Parser->GetTxtFmtColl( nColl, pCntxt->GetClass() );
4505 
4506 			if( bSetThis )
4507 			{
4508 				// if now another template should be set than
4509 				// previously, the previous template must be replaced by hard attributes
4510 				if( pCollToSet )
4511 				{
4512 					// Force the attributes set by the previous template
4513 					if( !pItemSet )
4514 						pItemSet = new SfxItemSet( pCollToSet->GetAttrSet() );
4515 					else
4516 					{
4517 						const SfxItemSet& rCollSet = pCollToSet->GetAttrSet();
4518 						SfxItemSet aItemSet( *rCollSet.GetPool(),
4519 											 rCollSet.GetRanges() );
4520 						aItemSet.Set( rCollSet );
4521 						pItemSet->Put( aItemSet );
4522 					}
4523 					// but remove the attributes that the current template sets
4524 					// because otherwise they will be overwritten later.
4525 					pItemSet->Differentiate( pNewColl->GetAttrSet() );
4526 				}
4527 
4528 				pCollToSet = pNewColl;
4529 			}
4530 			else
4531 			{
4532 				// Force attributes
4533 				if( !pItemSet )
4534 					pItemSet = new SfxItemSet( pNewColl->GetAttrSet() );
4535 				else
4536 				{
4537 					const SfxItemSet& rCollSet = pNewColl->GetAttrSet();
4538 					SfxItemSet aItemSet( *rCollSet.GetPool(),
4539 										 rCollSet.GetRanges() );
4540 					aItemSet.Set( rCollSet );
4541 					pItemSet->Put( aItemSet );
4542 				}
4543 			}
4544 		}
4545 		else
4546 		{
4547 			// Maybe there is a default template?
4548 			nColl = pCntxt->GetDfltTxtFmtColl();
4549 			if( nColl )
4550 				nDfltColl = nColl;
4551 		}
4552 
4553 		// get new paragraph inserts if necessary
4554 		if( pCntxt->IsLRSpaceChanged() )
4555 		{
4556 			sal_uInt16 nLeft=0, nRight=0;
4557 
4558 			pCntxt->GetMargins( nLeft, nRight, nFirstLineIndent );
4559 			nLeftMargin = nLeft;
4560 			nRightMargin = nRight;
4561 		}
4562 	}
4563 
4564 	// if a new template is to be set in the current context,
4565 	// its paragraph spacing must still be entered into the context.
4566 	if( pContext && nTopColl )
4567 	{
4568 	    // <TD><P CLASS=xxx> must become TD.xxx
4569 		if( nTopColl==RES_POOLCOLL_TEXT &&
4570 			(nDfltColl==RES_POOLCOLL_TABLE ||
4571 			 nDfltColl==RES_POOLCOLL_TABLE_HDLN) )
4572 			nTopColl = nDfltColl;
4573 
4574 		const SwTxtFmtColl *pTopColl =
4575 			pCSS1Parser->GetTxtFmtColl( nTopColl, rTopClass );
4576 		const SfxItemSet& rItemSet = pTopColl->GetAttrSet();
4577 		const SfxPoolItem *pItem;
4578 		if( SFX_ITEM_SET == rItemSet.GetItemState(RES_LR_SPACE,sal_True, &pItem) )
4579 		{
4580 			const SvxLRSpaceItem *pLRItem =
4581 				(const SvxLRSpaceItem *)pItem;
4582 
4583 			sal_Int32 nLeft = pLRItem->GetTxtLeft();
4584 			sal_Int32 nRight = pLRItem->GetRight();
4585 			nFirstLineIndent = pLRItem->GetTxtFirstLineOfst();
4586 
4587 			// In definition lists, the distances also include those of the
4588 			// previous level
4589 			if( RES_POOLCOLL_HTML_DD == nTopColl )
4590 			{
4591 				const SvxLRSpaceItem& rDTLRSpace = pCSS1Parser
4592 					->GetTxtFmtColl( RES_POOLCOLL_HTML_DT, aEmptyStr )
4593 					->GetLRSpace();
4594 				nLeft -= rDTLRSpace.GetTxtLeft();
4595 				nRight -= rDTLRSpace.GetRight();
4596 			}
4597 			else if( RES_POOLCOLL_HTML_DT == nTopColl )
4598 			{
4599 				nLeft = 0;
4600 				nRight = 0;
4601 			}
4602 
4603 			// the paragraph distances add up
4604             nLeftMargin = nLeftMargin + static_cast< sal_uInt16 >(nLeft);
4605             nRightMargin = nRightMargin + static_cast< sal_uInt16 >(nRight);
4606 
4607 			pContext->SetMargins( nLeftMargin, nRightMargin,
4608 								  nFirstLineIndent );
4609 		}
4610 		if( SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,sal_True, &pItem) )
4611 		{
4612 			const SvxULSpaceItem *pULItem =
4613 				(const SvxULSpaceItem *)pItem;
4614 			pContext->SetULSpace( pULItem->GetUpper(), pULItem->GetLower() );
4615 		}
4616 	}
4617 
4618 	// if no template is set in context, take text body
4619 	if( !pCollToSet )
4620 	{
4621 		pCollToSet = pCSS1Parser->GetTxtCollFromPool( nDfltColl );
4622 		const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4623 		if( !nLeftMargin )
4624             nLeftMargin = static_cast< sal_uInt16 >(rLRItem.GetTxtLeft());
4625 		if( !nRightMargin )
4626             nRightMargin = static_cast< sal_uInt16 >(rLRItem.GetRight());
4627 		if( !nFirstLineIndent )
4628 			nFirstLineIndent = rLRItem.GetTxtFirstLineOfst();
4629 	}
4630 
4631 	// remove previous hard attribution of the paragraph
4632 	if( aParaAttrs.Count() )
4633 	{
4634 		for( i=0; i<aParaAttrs.Count(); i++ )
4635 			aParaAttrs[i]->Invalidate();
4636 
4637 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
4638 	}
4639 
4640 	// Set the template
4641 	pDoc->SetTxtFmtColl( *pPam, pCollToSet );
4642 
4643 	// correct the paragraph indentation if necessary
4644 	const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4645 	sal_Bool bSetLRSpace;
4646 
4647        	bSetLRSpace = nLeftMargin != rLRItem.GetTxtLeft() ||
4648 					  nFirstLineIndent != rLRItem.GetTxtFirstLineOfst() ||
4649 					  nRightMargin != rLRItem.GetRight();
4650 
4651 	if( bSetLRSpace )
4652 	{
4653 		SvxLRSpaceItem aLRItem( rLRItem );
4654 		aLRItem.SetTxtLeft( nLeftMargin );
4655 		aLRItem.SetRight( nRightMargin );
4656 		aLRItem.SetTxtFirstLineOfst( nFirstLineIndent );
4657 		if( pItemSet )
4658 			pItemSet->Put( aLRItem );
4659 		else
4660 		{
4661 			NewAttr( &aAttrTab.pLRSpace, aLRItem );
4662 			aAttrTab.pLRSpace->SetLikePara();
4663 			aParaAttrs.Insert( aAttrTab.pLRSpace, aParaAttrs.Count() );
4664 			EndAttr( aAttrTab.pLRSpace, 0, sal_False );
4665 		}
4666 	}
4667 
4668 	// and now set the attributes
4669 	if( pItemSet )
4670 	{
4671 		InsertParaAttrs( *pItemSet );
4672 		delete pItemSet;
4673 	}
4674 }
4675 
4676 /*  */
4677 
NewCharFmt(int nToken)4678 void SwHTMLParser::NewCharFmt( int nToken )
4679 {
4680 	String aId, aStyle, aClass, aLang, aDir;
4681 
4682 	const HTMLOptions *pHTMLOptions = GetOptions();
4683 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4684 	{
4685 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4686 		switch( pOption->GetToken() )
4687 		{
4688 		case HTML_O_ID:
4689 			aId = pOption->GetString();
4690 			break;
4691 		case HTML_O_STYLE:
4692 			aStyle = pOption->GetString();
4693 			break;
4694 		case HTML_O_CLASS:
4695 			aClass = pOption->GetString();
4696 			break;
4697 		case HTML_O_LANG:
4698 			aLang = pOption->GetString();
4699 			break;
4700 		case HTML_O_DIR:
4701 			aDir = pOption->GetString();
4702 			break;
4703 		}
4704 	}
4705 
4706 	// set up a new context
4707     _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
4708 
4709 	// Set the template and store it in the context
4710     SwCharFmt* pCFmt = pCSS1Parser->GetChrFmt( static_cast< sal_uInt16 >(nToken), aClass );
4711 	ASSERT( pCFmt, "no character template found for token" );
4712 
4713 
4714 	// parse styles (to Class see NewPara)
4715 	if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4716 	{
4717 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4718 		SvxCSS1PropertyInfo aPropInfo;
4719 
4720 		if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4721 		{
4722 			ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4723 					"Class wird nicht beruecksichtigt" );
4724 			DoPositioning( aItemSet, aPropInfo, pCntxt );
4725 			InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
4726 		}
4727 	}
4728 
4729 	// Character templates are kept in their own stack and
4730 	// can never be inserted by styles. The attribute is therefore
4731 	// not included in the CSS1 Which range at all.
4732 	if( pCFmt )
4733 		InsertAttr( &aAttrTab.pCharFmts, SwFmtCharFmt( pCFmt ), pCntxt );
4734 
4735 	// memorize context
4736 	PushContext( pCntxt );
4737 }
4738 
4739 
4740 /*  */
4741 
InsertSpacer()4742 void SwHTMLParser::InsertSpacer()
4743 {
4744 	// and change it by the options if necessary
4745 	String aId;
4746     sal_Int16 eVertOri = text::VertOrientation::TOP;
4747     sal_Int16 eHoriOri = text::HoriOrientation::NONE;
4748 	Size aSize( 0, 0);
4749 	long nSize = 0;
4750 	sal_Bool bPrcWidth = sal_False;
4751 	sal_Bool bPrcHeight = sal_False;
4752 	sal_uInt16 nType = HTML_SPTYPE_HORI;
4753 
4754 	const HTMLOptions *pHTMLOptions = GetOptions();
4755 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4756 	{
4757 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4758 		switch( pOption->GetToken() )
4759 		{
4760 		case HTML_O_ID:
4761 			aId = pOption->GetString();
4762 			break;
4763 		case HTML_O_TYPE:
4764 			pOption->GetEnum( nType, aHTMLSpacerTypeTable );
4765 			break;
4766 		case HTML_O_ALIGN:
4767 			eVertOri =
4768                 pOption->GetEnum( aHTMLImgVAlignTable,
4769                                   eVertOri );
4770 			eHoriOri =
4771                 pOption->GetEnum( aHTMLImgHAlignTable,
4772                                   eHoriOri );
4773 			break;
4774 		case HTML_O_WIDTH:
4775 			// remember only as pixel values for now!
4776 			bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4777 			aSize.Width() = (long)pOption->GetNumber();
4778 			break;
4779 		case HTML_O_HEIGHT:
4780 			// remember only as pixel values for now!
4781 			bPrcHeight = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4782 			aSize.Height() = (long)pOption->GetNumber();
4783 			break;
4784 		case HTML_O_SIZE:
4785 			// remember only as pixel values for now!
4786 			nSize = pOption->GetNumber();
4787 			break;
4788 		}
4789 	}
4790 
4791 	switch( nType )
4792 	{
4793 	case HTML_SPTYPE_BLOCK:
4794 		{
4795 			// create an empty text frame
4796 
4797 			// get the itemset
4798 			SfxItemSet aFrmSet( pDoc->GetAttrPool(),
4799 								RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
4800 			if( !IsNewDoc() )
4801 				Reader::ResetFrmFmtAttrs( aFrmSet );
4802 
4803 			// set the anchor and the alignment
4804 			SetAnchorAndAdjustment( eVertOri, eHoriOri, aFrmSet );
4805 
4806 			// also the size of the frame
4807 			Size aDfltSz( MINFLY, MINFLY );
4808 			Size aSpace( 0, 0 );
4809 			SfxItemSet aDummyItemSet( pDoc->GetAttrPool(),
4810 								 pCSS1Parser->GetWhichMap() );
4811 			SvxCSS1PropertyInfo aDummyPropInfo;
4812 
4813 			SetFixSize( aSize, aDfltSz, bPrcWidth, bPrcHeight,
4814 						aDummyItemSet, aDummyPropInfo, aFrmSet );
4815 			SetSpace( aSpace, aDummyItemSet, aDummyPropInfo, aFrmSet );
4816 
4817 			// protect the content
4818             SvxProtectItem aProtectItem( RES_PROTECT) ;
4819 			aProtectItem.SetCntntProtect( sal_True );
4820 			aFrmSet.Put( aProtectItem );
4821 
4822 			// create the frame
4823 			RndStdIds eAnchorId =
4824 				((const SwFmtAnchor &)aFrmSet.Get(RES_ANCHOR)).GetAnchorId();
4825 			SwFrmFmt *pFlyFmt = pDoc->MakeFlySection( eAnchorId,
4826 											pPam->GetPoint(), &aFrmSet );
4827 			// If necessary, create frames and register auto-generated frames
4828 			RegisterFlyFrm( pFlyFmt );
4829 		}
4830 		break;
4831 	case HTML_SPTYPE_VERT:
4832 		if( nSize > 0 )
4833 		{
4834 			if( nSize && Application::GetDefaultDevice() )
4835 			{
4836 				nSize = Application::GetDefaultDevice()
4837 							->PixelToLogic( Size(0,nSize),
4838 											MapMode(MAP_TWIP) ).Height();
4839 			}
4840 
4841 			// set a paragraph spacing
4842 			SwTxtNode *pTxtNode = 0;
4843 			if( !pPam->GetPoint()->nContent.GetIndex() )
4844 			{
4845 				// change the lower paragraph spacing of the previous node,
4846 				// if possible
4847 
4848 				SetAttr();	// Set more open paragraph attributes
4849 
4850 				pTxtNode = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()-1]
4851 							   ->GetTxtNode();
4852 
4853 				// If the paragraph in front of it is not a txttenode, then now
4854 				// an empty paragraph is created which already creates a line height
4855 				// spacing
4856 				if( !pTxtNode )
4857 					nSize = nSize>HTML_PARSPACE ? nSize-HTML_PARSPACE : 0;
4858 			}
4859 
4860 			if( pTxtNode )
4861 			{
4862 				SvxULSpaceItem aULSpace( (const SvxULSpaceItem&)pTxtNode
4863 					->SwCntntNode::GetAttr( RES_UL_SPACE ) );
4864 				aULSpace.SetLower( aULSpace.GetLower() + (sal_uInt16)nSize );
4865                 pTxtNode->SetAttr( aULSpace );
4866 			}
4867 			else
4868 			{
4869                 NewAttr( &aAttrTab.pULSpace, SvxULSpaceItem( 0, (sal_uInt16)nSize, RES_UL_SPACE ) );
4870 				EndAttr( aAttrTab.pULSpace, 0, sal_False );
4871 
4872 				AppendTxtNode();	// do not change the distance!
4873 			}
4874 		}
4875 		break;
4876 	case HTML_SPTYPE_HORI:
4877 		if( nSize > 0 )
4878 		{
4879 			// if the paragraph is still empty, set a first-line indentation
4880 			// but span blocking font over a space.
4881 
4882 			if( nSize && Application::GetDefaultDevice() )
4883 			{
4884 				nSize = Application::GetDefaultDevice()
4885 							->PixelToLogic( Size(nSize,0),
4886 											MapMode(MAP_TWIP) ).Width();
4887 			}
4888 
4889 			if( !pPam->GetPoint()->nContent.GetIndex() )
4890 			{
4891 				sal_uInt16 nLeft=0, nRight=0;
4892 				short nIndent = 0;
4893 
4894 				GetMarginsFromContextWithNumBul( nLeft, nRight, nIndent );
4895                 nIndent = nIndent + (short)nSize;
4896 
4897                 SvxLRSpaceItem aLRItem( RES_LR_SPACE );
4898 				aLRItem.SetTxtLeft( nLeft );
4899 				aLRItem.SetRight( nRight );
4900 				aLRItem.SetTxtFirstLineOfst( nIndent );
4901 
4902 				NewAttr( &aAttrTab.pLRSpace, aLRItem );
4903 				EndAttr( aAttrTab.pLRSpace, 0, sal_False );
4904 			}
4905 			else
4906 			{
4907                 NewAttr( &aAttrTab.pKerning, SvxKerningItem( (short)nSize, RES_CHRATR_KERNING ) );
4908 				String aTmp( ' ' );
4909                 pDoc->InsertString( *pPam, aTmp );
4910 				EndAttr( aAttrTab.pKerning );
4911 			}
4912 		}
4913 	}
4914 }
4915 
ToTwips(sal_uInt16 nPixel) const4916 sal_uInt16 SwHTMLParser::ToTwips( sal_uInt16 nPixel ) const
4917 {
4918 	if( nPixel && Application::GetDefaultDevice() )
4919 	{
4920 		long nTwips = Application::GetDefaultDevice()->PixelToLogic(
4921 					Size( nPixel, nPixel ), MapMode( MAP_TWIP ) ).Width();
4922 		return nTwips <= USHRT_MAX ? (sal_uInt16)nTwips : USHRT_MAX;
4923 	}
4924 	else
4925 		return nPixel;
4926 }
4927 
GetCurrentBrowseWidth()4928 SwTwips SwHTMLParser::GetCurrentBrowseWidth()
4929 {
4930     const SwTwips nWidth = SwHTMLTableLayout::GetBrowseWidth( *pDoc );
4931 	if( nWidth )
4932 		return nWidth;
4933 
4934 	if( !aHTMLPageSize.Width() )
4935 	{
4936 		const SwFrmFmt& rPgFmt = pCSS1Parser->GetMasterPageDesc()->GetMaster();
4937 
4938 		const SwFmtFrmSize& rSz   = rPgFmt.GetFrmSize();
4939 		const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace();
4940 		const SvxULSpaceItem& rUL = rPgFmt.GetULSpace();
4941 		const SwFmtCol& rCol = rPgFmt.GetCol();
4942 
4943 		aHTMLPageSize.Width() = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight();
4944 		aHTMLPageSize.Height() = rSz.GetHeight() - rUL.GetUpper() - rUL.GetLower();
4945 
4946 		if( 1 < rCol.GetNumCols() )
4947 			aHTMLPageSize.Width() /= rCol.GetNumCols();
4948 	}
4949 
4950 	return aHTMLPageSize.Width();
4951 }
4952 
4953 
4954 /*  */
4955 
InsertIDOption()4956 void SwHTMLParser::InsertIDOption()
4957 {
4958 	String aId;
4959 	const HTMLOptions *pHTMLOptions = GetOptions();
4960 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
4961 	{
4962 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
4963 		if( HTML_O_ID==pOption->GetToken() )
4964 		{
4965 			aId = pOption->GetString();
4966 			break;
4967 		}
4968 	}
4969 
4970 	if( aId.Len() )
4971 		InsertBookmark( aId );
4972 }
4973 
4974 
4975 /*  */
4976 
4977 
InsertLineBreak()4978 void SwHTMLParser::InsertLineBreak()
4979 {
4980 	// <BR CLEAR=xxx> is handled as follows:
4981 	// 1.) Only paragraph-bound frames are considered, which are
4982 	//     are anchored in the current paragraph.
4983 	// 2.) For left-aligned frames at CLEAR=LEFT
4984 	//     or ALL and for right oriented frames with
4985 	//     CLEAR=RIGHT or ALL the pass is changed as follows:
4986 	// 3.) If the paragraph contains no text, the frame gets no
4987 	//     text flow
4988 	// 4.) otherwise a left aligned frame receives a right
4989 	//     "anchor only" text flow and right aligned frame receives a
4990 	//      left "anchor only" text flow.
4991 	// 5.) if in a non-empty paragraph the text flow of a frame
4992 	//     is changed, a new paragraph is opened
4993 	// 6.) If the text flow is not changed by any frame, a
4994 	//     hard line break is inserted
4995 
4996 	String aId, aStyle, aClass;			  	// the ID of the bookmark
4997 	sal_Bool bClearLeft = sal_False, bClearRight = sal_False;
4998 	sal_Bool bCleared = sal_False;	// was a CLEAR executed?
4999 
5000 	// then get the options
5001 	const HTMLOptions *pHTMLOptions = GetOptions();
5002 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
5003 	{
5004 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
5005 		switch( pOption->GetToken() )
5006 		{
5007 			case HTML_O_CLEAR:
5008 				{
5009 					const String &aClear = pOption->GetString();
5010 					if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_all ) )
5011 					{
5012 						bClearLeft = sal_True;
5013 						bClearRight = sal_True;
5014 					}
5015 					else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) )
5016 						bClearLeft = sal_True;
5017 					else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) )
5018 						bClearRight = sal_True;
5019 				}
5020 				break;
5021 			case HTML_O_ID:
5022 				aId = pOption->GetString();
5023 				break;
5024 			case HTML_O_STYLE:
5025 				aStyle = pOption->GetString();
5026 				break;
5027 			case HTML_O_CLASS:
5028 				aClass = pOption->GetString();
5029 				break;
5030 		}
5031 	}
5032 
5033 	// CLEAR is supported only for the current paragraph
5034 	if( bClearLeft || bClearRight )
5035 	{
5036 		SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
5037 		SwTxtNode* pTxtNd = rNodeIdx.GetNode().GetTxtNode();
5038 		if( pTxtNd )
5039 		{
5040 			const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
5041 
5042 			for( sal_uInt16 i=0; i<rFrmFmtTbl.Count(); i++ )
5043 			{
5044                 SwFrmFmt *const pFmt = rFrmFmtTbl[i];
5045                 SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
5046                 SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
5047                 if (pAPos &&
5048                     ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
5049                      (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
5050 					pAPos->nNode == rNodeIdx &&
5051 					pFmt->GetSurround().GetSurround() != SURROUND_NONE )
5052 				{
5053                     sal_Int16 eHori = RES_DRAWFRMFMT == pFmt->Which()
5054                         ? text::HoriOrientation::LEFT
5055 						: pFmt->GetHoriOrient().GetHoriOrient();
5056 
5057 					SwSurround eSurround = SURROUND_PARALLEL;
5058 					if( pPam->GetPoint()->nContent.GetIndex() )
5059 					{
5060                         if( bClearLeft && text::HoriOrientation::LEFT==eHori )
5061 							eSurround = SURROUND_RIGHT;
5062                         else if( bClearRight && text::HoriOrientation::RIGHT==eHori )
5063 							eSurround = SURROUND_LEFT;
5064 					}
5065                     else if( (bClearLeft && text::HoriOrientation::LEFT==eHori) ||
5066                              (bClearRight && text::HoriOrientation::RIGHT==eHori) )
5067 					{
5068 						eSurround = SURROUND_NONE;
5069 					}
5070 
5071 					if( SURROUND_PARALLEL != eSurround )
5072 					{
5073 						SwFmtSurround aSurround( eSurround );
5074 						if( SURROUND_NONE != eSurround )
5075 							aSurround.SetAnchorOnly( sal_True );
5076                         pFmt->SetFmtAttr( aSurround );
5077 						bCleared = sal_True;
5078 					}
5079 				} // Anchor is not in the node
5080 			} // Loop over fly frames
5081 		} // no text node
5082 	} // no CLEAR
5083 
5084 	// parse styles
5085     SvxFmtBreakItem aBreakItem( SVX_BREAK_NONE, RES_BREAK );
5086 	sal_Bool bBreakItem = sal_False;
5087 	if( HasStyleOptions( aStyle, aId, aClass ) )
5088 	{
5089 		SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
5090 		SvxCSS1PropertyInfo aPropInfo;
5091 
5092 		if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) )
5093 		{
5094 			if( pCSS1Parser->SetFmtBreak( aItemSet, aPropInfo ) )
5095 			{
5096 				aBreakItem = (const SvxFmtBreakItem &)aItemSet.Get( RES_BREAK );
5097 				bBreakItem = sal_True;
5098 			}
5099 			if( aPropInfo.aId.Len() )
5100 				InsertBookmark( aPropInfo.aId );
5101 		}
5102 	}
5103 
5104 	if( bBreakItem && SVX_BREAK_PAGE_AFTER==aBreakItem.GetBreak() )
5105 	{
5106 		NewAttr( &aAttrTab.pBreak, aBreakItem );
5107 		EndAttr( aAttrTab.pBreak, 0, sal_False );
5108 	}
5109 
5110 	if( !bCleared && !bBreakItem )
5111 	{
5112 		// if no CLEAR should be executed or could be executed
5113 		// a line break is inserted
5114 		String sTmp( (sal_Unicode)0x0a );	// make the Mac happy :-)
5115         pDoc->InsertString( *pPam, sTmp );
5116 	}
5117 	else if( pPam->GetPoint()->nContent.GetIndex() )
5118 	{
5119 		// if a claer was executed in a non-empty paragraph,
5120 		// a new paragraph must be opened afterwards.
5121 		// MIB 21.02.97: Actually, the lower paragraph should be set to 0.
5122 		// But this works with something like <BR ..><P>.
5123 		// (>Netacpe). Therefore we leave it for now.
5124 		AppendTxtNode( AM_NOSPACE );
5125 	}
5126 	if( bBreakItem && SVX_BREAK_PAGE_BEFORE==aBreakItem.GetBreak() )
5127 	{
5128 		NewAttr( &aAttrTab.pBreak, aBreakItem );
5129 		EndAttr( aAttrTab.pBreak, 0, sal_False );
5130 	}
5131 }
5132 
InsertHorzRule()5133 void SwHTMLParser::InsertHorzRule()
5134 {
5135 	sal_uInt16 nSize = 0;
5136 	sal_uInt16 nWidth = 0;
5137 
5138 	SvxAdjust eAdjust = SVX_ADJUST_END;
5139 
5140 	sal_Bool bPrcWidth = sal_False;
5141 	sal_Bool bNoShade = sal_False;
5142 	sal_Bool bColor = sal_False;
5143 
5144 	Color aColor;
5145 	String aId;
5146 
5147 	// get the options
5148 	const HTMLOptions *pHTMLOptions = GetOptions();
5149 	for( sal_uInt16 i = pHTMLOptions->Count(); i; )
5150 	{
5151 		const HTMLOption *pOption = (*pHTMLOptions)[--i];
5152 		switch( pOption->GetToken() )
5153 		{
5154 		case HTML_O_ID:
5155 			aId = pOption->GetString();
5156 			break;
5157 		case HTML_O_SIZE:
5158 			nSize = (sal_uInt16)pOption->GetNumber();
5159 			break;
5160 		case HTML_O_WIDTH:
5161 			bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
5162 			nWidth = (sal_uInt16)pOption->GetNumber();
5163 			if( bPrcWidth && nWidth>=100 )
5164 			{
5165 				// 100% lines are the default case (no attrs needed)
5166 				nWidth = 0;
5167 				bPrcWidth = sal_False;
5168 			}
5169 			break;
5170 		case HTML_O_ALIGN:
5171 			eAdjust =
5172                 (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eAdjust) );
5173 			break;
5174 		case HTML_O_NOSHADE:
5175 			bNoShade = sal_True;
5176 			break;
5177 		case HTML_O_COLOR:
5178 			pOption->GetColor( aColor );
5179 			bColor = sal_True;
5180 			break;
5181 		}
5182 	}
5183 
5184 	if( pPam->GetPoint()->nContent.GetIndex() )
5185 		AppendTxtNode( AM_NOSPACE );
5186 	if( nOpenParaToken )
5187 		EndPara();
5188 	AppendTxtNode();
5189 	pPam->Move( fnMoveBackward );
5190 
5191 	// ... and remember in a context
5192 	_HTMLAttrContext *pCntxt =
5193 		new _HTMLAttrContext( HTML_HORZRULE, RES_POOLCOLL_HTML_HR, aEmptyStr );
5194 
5195 	PushContext( pCntxt );
5196 
5197 	// set the new template
5198 	SetTxtCollAttrs( pCntxt );
5199 
5200 	// the hard attributes on this paragraph will never be invalid again
5201 	if( aParaAttrs.Count() )
5202 		aParaAttrs.Remove( 0, aParaAttrs.Count() );
5203 
5204 	if( nSize>0 || bColor || bNoShade )
5205 	{
5206 		// Set color and/or width of the line
5207 		if( !bColor )
5208 			aColor.SetColor( COL_GRAY );
5209 
5210 		SvxBorderLine aBorderLine( &aColor );
5211 		if( nSize )
5212 		{
5213 			long nPWidth = 0;
5214 			long nPHeight = (long)nSize;
5215 			SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
5216 			SvxCSS1Parser::SetBorderWidth( aBorderLine, (sal_uInt16)nPHeight,
5217 										   !bNoShade );
5218 		}
5219 		else if( bNoShade )
5220 		{
5221 			aBorderLine.SetOutWidth( DEF_LINE_WIDTH_2 );
5222 		}
5223 		else
5224 		{
5225 			aBorderLine.SetOutWidth( DEF_DOUBLE_LINE0_OUT );
5226 			aBorderLine.SetInWidth( DEF_DOUBLE_LINE0_IN );
5227 			aBorderLine.SetDistance( DEF_DOUBLE_LINE0_DIST );
5228 		}
5229 
5230         SvxBoxItem aBoxItem(RES_BOX);
5231 		aBoxItem.SetLine( &aBorderLine, BOX_LINE_BOTTOM );
5232 		_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aBoxItem );
5233 		aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5234 	}
5235 	if( nWidth )
5236 	{
5237 		// If we are not in a table, the width specification will be "killed" by
5238 		// paragraph indents. In a table this makes little
5239 		// sense. To avoid that the line is taken into account in the width calculation
5240 		// width calculation, it will still be assigned the appropriate
5241 		// LRSpace item to the line.
5242 #ifdef FIX41370
5243 		const SwFmtColl *pColl = GetCurrFmtColl();
5244 		SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5245 #endif
5246 		if( !pTable )
5247 		{
5248 			// "Tune" the length and alignment of the line using paragraph indents
5249 			long nBrowseWidth = GetCurrentBrowseWidth();
5250 			nWidth = bPrcWidth ? (sal_uInt16)((nWidth*nBrowseWidth) / 100)
5251 							   : ToTwips( (sal_uInt16)nBrowseWidth );
5252 			if( nWidth < MINLAY )
5253 				nWidth = MINLAY;
5254 
5255 			if( (long)nWidth < nBrowseWidth )
5256 			{
5257 #ifndef FIX41370
5258 				const SwFmtColl *pColl = GetCurrFmtColl();
5259 				SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5260 #endif
5261 				long nDist = nBrowseWidth - nWidth;
5262 
5263 				switch( eAdjust )
5264 				{
5265 				case SVX_ADJUST_RIGHT:
5266 					aLRItem.SetTxtLeft( (sal_uInt16)nDist );
5267 					break;
5268 				case SVX_ADJUST_LEFT:
5269 					aLRItem.SetRight( (sal_uInt16)nDist );
5270 					break;
5271 				case SVX_ADJUST_CENTER:
5272 				default:
5273 					nDist /= 2;
5274 					aLRItem.SetTxtLeft( (sal_uInt16)nDist );
5275 					aLRItem.SetRight( (sal_uInt16)nDist );
5276 					break;
5277 				}
5278 
5279 #ifndef FIX41370
5280 				_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5281 				aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5282 #endif
5283 			}
5284 		}
5285 
5286 #ifdef FIX41370
5287 		_HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5288 		aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5289 #endif
5290 	}
5291 
5292 	// Bookmarks cannot be inserted into hyperlinks
5293 	if( aId.Len() )
5294 		InsertBookmark( aId );
5295 
5296 	// get the current context from the stack
5297 	_HTMLAttrContext *pPoppedContext = PopContext( HTML_HORZRULE );
5298 	ASSERT( pPoppedContext==pCntxt, "where does an HR context come from?" );
5299 	delete pPoppedContext;
5300 
5301 	pPam->Move( fnMoveForward );
5302 
5303 	// and in the paragraph after that set the template that is current there
5304 	SetTxtCollAttrs();
5305 }
5306 
ParseMoreMetaOptions()5307 void SwHTMLParser::ParseMoreMetaOptions()
5308 {
5309     String aName, aContent;
5310     sal_Bool bHTTPEquiv = sal_False;
5311 
5312     const HTMLOptions *pHTMLOptions = GetOptions();
5313     for( sal_uInt16 i = pHTMLOptions->Count(); i; )
5314     {
5315         const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
5316         switch( pOption->GetToken() )
5317         {
5318         case HTML_O_NAME:
5319             aName = pOption->GetString();
5320             bHTTPEquiv = sal_False;
5321             break;
5322         case HTML_O_HTTPEQUIV:
5323             aName = pOption->GetString();
5324             bHTTPEquiv = sal_True;
5325             break;
5326         case HTML_O_CONTENT:
5327             aContent = pOption->GetString();
5328             break;
5329         }
5330     }
5331 
5332     // Here's where it gets a little tricky: we know for a fact that the doc-info
5333     // has not been changed. Therefore it is sufficient to query on generator and
5334     // refresh to find tokens which have not been processed yet,
5335     // because those are the only ones that do not modify the doc info.
5336     if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_generator ) ||
5337         aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_refresh ) ||
5338         aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_type ) ||
5339         aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_script_type ) )
5340         return;
5341 
5342     aContent.EraseAllChars( _CR );
5343     aContent.EraseAllChars( _LF );
5344 
5345     if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdendnote ) )
5346     {
5347         FillEndNoteInfo( aContent );
5348         return;
5349     }
5350 
5351     if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdfootnote ) )
5352     {
5353         FillFootNoteInfo( aContent );
5354         return;
5355     }
5356 
5357     String sText( String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
5358     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_meta) );
5359     sText.Append( ' ' );
5360     if( bHTTPEquiv  )
5361         sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_httpequiv) );
5362     else
5363         sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_name) );
5364     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5365     sText.Append( aName );
5366     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\" ") );
5367     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_content) );
5368     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5369     sText.Append( aContent );
5370     sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\">") );
5371 
5372     SwPostItField aPostItFld(
5373         (SwPostItFieldType*)pDoc->GetSysFldType( RES_POSTITFLD ),
5374         sText,
5375         aEmptyStr,
5376         aEmptyStr,
5377         aEmptyStr,
5378         DateTime() );
5379     SwFmtFld aFmtFld( aPostItFld );
5380     InsertAttr( aFmtFld );
5381 }
5382 
5383 /*  */
5384 
_HTMLAttr(const SwPosition & rPos,const SfxPoolItem & rItem,_HTMLAttr ** ppHd)5385 _HTMLAttr::_HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem,
5386 					  _HTMLAttr **ppHd ) :
5387 	nSttPara( rPos.nNode ),
5388 	nEndPara( rPos.nNode ),
5389 	nSttCntnt( rPos.nContent.GetIndex() ),
5390 	nEndCntnt(rPos.nContent.GetIndex() ),
5391 	bInsAtStart( sal_True ),
5392 	bLikePara( sal_False ),
5393 	bValid( sal_True ),
5394 	nCount( 1 ),
5395 	pNext( 0 ),
5396 	pPrev( 0 ),
5397 	ppHead( ppHd )
5398 {
5399 	pItem = rItem.Clone();
5400 }
5401 
_HTMLAttr(const _HTMLAttr & rAttr,const SwNodeIndex & rEndPara,sal_uInt16 nEndCnt,_HTMLAttr ** ppHd)5402 _HTMLAttr::_HTMLAttr( const _HTMLAttr &rAttr, const SwNodeIndex &rEndPara,
5403 					  sal_uInt16 nEndCnt, _HTMLAttr **ppHd ) :
5404 	nSttPara( rAttr.nSttPara ),
5405 	nEndPara( rEndPara ),
5406 	nSttCntnt( rAttr.nSttCntnt ),
5407 	nEndCntnt( nEndCnt ),
5408 	bInsAtStart( rAttr.bInsAtStart ),
5409 	bLikePara( rAttr.bLikePara ),
5410 	bValid( rAttr.bValid ),
5411 	nCount( rAttr.nCount ),
5412 	pNext( 0 ),
5413 	pPrev( 0 ),
5414 	ppHead( ppHd )
5415 {
5416 	pItem = rAttr.pItem->Clone();
5417 }
5418 
~_HTMLAttr()5419 _HTMLAttr::~_HTMLAttr()
5420 {
5421 	delete pItem;
5422 }
5423 
Clone(const SwNodeIndex & rEndPara,sal_uInt16 nEndCnt) const5424 _HTMLAttr *_HTMLAttr::Clone( const SwNodeIndex& rEndPara, sal_uInt16 nEndCnt ) const
5425 {
5426 	// recreate the attribute with the old start position
5427 	_HTMLAttr *pNew = new _HTMLAttr( *this, rEndPara, nEndCnt, ppHead );
5428 
5429 	// the Previous list must be taken over, the Next list must not!
5430 	pNew->pPrev = pPrev;
5431 
5432 	return pNew;
5433 }
5434 
Reset(const SwNodeIndex & rSttPara,sal_uInt16 nSttCnt,_HTMLAttr ** ppHd)5435 void _HTMLAttr::Reset( const SwNodeIndex& rSttPara, sal_uInt16 nSttCnt,
5436 					   _HTMLAttr **ppHd )
5437 {
5438 	// reset the beginning (and the end)
5439 	nSttPara = rSttPara;
5440 	nSttCntnt = nSttCnt;
5441 	nEndPara = rSttPara;
5442 	nEndCntnt = nSttCnt;
5443 
5444 	// correct the head and undo the concatenations
5445 	pNext = 0;
5446 	pPrev = 0;
5447 	ppHead = ppHd;
5448 }
5449 
InsertPrev(_HTMLAttr * pPrv)5450 void _HTMLAttr::InsertPrev( _HTMLAttr *pPrv )
5451 {
5452 	ASSERT( !pPrv->pNext || pPrv->pNext == this,
5453 			"_HTMLAttr::InsertPrev: pNext wrong" );
5454 	pPrv->pNext = 0;
5455 
5456 	ASSERT( 0 == pPrv->ppHead || ppHead == pPrv->ppHead,
5457 			"_HTMLAttr::InsertPrev: ppHead wrong" );
5458 	pPrv->ppHead = 0;
5459 
5460 	_HTMLAttr *pAttr = this;
5461 	while( pAttr->GetPrev() )
5462 		pAttr = pAttr->GetPrev();
5463 
5464 	pAttr->pPrev = pPrv;
5465 }
5466 
ParseMetaOptions(const uno::Reference<document::XDocumentProperties> & i_xDocProps,SvKeyValueIterator * i_pHeader)5467 bool SwHTMLParser::ParseMetaOptions(
5468         const uno::Reference<document::XDocumentProperties> & i_xDocProps,
5469         SvKeyValueIterator *i_pHeader )
5470 {
5471     // always call base ParseMetaOptions, it sets the encoding (#i96700#)
5472     bool ret( HTMLParser::ParseMetaOptions(i_xDocProps, i_pHeader) );
5473     if (!ret && IsNewDoc())
5474     {
5475         ParseMoreMetaOptions();
5476     }
5477     return ret;
5478 }
5479 
5480 // override so we can parse DOCINFO field subtypes INFO[1-4]
AddMetaUserDefined(::rtl::OUString const & i_rMetaName)5481 void SwHTMLParser::AddMetaUserDefined( ::rtl::OUString const & i_rMetaName )
5482 {
5483     // unless we already have 4 names, append the argument to m_InfoNames
5484     ::rtl::OUString* pName // the first empty string in m_InfoNames
5485          (!m_InfoNames[0].getLength() ? &m_InfoNames[0] :
5486          (!m_InfoNames[1].getLength() ? &m_InfoNames[1] :
5487          (!m_InfoNames[2].getLength() ? &m_InfoNames[2] :
5488          (!m_InfoNames[3].getLength() ? &m_InfoNames[3] : 0 ))));
5489     if (pName)
5490     {
5491         (*pName) = i_rMetaName;
5492     }
5493 }
5494 
5495