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