xref: /trunk/main/sw/source/filter/html/swhtml.cxx (revision 54c55739d259b6c09a298acbd77515f3caadc8c1)
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 Netscape.
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 paragraph'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 dependent attributes 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 clear 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         // (>Netscape). 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