update dev300-m58
[ooovba.git] / sw / source / filter / html / swhtml.cxx
blob446ad476933601c51ab96ad6c1080563a67412c7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swhtml.cxx,v $
10 * $Revision: 1.51.98.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
36 #include <com/sun/star/document/XDocumentProperties.hpp>
37 #include <com/sun/star/i18n/ScriptType.hpp>
39 #ifndef PRODUCT
40 #include <stdlib.h>
41 #endif
42 #include <hintids.hxx>
44 #define _SVSTDARR_STRINGS
45 #include <svtools/svstdarr.hxx>
46 #include <svtools/stritem.hxx>
47 #include <svtools/imap.hxx>
48 #include <svtools/htmltokn.h>
49 #include <svtools/htmlkywd.hxx>
50 #include <svtools/ctrltool.hxx>
51 #include <svtools/pathoptions.hxx>
52 #include <vcl/svapp.hxx>
53 #include <vcl/wrkwin.hxx>
54 #include <sfx2/fcontnr.hxx>
55 #include <sfx2/docfile.hxx>
57 #include <svx/htmlcfg.hxx>
58 #include <svx/linkmgr.hxx>
59 #include <svx/kernitem.hxx>
60 #include <svx/boxitem.hxx>
61 #include <svx/fhgtitem.hxx>
62 #include <svx/brkitem.hxx>
63 #include <svx/postitem.hxx>
64 #include <svx/wghtitem.hxx>
65 #include <svx/crsditem.hxx>
66 #include <svx/udlnitem.hxx>
67 #include <svx/escpitem.hxx>
68 #include <svx/blnkitem.hxx>
69 #include <svx/ulspitem.hxx>
70 #include <svx/colritem.hxx>
71 #include <svx/fontitem.hxx>
72 #include <svx/adjitem.hxx>
73 #include <svx/lrspitem.hxx>
74 #include <svx/protitem.hxx>
75 #include <svx/flstitem.hxx>
78 #include <frmatr.hxx>
79 #include <charatr.hxx>
80 #include <fmtfld.hxx>
81 #include <fmtpdsc.hxx>
82 #include <fmthbsh.hxx>
83 #include <txtfld.hxx>
84 #include <fmtanchr.hxx>
85 #include <fmtsrnd.hxx>
86 #include <fmtfsize.hxx>
87 #include <fmtclds.hxx>
88 #include <fchrfmt.hxx>
89 #include <fmtinfmt.hxx>
90 #include <docary.hxx>
91 #include <docstat.hxx>
92 #include <doc.hxx>
93 #include <pam.hxx>
94 #include <ndtxt.hxx>
95 #include <mdiexp.hxx> // ...Percent()
96 #include <expfld.hxx>
97 #include <poolfmt.hxx>
98 #include <pagedesc.hxx>
99 #include <IMark.hxx> // fuer SwBookmark ...
100 #include <docsh.hxx>
101 #include <editsh.hxx> // fuer Start/EndAction
102 #include <docufld.hxx>
103 #include <swcss1.hxx>
104 #include <htmlvsh.hxx>
105 #include <fltini.hxx>
106 #include <htmltbl.hxx>
107 #include <htmlnum.hxx>
108 #include <swhtml.hxx>
109 #include <linkenum.hxx>
110 #include <breakit.hxx>
111 #include <SwAppletImpl.hxx>
113 #include <sfx2/viewfrm.hxx>
115 #ifndef _STATSTR_HRC
116 #include <statstr.hrc> // ResId fuer Statusleiste
117 #endif
118 #include <swerror.h>
120 #define FONTSIZE_MASK 7
121 #define FONTCOLOR_MASK (1<<15)
122 #define FONT_MASK (1<<14)
124 #define HTML_ESC_PROP 80
125 #define HTML_ESC_SUPER DFLT_ESC_SUPER
126 #define HTML_ESC_SUB DFLT_ESC_SUB
128 #define HTML_SPTYPE_NONE 0
129 #define HTML_SPTYPE_BLOCK 1
130 #define HTML_SPTYPE_HORI 2
131 #define HTML_SPTYPE_VERT 3
133 #ifndef TOOLS_CONSTASCII_STRINGPARAM
134 #define TOOLS_CONSTASCII_STRINGPARAM( constAsciiStr ) constAsciiStr, sizeof( constAsciiStr )-1
135 #endif
137 using namespace ::com::sun::star;
139 // <P ALIGN=xxx>, <Hn ALIGN=xxx>, <TD ALIGN=xxx> usw.
140 HTMLOptionEnum __FAR_DATA aHTMLPAlignTable[] =
142 { OOO_STRING_SVTOOLS_HTML_AL_left, SVX_ADJUST_LEFT },
143 { OOO_STRING_SVTOOLS_HTML_AL_center, SVX_ADJUST_CENTER },
144 { OOO_STRING_SVTOOLS_HTML_AL_middle, SVX_ADJUST_CENTER }, // Netscape
145 { OOO_STRING_SVTOOLS_HTML_AL_right, SVX_ADJUST_RIGHT },
146 { OOO_STRING_SVTOOLS_HTML_AL_justify, SVX_ADJUST_BLOCK },
147 { OOO_STRING_SVTOOLS_HTML_AL_char, SVX_ADJUST_LEFT },
148 { 0, 0 }
151 // <SPACER TYPE=...>
152 static HTMLOptionEnum __FAR_DATA aHTMLSpacerTypeTable[] =
154 { OOO_STRING_SVTOOLS_HTML_SPTYPE_block, HTML_SPTYPE_BLOCK },
155 { OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal, HTML_SPTYPE_HORI },
156 { OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical, HTML_SPTYPE_VERT },
157 { 0, 0 }
160 SV_IMPL_PTRARR( _HTMLAttrs, _HTMLAttrPtr )
162 HTMLReader::HTMLReader()
164 bTmplBrowseMode = TRUE;
167 String HTMLReader::GetTemplateName() const
169 String sTemplate(
170 String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("internal")) );
171 sTemplate += INET_PATH_TOKEN;
172 sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("html") );
173 String sTemplateWithoutExt( sTemplate );
174 #ifndef MAC_WITHOUT_EXT
175 // --> OD 2005-01-26 - first search for OpenDocument Writer/Web template
176 sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".oth") );
177 // <--
178 #endif
180 SvtPathOptions aPathOpt;
181 // OpenDocument Writer/Web template (extension .oth)
182 BOOL bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
184 #ifndef MAC_WITHOUT_EXT
185 if( !bSet )
187 // 6.0 (extension .stw)
188 sTemplate = sTemplateWithoutExt;
189 // --> OD 2005-01-26 - no OpenDocument Writer/Web template found.
190 // search for OpenOffice.org Writer/Web template
191 sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".stw") );
192 // <--
193 bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
195 #endif
197 if( !bSet )
199 sTemplate.Erase();
200 ASSERT( !this,
201 "Die html.vor befindet sich nicht mehr im definierten Directory!");
204 return sTemplate;
207 int HTMLReader::SetStrmStgPtr()
209 ASSERT( pMedium, "Wo ist das Medium??" );
211 if( pMedium->IsRemote() || !pMedium->IsStorage() )
213 pStrm = pMedium->GetInStream();
214 return TRUE;
216 return FALSE;
220 // Aufruf fuer die allg. Reader-Schnittstelle
221 ULONG HTMLReader::Read( SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & rName )
223 if( !pStrm )
225 ASSERT( pStrm, "HTML-Read ohne Stream" );
226 return ERR_SWG_READ_ERROR;
229 if( !bInsertMode )
231 Reader::SetNoOutlineNum( rDoc );
232 Reader::ResetFrmFmts( rDoc );
234 // Die HTML-Seitenvorlage setzen, wenn des kein HTML-Dokument ist,
235 // sonst ist sie schon gesetzt.
236 if( !rDoc.get(IDocumentSettingAccess::HTML_MODE) )
238 rDoc.Insert( rPam, SwFmtPageDesc(
239 rDoc.GetPageDescFromPool( RES_POOLPAGE_HTML, false )), 0 );
243 // damit keiner das Doc klaut!
244 rDoc.acquire();
245 ULONG nRet = 0;
246 SvParserRef xParser = new SwHTMLParser( &rDoc, rPam, *pStrm,
247 rName, rBaseURL, !bInsertMode, pMedium,
248 IsReadUTF8(),
249 bIgnoreHTMLComments );
251 SvParserState eState = xParser->CallParser();
253 if( SVPAR_PENDING == eState )
254 pStrm->ResetError();
255 else if( SVPAR_ACCEPTED != eState )
257 String sErr( String::CreateFromInt32((sal_Int32)xParser->GetLineNr()));
258 sErr += ',';
259 sErr += String::CreateFromInt32((sal_Int32)xParser->GetLinePos());
261 // den Stream als Fehlernummer Transporter benutzen
262 nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr,
263 ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR );
267 return nRet;
271 /* \f */
273 SwHTMLParser::SwHTMLParser( SwDoc* pD, const SwPaM& rCrsr, SvStream& rIn,
274 const String& rPath,
275 const String& rBaseURL,
276 int bReadNewDoc,
277 SfxMedium* pMed, BOOL bReadUTF8,
278 sal_Bool bNoHTMLComments )
279 : SfxHTMLParser( rIn, static_cast< BOOL >(bReadNewDoc), pMed ),
280 SwClient( 0 ),
281 aPathToFile( rPath ),
282 sBaseURL( rBaseURL ),
283 pAppletImpl( 0 ),
284 pCSS1Parser( 0 ),
285 pNumRuleInfo( new SwHTMLNumRuleInfo ),
286 pPendStack( 0 ),
287 pDoc( pD ),
288 pActionViewShell( 0 ),
289 pSttNdIdx( 0 ),
290 pTable(0),
291 pFormImpl( 0 ),
292 pMarquee( 0 ),
293 pField( 0 ),
294 pImageMap( 0 ),
295 pImageMaps( 0 ),
296 pFootEndNoteImpl( 0 ),
297 nScriptStartLineNr( 0 ),
298 nBaseFontStMin( 0 ),
299 nFontStMin( 0 ),
300 nDefListDeep( 0 ),
301 nFontStHeadStart( 0 ),
302 nSBModuleCnt( 0 ),
303 nMissingImgMaps( 0 ),
304 nParaCnt( 5 ),
305 // --> OD 2007-10-26 #i83625#
306 nContextStMin( 0 ),
307 nContextStAttrMin( 0 ),
308 // <--
309 nOpenParaToken( 0 ),
310 eJumpTo( JUMPTO_NONE ),
311 #ifndef PRODUCT
312 nContinue( 0 ),
313 #endif
314 eParaAdjust( SVX_ADJUST_END ),
315 bDocInitalized( FALSE ),
316 bSetModEnabled( FALSE ),
317 bInFloatingFrame( FALSE ),
318 bInField( FALSE ),
319 bCallNextToken( FALSE ),
320 bIgnoreRawData( FALSE ),
321 bNoParSpace( FALSE ),
322 bInNoEmbed( FALSE ),
323 bInTitle( FALSE ),
324 bUpdateDocStat( FALSE ),
325 bFixSelectWidth( FALSE ),
326 bFixSelectHeight( FALSE ),
327 bTextArea( FALSE ),
328 bSelect( FALSE ),
329 bInFootEndNoteAnchor( FALSE ),
330 bInFootEndNoteSymbol( FALSE ),
331 // bIgnoreHTMLComments( bNoHTMLComments )
332 bIgnoreHTMLComments( bNoHTMLComments ),
333 bRemoveHidden( FALSE ),
334 pTempViewFrame(0)
336 nEventId = 0;
337 bUpperSpace = bViewCreated = bChkJumpMark =
338 bSetCrsr = FALSE;
340 eScriptLang = HTML_SL_UNKNOWN;
341 bAnyStarBasic = TRUE;
343 pPam = new SwPaM( *rCrsr.GetPoint() );
344 memset( &aAttrTab, 0, sizeof( _HTMLAttrTable ));
346 // Die Font-Groessen 1-7 aus der INI-Datei lesen
347 SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get();
348 aFontHeights[0] = pHtmlOptions->GetFontSize( 0 ) * 20;
349 aFontHeights[1] = pHtmlOptions->GetFontSize( 1 ) * 20;
350 aFontHeights[2] = pHtmlOptions->GetFontSize( 2 ) * 20;
351 aFontHeights[3] = pHtmlOptions->GetFontSize( 3 ) * 20;
352 aFontHeights[4] = pHtmlOptions->GetFontSize( 4 ) * 20;
353 aFontHeights[5] = pHtmlOptions->GetFontSize( 5 ) * 20;
354 aFontHeights[6] = pHtmlOptions->GetFontSize( 6 ) * 20;
356 bKeepUnknown = pHtmlOptions->IsImportUnknown();
358 if(bReadNewDoc)
360 SvxFontHeightItem aFontHeight(aFontHeights[2], 100, RES_CHRATR_FONTSIZE);
361 pDoc->SetDefault( aFontHeight );
362 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
363 pDoc->SetDefault( aFontHeight );
364 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
365 pDoc->SetDefault( aFontHeight );
368 // Waehrend des Imports in den HTML-Modus schalten, damit die
369 // richrigen Vorlagen angelegt werden
370 bOldIsHTMLMode = pDoc->get(IDocumentSettingAccess::HTML_MODE);
371 pDoc->set(IDocumentSettingAccess::HTML_MODE, true);
373 pCSS1Parser = new SwCSS1Parser( pDoc, aFontHeights, sBaseURL, IsNewDoc() );
374 pCSS1Parser->SetIgnoreFontFamily( pHtmlOptions->IsIgnoreFontFamily() );
376 if( bReadUTF8 )
378 SetSrcEncoding( RTL_TEXTENCODING_UTF8 );
380 else
382 SwDocShell *pDocSh = pDoc->GetDocShell();
383 SvKeyValueIterator *pHeaderAttrs =
384 pDocSh->GetHeaderAttributes();
385 if( pHeaderAttrs )
386 SetEncodingByHTTPHeader( pHeaderAttrs );
388 pCSS1Parser->SetDfltEncoding( gsl_getSystemTextEncoding() );
390 // Timer nur bei ganz normalen Dokumenten aufsetzen!
391 SwDocShell* pDocSh = pDoc->GetDocShell();
392 if( pDocSh )
394 bViewCreated = TRUE; // nicht, synchron laden
396 // es ist ein Sprungziel vorgegeben.
398 if( pMed )
400 sJmpMark = pMed->GetURLObject().GetMark();
401 if( sJmpMark.Len() )
403 eJumpTo = JUMPTO_MARK;
404 String sCmp;
405 xub_StrLen nLastPos, nPos = 0;
406 while( STRING_NOTFOUND != ( nLastPos =
407 sJmpMark.Search( cMarkSeperator, nPos + 1 )) )
408 nPos = nLastPos;
410 if( nPos && ( sCmp = sJmpMark.Copy( nPos + 1 ) ).
411 EraseAllChars().Len() )
413 sCmp.ToLowerAscii();
414 if( sCmp.EqualsAscii( pMarkToRegion ) )
415 eJumpTo = JUMPTO_REGION;
416 else if( sCmp.EqualsAscii( pMarkToTable ) )
417 eJumpTo = JUMPTO_TABLE;
418 else if( sCmp.EqualsAscii( pMarkToGraphic ) )
419 eJumpTo = JUMPTO_GRAPHIC;
420 else if( sCmp.EqualsAscii( pMarkToOutline ) ||
421 sCmp.EqualsAscii( pMarkToText ) ||
422 sCmp.EqualsAscii( pMarkToFrame ) )
423 eJumpTo = JUMPTO_NONE; // das ist nichts gueltiges!
424 else
425 // ansonsten ist das ein normaler (Book)Mark
426 nPos = STRING_LEN;
428 else
429 nPos = STRING_LEN;
431 sJmpMark.Erase( nPos );
432 if( !sJmpMark.Len() )
433 eJumpTo = JUMPTO_NONE;
439 __EXPORT SwHTMLParser::~SwHTMLParser()
441 #ifndef PRODUCT
442 ASSERT( !nContinue, "DTOR im Continue - Das geht schief!!!" );
443 #endif
444 BOOL bAsync = pDoc->IsInLoadAsynchron();
445 pDoc->SetInLoadAsynchron( FALSE );
446 pDoc->set(IDocumentSettingAccess::HTML_MODE, bOldIsHTMLMode);
448 if( pDoc->GetDocShell() && nEventId )
449 Application::RemoveUserEvent( nEventId );
451 // das DocumentDetected kann ggfs. die DocShells loeschen, darum nochmals
452 // abfragen
453 if( pDoc->GetDocShell() )
455 // Gelinkte Bereiche updaten
456 USHORT nLinkMode = pDoc->getLinkUpdateMode( true );
457 if( nLinkMode != NEVER && bAsync &&
458 SFX_CREATE_MODE_INTERNAL!=pDoc->GetDocShell()->GetCreateMode() )
459 pDoc->GetLinkManager().UpdateAllLinks( nLinkMode == MANUAL,
460 TRUE, FALSE );
462 if ( pDoc->GetDocShell()->IsLoading() )
464 // --> OD 2006-11-07 #i59688#
465 pDoc->GetDocShell()->LoadingFinished();
469 delete pSttNdIdx;
471 if( aSetAttrTab.Count() )
473 ASSERT( !aSetAttrTab.Count(),"Es stehen noch Attribute auf dem Stack" );
474 aSetAttrTab.DeleteAndDestroy( 0, aSetAttrTab.Count() );
477 delete pPam;
478 delete pCSS1Parser;
479 delete pNumRuleInfo;
480 DeleteFormImpl();
481 DeleteFootEndNoteImpl();
483 ASSERT( !pTable, "Es existiert noch eine offene Tabelle" );
484 delete pImageMaps;
485 //delete pTable;
487 ASSERT( !pPendStack,
488 "SwHTMLParser::~SwHTMLParser: Hier sollte es keinen Pending-Stack mehr geben" );
489 while( pPendStack )
491 SwPendingStack* pTmp = pPendStack;
492 pPendStack = pPendStack->pNext;
493 delete pTmp->pData;
494 delete pTmp;
497 if( !pDoc->release() )
499 // keiner will mehr das Doc haben, also weg damit
500 delete pDoc;
501 pDoc = NULL;
504 if ( pTempViewFrame )
506 pTempViewFrame->DoClose();
508 // the temporary view frame is hidden, so the hidden flag might need to be removed
509 if ( bRemoveHidden && pDoc && pDoc->GetDocShell() && pDoc->GetDocShell()->GetMedium() )
510 pDoc->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN );
514 IMPL_LINK( SwHTMLParser, AsyncCallback, void*, /*pVoid*/ )
516 nEventId=0;
518 // --> FME 2005-08-18 #i47907# If the document has already been destructed,
519 // the parser should be aware of this:
520 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
521 || 1 == pDoc->getReferenceCount() )
523 // wurde der Import vom SFX abgebrochen?
524 eState = SVPAR_ERROR;
526 // <--
528 GetAsynchCallLink().Call(0);
529 return 0;
532 SvParserState __EXPORT SwHTMLParser::CallParser()
534 // einen temporaeren Index anlegen, auf Pos 0 so wird er nicht bewegt!
535 pSttNdIdx = new SwNodeIndex( pDoc->GetNodes() );
536 if( !IsNewDoc() ) // in ein Dokument einfuegen ?
538 const SwPosition* pPos = pPam->GetPoint();
540 pDoc->SplitNode( *pPos, false );
542 *pSttNdIdx = pPos->nNode.GetIndex()-1;
543 pDoc->SplitNode( *pPos, false );
545 SwPaM aInsertionRangePam( *pPos );
547 pPam->Move( fnMoveBackward );
549 // #106634# split any redline over the insertion point
550 aInsertionRangePam.SetMark();
551 *aInsertionRangePam.GetPoint() = *pPam->GetPoint();
552 aInsertionRangePam.Move( fnMoveBackward );
553 pDoc->SplitRedline( aInsertionRangePam );
555 pDoc->SetTxtFmtColl( *pPam,
556 pCSS1Parser->GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
559 if( GetMedium() )
561 if( !bViewCreated )
563 nEventId = Application::PostUserEvent( LINK( this, SwHTMLParser, AsyncCallback ), 0 );
565 else
567 bViewCreated = TRUE;
568 nEventId = 0;
572 // Laufbalken anzeigen
573 else if( !GetMedium() || !GetMedium()->IsRemote() )
575 rInput.Seek(STREAM_SEEK_TO_END);
576 rInput.ResetError();
577 ::StartProgress( STR_STATSTR_W4WREAD, 0, rInput.Tell(),
578 pDoc->GetDocShell() );
579 rInput.Seek(STREAM_SEEK_TO_BEGIN);
580 rInput.ResetError();
583 SwPageDesc& rDesc = pDoc->_GetPageDesc( 0 );
584 rDesc.Add( this );
586 SvParserState eRet = HTMLParser::CallParser();
587 return eRet;
590 void __EXPORT SwHTMLParser::Continue( int nToken )
592 #ifndef PRODUCT
593 ASSERT( !nContinue, "Continue im Continue - Das sollte doch nicht sein, oder?" );
594 nContinue++;
595 #endif
597 // Wenn der Import (vom SFX) abgebrochen wurde, wird ein Fehler
598 // gesetzt aber trotzdem noch weiter gemacht, damit vernuenftig
599 // aufgeraeumt wird.
600 ASSERT( SVPAR_ERROR!=eState,
601 "SwHTMLParser::Continue: bereits ein Fehler gesetzt" );
602 if( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
603 eState = SVPAR_ERROR;
605 // Die ViewShell vom Dokument holen, merken und als aktuelle setzen.
606 ViewShell *pInitVSh = CallStartAction();
608 if( SVPAR_ERROR != eState && GetMedium() && !bViewCreated )
610 // Beim ersten Aufruf erstmal returnen, Doc anzeigen
611 // und auf Timer Callback warten.
612 // An dieser Stelle wurde im CallParser gerade mal ein Zeichen
613 // gelesen und ein SaveState(0) gerufen.
614 eState = SVPAR_PENDING;
615 bViewCreated = TRUE;
616 pDoc->SetInLoadAsynchron( TRUE );
618 #ifndef PRODUCT
619 nContinue--;
620 #endif
622 return;
625 bSetModEnabled = FALSE;
626 if( pDoc->GetDocShell() &&
627 0 != (bSetModEnabled = pDoc->GetDocShell()->IsEnableSetModified()) )
629 pDoc->GetDocShell()->EnableSetModified( FALSE );
632 // waehrend des einlesens kein OLE-Modified rufen
633 Link aOLELink( pDoc->GetOle2Link() );
634 pDoc->SetOle2Link( Link() );
636 BOOL bModified = pDoc->IsModified();
637 BOOL bWasUndo = pDoc->DoesUndo();
638 pDoc->DoUndo( FALSE );
640 // Wenn der Import abgebrochen wird, kein Continue mehr rufen.
641 // Falls ein Pending-Stack existiert aber durch einen Aufruf
642 // von NextToken dafuer sorgen, dass der Pending-Stack noch
643 // beendet wird.
644 if( SVPAR_ERROR == eState )
646 ASSERT( !pPendStack || pPendStack->nToken,
647 "SwHTMLParser::Continue: Pending-Stack ohne Token" );
648 if( pPendStack && pPendStack->nToken )
649 NextToken( pPendStack->nToken );
650 ASSERT( !pPendStack,
651 "SwHTMLParser::Continue: Es gibt wieder einen Pend-Stack" );
653 else
655 HTMLParser::Continue( pPendStack ? pPendStack->nToken : nToken );
658 // Laufbalken wieder abschalten
659 EndProgress( pDoc->GetDocShell() );
661 BOOL bLFStripped = FALSE;
662 if( SVPAR_PENDING != GetStatus() )
664 // noch die letzten Attribute setzen
666 if( aScriptSource.Len() )
668 SwScriptFieldType *pType =
669 (SwScriptFieldType*)pDoc->GetSysFldType( RES_SCRIPTFLD );
671 SwScriptField aFld( pType, aScriptType, aScriptSource,
672 FALSE );
673 InsertAttr( SwFmtFld( aFld ) );
676 if( pAppletImpl )
678 if( pAppletImpl->GetApplet().is() )
679 EndApplet();
680 else
681 EndObject();
684 // ggf. ein noch vorhandes LF hinter dem letzen Absatz entfernen
685 if( IsNewDoc() )
686 bLFStripped = StripTrailingLF() > 0;
688 // noch offene Nummerierungen beenden.
689 while( GetNumInfo().GetNumRule() )
690 EndNumBulList();
692 ASSERT( !nContextStMin, "Es gibt geschuetzte Kontexte" );
693 nContextStMin = 0;
694 while( aContexts.Count() )
696 _HTMLAttrContext *pCntxt = PopContext();
697 if( pCntxt )
699 EndContext( pCntxt );
700 delete pCntxt;
704 if( aParaAttrs.Count() )
705 aParaAttrs.Remove( 0, aParaAttrs.Count() );
707 SetAttr( FALSE );
709 // Noch die erst verzoegert gesetzten Styles setzen
710 pCSS1Parser->SetDelayedStyles();
713 // den Start wieder korrigieren
714 if( !IsNewDoc() && pSttNdIdx->GetIndex() )
716 SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode();
717 SwNodeIndex aNxtIdx( *pSttNdIdx );
718 if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx ))
720 xub_StrLen nStt = pTxtNode->GetTxt().Len();
721 // wenn der Cursor noch in dem Node steht, dann setze in an das Ende
722 if( pPam->GetPoint()->nNode == aNxtIdx )
724 pPam->GetPoint()->nNode = *pSttNdIdx;
725 pPam->GetPoint()->nContent.Assign( pTxtNode, nStt );
728 #ifndef PRODUCT
729 // !!! sollte nicht moeglich sein, oder ??
730 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( TRUE ).nNode.GetIndex(),
731 "Pam.Bound1 steht noch im Node" );
732 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( FALSE ).nNode.GetIndex(),
733 "Pam.Bound2 steht noch im Node" );
735 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( TRUE ).nNode.GetIndex() )
737 xub_StrLen nCntPos = pPam->GetBound( TRUE ).nContent.GetIndex();
738 pPam->GetBound( TRUE ).nContent.Assign( pTxtNode,
739 pTxtNode->GetTxt().Len() + nCntPos );
741 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( FALSE ).nNode.GetIndex() )
743 xub_StrLen nCntPos = pPam->GetBound( FALSE ).nContent.GetIndex();
744 pPam->GetBound( FALSE ).nContent.Assign( pTxtNode,
745 pTxtNode->GetTxt().Len() + nCntPos );
747 #endif
748 // Zeichen Attribute beibehalten!
749 SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode();
750 if( pTxtNode->GetTxt().Len() )
751 pDelNd->FmtToTxtAttr( pTxtNode );
752 else
753 pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() );
754 pTxtNode->JoinNext();
759 if( SVPAR_ACCEPTED == eState )
761 if( nMissingImgMaps )
763 // es fehlen noch ein paar Image-Map zuordungen.
764 // vielleicht sind die Image-Maps ja jetzt da?
765 ConnectImageMaps();
768 // jetzt noch den letzten ueberfluessigen Absatz loeschen
769 SwPosition* pPos = pPam->GetPoint();
770 if( !pPos->nContent.GetIndex() && !bLFStripped )
772 SwTxtNode* pAktNd;
773 ULONG nNodeIdx = pPos->nNode.GetIndex();
775 BOOL bHasFlysOrMarks =
776 HasCurrentParaFlys() || HasCurrentParaBookmarks( TRUE );
778 if( IsNewDoc() )
780 const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
781 if( !pPam->GetPoint()->nContent.GetIndex() &&
782 ( pPrev->IsCntntNode() ||
783 (pPrev->IsEndNode() &&
784 pPrev->StartOfSectionNode()->IsSectionNode()) ) )
786 SwCntntNode* pCNd = pPam->GetCntntNode();
787 if( pCNd && pCNd->StartOfSectionIndex()+2 <
788 pCNd->EndOfSectionIndex() && !bHasFlysOrMarks )
790 ViewShell *pVSh = CheckActionViewShell();
791 SwCrsrShell *pCrsrSh = pVSh && pVSh->ISA(SwCrsrShell)
792 ? static_cast < SwCrsrShell * >( pVSh )
793 : 0;
794 if( pCrsrSh &&
795 pCrsrSh->GetCrsr()->GetPoint()
796 ->nNode.GetIndex() == nNodeIdx )
798 pCrsrSh->MovePara(fnParaPrev, fnParaEnd );
799 pCrsrSh->SetMark();
800 pCrsrSh->ClearMark();
802 pPam->GetBound(TRUE).nContent.Assign( 0, 0 );
803 pPam->GetBound(FALSE).nContent.Assign( 0, 0 );
804 pDoc->GetNodes().Delete( pPam->GetPoint()->nNode );
808 else if( 0 != ( pAktNd = pDoc->GetNodes()[ nNodeIdx ]->GetTxtNode()) && !bHasFlysOrMarks )
810 if( pAktNd->CanJoinNext( &pPos->nNode ))
812 SwTxtNode* pNextNd = pPos->nNode.GetNode().GetTxtNode();
813 pPos->nContent.Assign( pNextNd, 0 );
814 pPam->SetMark(); pPam->DeleteMark();
815 pNextNd->JoinPrev();
817 else if( !pAktNd->GetTxt().Len() )
819 pPos->nContent.Assign( 0, 0 );
820 pPam->SetMark(); pPam->DeleteMark();
821 pDoc->GetNodes().Delete( pPos->nNode, 1 );
822 pPam->Move( fnMoveBackward );
827 // nun noch das SplitNode vom Anfang aufheben
828 else if( !IsNewDoc() )
830 if( pPos->nContent.GetIndex() ) // dann gabs am Ende kein <P>,
831 pPam->Move( fnMoveForward, fnGoNode ); // als zum naechsten Node
832 SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
833 SwNodeIndex aPrvIdx( pPos->nNode );
834 if( pTxtNode && pTxtNode->CanJoinPrev( &aPrvIdx ) &&
835 *pSttNdIdx <= aPrvIdx )
837 // eigentlich muss hier ein JoinNext erfolgen, aber alle Cursor
838 // usw. sind im pTxtNode angemeldet, so dass der bestehen
839 // bleiben MUSS.
841 // Absatz in Zeichen-Attribute umwandeln, aus dem Prev die
842 // Absatzattribute und die Vorlage uebernehmen!
843 SwTxtNode* pPrev = aPrvIdx.GetNode().GetTxtNode();
844 pTxtNode->ChgFmtColl( pPrev->GetTxtColl() );
845 pTxtNode->FmtToTxtAttr( pPrev );
846 pTxtNode->ResetAllAttr();
848 if( pPrev->HasSwAttrSet() )
849 pTxtNode->SetAttr( *pPrev->GetpSwAttrSet() );
851 if( &pPam->GetBound(TRUE).nNode.GetNode() == pPrev )
852 pPam->GetBound(TRUE).nContent.Assign( pTxtNode, 0 );
853 if( &pPam->GetBound(FALSE).nNode.GetNode() == pPrev )
854 pPam->GetBound(FALSE).nContent.Assign( pTxtNode, 0 );
856 pTxtNode->JoinPrev();
860 // und noch die DocumentInfo aufbereiten
861 if( IsNewDoc() )
863 SwDocShell *pDocShell(pDoc->GetDocShell());
864 DBG_ASSERT(pDocShell, "no SwDocShell");
865 if (pDocShell) {
866 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
867 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
868 uno::Reference<document::XDocumentProperties> xDocProps(
869 xDPS->getDocumentProperties());
870 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
871 if ( xDocProps.is() && (xDocProps->getAutoloadSecs() > 0) &&
872 xDocProps->getAutoloadURL().equalsAscii("") )
874 xDocProps->setAutoloadURL(aPathToFile);
879 if( bUpdateDocStat )
881 SwDocStat aStat( pDoc->GetDocStat() );
882 pDoc->UpdateDocStat( aStat );
886 if( SVPAR_PENDING != GetStatus() )
887 delete pSttNdIdx, pSttNdIdx = 0;
889 // sollte der Parser der Letzte sein, der das Doc haelt, dann braucht
890 // man hier auch nichts mehr tun, Doc wird gleich zerstoert!
891 if( 1 < pDoc->getReferenceCount() )
893 if( bWasUndo )
895 pDoc->DelAllUndoObj();
896 pDoc->DoUndo( TRUE );
898 else if( !pInitVSh )
900 // Wenn zu Beginn des Continue keine Shell vorhanden war,
901 // kann trotzdem mitlerweile eine angelegt worden sein.
902 // In dieses Fall stimmt das bWasUndo-Flag nicht und
903 // wir muessen das Undo noch anschalten.
904 ViewShell *pTmpVSh = CheckActionViewShell();
905 if( pTmpVSh )
906 pDoc->DoUndo( TRUE );
909 pDoc->SetOle2Link( aOLELink );
910 if( !bModified )
911 pDoc->ResetModified();
912 if( bSetModEnabled && pDoc->GetDocShell() )
914 pDoc->GetDocShell()->EnableSetModified( TRUE );
915 bSetModEnabled = FALSE; // this is unnecessary here
920 // Wenn die Dokuemnt-ViewShell noch existiert und eine Action
921 // offen ist (muss bei Abbruch nicht sein), die Action beenden,
922 // uns von der Shell abmelden und schliesslich die alte Shell
923 // wieder rekonstruieren.
924 CallEndAction( TRUE );
926 #ifndef PRODUCT
927 nContinue--;
928 #endif
931 void SwHTMLParser::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew )
933 switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
935 case RES_OBJECTDYING:
936 if( ((SwPtrMsgPoolItem *)pOld)->pObject == pRegisteredIn )
938 // dann uns selbst beenden
939 pRegisteredIn->Remove( this );
940 ReleaseRef(); // ansonsten sind wir fertig!
942 break;
946 void SwHTMLParser::DocumentDetected()
948 ASSERT( !bDocInitalized, "DocumentDetected mehrfach aufgerufen" );
949 bDocInitalized = TRUE;
950 if( IsNewDoc() )
952 if( IsInHeader() )
953 FinishHeader( TRUE );
955 CallEndAction( TRUE, TRUE );
957 pDoc->DoUndo( FALSE );
958 // Durch das DocumentDetected wurde im allgemeinen eine
959 // ViewShell angelegt. Es kann aber auch sein, dass sie
960 // erst spaeter angelegt wird, naemlich dann, wenn die UI
961 // gecaptured ist.
962 CallStartAction();
966 // wird fuer jedes Token gerufen, das in CallParser erkannt wird
967 void __EXPORT SwHTMLParser::NextToken( int nToken )
969 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
970 || 1 == pDoc->getReferenceCount() )
972 // wurde der Import vom SFX abgebrochen? Wenn ein Pending-Stack
973 // existiert den noch aufraumen
974 eState = SVPAR_ERROR;
975 ASSERT( !pPendStack || pPendStack->nToken,
976 "SwHTMLParser::NextToken: Pending-Stack ohne Token" );
977 if( 1 == pDoc->getReferenceCount() || !pPendStack )
978 return ;
981 #ifndef PRODUCT
982 if( pPendStack )
984 switch( nToken )
986 // Tabellen werden ueber rekusive Methodenaufrufe gelesen
987 case HTML_TABLE_ON:
988 // Bei CSS-Deklarationen muss evtl. noch auf das
989 // Ende eines File-Downloads gewartet werden.
990 case HTML_LINK:
991 // Bei Controls muss evtl. noch die Groesse gesetzt werden.
992 case HTML_INPUT:
993 case HTML_TEXTAREA_ON:
994 case HTML_SELECT_ON:
995 case HTML_SELECT_OFF:
996 break;
997 default:
998 ASSERT( !pPendStack, "Unbekanntes Token fuer Pending-Stack" );
999 break;
1002 #endif
1004 // Die folgeneden Spezialfaelle muessen vor der Filter-Detection behandelt
1005 // werden, denn der Inhalt des Titels, etc. wird auch in Netcape nicht
1006 // zur Filter-Detection herangezogen.
1007 if( !pPendStack )
1009 if( bInTitle )
1011 switch( nToken )
1013 case HTML_TITLE_OFF:
1014 if( IsNewDoc() && sTitle.Len() )
1016 if( pDoc->GetDocShell() ) {
1017 uno::Reference<document::XDocumentPropertiesSupplier>
1018 xDPS(pDoc->GetDocShell()->GetModel(),
1019 uno::UNO_QUERY_THROW);
1020 uno::Reference<document::XDocumentProperties> xDocProps(
1021 xDPS->getDocumentProperties());
1022 DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
1023 if (xDocProps.is()) {
1024 xDocProps->setTitle(sTitle);
1027 pDoc->GetDocShell()->SetTitle( sTitle );
1030 bInTitle = FALSE;
1031 sTitle.Erase();
1032 break;
1034 case HTML_NONBREAKSPACE:
1035 sTitle += ' ';
1036 break;
1038 case HTML_SOFTHYPH:
1039 sTitle += '-';
1040 break;
1042 case HTML_TEXTTOKEN:
1043 sTitle += aToken;
1044 break;
1046 default:
1047 sTitle += '<';
1048 if( (HTML_TOKEN_ONOFF & nToken) && (1 & nToken) )
1049 sTitle += '/';
1050 sTitle += sSaveToken;
1051 if( aToken.Len() )
1053 sTitle += ' ';
1054 sTitle += aToken;
1056 sTitle += '>';
1057 break;
1060 return;
1064 // Wenn wir noch nicht wissen, was fuer ein Dokument wir vor uns haben,
1065 // versuchen wir das erstmal rauszufinden. Das muss fuer Controls in
1066 // Fall vor dem Einfuegen des Controls passieren, weil beim Einfuegen
1067 // bereits eine View benoetigt wird.
1068 if( !bDocInitalized )
1069 DocumentDetected();
1071 BOOL bGetIDOption = FALSE, bInsertUnknown = FALSE;
1072 BOOL bUpperSpaceSave = bUpperSpace;
1073 bUpperSpace = FALSE;
1075 // Die folgenden Speziallfaelle muessen oder koennen nach der
1076 // Filter-Detection erfolgen.
1077 if( !pPendStack )
1079 if( bInFloatingFrame )
1081 // <SCRIPT> wird hier (von uns) ignoriert, weil es auch in
1082 // Applets ignoriert wird!
1083 if( HTML_IFRAME_OFF == nToken )
1085 bCallNextToken = FALSE;
1086 EndFloatingFrame();
1089 return;
1091 else if( bInNoEmbed )
1093 switch( nToken )
1095 case HTML_NOEMBED_OFF:
1096 aContents.ConvertLineEnd();
1097 InsertComment( aContents, OOO_STRING_SVTOOLS_HTML_noembed );
1098 aContents.Erase();
1099 bCallNextToken = FALSE;
1100 bInNoEmbed = FALSE;
1101 break;
1103 case HTML_RAWDATA:
1104 InsertCommentText( OOO_STRING_SVTOOLS_HTML_noembed );
1105 break;
1107 default:
1108 ASSERT( !this, "SwHTMLParser::NextToken: ungueltiges Tag" );
1109 break;
1112 return;
1114 else if( pAppletImpl )
1116 // in einem Applet interessieren uns (erstmal) nur <PARAM>-Tags
1117 // und das </APPLET>.
1118 // <SCRIPT> wird hier (von Netscape) ignoriert!
1120 switch( nToken )
1122 case HTML_APPLET_OFF:
1123 bCallNextToken = FALSE;
1124 EndApplet();
1125 break;
1126 case HTML_OBJECT_OFF:
1127 bCallNextToken = FALSE;
1128 EndObject();
1129 break;
1131 case HTML_PARAM:
1132 InsertParam();
1133 break;
1136 return;
1138 else if( bTextArea )
1140 // in einer TextArea wird alles bis zum </TEXTAREA> als Text
1141 // eingefuegt
1142 // <SCRIPT> wird hier (von Netscape) ignoriert!
1144 switch( nToken )
1146 case HTML_TEXTAREA_OFF:
1147 bCallNextToken = FALSE;
1148 EndTextArea();
1149 break;
1151 default:
1152 InsertTextAreaText( static_cast< sal_uInt16 >(nToken) );
1153 break;
1156 return;
1158 else if( bSelect )
1160 // MUSS nach bNoScript kommen!
1161 switch( nToken )
1163 case HTML_SELECT_OFF:
1164 bCallNextToken = FALSE;
1165 EndSelect();
1166 return;
1168 case HTML_OPTION:
1169 InsertSelectOption();
1170 return;
1172 case HTML_TEXTTOKEN:
1173 InsertSelectText();
1174 return;
1176 case HTML_INPUT:
1177 case HTML_SCRIPT_ON:
1178 case HTML_SCRIPT_OFF:
1179 case HTML_NOSCRIPT_ON:
1180 case HTML_NOSCRIPT_OFF:
1181 case HTML_RAWDATA:
1182 // im normalen switch bahandeln
1183 break;
1185 default:
1186 // ignorieren
1187 return;
1190 else if( pMarquee )
1192 // in einer TextArea wird alles bis zum </TEXTAREA> als Text
1193 // eingefuegt
1194 // Die <SCRIPT>-Tags werden vom MS-IE ignoriert, von uns das
1195 // geasmte Script
1196 switch( nToken )
1198 case HTML_MARQUEE_OFF:
1199 bCallNextToken = FALSE;
1200 EndMarquee();
1201 break;
1203 case HTML_TEXTTOKEN:
1204 InsertMarqueeText();
1205 break;
1208 return;
1210 else if( bInField )
1212 switch( nToken )
1214 case HTML_SDFIELD_OFF:
1215 bCallNextToken = FALSE;
1216 EndField();
1217 break;
1219 case HTML_TEXTTOKEN:
1220 InsertFieldText();
1221 break;
1224 return;
1226 else if( bInFootEndNoteAnchor || bInFootEndNoteSymbol )
1228 switch( nToken )
1230 case HTML_ANCHOR_OFF:
1231 EndAnchor();
1232 bCallNextToken = FALSE;
1233 break;
1235 case HTML_TEXTTOKEN:
1236 InsertFootEndNoteText();
1237 break;
1239 return;
1241 else if( aUnknownToken.Len() )
1243 // Fix i#59064 : Paste content of unknown tags.
1244 if (aToken.Len() > 0)
1246 if( !bDocInitalized )
1247 DocumentDetected();
1248 pDoc->Insert( *pPam, aToken, true );
1250 // wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber
1251 // nicht leer ist, dann sind die Absatz-Attribute entgueltig.
1252 if( aParaAttrs.Count() )
1253 aParaAttrs.Remove( 0, aParaAttrs.Count() );
1255 SetAttr();
1258 // Unbekannte Token im Header werden nur durch ein passendes
1259 // End-Token, </HEAD> oder <BODY> wieder beendet. Darin wird Text
1260 // ignoriert.
1261 switch( nToken )
1263 case HTML_UNKNOWNCONTROL_OFF:
1264 if( aUnknownToken.CompareTo(sSaveToken) != COMPARE_EQUAL )
1265 return;
1266 case HTML_FRAMESET_ON:
1267 case HTML_HEAD_OFF:
1268 case HTML_BODY_ON:
1269 case HTML_IMAGE: // Warum auch immer Netscape das tut.
1270 aUnknownToken.Erase();
1271 break;
1272 case HTML_TEXTTOKEN:
1273 return;
1274 default:
1275 aUnknownToken.Erase();
1276 break;
1281 switch( nToken )
1283 case HTML_BODY_ON:
1284 if( aStyleSource.Len() )
1286 pCSS1Parser->ParseStyleSheet( aStyleSource );
1287 aStyleSource.Erase();
1289 if( IsNewDoc() )
1291 InsertBodyOptions();
1292 // Falls es eine Vorlage fuer die erste oder rechte Seite gibt,
1293 // setzen wir die hier.
1294 const SwPageDesc *pPageDesc = 0;
1295 if( pCSS1Parser->IsSetFirstPageDesc() )
1296 pPageDesc = pCSS1Parser->GetFirstPageDesc();
1297 else if( pCSS1Parser->IsSetRightPageDesc() )
1298 pPageDesc = pCSS1Parser->GetRightPageDesc();
1300 if( pPageDesc )
1301 pDoc->Insert( *pPam, SwFmtPageDesc( pPageDesc ), 0 );
1303 break;
1305 case HTML_LINK:
1306 InsertLink();
1307 break;
1309 case HTML_BASE:
1311 const HTMLOptions *pHTMLOptions = GetOptions();
1312 for( USHORT i = pHTMLOptions->Count(); i; )
1314 const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1315 switch( pOption->GetToken() )
1317 case HTML_O_HREF:
1318 sBaseURL = pOption->GetString();
1319 break;
1320 case HTML_O_TARGET:
1321 if( IsNewDoc() )
1323 SwDocShell *pDocShell(pDoc->GetDocShell());
1324 DBG_ASSERT(pDocShell, "no SwDocShell");
1325 if (pDocShell) {
1326 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1327 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1328 uno::Reference<document::XDocumentProperties>
1329 xDocProps(xDPS->getDocumentProperties());
1330 DBG_ASSERT(xDocProps.is(),"no DocumentProperties");
1331 if (xDocProps.is()) {
1332 xDocProps->setDefaultTarget(
1333 pOption->GetString());
1337 break;
1341 break;
1343 case HTML_META:
1345 SvKeyValueIterator *pHTTPHeader = 0;
1346 if( IsNewDoc() )
1348 SwDocShell *pDocSh = pDoc->GetDocShell();
1349 if( pDocSh )
1350 pHTTPHeader = pDocSh->GetHeaderAttributes();
1352 SwDocShell *pDocShell(pDoc->GetDocShell());
1353 DBG_ASSERT(pDocShell, "no SwDocShell");
1354 if (pDocShell)
1356 uno::Reference<document::XDocumentProperties> xDocProps;
1357 if (IsNewDoc())
1359 const uno::Reference<document::XDocumentPropertiesSupplier>
1360 xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW );
1361 xDocProps = xDPS->getDocumentProperties();
1362 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
1364 ParseMetaOptions( xDocProps, pHTTPHeader );
1367 break;
1369 case HTML_TITLE_ON:
1370 bInTitle = TRUE;
1371 break;
1373 case HTML_SCRIPT_ON:
1374 NewScript();
1375 break;
1377 case HTML_SCRIPT_OFF:
1378 EndScript();
1379 break;
1381 case HTML_NOSCRIPT_ON:
1382 case HTML_NOSCRIPT_OFF:
1383 bInsertUnknown = TRUE;
1384 break;
1386 case HTML_STYLE_ON:
1387 NewStyle();
1388 break;
1390 case HTML_STYLE_OFF:
1391 EndStyle();
1392 break;
1394 case HTML_RAWDATA:
1395 if( !bIgnoreRawData )
1397 if( IsReadScript() )
1399 AddScriptSource();
1401 else if( IsReadStyle() )
1403 if( aStyleSource.Len() )
1404 aStyleSource += '\n';
1405 aStyleSource += aToken;
1408 break;
1410 case HTML_OBJECT_ON:
1411 #ifdef SOLAR_JAVA
1412 NewObject();
1413 bCallNextToken = pAppletImpl!=0 && pTable!=0;
1414 #endif
1415 break;
1417 case HTML_APPLET_ON:
1418 #ifdef SOLAR_JAVA
1419 InsertApplet();
1420 bCallNextToken = pAppletImpl!=0 && pTable!=0;
1421 #endif
1422 break;
1424 case HTML_IFRAME_ON:
1425 InsertFloatingFrame();
1426 bCallNextToken = bInFloatingFrame && pTable!=0;
1427 break;
1429 case HTML_LINEBREAK:
1430 if( !IsReadPRE() )
1432 InsertLineBreak();
1433 break;
1435 else
1436 bGetIDOption = TRUE;
1437 // <BR>s in <PRE> aehneln echten LFs, deshalb kein break
1439 case HTML_NEWPARA:
1440 // CR in PRE/LISTING/XMP
1442 if( HTML_NEWPARA==nToken ||
1443 pPam->GetPoint()->nContent.GetIndex() )
1445 AppendTxtNode(); // lf gibts hier nicht, deshalb unkritisch
1446 SetTxtCollAttrs();
1448 // Laufbalkenanzeige
1449 if( !GetMedium() || !GetMedium()->IsRemote() )
1450 ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
1452 break;
1454 case HTML_NONBREAKSPACE:
1455 pDoc->Insert( *pPam, CHAR_HARDBLANK );
1456 break;
1458 case HTML_SOFTHYPH:
1459 pDoc->Insert( *pPam, CHAR_SOFTHYPHEN );
1460 break;
1462 case HTML_LINEFEEDCHAR:
1463 if( pPam->GetPoint()->nContent.GetIndex() )
1464 AppendTxtNode();
1465 if( !pTable && !pDoc->IsInHeaderFooter( pPam->GetPoint()->nNode ) )
1467 NewAttr( &aAttrTab.pBreak, SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
1468 EndAttr( aAttrTab.pBreak, 0, FALSE );
1470 break;
1472 case HTML_TEXTTOKEN:
1473 // dann fuege den String ein, ohne das Attribute am Ende
1474 // aufgespannt werden.
1475 if( aToken.Len() && ' '==aToken.GetChar(0) && !IsReadPRE() )
1477 xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
1478 if( nPos )
1480 const String& rText =
1481 pDoc->GetNodes()[ pPam->GetPoint()->nNode ]->GetTxtNode()
1482 ->GetTxt();
1483 sal_Unicode cLast = rText.GetChar(--nPos);
1484 if( ' ' == cLast || '\x0a' == cLast)
1485 aToken.Erase(0,1);
1487 else
1488 aToken.Erase(0,1);
1490 if( !aToken.Len() )
1492 bUpperSpace = bUpperSpaceSave;
1493 break;
1497 if( aToken.Len() )
1499 if( !bDocInitalized )
1500 DocumentDetected();
1501 pDoc->Insert( *pPam, aToken, true );
1503 // wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber
1504 // nicht leer ist, dann sind die Absatz-Attribute entgueltig.
1505 if( aParaAttrs.Count() )
1506 aParaAttrs.Remove( 0, aParaAttrs.Count() );
1508 SetAttr();
1510 break;
1512 case HTML_HORZRULE:
1513 InsertHorzRule();
1514 break;
1516 case HTML_IMAGE:
1517 InsertImage();
1518 // sollte der Parser der Letzte sein, der das Doc haelt, dann kann
1519 // man hier abbrechen und einen Fehler setzen.
1520 if( 1 == pDoc->getReferenceCount() )
1522 eState = SVPAR_ERROR;
1524 break;
1526 case HTML_SPACER:
1527 InsertSpacer();
1528 break;
1530 case HTML_EMBED:
1531 InsertEmbed();
1532 break;
1534 case HTML_NOEMBED_ON:
1535 bInNoEmbed = TRUE;
1536 bCallNextToken = pTable!=0;
1537 ReadRawData( OOO_STRING_SVTOOLS_HTML_noembed );
1538 break;
1540 case HTML_DEFLIST_ON:
1541 if( nOpenParaToken )
1542 EndPara();
1543 NewDefList();
1544 break;
1545 case HTML_DEFLIST_OFF:
1546 if( nOpenParaToken )
1547 EndPara();
1548 EndDefListItem( 0, FALSE, 1==nDefListDeep );
1549 EndDefList();
1550 break;
1552 case HTML_DD_ON:
1553 case HTML_DT_ON:
1554 if( nOpenParaToken )
1555 EndPara();
1556 EndDefListItem( 0, FALSE );// <DD>/<DT> beenden und keine Vorl. setzen
1557 NewDefListItem( nToken );
1558 break;
1560 case HTML_DD_OFF:
1561 case HTML_DT_OFF:
1562 // siehe HTML_LI_OFF
1563 // eigentlich muesste man ein DD/DT jetzt beenden. Da aber sowhl
1564 // Netscape als auch Microsoft das nicht tun, machen wir das eben
1565 // auch nicht.
1566 EndDefListItem( nToken, FALSE );
1567 break;
1569 // Bereiche
1570 case HTML_DIVISION_ON:
1571 case HTML_CENTER_ON:
1572 if( nOpenParaToken )
1574 if( IsReadPRE() )
1575 nOpenParaToken = 0;
1576 else
1577 EndPara();
1579 NewDivision( nToken );
1580 break;
1582 case HTML_DIVISION_OFF:
1583 case HTML_CENTER_OFF:
1584 if( nOpenParaToken )
1586 if( IsReadPRE() )
1587 nOpenParaToken = 0;
1588 else
1589 EndPara();
1591 EndDivision( nToken );
1592 break;
1594 case HTML_MULTICOL_ON:
1595 if( nOpenParaToken )
1596 EndPara();
1597 NewMultiCol();
1598 break;
1600 case HTML_MULTICOL_OFF:
1601 if( nOpenParaToken )
1602 EndPara();
1603 EndTag( HTML_MULTICOL_ON );
1604 break;
1606 case HTML_MARQUEE_ON:
1607 NewMarquee();
1608 bCallNextToken = pMarquee!=0 && pTable!=0;
1609 break;
1611 case HTML_FORM_ON:
1612 NewForm();
1613 break;
1614 case HTML_FORM_OFF:
1615 EndForm();
1616 break;
1618 // Vorlagen:
1619 case HTML_PARABREAK_ON:
1620 if( nOpenParaToken )
1621 EndPara( TRUE );
1622 NewPara();
1623 break;
1625 case HTML_PARABREAK_OFF:
1626 EndPara( TRUE );
1627 break;
1629 case HTML_ADDRESS_ON:
1630 if( nOpenParaToken )
1631 EndPara();
1632 NewTxtFmtColl( HTML_ADDRESS_ON, RES_POOLCOLL_SENDADRESS );
1633 break;
1635 case HTML_ADDRESS_OFF:
1636 if( nOpenParaToken )
1637 EndPara();
1638 EndTxtFmtColl( HTML_ADDRESS_OFF );
1639 break;
1641 case HTML_BLOCKQUOTE_ON:
1642 case HTML_BLOCKQUOTE30_ON:
1643 if( nOpenParaToken )
1644 EndPara();
1645 NewTxtFmtColl( HTML_BLOCKQUOTE_ON, RES_POOLCOLL_HTML_BLOCKQUOTE );
1646 break;
1648 case HTML_BLOCKQUOTE_OFF:
1649 case HTML_BLOCKQUOTE30_OFF:
1650 if( nOpenParaToken )
1651 EndPara();
1652 EndTxtFmtColl( HTML_BLOCKQUOTE_ON );
1653 break;
1655 case HTML_PREFORMTXT_ON:
1656 case HTML_LISTING_ON:
1657 case HTML_XMP_ON:
1658 if( nOpenParaToken )
1659 EndPara();
1660 NewTxtFmtColl( nToken, RES_POOLCOLL_HTML_PRE );
1661 break;
1663 case HTML_PREFORMTXT_OFF:
1664 bNoParSpace = TRUE; // der letzte PRE-Absatz muss einen Zeilenabstand bekommen
1665 EndTxtFmtColl( HTML_PREFORMTXT_OFF );
1666 break;
1668 case HTML_LISTING_OFF:
1669 case HTML_XMP_OFF:
1670 EndTxtFmtColl( nToken );
1671 break;
1673 case HTML_HEAD1_ON:
1674 case HTML_HEAD2_ON:
1675 case HTML_HEAD3_ON:
1676 case HTML_HEAD4_ON:
1677 case HTML_HEAD5_ON:
1678 case HTML_HEAD6_ON:
1679 if( nOpenParaToken )
1681 if( IsReadPRE() )
1682 nOpenParaToken = 0;
1683 else
1684 EndPara();
1686 NewHeading( nToken );
1687 break;
1689 case HTML_HEAD1_OFF:
1690 case HTML_HEAD2_OFF:
1691 case HTML_HEAD3_OFF:
1692 case HTML_HEAD4_OFF:
1693 case HTML_HEAD5_OFF:
1694 case HTML_HEAD6_OFF:
1695 EndHeading();
1696 break;
1698 case HTML_TABLE_ON:
1699 if( pPendStack )
1700 BuildTable( SVX_ADJUST_END );
1701 else
1703 if( nOpenParaToken )
1704 EndPara();
1705 ASSERT( !pTable, "Tabelle in Tabelle darf hier nicht vorkommen" );
1706 if( !pTable && (IsNewDoc() || !pPam->GetNode()->FindTableNode()) &&
1707 (pPam->GetPoint()->nNode.GetIndex() >
1708 pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
1709 !pPam->GetNode()->FindFootnoteStartNode() ) )
1711 if ( nParaCnt < 5 )
1712 Show(); // bis hierhin schon mal anzeigen
1714 SvxAdjust eAdjust = aAttrTab.pAdjust
1715 ? ((const SvxAdjustItem&)aAttrTab.pAdjust->GetItem()).
1716 GetAdjust()
1717 : SVX_ADJUST_END;
1718 BuildTable( eAdjust );
1720 else
1721 bInsertUnknown = bKeepUnknown;
1723 break;
1725 // Listen
1726 case HTML_DIRLIST_ON:
1727 case HTML_MENULIST_ON:
1728 case HTML_ORDERLIST_ON:
1729 case HTML_UNORDERLIST_ON:
1730 if( nOpenParaToken )
1731 EndPara();
1732 NewNumBulList( nToken );
1733 break;
1735 case HTML_DIRLIST_OFF:
1736 case HTML_MENULIST_OFF:
1737 case HTML_ORDERLIST_OFF:
1738 case HTML_UNORDERLIST_OFF:
1739 if( nOpenParaToken )
1740 EndPara();
1741 EndNumBulListItem( 0, TRUE, GetNumInfo().GetDepth()==1 );
1742 EndNumBulList( nToken );
1743 break;
1745 case HTML_LI_ON:
1746 case HTML_LISTHEADER_ON:
1747 if( nOpenParaToken &&
1748 (pPam->GetPoint()->nContent.GetIndex()
1749 || HTML_PARABREAK_ON==nOpenParaToken) )
1751 // nure bei <P><LI> den Absatz beenden, aber nicht bei <DD><LI>
1752 EndPara();
1755 EndNumBulListItem( 0, FALSE );// <LI>/<LH> beenden und keine Vorl. setzen
1756 NewNumBulListItem( nToken );
1757 break;
1759 case HTML_LI_OFF:
1760 case HTML_LISTHEADER_OFF:
1761 EndNumBulListItem( nToken, FALSE );
1762 break;
1764 // Attribute :
1765 case HTML_ITALIC_ON:
1767 SvxPostureItem aPosture( ITALIC_NORMAL, RES_CHRATR_POSTURE );
1768 SvxPostureItem aPostureCJK( ITALIC_NORMAL, RES_CHRATR_CJK_POSTURE );
1769 SvxPostureItem aPostureCTL( ITALIC_NORMAL, RES_CHRATR_CTL_POSTURE );
1770 NewStdAttr( HTML_ITALIC_ON,
1771 &aAttrTab.pItalic, aPosture,
1772 &aAttrTab.pItalicCJK, &aPostureCJK,
1773 &aAttrTab.pItalicCTL, &aPostureCTL );
1775 break;
1777 case HTML_BOLD_ON:
1779 SvxWeightItem aWeight( WEIGHT_BOLD, RES_CHRATR_WEIGHT );
1780 SvxWeightItem aWeightCJK( WEIGHT_BOLD, RES_CHRATR_CJK_WEIGHT );
1781 SvxWeightItem aWeightCTL( WEIGHT_BOLD, RES_CHRATR_CTL_WEIGHT );
1782 NewStdAttr( HTML_BOLD_ON,
1783 &aAttrTab.pBold, aWeight,
1784 &aAttrTab.pBoldCJK, &aWeightCJK,
1785 &aAttrTab.pBoldCTL, &aWeightCTL );
1787 break;
1790 case HTML_STRIKE_ON:
1791 case HTML_STRIKETHROUGH_ON:
1793 NewStdAttr( HTML_STRIKE_ON, &aAttrTab.pStrike,
1794 SvxCrossedOutItem(STRIKEOUT_SINGLE, RES_CHRATR_CROSSEDOUT) );
1796 break;
1798 case HTML_UNDERLINE_ON:
1800 NewStdAttr( HTML_UNDERLINE_ON, &aAttrTab.pUnderline,
1801 SvxUnderlineItem(UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE) );
1803 break;
1805 case HTML_SUPERSCRIPT_ON:
1807 NewStdAttr( HTML_SUPERSCRIPT_ON, &aAttrTab.pEscapement,
1808 SvxEscapementItem(HTML_ESC_SUPER,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1810 break;
1812 case HTML_SUBSCRIPT_ON:
1814 NewStdAttr( HTML_SUBSCRIPT_ON, &aAttrTab.pEscapement,
1815 SvxEscapementItem(HTML_ESC_SUB,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1817 break;
1819 case HTML_BLINK_ON:
1821 NewStdAttr( HTML_BLINK_ON, &aAttrTab.pBlink,
1822 SvxBlinkItem( TRUE, RES_CHRATR_BLINK ) );
1824 break;
1826 case HTML_SPAN_ON:
1827 NewStdAttr( HTML_SPAN_ON );
1828 break;
1831 case HTML_ITALIC_OFF:
1832 case HTML_BOLD_OFF:
1833 case HTML_STRIKE_OFF:
1834 case HTML_UNDERLINE_OFF:
1835 case HTML_SUPERSCRIPT_OFF:
1836 case HTML_SUBSCRIPT_OFF:
1837 case HTML_BLINK_OFF:
1838 case HTML_SPAN_OFF:
1839 EndTag( nToken );
1840 break;
1842 case HTML_STRIKETHROUGH_OFF:
1843 EndTag( HTML_STRIKE_OFF );
1844 break;
1846 case HTML_BASEFONT_ON:
1847 NewBasefontAttr();
1848 break;
1849 case HTML_BASEFONT_OFF:
1850 EndBasefontAttr();
1851 break;
1852 case HTML_FONT_ON:
1853 case HTML_BIGPRINT_ON:
1854 case HTML_SMALLPRINT_ON:
1855 NewFontAttr( nToken );
1856 break;
1857 case HTML_FONT_OFF:
1858 case HTML_BIGPRINT_OFF:
1859 case HTML_SMALLPRINT_OFF:
1860 EndFontAttr( nToken );
1861 break;
1863 case HTML_EMPHASIS_ON:
1864 case HTML_CITIATION_ON:
1865 case HTML_STRONG_ON:
1866 case HTML_CODE_ON:
1867 case HTML_SAMPLE_ON:
1868 case HTML_KEYBOARD_ON:
1869 case HTML_VARIABLE_ON:
1870 case HTML_DEFINSTANCE_ON:
1871 case HTML_SHORTQUOTE_ON:
1872 case HTML_LANGUAGE_ON:
1873 case HTML_AUTHOR_ON:
1874 case HTML_PERSON_ON:
1875 case HTML_ACRONYM_ON:
1876 case HTML_ABBREVIATION_ON:
1877 case HTML_INSERTEDTEXT_ON:
1878 case HTML_DELETEDTEXT_ON:
1880 case HTML_TELETYPE_ON:
1881 NewCharFmt( nToken );
1882 break;
1884 case HTML_SDFIELD_ON:
1885 NewField();
1886 bCallNextToken = bInField && pTable!=0;
1887 break;
1889 case HTML_EMPHASIS_OFF:
1890 case HTML_CITIATION_OFF:
1891 case HTML_STRONG_OFF:
1892 case HTML_CODE_OFF:
1893 case HTML_SAMPLE_OFF:
1894 case HTML_KEYBOARD_OFF:
1895 case HTML_VARIABLE_OFF:
1896 case HTML_DEFINSTANCE_OFF:
1897 case HTML_SHORTQUOTE_OFF:
1898 case HTML_LANGUAGE_OFF:
1899 case HTML_AUTHOR_OFF:
1900 case HTML_PERSON_OFF:
1901 case HTML_ACRONYM_OFF:
1902 case HTML_ABBREVIATION_OFF:
1903 case HTML_INSERTEDTEXT_OFF:
1904 case HTML_DELETEDTEXT_OFF:
1906 case HTML_TELETYPE_OFF:
1907 EndTag( nToken );
1908 break;
1910 case HTML_HEAD_OFF:
1911 if( aStyleSource.Len() )
1913 pCSS1Parser->ParseStyleSheet( aStyleSource );
1914 aStyleSource.Erase();
1916 break;
1918 case HTML_DOCTYPE:
1919 case HTML_BODY_OFF:
1920 case HTML_HTML_OFF:
1921 case HTML_HEAD_ON:
1922 case HTML_TITLE_OFF:
1923 break; // nicht weiter auswerten, oder???
1924 case HTML_HTML_ON:
1926 const HTMLOptions *pHTMLOptions = GetOptions();
1927 for( USHORT i = pHTMLOptions->Count(); i; )
1929 const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1930 if( HTML_O_DIR == pOption->GetToken() )
1932 const String& rDir = pOption->GetString();
1933 SfxItemSet aItemSet( pDoc->GetAttrPool(),
1934 pCSS1Parser->GetWhichMap() );
1935 SvxCSS1PropertyInfo aPropInfo;
1936 String aDummy;
1937 ParseStyleOptions( aDummy, aDummy, aDummy, aItemSet,
1938 aPropInfo, 0, &rDir );
1940 pCSS1Parser->SetPageDescAttrs( 0, &aItemSet );
1941 break;
1945 break;
1947 case HTML_INPUT:
1948 InsertInput();
1949 break;
1951 case HTML_TEXTAREA_ON:
1952 NewTextArea();
1953 bCallNextToken = bTextArea && pTable!=0;
1954 break;
1956 case HTML_SELECT_ON:
1957 NewSelect();
1958 bCallNextToken = bSelect && pTable!=0;
1959 break;
1961 case HTML_ANCHOR_ON:
1962 NewAnchor();
1963 break;
1965 case HTML_ANCHOR_OFF:
1966 EndAnchor();
1967 break;
1969 case HTML_COMMENT:
1970 if( ( aToken.Len() > 5 ) && ( ! bIgnoreHTMLComments ) )
1972 // als Post-It einfuegen
1973 // MIB 8.12.2000: If there are no space characters right behind
1974 // the <!-- and on front of the -->, leave the comment untouched.
1975 if( ' ' == aToken.GetChar( 3 ) &&
1976 ' ' == aToken.GetChar( aToken.Len()-3 ) )
1978 String aComment( aToken.Copy( 3, aToken.Len()-5 ) );
1979 aComment.EraseLeadingChars().EraseTrailingChars();
1980 InsertComment( aComment );
1982 else
1984 String aComment( '<' );
1985 (aComment += aToken) += '>';
1986 InsertComment( aComment );
1989 break;
1991 case HTML_MAP_ON:
1992 // Image Maps werden asynchron gelesen: Zunaechst wird nur eine
1993 // ImageMap angelegt. Die Bereiche kommen spaeter. Trozdem wird
1994 // die ImageMap schon in das IMap-Array eingetragen, denn sie
1995 // koennte ja schon verwendet werden.
1996 pImageMap = new ImageMap;
1997 if( ParseMapOptions( pImageMap) )
1999 if( !pImageMaps )
2000 pImageMaps = new ImageMaps;
2001 pImageMaps->Insert( pImageMap, pImageMaps->Count() );
2003 else
2005 delete pImageMap;
2006 pImageMap = 0;
2008 break;
2010 case HTML_MAP_OFF:
2011 // jetzt gibt es keine ImageMap mehr (IMap nicht Loeschen, denn
2012 // die stckt ja schon in dem Array!)
2013 pImageMap = 0;
2014 break;
2016 case HTML_AREA:
2017 if( pImageMap )
2018 ParseAreaOptions( pImageMap, sBaseURL, SFX_EVENT_MOUSEOVER_OBJECT,
2019 SFX_EVENT_MOUSEOUT_OBJECT );
2020 break;
2022 case HTML_FRAMESET_ON:
2023 bInsertUnknown = bKeepUnknown;
2024 break;
2026 case HTML_NOFRAMES_ON:
2027 if( IsInHeader() )
2028 FinishHeader( TRUE );
2029 bInsertUnknown = bKeepUnknown;
2030 break;
2032 case HTML_UNKNOWNCONTROL_ON:
2033 // Im Header muss der Inhalt von unbekannten Token ignoriert werden,
2034 // es sei denn, das Token faengt mit einem '!' an.
2035 if( IsInHeader() && !IsReadPRE() && !aUnknownToken.Len() &&
2036 sSaveToken.Len() && '!' != sSaveToken.GetChar(0) &&
2037 '%' != sSaveToken.GetChar(0) )
2038 aUnknownToken = sSaveToken;
2039 // kein break
2041 default:
2042 bInsertUnknown = bKeepUnknown;
2043 break;
2046 if( bGetIDOption )
2047 InsertIDOption();
2049 if( bInsertUnknown )
2051 String aComment(
2052 String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
2053 if( (HTML_TOKEN_ONOFF & nToken) != 0 && (1 & nToken) != 0 )
2054 aComment += '/';
2055 aComment += sSaveToken;
2056 if( aToken.Len() )
2058 UnescapeToken();
2059 (aComment += ' ') += aToken;
2061 aComment += '>';
2062 InsertComment( aComment );
2065 // wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber
2066 // nicht leer ist, dann sind die Absatz-Attribute entgueltig.
2067 if( aParaAttrs.Count() && pPam->GetPoint()->nContent.GetIndex() )
2068 aParaAttrs.Remove( 0, aParaAttrs.Count() );
2071 /* \f */
2073 extern BOOL lcl_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 );
2075 void lcl_swhtml_getItemInfo( const _HTMLAttr& rAttr,
2076 sal_Bool& rScriptDependent, sal_Bool& rFont,
2077 sal_uInt16& rScriptType )
2079 sal_uInt16 nWhich = rAttr.GetItem().Which();
2080 switch( nWhich )
2082 case RES_CHRATR_FONT:
2083 rFont = sal_True;
2084 case RES_CHRATR_FONTSIZE:
2085 case RES_CHRATR_LANGUAGE:
2086 case RES_CHRATR_POSTURE:
2087 case RES_CHRATR_WEIGHT:
2088 rScriptType = i18n::ScriptType::LATIN;
2089 rScriptDependent = sal_True;
2090 break;
2091 case RES_CHRATR_CJK_FONT:
2092 rFont = sal_True;
2093 case RES_CHRATR_CJK_FONTSIZE:
2094 case RES_CHRATR_CJK_LANGUAGE:
2095 case RES_CHRATR_CJK_POSTURE:
2096 case RES_CHRATR_CJK_WEIGHT:
2097 rScriptType = i18n::ScriptType::ASIAN;
2098 rScriptDependent = sal_True;
2099 break;
2100 case RES_CHRATR_CTL_FONT:
2101 rFont = sal_True;
2102 case RES_CHRATR_CTL_FONTSIZE:
2103 case RES_CHRATR_CTL_LANGUAGE:
2104 case RES_CHRATR_CTL_POSTURE:
2105 case RES_CHRATR_CTL_WEIGHT:
2106 rScriptType = i18n::ScriptType::COMPLEX;
2107 rScriptDependent = sal_True;
2108 break;
2109 default:
2110 rScriptDependent = sal_False;
2111 rFont = sal_False;
2112 break;
2116 BOOL SwHTMLParser::AppendTxtNode( SwHTMLAppendMode eMode, BOOL bUpdateNum )
2118 // Ein harter Zeilen-Umbruch am Ende muss immer entfernt werden.
2119 // Einen zweiten ersetzen wir durch einen Absatz-Abstand.
2120 xub_StrLen nLFStripped = StripTrailingLF();
2121 if( (AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode) && nLFStripped > 1 )
2122 eMode = AM_SPACE;
2124 // die harten Attribute an diesem Absatz werden nie mehr ungueltig
2125 if( aParaAttrs.Count() )
2126 aParaAttrs.Remove( 0, aParaAttrs.Count() );
2128 if( AM_SPACE==eMode || AM_NOSPACE==eMode )
2130 SwTxtNode *pTxtNode =
2131 pDoc->GetNodes()[pPam->GetPoint()->nNode]->GetTxtNode();
2133 const SvxULSpaceItem& rULSpace =
2134 (const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2136 BOOL bChange = AM_NOSPACE==eMode ? rULSpace.GetLower() > 0
2137 : rULSpace.GetLower() == 0;
2139 if( bChange )
2141 const SvxULSpaceItem& rCollULSpace =
2142 pTxtNode->GetAnyFmtColl().GetULSpace();
2144 BOOL bMayReset = AM_NOSPACE==eMode ? rCollULSpace.GetLower() == 0
2145 : rCollULSpace.GetLower() > 0;
2147 if( bMayReset &&
2148 rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2150 pTxtNode->ResetAttr( RES_UL_SPACE );
2152 else
2154 pTxtNode->SetAttr(
2155 SvxULSpaceItem( rULSpace.GetUpper(),
2156 AM_NOSPACE==eMode ? 0 : HTML_PARSPACE, RES_UL_SPACE ) );
2160 bNoParSpace = AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode;
2162 SwPosition aOldPos( *pPam->GetPoint() );
2164 BOOL bRet = pDoc->AppendTxtNode( *pPam->GetPoint() );
2166 // Zeichen-Attribute aufspalten und ggf keine setzen, die ueber den
2167 // ganzen Absatz gesetzt sind
2168 const SwNodeIndex& rEndIdx = aOldPos.nNode;
2169 xub_StrLen nEndCnt = aOldPos.nContent.GetIndex();
2170 const SwPosition& rPos = *pPam->GetPoint();
2172 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
2173 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
2174 nCnt--; ++pTbl )
2176 _HTMLAttr *pAttr = *pTbl;
2177 if( pAttr && pAttr->GetItem().Which() < RES_PARATR_BEGIN )
2179 BOOL bWholePara = FALSE;
2181 while( pAttr )
2183 _HTMLAttr *pNext = pAttr->GetNext();
2184 if( pAttr->GetSttParaIdx() < rEndIdx.GetIndex() ||
2185 (!bWholePara &&
2186 pAttr->GetSttPara() == rEndIdx &&
2187 pAttr->GetSttCnt() != nEndCnt) )
2189 bWholePara =
2190 pAttr->GetSttPara() == rEndIdx &&
2191 pAttr->GetSttCnt() == 0;
2193 xub_StrLen nStt = pAttr->nSttCntnt;
2194 sal_Bool bScript = sal_False, bFont = sal_False;
2195 sal_uInt16 nScriptItem;
2196 sal_Bool bInsert = sal_True;
2197 lcl_swhtml_getItemInfo( *pAttr, bScript, bFont,
2198 nScriptItem );
2199 // den besehrigen Teil setzen
2200 if( bInsert && bScript )
2202 const SwTxtNode *pTxtNd =
2203 pAttr->GetSttPara().GetNode().GetTxtNode();
2204 ASSERT( pTxtNd, "No text node" );
2205 if( pTxtNd )
2207 const String& rText = pTxtNd->GetTxt();
2208 sal_uInt16 nScriptTxt =
2209 pBreakIt->GetBreakIter()->getScriptType(
2210 rText, pAttr->GetSttCnt() );
2211 xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2212 ->endOfScript( rText, nStt, nScriptTxt );
2213 while( nScriptEnd < nEndCnt )
2215 if( nScriptItem == nScriptTxt )
2217 _HTMLAttr *pSetAttr =
2218 pAttr->Clone( rEndIdx, nScriptEnd );
2219 pSetAttr->nSttCntnt = nStt;
2220 pSetAttr->ClearPrev();
2221 if( !pNext || bWholePara )
2223 USHORT nTmp = pSetAttr->bInsAtStart ? 0
2224 : aSetAttrTab.Count();
2225 aSetAttrTab.Insert( pSetAttr, nTmp );
2227 else
2228 pNext->InsertPrev( pSetAttr );
2230 nStt = nScriptEnd;
2231 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
2232 rText, nStt );
2233 nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2234 ->endOfScript( rText, nStt, nScriptTxt );
2236 bInsert = nScriptItem == nScriptTxt;
2239 if( bInsert )
2241 _HTMLAttr *pSetAttr =
2242 pAttr->Clone( rEndIdx, nEndCnt );
2243 pSetAttr->nSttCntnt = nStt;
2245 // Wenn das Attribut den gesamten Absatz umspannt, werden
2246 // alle auesseren Attribute nicht mehr beachtet. Deshalb
2247 // darf es auch nicht in die Prev-Liste eines ausseren
2248 // Attributs eingetragen werden, denn dieses wird ja
2249 // erstmal nicht gesetzt. Das fuehrt zu verschiebenungen,
2250 // wenn Felder ins Rennen kommen (siehe #51020#)
2251 if( !pNext || bWholePara )
2253 USHORT nTmp = pSetAttr->bInsAtStart ? 0
2254 : aSetAttrTab.Count();
2255 aSetAttrTab.Insert( pSetAttr, nTmp );
2257 else
2258 pNext->InsertPrev( pSetAttr );
2260 else
2262 _HTMLAttr *pPrev = pAttr->GetPrev();
2263 if( pPrev )
2265 // Die Previous-Attribute muessen trotzdem gesetzt werden.
2266 if( !pNext || bWholePara )
2268 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
2269 aSetAttrTab.Insert( pPrev, nTmp );
2271 else
2272 pNext->InsertPrev( pPrev );
2275 pAttr->ClearPrev();
2278 pAttr->SetStart( rPos );
2279 pAttr = pNext;
2284 if( bUpdateNum )
2286 if( GetNumInfo().GetDepth() )
2288 BYTE nLvl = GetNumInfo().GetLevel();
2289 // --> OD 2008-04-02 #refactorlists#
2290 // SetNoNum (&nLvl, TRUE);
2291 // SetNodeNum( nLvl);
2292 SetNodeNum( nLvl, false );
2293 // <--
2295 else
2296 pPam->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE );
2299 // Attrubute im Absatz davor sollte man jetzt setzen (wegen JavaScript)
2300 SetAttr();
2302 // Now it is time to get rid of all script dependent hints that are
2303 // equal to the settings in the style
2304 SwTxtNode *pTxtNd = rEndIdx.GetNode().GetTxtNode();
2305 ASSERT( pTxtNd, "There is the txt node" );
2306 sal_uInt16 nCntAttr = (pTxtNd && pTxtNd->GetpSwpHints())
2307 ? pTxtNd->GetSwpHints().Count() : 0;
2308 if( nCntAttr )
2310 // These are the end position of all script depenent hints.
2311 // If we find a hint that starts before the current end position,
2312 // we have to set it. If we finf a hint that start behind or at
2313 // that position, we have to take the hint's value into account.
2314 // If it is equal to the style, or in fact the paragarph's value
2315 // for that hint, the hint is removed. Otherwise it's end position
2316 // is remembered.
2317 xub_StrLen aEndPos[15] =
2318 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2319 SwpHints& rHints = pTxtNd->GetSwpHints();
2320 for( sal_uInt16 i=0; i < nCntAttr; i++ )
2322 SwTxtAttr *pHt = rHints.GetTextHint( i );
2323 sal_uInt16 nWhich = pHt->Which();
2324 sal_Int16 nIdx = -1;
2325 if( RES_CHRATR_CJK_FONT <= nWhich &&
2326 nWhich <= RES_CHRATR_CTL_WEIGHT )
2328 nIdx = static_cast< USHORT >(nWhich - RES_CHRATR_CJK_FONT + 5);
2330 else switch( nWhich )
2332 case RES_CHRATR_FONT: nIdx = 0; break;
2333 case RES_CHRATR_FONTSIZE: nIdx = 1; break;
2334 case RES_CHRATR_LANGUAGE: nIdx = 2; break;
2335 case RES_CHRATR_POSTURE: nIdx = 3; break;
2336 case RES_CHRATR_WEIGHT: nIdx = 4; break;
2338 if( nIdx != -1 )
2340 xub_StrLen nStt = *pHt->GetStart();
2341 if( nStt >= aEndPos[nIdx] )
2343 sal_Bool bFont = (nIdx % 5) == 0;
2344 const SfxPoolItem& rItem =
2345 ((const SwCntntNode *)pTxtNd)->GetAttr( nWhich );
2346 if( bFont ? lcl_css1atr_equalFontItems(rItem,pHt->GetAttr())
2347 : rItem == pHt->GetAttr() )
2349 // The hint is the same as set in the paragraph and
2350 // therfor, it can be deleted
2351 // CAUTION!!! This WILL delete the hint and it MAY
2352 // also delete the SwpHints!!! To avoid any trouble
2353 // we leave the loop immediately if this is the last
2354 // hint.
2355 pTxtNd->Delete( pHt, sal_True );
2356 if( 1 == nCntAttr )
2357 break;
2358 i--;
2359 nCntAttr--;
2361 else
2363 // The hint is deifferent. Therfor all hints within that
2364 // hint have to be ignored.
2365 aEndPos[nIdx] = pHt->GetEnd() ? *pHt->GetEnd() : nStt;
2368 else
2370 // The hint starts before another one ends.
2371 // The hint in this case is not deleted
2372 ASSERT( pHt->GetEnd() && *pHt->GetEnd() <= aEndPos[nIdx],
2373 "hints aren't nested properly!" );
2380 if( !pTable && !--nParaCnt )
2381 Show();
2383 return bRet;
2386 void SwHTMLParser::AddParSpace()
2388 if( !bNoParSpace )
2389 return;
2391 bNoParSpace = FALSE;
2393 ULONG nNdIdx = pPam->GetPoint()->nNode.GetIndex() - 1;
2395 SwTxtNode *pTxtNode = pDoc->GetNodes()[nNdIdx]->GetTxtNode();
2396 if( !pTxtNode )
2397 return;
2399 SvxULSpaceItem rULSpace =
2400 (const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2401 if( !rULSpace.GetLower() )
2403 const SvxULSpaceItem& rCollULSpace =
2404 pTxtNode->GetAnyFmtColl().GetULSpace();
2405 if( rCollULSpace.GetLower() &&
2406 rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2408 pTxtNode->ResetAttr( RES_UL_SPACE );
2410 else
2412 pTxtNode->SetAttr(
2413 SvxULSpaceItem( rULSpace.GetUpper(), HTML_PARSPACE, RES_UL_SPACE ) );
2419 void SwHTMLParser::Show()
2421 // Hier wird
2422 // - ein EndAction gerufen, damit formatiert wird
2423 // - ein Reschedule gerufen,
2424 // - die eiegen View-Shell wieder gesetzt
2425 // - und Start-Action gerufen
2427 ASSERT( SVPAR_WORKING==eState, "Show nicht im Working-State - Das kann ins Auge gehen" );
2428 ViewShell *pOldVSh = CallEndAction();
2430 GetpApp()->Reschedule();
2432 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2433 || 1 == pDoc->getReferenceCount() )
2435 // wurde der Import vom SFX abgebrochen?
2436 eState = SVPAR_ERROR;
2439 // Die ViewShell nochmal holen, denn sie koennte im Reschedule
2440 // zerstoert wirden sein.
2441 ViewShell *pVSh = CallStartAction( pOldVSh );
2443 // ist der aktuelle Node nicht mehr sichtbar, dann benutzen wir
2444 // eine groessere Schrittweite
2445 if( pVSh )
2446 nParaCnt = pDoc->GetNodes()[pPam->GetPoint()->nNode]
2447 ->IsInVisibleArea(pVSh) ? 5 : 50;
2450 void SwHTMLParser::ShowStatline()
2452 // Hier wird
2453 // - ein Reschedule gerufen, damit gescrollt werden kann
2454 // - die eiegen View-Shell wieder gesetzt
2455 // - ein Start/End-Action gerufen, wenn gescrollt wurde.
2457 ASSERT( SVPAR_WORKING==eState, "ShowStatLine nicht im Working-State - Das kann ins Auge gehen" );
2459 // Laufbalkenanzeige
2460 if( !GetMedium() || !GetMedium()->IsRemote() )
2462 ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
2463 CheckActionViewShell();
2465 else
2467 GetpApp()->Reschedule();
2469 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2470 || 1 == pDoc->getReferenceCount() )
2471 // wurde der Import vom SFX abgebrochen?
2472 eState = SVPAR_ERROR;
2474 ViewShell *pVSh = CheckActionViewShell();
2475 if( pVSh && pVSh->HasInvalidRect() )
2477 CallEndAction( FALSE, FALSE );
2478 CallStartAction( pVSh, FALSE );
2483 ViewShell *SwHTMLParser::CallStartAction( ViewShell *pVSh, BOOL bChkPtr )
2485 ASSERT( !pActionViewShell, "CallStartAction: ViewShell schon gesetzt" );
2487 if( !pVSh || bChkPtr )
2489 #ifndef PRODUCT
2490 ViewShell *pOldVSh = pVSh;
2491 #endif
2492 pDoc->GetEditShell( &pVSh );
2493 ASSERT( !pVSh || !pOldVSh || pOldVSh == pVSh, "CallStartAction: Wer hat die ViewShell ausgetauscht?" );
2494 #ifndef PRODUCT
2495 if( pOldVSh && !pVSh )
2496 pVSh = 0;
2497 #endif
2499 pActionViewShell = pVSh;
2501 if( pActionViewShell )
2503 if( pActionViewShell->ISA( SwEditShell ) )
2504 ((SwEditShell*)pActionViewShell)->StartAction();
2505 else
2506 pActionViewShell->StartAction();
2509 return pActionViewShell;
2512 ViewShell *SwHTMLParser::CallEndAction( BOOL bChkAction, BOOL bChkPtr )
2514 if( bChkPtr )
2516 ViewShell *pVSh = 0;
2517 pDoc->GetEditShell( &pVSh );
2518 ASSERT( !pVSh || pActionViewShell == pVSh,
2519 "CallEndAction: Wer hat die ViewShell ausgetauscht?" );
2520 #if OSL_DEBUG_LEVEL > 1
2521 if( pActionViewShell && !pVSh )
2522 pVSh = 0;
2523 #endif
2524 if( pVSh != pActionViewShell )
2525 pActionViewShell = 0;
2528 if( !pActionViewShell || (bChkAction && !pActionViewShell->ActionPend()) )
2529 return pActionViewShell;
2531 if( bSetCrsr )
2533 // an allen CrsrEditShells die Cursor auf den Doc-Anfang setzen
2534 ViewShell *pSh = pActionViewShell;
2535 do {
2536 if( pSh->IsA( TYPE( SwCrsrShell ) ) )
2537 ((SwCrsrShell*)pSh)->SttEndDoc(TRUE);
2538 pSh = (ViewShell *)pSh->GetNext();
2539 } while( pSh != pActionViewShell );
2541 bSetCrsr = FALSE;
2543 if( pActionViewShell->ISA( SwEditShell ) )
2545 //Schon gescrollt?, dann dafuer sorgen, dass die View sich nicht bewegt!
2546 const BOOL bOldLock = pActionViewShell->IsViewLocked();
2547 pActionViewShell->LockView( TRUE );
2548 const BOOL bOldEndActionByVirDev = pActionViewShell->IsEndActionByVirDev();
2549 pActionViewShell->SetEndActionByVirDev( TRUE );;
2550 ((SwEditShell*)pActionViewShell)->EndAction();
2551 pActionViewShell->SetEndActionByVirDev( bOldEndActionByVirDev );
2552 pActionViewShell->LockView( bOldLock );
2554 // bChkJumpMark ist nur gesetzt, wenn das Object auch gefunden wurde
2555 if( bChkJumpMark )
2557 const Point aVisSttPos( DOCUMENTBORDER, DOCUMENTBORDER );
2558 if( GetMedium() && aVisSttPos == pActionViewShell->VisArea().Pos() )
2559 ::JumpToSwMark( pActionViewShell,
2560 GetMedium()->GetURLObject().GetMark() );
2561 bChkJumpMark = FALSE;
2564 else
2565 pActionViewShell->EndAction();
2567 // sollte der Parser der Letzte sein, der das Doc haelt, dann kann
2568 // man hier abbrechen und einen Fehler setzen.
2569 if( 1 == pDoc->getReferenceCount() )
2571 eState = SVPAR_ERROR;
2574 ViewShell *pVSh = pActionViewShell;
2575 pActionViewShell = 0;
2577 return pVSh;
2580 ViewShell *SwHTMLParser::CheckActionViewShell()
2582 ViewShell *pVSh = 0;
2583 pDoc->GetEditShell( &pVSh );
2584 ASSERT( !pVSh || pActionViewShell == pVSh,
2585 "CheckActionViewShell: Wer hat die ViewShell ausgetauscht?" );
2586 #if OSL_DEBUG_LEVEL > 1
2587 if( pActionViewShell && !pVSh )
2588 pVSh = 0;
2589 #endif
2590 if( pVSh != pActionViewShell )
2591 pActionViewShell = 0;
2593 return pActionViewShell;
2596 /* \f */
2598 void SwHTMLParser::_SetAttr( BOOL bChkEnd, BOOL bBeforeTable,
2599 _HTMLAttrs *pPostIts )
2601 SwPaM* pAttrPam = new SwPaM( *pPam->GetPoint() );
2602 const SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
2603 xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2604 _HTMLAttr* pAttr;
2605 SwCntntNode* pCNd;
2606 USHORT n;
2608 _HTMLAttrs aFields( 5, 5 );
2610 for( n = aSetAttrTab.Count(); n; )
2612 pAttr = aSetAttrTab[ --n ];
2613 USHORT nWhich = pAttr->pItem->Which();
2615 ULONG nEndParaIdx = pAttr->GetEndParaIdx();
2616 BOOL bSetAttr;
2617 if( bChkEnd )
2619 // fix #42192#: Zechen-Attribute mit Ende moeglich frueh,
2620 // also noch im aktuellen Absatz setzen (wegen JavaScript
2621 // und diversen Chats). das darf man aber nicht fuer Attribute,
2622 // die ueber den ganzen Absatz aufgspannt werden sollen, weil
2623 // sie aus Absatzvorlgen stammen, die nicht gesetzt werden
2624 // koennen. Weil die Attribute mit SETATTR_DONTREPLACE
2625 // eingefuegt werden, sollte man sie auch anchtraeglich
2626 // noch setzen koennen.
2627 bSetAttr = ( nEndParaIdx < rEndIdx.GetIndex() &&
2628 (RES_LR_SPACE != nWhich || !GetNumInfo().GetNumRule()) ) ||
2629 ( !pAttr->IsLikePara() &&
2630 nEndParaIdx == rEndIdx.GetIndex() &&
2631 pAttr->GetEndCnt() < nEndCnt &&
2632 (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)) ) ||
2633 ( bBeforeTable &&
2634 nEndParaIdx == rEndIdx.GetIndex() &&
2635 !pAttr->GetEndCnt() );
2637 else
2639 // Attribiute im Content-Bereich duerfen nicht gesetzt
2640 // werden, wenn wir in einem Sonderbereich stehen, aber
2641 // umgekekehrt schon.
2642 ULONG nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2643 bSetAttr = nEndParaIdx < rEndIdx.GetIndex() ||
2644 rEndIdx.GetIndex() > nEndOfIcons ||
2645 nEndParaIdx <= nEndOfIcons;
2648 if( bSetAttr )
2650 // Das Attribute darf nicht in der liste der vorlaeufigen
2651 // Absatz-Attribute stehen, weil es sonst geloescht wurde.
2652 USHORT ii = aParaAttrs.Count();
2653 while( ii-- )
2655 ASSERT( pAttr != aParaAttrs[ii],
2656 "SetAttr: Attribut duerfte noch nicht gesetzt werden" );
2657 aParaAttrs.Remove( ii );
2661 // dann also setzen
2662 aSetAttrTab.Remove( n, 1 );
2664 while( pAttr )
2666 _HTMLAttr *pPrev = pAttr->GetPrev();
2667 if( !pAttr->bValid )
2669 // ungueltige Attribute koennen gloescht werden
2670 delete pAttr;
2671 pAttr = pPrev;
2672 continue; //break;
2676 pCNd = pDoc->GetNodes()[ pAttr->nSttPara ]->GetCntntNode();
2677 if( !pCNd )
2679 // durch die elende Loescherei von Nodes kann auch mal
2680 // ein Index auf einen End-Node zeigen :-(
2681 if ( (pAttr->GetSttPara() == pAttr->GetEndPara()) &&
2682 !isTXTATR_NOEND(nWhich) )
2684 // wenn der End-Index auch auf den Node zeigt
2685 // brauchen wir auch kein Attribut mehr zu setzen,
2686 // es sei denn, es ist ein Text-Attribut.
2687 delete pAttr;
2688 pAttr = pPrev;
2689 continue; //break;
2691 pCNd = pDoc->GetNodes().GoNext( &(pAttr->nSttPara) );
2692 if( pCNd )
2693 pAttr->nSttCntnt = 0;
2694 else
2696 ASSERT( !this, "SetAttr: GoNext() failed!" );
2697 delete pAttr;
2698 pAttr = pPrev;
2699 continue; // break;
2702 pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2706 // durch das Loeschen von BRs kann der Start-Index
2707 // auch mal hinter das Ende des Textes zeigen
2708 if( pAttr->nSttCntnt > pCNd->Len() )
2709 pAttr->nSttCntnt = pCNd->Len();
2710 pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2712 pAttrPam->SetMark();
2713 if ( (pAttr->GetSttPara() != pAttr->GetEndPara()) &&
2714 !isTXTATR_NOEND(nWhich) )
2716 pCNd = pDoc->GetNodes()[ pAttr->nEndPara ]->GetCntntNode();
2717 if( !pCNd )
2719 pCNd = pDoc->GetNodes().GoPrevious( &(pAttr->nEndPara) );
2720 if( pCNd )
2721 pAttr->nEndCntnt = pCNd->Len();
2722 else
2724 ASSERT( !this, "SetAttr: GoPrevious() failed!" );
2725 pAttrPam->DeleteMark();
2726 delete pAttr;
2727 pAttr = pPrev;
2728 continue; // break;
2732 pAttrPam->GetPoint()->nNode = pAttr->nEndPara;
2734 else if( pAttr->IsLikePara() )
2736 pAttr->nEndCntnt = pCNd->Len();
2739 // durch das Loeschen von BRs kann der End-Index
2740 // auch mal hinter das Ende des Textes zeigen
2741 if( pAttr->nEndCntnt > pCNd->Len() )
2742 pAttr->nEndCntnt = pCNd->Len();
2744 pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nEndCntnt );
2745 if( bBeforeTable &&
2746 pAttrPam->GetPoint()->nNode.GetIndex() ==
2747 rEndIdx.GetIndex() )
2749 // wenn wir vor dem Einfuegen einer Tabelle stehen
2750 // und das Attribut im aktuellen Node beendet wird,
2751 // muessen wir es im Node davor beenden oder wegschmeissen,
2752 // wenn es erst in dem Node beginnt
2753 if( nWhich != RES_BREAK && nWhich != RES_PAGEDESC &&
2754 !isTXTATR_NOEND(nWhich) )
2756 if( pAttrPam->GetMark()->nNode.GetIndex() !=
2757 rEndIdx.GetIndex() )
2759 ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2760 "Content-Position vor Tabelle nicht 0???" );
2761 pAttrPam->Move( fnMoveBackward );
2763 else
2765 pAttrPam->DeleteMark();
2766 delete pAttr;
2767 pAttr = pPrev;
2768 continue;
2773 switch( nWhich )
2775 case RES_FLTR_BOOKMARK: // insert bookmark
2777 const String sName( ((SfxStringItem*)pAttr->pItem)->GetValue() );
2778 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
2779 IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark( sName );
2780 if( ppBkmk != pMarkAccess->getMarksEnd() &&
2781 ppBkmk->get()->GetMarkStart() == *pAttrPam->GetPoint() )
2782 break; // do not generate duplicates on this position
2783 pAttrPam->DeleteMark();
2784 const ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
2785 *pAttrPam,
2786 sName,
2787 IDocumentMarkAccess::BOOKMARK );
2789 // jump to bookmark
2790 if( JUMPTO_MARK == eJumpTo && pNewMark->GetName() == ::rtl::OUString(sJmpMark) )
2792 bChkJumpMark = TRUE;
2793 eJumpTo = JUMPTO_NONE;
2796 break;
2797 case RES_TXTATR_FIELD:
2799 USHORT nFldWhich =
2800 pPostIts ? ((const SwFmtFld *)pAttr->pItem)
2801 ->GetFld()->GetTyp()->Which() : 0;
2802 if( pPostIts && (RES_POSTITFLD == nFldWhich ||
2803 RES_SCRIPTFLD == nFldWhich) )
2805 pPostIts->Insert( pAttr, 0 );
2807 else
2809 aFields.Insert( pAttr, aFields.Count() );
2812 pAttrPam->DeleteMark();
2813 pAttr = pPrev;
2814 continue;
2816 case RES_LR_SPACE:
2817 if( pAttrPam->GetPoint()->nNode.GetIndex() ==
2818 pAttrPam->GetMark()->nNode.GetIndex() &&
2819 pCNd )
2821 // wegen Numerierungen dieses Attribut direkt
2822 // am Node setzen
2823 pCNd->SetAttr( *pAttr->pItem );
2824 break;
2826 ASSERT( !this,
2827 "LRSpace ueber mehrere Absaetze gesetzt!" );
2828 // kein break (hier sollen wir trotzdem nie hinkommen;
2829 default:
2831 // ggfs. ein Bookmark anspringen
2832 if( RES_TXTATR_INETFMT == nWhich &&
2833 JUMPTO_MARK == eJumpTo &&
2834 sJmpMark == ((SwFmtINetFmt*)pAttr->pItem)->GetName() )
2836 bChkJumpMark = TRUE;
2837 eJumpTo = JUMPTO_NONE;
2840 pDoc->Insert( *pAttrPam, *pAttr->pItem, nsSetAttrMode::SETATTR_DONTREPLACE );
2842 pAttrPam->DeleteMark();
2844 delete pAttr;
2845 pAttr = pPrev;
2850 for( n = aMoveFlyFrms.Count(); n; )
2852 SwFrmFmt *pFrmFmt = aMoveFlyFrms[ --n ];
2854 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
2855 ASSERT( FLY_AT_CNTNT==rAnchor.GetAnchorId(),
2856 "Nur Auto-Rahmen brauchen eine Spezialbehandlung" );
2857 const SwPosition *pFlyPos = rAnchor.GetCntntAnchor();
2858 ULONG nFlyParaIdx = pFlyPos->nNode.GetIndex();
2859 BOOL bMoveFly;
2860 if( bChkEnd )
2862 bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2863 ( nFlyParaIdx == rEndIdx.GetIndex() &&
2864 aMoveFlyCnts[n] < nEndCnt );
2866 else
2868 ULONG nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2869 bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2870 rEndIdx.GetIndex() > nEndOfIcons ||
2871 nFlyParaIdx <= nEndOfIcons;
2873 if( bMoveFly )
2875 pFrmFmt->DelFrms();
2876 *pAttrPam->GetPoint() = *pFlyPos;
2877 pAttrPam->GetPoint()->nContent.Assign( pAttrPam->GetCntntNode(),
2878 aMoveFlyCnts[n] );
2879 SwFmtAnchor aAnchor( rAnchor );
2880 aAnchor.SetType( FLY_AUTO_CNTNT );
2881 aAnchor.SetAnchor( pAttrPam->GetPoint() );
2882 pFrmFmt->SetFmtAttr( aAnchor );
2884 const SwFmtHoriOrient& rHoriOri = pFrmFmt->GetHoriOrient();
2885 if( text::HoriOrientation::LEFT == rHoriOri.GetHoriOrient() )
2887 SwFmtHoriOrient aHoriOri( rHoriOri );
2888 aHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2889 pFrmFmt->SetFmtAttr( aHoriOri );
2891 const SwFmtVertOrient& rVertOri = pFrmFmt->GetVertOrient();
2892 if( text::VertOrientation::TOP == rVertOri.GetVertOrient() )
2894 SwFmtVertOrient aVertOri( rVertOri );
2895 aVertOri.SetRelationOrient( text::RelOrientation::CHAR );
2896 pFrmFmt->SetFmtAttr( aVertOri );
2899 pFrmFmt->MakeFrms();
2900 aMoveFlyFrms.Remove( n, 1 );
2901 aMoveFlyCnts.Remove( n, 1 );
2904 while( aFields.Count() )
2906 pAttr = aFields[0];
2908 pCNd = pDoc->GetNodes()[ pAttr->nSttPara ]->GetCntntNode();
2909 pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2910 pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2912 if( bBeforeTable &&
2913 pAttrPam->GetPoint()->nNode.GetIndex() == rEndIdx.GetIndex() )
2915 ASSERT( !bBeforeTable, "Aha, der Fall tritt also doch ein" );
2916 ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2917 "Content-Position vor Tabelle nicht 0???" );
2918 // !!!
2919 pAttrPam->Move( fnMoveBackward );
2922 pDoc->Insert( *pAttrPam, *pAttr->pItem, 0 );
2924 aFields.Remove( 0, 1 );
2925 delete pAttr;
2928 delete pAttrPam;
2931 void SwHTMLParser::NewAttr( _HTMLAttr **ppAttr, const SfxPoolItem& rItem )
2933 // Font-Hoehen und -Farben- sowie Escapement-Attribute duerfen nicht
2934 // zusammengefasst werden. Sie werden deshalb in einer Liste gespeichert,
2935 // in der das zuletzt aufgespannte Attribut vorne steht und der Count
2936 // immer 1 ist. Fuer alle anderen Attribute wird der Count einfach
2937 // hochgezaehlt.
2938 if( *ppAttr )
2940 _HTMLAttr *pAttr = new _HTMLAttr( *pPam->GetPoint(), rItem,
2941 ppAttr );
2942 pAttr->InsertNext( *ppAttr );
2943 (*ppAttr) = pAttr;
2945 else
2946 (*ppAttr) = new _HTMLAttr( *pPam->GetPoint(), rItem, ppAttr );
2950 void SwHTMLParser::EndAttr( _HTMLAttr* pAttr, _HTMLAttr **ppDepAttr,
2951 BOOL bChkEmpty )
2953 ASSERT( !ppDepAttr, "SwHTMLParser::EndAttr: ppDepAttr-Feature ungetestet?" );
2954 // Der Listenkopf ist im Attribut gespeichert
2955 _HTMLAttr **ppHead = pAttr->ppHead;
2957 ASSERT( ppHead, "keinen Attributs-Listenkopf gefunden!" );
2959 // die aktuelle Psoition als Ende-Position merken
2960 const SwNodeIndex* pEndIdx = &pPam->GetPoint()->nNode;
2961 xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2963 // WIrd das zueltzt gestartete oder ein frueher gestartetes Attribut
2964 // beendet?
2965 _HTMLAttr *pLast = 0;
2966 if( ppHead && pAttr != *ppHead )
2968 // Es wird nicht das zuletzt gestartete Attribut beendet
2970 // Dann suche wir das unmittelbar danach gestartete Attribut, das
2971 // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
2972 // mehr in der Liste
2973 pLast = *ppHead;
2974 while( pLast && pLast->GetNext() != pAttr )
2975 pLast = pLast->GetNext();
2977 ASSERT( pLast, "Attribut nicht in eigener Liste gefunden!" );
2979 // das Attribut nicht an der PaM-Psoition beenden, sondern da,
2980 // wo das danch gestartete Attribut anfing???
2981 //pEndIdx = &pPrev->GetSttPara();
2982 //nEndCnt = pPrev->GetSttCnt();
2985 BOOL bMoveBack = FALSE;
2986 USHORT nWhich = pAttr->pItem->Which();
2987 if( /*!pLast &&*/ !nEndCnt && RES_PARATR_BEGIN <= nWhich &&
2988 *pEndIdx != pAttr->GetSttPara() )
2990 // dann eine Cntntnt Position zurueck!
2991 bMoveBack = pPam->Move( fnMoveBackward );
2992 nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2995 // nun das Attrubut beenden
2996 _HTMLAttr *pNext = pAttr->GetNext();
2999 sal_Bool bInsert;
3000 sal_uInt16 nScriptItem = 0;
3001 sal_Bool bScript = sal_False, bFont = sal_False;
3002 // ein Bereich ??
3003 if( !bChkEmpty || (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
3004 RES_PAGEDESC == nWhich || RES_BREAK == nWhich ||
3005 *pEndIdx != pAttr->GetSttPara() ||
3006 nEndCnt != pAttr->GetSttCnt() )
3008 bInsert = sal_True;
3009 // We do some optimization for script depenedent attribtes here.
3010 if( *pEndIdx == pAttr->GetSttPara() )
3012 lcl_swhtml_getItemInfo( *pAttr, bScript, bFont, nScriptItem );
3015 else
3017 bInsert = sal_False;
3020 if( bInsert && bScript )
3022 const SwTxtNode *pTxtNd = pAttr->GetSttPara().GetNode()
3023 .GetTxtNode();
3024 ASSERT( pTxtNd, "No text node" );
3025 const String& rText = pTxtNd->GetTxt();
3026 sal_uInt16 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
3027 rText, pAttr->GetSttCnt() );
3028 xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
3029 ->endOfScript( rText, pAttr->GetSttCnt(), nScriptTxt );
3030 while( nScriptEnd < nEndCnt )
3032 if( nScriptItem == nScriptTxt )
3034 _HTMLAttr *pSetAttr = pAttr->Clone( *pEndIdx, nScriptEnd );
3035 pSetAttr->ClearPrev();
3036 if( pNext )
3037 pNext->InsertPrev( pSetAttr );
3038 else
3040 USHORT nTmp = pSetAttr->bInsAtStart ? 0
3041 : aSetAttrTab.Count();
3042 aSetAttrTab.Insert( pSetAttr, nTmp );
3045 pAttr->nSttCntnt = nScriptEnd;
3046 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
3047 rText, nScriptEnd );
3048 nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
3049 ->endOfScript( rText, nScriptEnd, nScriptTxt );
3051 bInsert = nScriptItem == nScriptTxt;
3053 if( bInsert )
3055 pAttr->nEndPara = *pEndIdx;
3056 pAttr->nEndCntnt = nEndCnt;
3057 pAttr->bInsAtStart = RES_TXTATR_INETFMT != nWhich &&
3058 RES_TXTATR_CHARFMT != nWhich;
3060 if( !pNext )
3062 // keine offenen Attribute dieses Typs mehr da,
3063 // dann koennen alle gesetzt werden, es sei denn
3064 // sie haengen noch von einem anderen Attribut ab,
3065 // dann werden sie dort angehaengt
3066 if( ppDepAttr && *ppDepAttr )
3067 (*ppDepAttr)->InsertPrev( pAttr );
3068 else
3070 USHORT nTmp = pAttr->bInsAtStart ? 0 : aSetAttrTab.Count();
3071 aSetAttrTab.Insert( pAttr, nTmp );
3074 else
3076 // es gibt noch andere offene Attribute des Typs,
3077 // daher muss das Setzen zurueckgestellt werden.
3078 // das aktuelle Attribut wird deshalb hinten an die
3079 // Previous-Liste des Nachfolgers angehaengt
3080 pNext->InsertPrev( pAttr );
3083 else
3085 // dann nicht einfuegen, sondern Loeschen. Durch das "tuerken" von
3086 // Vorlagen durch harte Attributierung koennen sich auch mal andere
3087 // leere Attribute in der Prev-Liste befinden, die dann trotzdem
3088 // gesetzt werden muessen
3089 _HTMLAttr *pPrev = pAttr->GetPrev();
3090 delete pAttr;
3092 if( pPrev )
3094 // Die Previous-Attribute muessen trotzdem gesetzt werden.
3095 if( pNext )
3096 pNext->InsertPrev( pPrev );
3097 else
3099 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3100 aSetAttrTab.Insert( pPrev, nTmp );
3106 // wenn das erste Attribut der Liste gesetzt wurde muss noch der
3107 // Listenkopf korrigiert werden.
3108 if( pLast )
3109 pLast->pNext = pNext;
3110 else if( ppHead )
3111 *ppHead = pNext;
3113 if( bMoveBack )
3114 pPam->Move( fnMoveForward );
3117 void SwHTMLParser::DeleteAttr( _HTMLAttr* pAttr )
3119 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3120 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3121 ASSERT( !aParaAttrs.Count(),
3122 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3123 if( aParaAttrs.Count() )
3124 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3126 // Der Listenkopf ist im Attribut gespeichert
3127 _HTMLAttr **ppHead = pAttr->ppHead;
3129 ASSERT( ppHead, "keinen Attributs-Listenkopf gefunden!" );
3131 // Wird das zueltzt gestartete oder ein frueher gestartetes Attribut
3132 // entfernt?
3133 _HTMLAttr *pLast = 0;
3134 if( ppHead && pAttr != *ppHead )
3136 // Es wird nicht das zuletzt gestartete Attribut beendet
3138 // Dann suche wir das unmittelbar danach gestartete Attribut, das
3139 // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
3140 // mehr in der Liste
3141 pLast = *ppHead;
3142 while( pLast && pLast->GetNext() != pAttr )
3143 pLast = pLast->GetNext();
3145 ASSERT( pLast, "Attribut nicht in eigener Liste gefunden!" );
3148 // nun das Attrubut entfernen
3149 _HTMLAttr *pNext = pAttr->GetNext();
3150 _HTMLAttr *pPrev = pAttr->GetPrev();
3151 delete pAttr;
3153 if( pPrev )
3155 // Die Previous-Attribute muessen trotzdem gesetzt werden.
3156 if( pNext )
3157 pNext->InsertPrev( pPrev );
3158 else
3160 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3161 aSetAttrTab.Insert( pPrev, nTmp );
3165 // wenn das erste Attribut der Liste entfernt wurde muss noch der
3166 // Listenkopf korrigiert werden.
3167 if( pLast )
3168 pLast->pNext = pNext;
3169 else if( ppHead )
3170 *ppHead = pNext;
3173 void SwHTMLParser::SaveAttrTab( _HTMLAttrTable& rNewAttrTab )
3175 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3176 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3177 ASSERT( !aParaAttrs.Count(),
3178 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3179 if( aParaAttrs.Count() )
3180 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3182 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3183 _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3185 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3186 nCnt--; (++pTbl, ++pSaveTbl) )
3188 *pSaveTbl = *pTbl;
3190 _HTMLAttr *pAttr = *pSaveTbl;
3191 while( pAttr )
3193 pAttr->SetHead( pSaveTbl );
3194 pAttr = pAttr->GetNext();
3197 *pTbl = 0;
3201 void SwHTMLParser::SplitAttrTab( _HTMLAttrTable& rNewAttrTab,
3202 BOOL bMoveEndBack )
3204 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3205 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3206 ASSERT( !aParaAttrs.Count(),
3207 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3208 if( aParaAttrs.Count() )
3209 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3211 const SwNodeIndex& nSttIdx = pPam->GetPoint()->nNode;
3212 SwNodeIndex nEndIdx( nSttIdx );
3214 // alle noch offenen Attribute beenden und hinter der Tabelle
3215 // neu aufspannen
3216 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3217 _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3218 BOOL bSetAttr = TRUE;
3219 xub_StrLen nSttCnt = pPam->GetPoint()->nContent.GetIndex();
3220 xub_StrLen nEndCnt = nSttCnt;
3222 if( bMoveEndBack )
3224 ULONG nOldEnd = nEndIdx.GetIndex();
3225 ULONG nTmpIdx;
3226 if( ( nTmpIdx = pDoc->GetNodes().GetEndOfExtras().GetIndex()) >= nOldEnd ||
3227 ( nTmpIdx = pDoc->GetNodes().GetEndOfAutotext().GetIndex()) >= nOldEnd )
3229 nTmpIdx = pDoc->GetNodes().GetEndOfInserts().GetIndex();
3231 SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious(&nEndIdx);
3233 // keine Attribute setzen, wenn der PaM aus dem Content-Bereich
3234 // herausgeschoben wurde.
3235 bSetAttr = pCNd && nTmpIdx < nEndIdx.GetIndex();
3237 nEndCnt = (bSetAttr ? pCNd->Len() : 0);
3239 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3240 nCnt--; (++pTbl, ++pSaveTbl) )
3242 _HTMLAttr *pAttr = *pTbl;
3243 *pSaveTbl = 0;
3244 while( pAttr )
3246 _HTMLAttr *pNext = pAttr->GetNext();
3247 _HTMLAttr *pPrev = pAttr->GetPrev();
3249 if( bSetAttr &&
3250 ( pAttr->GetSttParaIdx() < nEndIdx.GetIndex() ||
3251 (pAttr->GetSttPara() == nEndIdx &&
3252 pAttr->GetSttCnt() != nEndCnt) ) )
3254 // das Attribut muss vor der Liste gesetzt werden. Da wir
3255 // das Original noch brauchen, weil Zeiger auf das Attribut
3256 // noch in den Kontexten existieren, muessen wir es clonen.
3257 // Die Next-Liste geht dabei verloren, aber die
3258 // Previous-Liste bleibt erhalten
3259 _HTMLAttr *pSetAttr = pAttr->Clone( nEndIdx, nEndCnt );
3261 if( pNext )
3262 pNext->InsertPrev( pSetAttr );
3263 else
3265 USHORT nTmp = pSetAttr->bInsAtStart ? 0
3266 : aSetAttrTab.Count();
3267 aSetAttrTab.Insert( pSetAttr, nTmp );
3270 else if( pPrev )
3272 // Wenn das Attribut nicht gesetzt vor der Tabelle
3273 // gesetzt werden muss, muessen der Previous-Attribute
3274 // trotzdem gesetzt werden.
3275 if( pNext )
3276 pNext->InsertPrev( pPrev );
3277 else
3279 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3280 aSetAttrTab.Insert( pPrev, nTmp );
3284 // den Start des Attributs neu setzen und die Verkettungen
3285 // aufbrechen
3286 pAttr->Reset( nSttIdx, nSttCnt, pSaveTbl );
3288 if( *pSaveTbl )
3290 _HTMLAttr *pSAttr = *pSaveTbl;
3291 while( pSAttr->GetNext() )
3292 pSAttr = pSAttr->GetNext();
3293 pSAttr->InsertNext( pAttr );
3295 else
3296 *pSaveTbl = pAttr;
3298 pAttr = pNext;
3301 *pTbl = 0;
3305 void SwHTMLParser::RestoreAttrTab( const _HTMLAttrTable& rNewAttrTab,
3306 BOOL bSetNewStart )
3308 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3309 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3310 ASSERT( !aParaAttrs.Count(),
3311 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3312 if( aParaAttrs.Count() )
3313 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3315 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3316 _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3318 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3319 nCnt--; (++pTbl, ++pSaveTbl) )
3321 ASSERT( !*pTbl, "Die Attribut-Tabelle ist nicht leer!" );
3323 const SwPosition *pPos = pPam->GetPoint();
3324 const SwNodeIndex& rSttPara = pPos->nNode;
3325 xub_StrLen nSttCnt = pPos->nContent.GetIndex();
3327 *pTbl = *pSaveTbl;
3329 _HTMLAttr *pAttr = *pTbl;
3330 while( pAttr )
3332 ASSERT( !pAttr->GetPrev() || !pAttr->GetPrev()->ppHead,
3333 "Previous-Attribut hat noch einen Header" );
3334 pAttr->SetHead( pTbl );
3335 if( bSetNewStart )
3337 pAttr->nSttPara = rSttPara;
3338 pAttr->nEndPara = rSttPara;
3339 pAttr->nSttCntnt = nSttCnt;
3340 pAttr->nEndCntnt = nSttCnt;
3342 pAttr = pAttr->GetNext();
3345 *pSaveTbl = 0;
3349 void SwHTMLParser::InsertAttr( const SfxPoolItem& rItem, BOOL bLikePara,
3350 BOOL bInsAtStart )
3352 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(),
3353 rItem );
3354 if( bLikePara )
3355 pTmp->SetLikePara();
3356 USHORT nTmp = bInsAtStart ? 0 : aSetAttrTab.Count();
3357 aSetAttrTab.Insert( pTmp, nTmp );
3360 void SwHTMLParser::InsertAttrs( _HTMLAttrs& rAttrs )
3362 while( rAttrs.Count() )
3364 _HTMLAttr *pAttr = rAttrs[0];
3365 InsertAttr( pAttr->GetItem() );
3366 rAttrs.Remove( 0, 1 );
3367 delete pAttr;
3371 /* \f */
3373 void SwHTMLParser::NewStdAttr( int nToken )
3375 String aId, aStyle, aClass, aLang, aDir;
3377 const HTMLOptions *pHTMLOptions = GetOptions();
3378 for( USHORT i = pHTMLOptions->Count(); i; )
3380 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3381 switch( pOption->GetToken() )
3383 case HTML_O_ID:
3384 aId = pOption->GetString();
3385 break;
3386 case HTML_O_STYLE:
3387 aStyle = pOption->GetString();
3388 break;
3389 case HTML_O_CLASS:
3390 aClass = pOption->GetString();
3391 break;
3392 case HTML_O_LANG:
3393 aLang = pOption->GetString();
3394 break;
3395 case HTML_O_DIR:
3396 aDir = pOption->GetString();
3397 break;
3401 // einen neuen Kontext anlegen
3402 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3404 // Styles parsen
3405 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3407 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3408 SvxCSS1PropertyInfo aPropInfo;
3410 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3412 if( HTML_SPAN_ON != nToken || !aClass.Len() ||
3413 !CreateContainer( aClass, aItemSet, aPropInfo, pCntxt ) )
3414 DoPositioning( aItemSet, aPropInfo, pCntxt );
3415 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3419 // den Kontext merken
3420 PushContext( pCntxt );
3423 void SwHTMLParser::NewStdAttr( int nToken,
3424 _HTMLAttr **ppAttr, const SfxPoolItem & rItem,
3425 _HTMLAttr **ppAttr2, const SfxPoolItem *pItem2,
3426 _HTMLAttr **ppAttr3, const SfxPoolItem *pItem3 )
3428 String aId, aStyle, aClass, aLang, aDir;
3430 const HTMLOptions *pHTMLOptions = GetOptions();
3431 for( USHORT i = pHTMLOptions->Count(); i; )
3433 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3434 switch( pOption->GetToken() )
3436 case HTML_O_ID:
3437 aId = pOption->GetString();
3438 break;
3439 case HTML_O_STYLE:
3440 aStyle = pOption->GetString();
3441 break;
3442 case HTML_O_CLASS:
3443 aClass = pOption->GetString();
3444 break;
3445 case HTML_O_LANG:
3446 aLang = pOption->GetString();
3447 break;
3448 case HTML_O_DIR:
3449 aDir = pOption->GetString();
3450 break;
3454 // einen neuen Kontext anlegen
3455 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3457 // Styles parsen
3458 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3460 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3461 SvxCSS1PropertyInfo aPropInfo;
3463 aItemSet.Put( rItem );
3464 if( pItem2 )
3465 aItemSet.Put( *pItem2 );
3466 if( pItem3 )
3467 aItemSet.Put( *pItem3 );
3469 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3470 DoPositioning( aItemSet, aPropInfo, pCntxt );
3472 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3474 else
3476 InsertAttr( ppAttr ,rItem, pCntxt );
3477 if( pItem2 )
3479 ASSERT( ppAttr2, "missing table entry for item2" );
3480 InsertAttr( ppAttr2, *pItem2, pCntxt );
3482 if( pItem3 )
3484 ASSERT( ppAttr3, "missing table entry for item3" );
3485 InsertAttr( ppAttr3, *pItem3, pCntxt );
3489 // den Kontext merken
3490 PushContext( pCntxt );
3493 void SwHTMLParser::EndTag( int nToken )
3495 // den Kontext holen
3496 _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
3497 if( pCntxt )
3499 // und ggf. die Attribute beenden
3500 EndContext( pCntxt );
3501 delete pCntxt;
3506 void SwHTMLParser::NewBasefontAttr()
3508 String aId, aStyle, aClass, aLang, aDir;
3509 USHORT nSize = 3;
3511 const HTMLOptions *pHTMLOptions = GetOptions();
3512 for( USHORT i = pHTMLOptions->Count(); i; )
3514 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3515 switch( pOption->GetToken() )
3517 case HTML_O_SIZE:
3518 nSize = (USHORT)pOption->GetNumber();
3519 break;
3520 case HTML_O_ID:
3521 aId = pOption->GetString();
3522 break;
3523 case HTML_O_STYLE:
3524 aStyle = pOption->GetString();
3525 break;
3526 case HTML_O_CLASS:
3527 aClass = pOption->GetString();
3528 break;
3529 case HTML_O_LANG:
3530 aLang = pOption->GetString();
3531 break;
3532 case HTML_O_DIR:
3533 aDir = pOption->GetString();
3534 break;
3538 if( nSize < 1 )
3539 nSize = 1;
3541 if( nSize > 7 )
3542 nSize = 7;
3544 // einen neuen Kontext anlegen
3545 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_BASEFONT_ON );
3547 // Styles parsen
3548 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3550 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3551 SvxCSS1PropertyInfo aPropInfo;
3553 SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3554 aItemSet.Put( aFontHeight );
3555 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3556 aItemSet.Put( aFontHeight );
3557 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3558 aItemSet.Put( aFontHeight );
3560 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3561 DoPositioning( aItemSet, aPropInfo, pCntxt );
3563 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3565 else
3567 SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3568 InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3569 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3570 InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3571 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3572 InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3575 // den Kontext merken
3576 PushContext( pCntxt );
3578 // die Font-Size merken
3579 aBaseFontStack.Insert( nSize, aBaseFontStack.Count() );
3582 void SwHTMLParser::EndBasefontAttr()
3584 EndTag( HTML_BASEFONT_ON );
3586 // Stack-Unterlauf in Tabellen vermeiden
3587 if( aBaseFontStack.Count() > nBaseFontStMin )
3588 aBaseFontStack.Remove( aBaseFontStack.Count()-1, 1 );
3591 void SwHTMLParser::NewFontAttr( int nToken )
3593 USHORT nBaseSize =
3594 ( aBaseFontStack.Count() > nBaseFontStMin
3595 ? (aBaseFontStack[aBaseFontStack.Count()-1] & FONTSIZE_MASK)
3596 : 3 );
3597 USHORT nFontSize =
3598 ( aFontStack.Count() > nFontStMin
3599 ? (aFontStack[aFontStack.Count()-1] & FONTSIZE_MASK)
3600 : nBaseSize );
3602 String aFace, aId, aStyle, aClass, aLang, aDir;
3603 Color aColor;
3604 ULONG nFontHeight = 0; // tatsaechlich einzustellende Font-Hoehe
3605 USHORT nSize = 0; // Fontgroesse in Netscape-Notation (1-7)
3606 BOOL bColor = FALSE;
3608 const HTMLOptions *pHTMLOptions = GetOptions();
3609 for( USHORT i = pHTMLOptions->Count(); i; )
3611 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3612 switch( pOption->GetToken() )
3614 case HTML_O_SIZE:
3615 if( HTML_FONT_ON==nToken && pOption->GetString().Len() )
3617 INT32 nSSize;
3618 if( '+' == pOption->GetString().GetChar(0) ||
3619 '-' == pOption->GetString().GetChar(0) )
3620 nSSize = nBaseSize + pOption->GetSNumber();
3621 else
3622 nSSize = (INT32)pOption->GetNumber();
3624 if( nSSize < 1 )
3625 nSSize = 1;
3626 else if( nSSize > 7 )
3627 nSSize = 7;
3629 nSize = (USHORT)nSSize;
3630 nFontHeight = aFontHeights[nSize-1];
3632 break;
3633 case HTML_O_COLOR:
3634 if( HTML_FONT_ON==nToken )
3636 pOption->GetColor( aColor );
3637 bColor = TRUE;
3639 break;
3640 case HTML_O_FACE:
3641 if( HTML_FONT_ON==nToken )
3642 aFace = pOption->GetString();
3643 break;
3644 case HTML_O_ID:
3645 aId = pOption->GetString();
3646 break;
3647 case HTML_O_STYLE:
3648 aStyle = pOption->GetString();
3649 break;
3650 case HTML_O_CLASS:
3651 aClass = pOption->GetString();
3652 break;
3653 case HTML_O_LANG:
3654 aLang = pOption->GetString();
3655 break;
3656 case HTML_O_DIR:
3657 aDir = pOption->GetString();
3658 break;
3662 if( HTML_FONT_ON != nToken )
3664 // HTML_BIGPRINT_ON oder HTML_SMALLPRINT_ON
3666 // in Ueberschriften bestimmt die aktuelle Ueberschrift
3667 // die Font-Hoehe und nicht BASEFONT
3668 USHORT nPoolId = GetCurrFmtColl()->GetPoolFmtId();
3669 if( (nPoolId>=RES_POOLCOLL_HEADLINE1 &&
3670 nPoolId<=RES_POOLCOLL_HEADLINE6) )
3672 // wenn die Schriftgroesse in der Ueberschrift noch
3673 // nicht veraendert ist, die aus der Vorlage nehmen
3674 if( nFontStHeadStart==aFontStack.Count() )
3675 nFontSize = static_cast< USHORT >(6 - (nPoolId - RES_POOLCOLL_HEADLINE1));
3677 else
3678 nPoolId = 0;
3680 if( HTML_BIGPRINT_ON == nToken )
3681 nSize = ( nFontSize<7 ? nFontSize+1 : 7 );
3682 else
3683 nSize = ( nFontSize>1 ? nFontSize-1 : 1 );
3685 // in Ueberschriften wird die neue Fonthoehe wenn moeglich aus
3686 // den Vorlagen geholt.
3687 if( nPoolId && nSize>=1 && nSize <=6 )
3688 nFontHeight =
3689 pCSS1Parser->GetTxtCollFromPool(
3690 RES_POOLCOLL_HEADLINE1+6-nSize )->GetSize().GetHeight();
3691 else
3692 nFontHeight = aFontHeights[nSize-1];
3695 ASSERT( !nSize == !nFontHeight, "HTML-Font-Size != Font-Height" );
3697 String aFontName, aStyleName;
3698 FontFamily eFamily = FAMILY_DONTKNOW; // Family und Pitch,
3699 FontPitch ePitch = PITCH_DONTKNOW; // falls nicht gefunden
3700 rtl_TextEncoding eEnc = gsl_getSystemTextEncoding();
3702 if( aFace.Len() && !pCSS1Parser->IsIgnoreFontFamily() )
3704 const FontList *pFList = 0;
3705 SwDocShell *pDocSh = pDoc->GetDocShell();
3706 if( pDocSh )
3708 const SvxFontListItem *pFListItem =
3709 (const SvxFontListItem *)pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST);
3710 if( pFListItem )
3711 pFList = pFListItem->GetFontList();
3714 BOOL bFound = FALSE;
3715 xub_StrLen nStrPos = 0;
3716 while( nStrPos!=STRING_NOTFOUND )
3718 String aFName = aFace.GetToken( 0, ',', nStrPos );
3719 aFName.EraseTrailingChars().EraseLeadingChars();
3720 if( aFName.Len() )
3722 if( !bFound && pFList )
3724 sal_Handle hFont = pFList->GetFirstFontInfo( aFName );
3725 if( 0 != hFont )
3727 const FontInfo& rFInfo = pFList->GetFontInfo( hFont );
3728 if( RTL_TEXTENCODING_DONTKNOW != rFInfo.GetCharSet() )
3730 bFound = TRUE;
3731 if( RTL_TEXTENCODING_SYMBOL == rFInfo.GetCharSet() )
3732 eEnc = RTL_TEXTENCODING_SYMBOL;
3736 if( aFontName.Len() )
3737 aFontName += ';';
3738 aFontName += aFName;
3744 // einen neuen Kontext anlegen
3745 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3747 // Styles parsen
3748 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3750 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3751 SvxCSS1PropertyInfo aPropInfo;
3753 if( nFontHeight )
3755 SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3756 aItemSet.Put( aFontHeight );
3757 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3758 aItemSet.Put( aFontHeight );
3759 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3760 aItemSet.Put( aFontHeight );
3762 if( bColor )
3763 aItemSet.Put( SvxColorItem(aColor, RES_CHRATR_COLOR) );
3764 if( aFontName.Len() )
3766 SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3767 aItemSet.Put( aFont );
3768 aFont.SetWhich( RES_CHRATR_CJK_FONT );
3769 aItemSet.Put( aFont );
3770 aFont.SetWhich( RES_CHRATR_CTL_FONT );
3771 aItemSet.Put( aFont );
3775 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3776 DoPositioning( aItemSet, aPropInfo, pCntxt );
3778 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3780 else
3782 if( nFontHeight )
3784 SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3785 InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3786 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3787 InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3788 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3789 InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3791 if( bColor )
3792 InsertAttr( &aAttrTab.pFontColor, SvxColorItem(aColor, RES_CHRATR_COLOR), pCntxt );
3793 if( aFontName.Len() )
3795 SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3796 InsertAttr( &aAttrTab.pFont, aFont, pCntxt );
3797 aFont.SetWhich( RES_CHRATR_CJK_FONT );
3798 InsertAttr( &aAttrTab.pFontCJK, aFont, pCntxt );
3799 aFont.SetWhich( RES_CHRATR_CTL_FONT );
3800 InsertAttr( &aAttrTab.pFontCTL, aFont, pCntxt );
3804 // den Kontext merken
3805 PushContext( pCntxt );
3807 aFontStack.Insert( nSize, aFontStack.Count() );
3810 void SwHTMLParser::EndFontAttr( int nToken )
3812 EndTag( nToken );
3814 // Stack-Unterlauf in Tabellen vermeiden
3815 if( aFontStack.Count() > nFontStMin )
3816 aFontStack.Remove( aFontStack.Count()-1, 1 );
3819 /* \f */
3821 void SwHTMLParser::NewPara()
3823 if( pPam->GetPoint()->nContent.GetIndex() )
3824 AppendTxtNode( AM_SPACE );
3825 else
3826 AddParSpace();
3828 eParaAdjust = SVX_ADJUST_END;
3829 String aId, aStyle, aClass, aLang, aDir;
3831 const HTMLOptions *pHTMLOptions = GetOptions();
3832 for( USHORT i = pHTMLOptions->Count(); i; )
3834 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3835 switch( pOption->GetToken() )
3837 case HTML_O_ID:
3838 aId = pOption->GetString();
3839 break;
3840 case HTML_O_ALIGN:
3841 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3842 break;
3843 case HTML_O_STYLE:
3844 aStyle = pOption->GetString();
3845 break;
3846 case HTML_O_CLASS:
3847 aClass = pOption->GetString();
3848 break;
3849 case HTML_O_LANG:
3850 aLang = pOption->GetString();
3851 break;
3852 case HTML_O_DIR:
3853 aDir = pOption->GetString();
3854 break;
3858 // einen neuen Kontext anlegen
3859 _HTMLAttrContext *pCntxt =
3860 aClass.Len() ? new _HTMLAttrContext( HTML_PARABREAK_ON,
3861 RES_POOLCOLL_TEXT, aClass )
3862 : new _HTMLAttrContext( HTML_PARABREAK_ON );
3864 // Styles parsen (Class nicht beruecksichtigen. Das geht nur, solange
3865 // keine der CSS1-Properties der Klasse hart formatiert werden muss!!!)
3866 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
3868 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3869 SvxCSS1PropertyInfo aPropInfo;
3871 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
3873 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
3874 "Class wird nicht beruecksichtigt" );
3875 DoPositioning( aItemSet, aPropInfo, pCntxt );
3876 InsertAttrs( aItemSet, aPropInfo, pCntxt );
3880 if( SVX_ADJUST_END != eParaAdjust )
3881 InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
3883 // und auf den Stack packen
3884 PushContext( pCntxt );
3886 // die aktuelle Vorlage oder deren Attribute setzen
3887 SetTxtCollAttrs( aClass.Len() ? pCntxt : 0 );
3889 // Laufbalkenanzeige
3890 ShowStatline();
3892 ASSERT( !nOpenParaToken, "Jetzt geht ein offenes Absatz-Element verloren" );
3893 nOpenParaToken = HTML_PARABREAK_ON;
3896 void SwHTMLParser::EndPara( BOOL bReal )
3898 if( HTML_LI_ON==nOpenParaToken && pTable )
3900 #ifndef PRODUCT
3901 const SwNumRule *pNumRule = pPam->GetNode()->GetTxtNode()->GetNumRule();
3902 #endif
3903 ASSERT( pNumRule, "Wo ist die Numrule geblieben" );
3906 // leere Absaetze werden von Netscape uebersprungen, von uns jetzt auch
3907 if( bReal )
3909 if( pPam->GetPoint()->nContent.GetIndex() )
3910 AppendTxtNode( AM_SPACE );
3911 else
3912 AddParSpace();
3915 // wenn ein DD oder DT offen war, handelt es sich um eine
3916 // implizite Def-Liste, die jetzt beendet werden muss
3917 if( (nOpenParaToken==HTML_DT_ON || nOpenParaToken==HTML_DD_ON) &&
3918 nDefListDeep)
3920 nDefListDeep--;
3923 // den Kontext vom Stack holen. Er kann auch von einer implizit
3924 // geoeffneten Definitionsliste kommen
3925 _HTMLAttrContext *pCntxt =
3926 PopContext( static_cast< sal_uInt16 >(nOpenParaToken ? (nOpenParaToken & ~1)
3927 : HTML_PARABREAK_ON) );
3929 // Attribute beenden
3930 if( pCntxt )
3932 EndContext( pCntxt );
3933 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
3934 delete pCntxt;
3937 // und die bisherige Vorlage neu setzen
3938 if( bReal )
3939 SetTxtCollAttrs();
3941 nOpenParaToken = 0;
3945 void SwHTMLParser::NewHeading( int nToken )
3947 eParaAdjust = SVX_ADJUST_END;
3949 String aId, aStyle, aClass, aLang, aDir;
3951 const HTMLOptions *pHTMLOptions = GetOptions();
3952 for( USHORT i = pHTMLOptions->Count(); i; )
3954 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3955 switch( pOption->GetToken() )
3957 case HTML_O_ID:
3958 aId = pOption->GetString();
3959 break;
3960 case HTML_O_ALIGN:
3961 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3962 break;
3963 case HTML_O_STYLE:
3964 aStyle = pOption->GetString();
3965 break;
3966 case HTML_O_CLASS:
3967 aClass = pOption->GetString();
3968 break;
3969 case HTML_O_LANG:
3970 aLang = pOption->GetString();
3971 break;
3972 case HTML_O_DIR:
3973 aDir = pOption->GetString();
3974 break;
3978 // einen neuen Absatz aufmachen
3979 if( pPam->GetPoint()->nContent.GetIndex() )
3980 AppendTxtNode( AM_SPACE );
3981 else
3982 AddParSpace();
3984 // die passende Vorlage suchen
3985 USHORT nTxtColl;
3986 switch( nToken )
3988 case HTML_HEAD1_ON: nTxtColl = RES_POOLCOLL_HEADLINE1; break;
3989 case HTML_HEAD2_ON: nTxtColl = RES_POOLCOLL_HEADLINE2; break;
3990 case HTML_HEAD3_ON: nTxtColl = RES_POOLCOLL_HEADLINE3; break;
3991 case HTML_HEAD4_ON: nTxtColl = RES_POOLCOLL_HEADLINE4; break;
3992 case HTML_HEAD5_ON: nTxtColl = RES_POOLCOLL_HEADLINE5; break;
3993 case HTML_HEAD6_ON: nTxtColl = RES_POOLCOLL_HEADLINE6; break;
3994 default: nTxtColl = RES_POOLCOLL_STANDARD; break;
3997 // den Kontext anlegen
3998 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nTxtColl, aClass );
4000 // Styles parsen (zu Class siehe auch NewPara)
4001 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4003 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4004 SvxCSS1PropertyInfo aPropInfo;
4006 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4008 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4009 "Class wird nicht beruecksichtigt" );
4010 DoPositioning( aItemSet, aPropInfo, pCntxt );
4011 InsertAttrs( aItemSet, aPropInfo, pCntxt );
4015 if( SVX_ADJUST_END != eParaAdjust )
4016 InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
4018 // udn auf den Stack packen
4019 PushContext( pCntxt );
4021 // und die Vorlage oder deren Attribute setzen
4022 SetTxtCollAttrs( pCntxt );
4024 nFontStHeadStart = aFontStack.Count();
4026 // Laufbalkenanzeige
4027 ShowStatline();
4030 void SwHTMLParser::EndHeading()
4032 // einen neuen Absatz aufmachen
4033 if( pPam->GetPoint()->nContent.GetIndex() )
4034 AppendTxtNode( AM_SPACE );
4035 else
4036 AddParSpace();
4038 // Kontext zu dem Token suchen und vom Stack holen
4039 _HTMLAttrContext *pCntxt = 0;
4040 USHORT nPos = aContexts.Count();
4041 while( !pCntxt && nPos>nContextStMin )
4043 switch( aContexts[--nPos]->GetToken() )
4045 case HTML_HEAD1_ON:
4046 case HTML_HEAD2_ON:
4047 case HTML_HEAD3_ON:
4048 case HTML_HEAD4_ON:
4049 case HTML_HEAD5_ON:
4050 case HTML_HEAD6_ON:
4051 pCntxt = aContexts[nPos];
4052 aContexts.Remove( nPos, 1 );
4053 break;
4057 // und noch Attribute beenden
4058 if( pCntxt )
4060 EndContext( pCntxt );
4061 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4062 delete pCntxt;
4065 // die bisherige Vorlage neu setzen
4066 SetTxtCollAttrs();
4068 nFontStHeadStart = nFontStMin;
4071 /* \f */
4073 void SwHTMLParser::NewTxtFmtColl( int nToken, USHORT nColl )
4075 String aId, aStyle, aClass, aLang, aDir;
4077 const HTMLOptions *pHTMLOptions = GetOptions();
4078 for( USHORT i = pHTMLOptions->Count(); i; )
4080 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4081 switch( pOption->GetToken() )
4083 case HTML_O_ID:
4084 aId = pOption->GetString();
4085 break;
4086 case HTML_O_STYLE:
4087 aStyle = pOption->GetString();
4088 break;
4089 case HTML_O_CLASS:
4090 aClass = pOption->GetString();
4091 break;
4092 case HTML_O_LANG:
4093 aLang = pOption->GetString();
4094 break;
4095 case HTML_O_DIR:
4096 aDir = pOption->GetString();
4097 break;
4101 // einen neuen Absatz aufmachen
4102 SwHTMLAppendMode eMode = AM_NORMAL;
4103 switch( nToken )
4105 case HTML_LISTING_ON:
4106 case HTML_XMP_ON:
4107 // Diese beiden Tags werden jetzt auf die PRE-Vorlage gemappt.
4108 // Fuer dem Fall, dass ein CLASS angegeben ist, loeschen wir
4109 // es damit wir nicht die CLASS der PRE-Vorlage bekommen.
4110 aClass = aEmptyStr;
4111 case HTML_BLOCKQUOTE_ON:
4112 case HTML_BLOCKQUOTE30_ON:
4113 case HTML_PREFORMTXT_ON:
4114 eMode = AM_SPACE;
4115 break;
4116 case HTML_ADDRESS_ON:
4117 eMode = AM_NOSPACE; // ADDRESS kann auf einen <P> ohne </P> folgen
4118 break;
4119 case HTML_DT_ON:
4120 case HTML_DD_ON:
4121 eMode = AM_SOFTNOSPACE;
4122 break;
4123 default:
4124 ASSERT( !this, "unbekannte Vorlage" );
4125 break;
4127 if( pPam->GetPoint()->nContent.GetIndex() )
4128 AppendTxtNode( eMode );
4129 else if( AM_SPACE==eMode )
4130 AddParSpace();
4132 // ... und in einem Kontext merken
4133 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nColl, aClass );
4135 // Styles parsen (zu Class siehe auch NewPara)
4136 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4138 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4139 SvxCSS1PropertyInfo aPropInfo;
4141 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4143 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4144 "Class wird nicht beruecksichtigt" );
4145 DoPositioning( aItemSet, aPropInfo, pCntxt );
4146 InsertAttrs( aItemSet, aPropInfo, pCntxt );
4150 PushContext( pCntxt );
4152 // die neue Vorlage setzen
4153 SetTxtCollAttrs( pCntxt );
4155 // Laufbalkenanzeige aktualisieren
4156 ShowStatline();
4159 void SwHTMLParser::EndTxtFmtColl( int nToken )
4161 SwHTMLAppendMode eMode = AM_NORMAL;
4162 switch( nToken & ~1 )
4164 case HTML_BLOCKQUOTE_ON:
4165 case HTML_BLOCKQUOTE30_ON:
4166 case HTML_PREFORMTXT_ON:
4167 case HTML_LISTING_ON:
4168 case HTML_XMP_ON:
4169 eMode = AM_SPACE;
4170 break;
4171 case HTML_ADDRESS_ON:
4172 case HTML_DT_ON:
4173 case HTML_DD_ON:
4174 eMode = AM_SOFTNOSPACE;
4175 break;
4176 default:
4177 ASSERT( !this, "unbekannte Vorlage" );
4178 break;
4180 if( pPam->GetPoint()->nContent.GetIndex() )
4181 AppendTxtNode( eMode );
4182 else if( AM_SPACE==eMode )
4183 AddParSpace();
4185 // den aktuellen Kontext vom Stack holen
4186 _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
4188 // und noch Attribute beenden
4189 if( pCntxt )
4191 EndContext( pCntxt );
4192 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4193 delete pCntxt;
4196 // und die bisherige Vorlage setzen
4197 SetTxtCollAttrs();
4200 /* \f */
4202 void SwHTMLParser::NewDefList()
4204 String aId, aStyle, aClass, aLang, aDir;
4206 const HTMLOptions *pHTMLOptions = GetOptions();
4207 for( USHORT i = pHTMLOptions->Count(); i; )
4209 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4210 switch( pOption->GetToken() )
4212 case HTML_O_ID:
4213 aId = pOption->GetString();
4214 break;
4215 case HTML_O_STYLE:
4216 aStyle = pOption->GetString();
4217 break;
4218 case HTML_O_CLASS:
4219 aClass = pOption->GetString();
4220 break;
4221 case HTML_O_LANG:
4222 aLang = pOption->GetString();
4223 break;
4224 case HTML_O_DIR:
4225 aDir = pOption->GetString();
4226 break;
4230 // einen neuen Absatz aufmachen
4231 BOOL bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 0;
4232 if( pPam->GetPoint()->nContent.GetIndex() )
4233 AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4234 else if( bSpace )
4235 AddParSpace();
4237 // ein Level mehr
4238 nDefListDeep++;
4241 BOOL bInDD = FALSE, bNotInDD = FALSE;
4242 USHORT nPos = aContexts.Count();
4243 while( !bInDD && !bNotInDD && nPos>nContextStMin )
4245 USHORT nCntxtToken = aContexts[--nPos]->GetToken();
4246 switch( nCntxtToken )
4248 case HTML_DEFLIST_ON:
4249 case HTML_DIRLIST_ON:
4250 case HTML_MENULIST_ON:
4251 case HTML_ORDERLIST_ON:
4252 case HTML_UNORDERLIST_ON:
4253 bNotInDD = TRUE;
4254 break;
4255 case HTML_DD_ON:
4256 bInDD = TRUE;
4257 break;
4262 // ... und in einem Kontext merken
4263 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_DEFLIST_ON );
4265 // darin auch die Raender merken
4266 sal_uInt16 nLeft=0, nRight=0;
4267 short nIndent=0;
4268 GetMarginsFromContext( nLeft, nRight, nIndent );
4270 // Die Einrueckung, die sich schon aus einem DL-ergibt, entspricht der
4271 // eines DT auf dem aktuellen Level, und die entspricht der eines
4272 // DD auf dem Level davor. Fue einen Level >=2 muss also ein DD-Abstand
4273 // hinzugefuegt werden
4274 if( !bInDD && nDefListDeep > 1 )
4277 // und den der DT-Vorlage des aktuellen Levels
4278 SvxLRSpaceItem rLRSpace =
4279 pCSS1Parser->GetTxtFmtColl( RES_POOLCOLL_HTML_DD, aEmptyStr )
4280 ->GetLRSpace();
4281 nLeft = nLeft + static_cast< sal_uInt16 >(rLRSpace.GetTxtLeft());
4284 pCntxt->SetMargins( nLeft, nRight, nIndent );
4286 // Styles parsen
4287 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
4289 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4290 SvxCSS1PropertyInfo aPropInfo;
4292 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
4294 DoPositioning( aItemSet, aPropInfo, pCntxt );
4295 InsertAttrs( aItemSet, aPropInfo, pCntxt );
4299 PushContext( pCntxt );
4301 // die Attribute der neuen Vorlage setzen
4302 if( nDefListDeep > 1 )
4303 SetTxtCollAttrs( pCntxt );
4306 void SwHTMLParser::EndDefList()
4308 BOOL bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 1;
4309 if( pPam->GetPoint()->nContent.GetIndex() )
4310 AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4311 else if( bSpace )
4312 AddParSpace();
4314 // ein Level weniger
4315 if( nDefListDeep > 0 )
4316 nDefListDeep--;
4318 // den aktuellen Kontext vom Stack holen
4319 _HTMLAttrContext *pCntxt = PopContext( HTML_DEFLIST_ON );
4321 // und noch Attribute beenden
4322 if( pCntxt )
4324 EndContext( pCntxt );
4325 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4326 delete pCntxt;
4329 // und Vorlage setzen
4330 SetTxtCollAttrs();
4333 void SwHTMLParser::NewDefListItem( int nToken )
4335 // festellen, ob das DD/DT in einer DL vorkommt
4336 BOOL bInDefList = FALSE, bNotInDefList = FALSE;
4337 USHORT nPos = aContexts.Count();
4338 while( !bInDefList && !bNotInDefList && nPos>nContextStMin )
4340 USHORT nCntxtToken = aContexts[--nPos]->GetToken();
4341 switch( nCntxtToken )
4343 case HTML_DEFLIST_ON:
4344 bInDefList = TRUE;
4345 break;
4346 case HTML_DIRLIST_ON:
4347 case HTML_MENULIST_ON:
4348 case HTML_ORDERLIST_ON:
4349 case HTML_UNORDERLIST_ON:
4350 bNotInDefList = TRUE;
4351 break;
4355 // wenn nicht, implizit eine neue DL aufmachen
4356 if( !bInDefList )
4358 nDefListDeep++;
4359 ASSERT( !nOpenParaToken,
4360 "Jetzt geht ein offenes Absatz-Element verloren" );
4361 nOpenParaToken = static_cast< sal_uInt16 >(nToken);
4364 NewTxtFmtColl( nToken, static_cast< USHORT >(nToken==HTML_DD_ON ? RES_POOLCOLL_HTML_DD
4365 : RES_POOLCOLL_HTML_DT) );
4368 void SwHTMLParser::EndDefListItem( int nToken, BOOL bSetColl,
4369 BOOL /*bLastPara*/ )
4371 // einen neuen Absatz aufmachen
4372 if( !nToken && pPam->GetPoint()->nContent.GetIndex() )
4373 AppendTxtNode( AM_SOFTNOSPACE );
4375 // Kontext zu dem Token suchen und vom Stack holen
4376 nToken &= ~1;
4377 _HTMLAttrContext *pCntxt = 0;
4378 USHORT nPos = aContexts.Count();
4379 while( !pCntxt && nPos>nContextStMin )
4381 USHORT nCntxtToken = aContexts[--nPos]->GetToken();
4382 switch( nCntxtToken )
4384 case HTML_DD_ON:
4385 case HTML_DT_ON:
4386 if( !nToken || nToken == nCntxtToken )
4388 pCntxt = aContexts[nPos];
4389 aContexts.Remove( nPos, 1 );
4391 break;
4392 case HTML_DEFLIST_ON:
4393 // keine DD/DT ausserhalb der aktuelen DefListe betrachten
4394 case HTML_DIRLIST_ON:
4395 case HTML_MENULIST_ON:
4396 case HTML_ORDERLIST_ON:
4397 case HTML_UNORDERLIST_ON:
4398 // und auch nicht ausserhalb einer anderen Liste
4399 nPos = nContextStMin;
4400 break;
4404 // und noch Attribute beenden
4405 if( pCntxt )
4407 EndContext( pCntxt );
4408 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4409 delete pCntxt;
4412 // und die bisherige Vorlage setzen
4413 if( bSetColl )
4414 SetTxtCollAttrs();
4417 /* \f */
4419 BOOL SwHTMLParser::HasCurrentParaFlys( BOOL bNoSurroundOnly,
4420 BOOL bSurroundOnly ) const
4422 // bNoSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
4423 // ohne Umlauf
4424 // bSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
4425 // mit Umlauf aber keinen ohne Umlauf
4426 // sonst: Der Absatz enthaelt irgendeinen Rahmen
4427 SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
4429 SwFrmFmt* pFmt;
4430 const SwFmtAnchor* pAnchor;
4431 const SwPosition* pAPos;
4432 const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
4434 USHORT i;
4435 BOOL bFound = FALSE;
4436 for( i=0; i<rFrmFmtTbl.Count(); i++ )
4438 pFmt = rFrmFmtTbl[i];
4439 pAnchor = &pFmt->GetAnchor();
4440 // Ein Rahmen wurde gefunden, wenn
4441 // - er absatzgebunden ist, und
4442 // - im aktuellen Absatz verankert ist, und
4443 // - jeder absatzgebunene Rahmen zaehlt, oder
4444 // - (nur Rahmen oder umlauf zaehlen und ) der Rahmen keinen
4445 // Umlauf besitzt
4447 if( 0 != ( pAPos = pAnchor->GetCntntAnchor()) &&
4448 (FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
4449 FLY_AUTO_CNTNT == pAnchor->GetAnchorId()) &&
4450 pAPos->nNode == rNodeIdx )
4452 if( !(bNoSurroundOnly || bSurroundOnly) )
4454 bFound = TRUE;
4455 break;
4457 else
4459 // fix #42282#: Wenn Rahmen mit Umlauf gesucht sind,
4460 // auch keine mit Durchlauf beachten. Dabei handelt es
4461 // sich (noch) um HIDDEN-Controls, und denen weicht man
4462 // besser auch nicht aus.
4463 SwSurround eSurround = pFmt->GetSurround().GetSurround();
4464 if( bNoSurroundOnly )
4466 if( SURROUND_NONE==eSurround )
4468 bFound = TRUE;
4469 break;
4472 if( bSurroundOnly )
4474 if( SURROUND_NONE==eSurround )
4476 bFound = FALSE;
4477 break;
4479 else if( SURROUND_THROUGHT!=eSurround )
4481 bFound = TRUE;
4482 // weitersuchen: Es koennten ja noch welche ohne
4483 // Umlauf kommen ...
4490 return bFound;
4493 /* \f */
4495 // die speziellen Methoden zum Einfuegen von Objecten
4497 const SwFmtColl *SwHTMLParser::GetCurrFmtColl() const
4499 const SwCntntNode* pCNd = pPam->GetCntntNode();
4500 return &pCNd->GetAnyFmtColl();
4504 void SwHTMLParser::SetTxtCollAttrs( _HTMLAttrContext *pContext )
4506 SwTxtFmtColl *pCollToSet = 0; // die zu setzende Vorlage
4507 SfxItemSet *pItemSet = 0; // der Set fuer harte Attrs
4508 USHORT nTopColl = pContext ? pContext->GetTxtFmtColl() : 0;
4509 const String& rTopClass = pContext ? pContext->GetClass() : (const String&) aEmptyStr;
4510 USHORT nDfltColl = RES_POOLCOLL_TEXT;
4512 BOOL bInPRE=FALSE; // etwas Kontext Info
4514 USHORT nLeftMargin = 0, nRightMargin = 0; // die Einzuege und
4515 short nFirstLineIndent = 0; // Abstaende
4516 USHORT i;
4518 for( i = nContextStAttrMin; i < aContexts.Count(); i++ )
4520 const _HTMLAttrContext *pCntxt = aContexts[i];
4522 USHORT nColl = pCntxt->GetTxtFmtColl();
4523 if( nColl )
4525 // Es gibt eine Vorlage, die zu setzen ist. Dann
4526 // muss zunaechst einmal entschieden werden,
4527 // ob die Vorlage auch gesetzt werden kann
4528 BOOL bSetThis = TRUE;
4529 switch( nColl )
4531 case USHORT(RES_POOLCOLL_HTML_PRE):
4532 bInPRE = TRUE;
4533 break;
4534 case USHORT(RES_POOLCOLL_TEXT):
4535 // <TD><P CLASS=xxx> muss TD.xxx werden
4536 if( nDfltColl==RES_POOLCOLL_TABLE ||
4537 nDfltColl==RES_POOLCOLL_TABLE_HDLN )
4538 nColl = nDfltColl;
4539 break;
4540 case USHORT(RES_POOLCOLL_HTML_HR):
4541 // <HR> auch in <PRE> als Vorlage setzen, sonst kann man sie
4542 // nicht mehr exportieren
4543 break;
4544 default:
4545 if( bInPRE )
4546 bSetThis = FALSE;
4547 break;
4550 SwTxtFmtColl *pNewColl =
4551 pCSS1Parser->GetTxtFmtColl( nColl, pCntxt->GetClass() );
4553 if( bSetThis )
4555 // wenn jetzt eine andere Vorlage gesetzt werden soll als
4556 // bisher, muss die bishere Vorlage durch harte Attributierung
4557 // ersetzt werden
4559 if( pCollToSet )
4561 // die Attribute, die die bisherige Vorlage setzt
4562 // hart einfuegen
4563 if( !pItemSet )
4564 pItemSet = new SfxItemSet( pCollToSet->GetAttrSet() );
4565 else
4567 const SfxItemSet& rCollSet = pCollToSet->GetAttrSet();
4568 SfxItemSet aItemSet( *rCollSet.GetPool(),
4569 rCollSet.GetRanges() );
4570 aItemSet.Set( rCollSet );
4571 pItemSet->Put( aItemSet );
4573 // aber die Attribute, die aktuelle Vorlage setzt
4574 // entfernen, weil sie sonst spaeter ueberschrieben
4575 // werden
4576 pItemSet->Differentiate( pNewColl->GetAttrSet() );
4579 pCollToSet = pNewColl;
4581 else
4583 // hart Attributieren
4584 if( !pItemSet )
4585 pItemSet = new SfxItemSet( pNewColl->GetAttrSet() );
4586 else
4588 const SfxItemSet& rCollSet = pNewColl->GetAttrSet();
4589 SfxItemSet aItemSet( *rCollSet.GetPool(),
4590 rCollSet.GetRanges() );
4591 aItemSet.Set( rCollSet );
4592 pItemSet->Put( aItemSet );
4596 else
4598 // vielliecht gibt es ja eine Default-Vorlage?
4599 nColl = pCntxt->GetDfltTxtFmtColl();
4600 if( nColl )
4601 nDfltColl = nColl;
4604 // ggf. neue Absatz-Einzuege holen
4605 if( pCntxt->IsLRSpaceChanged() )
4607 USHORT nLeft=0, nRight=0;
4609 pCntxt->GetMargins( nLeft, nRight, nFirstLineIndent );
4610 nLeftMargin = nLeft;
4611 nRightMargin = nRight;
4615 // wenn im aktuellen Kontext eine neue Vorlage gesetzt werden soll,
4616 // muessen deren Absatz-Abstaende noch in den Kontext eingetragen werden
4617 if( pContext && nTopColl )
4619 // <TD><P CLASS=xxx> muss TD.xxx werden
4620 if( nTopColl==RES_POOLCOLL_TEXT &&
4621 (nDfltColl==RES_POOLCOLL_TABLE ||
4622 nDfltColl==RES_POOLCOLL_TABLE_HDLN) )
4623 nTopColl = nDfltColl;
4625 const SwTxtFmtColl *pTopColl =
4626 pCSS1Parser->GetTxtFmtColl( nTopColl, rTopClass );
4627 const SfxItemSet& rItemSet = pTopColl->GetAttrSet();
4628 const SfxPoolItem *pItem;
4629 if( SFX_ITEM_SET == rItemSet.GetItemState(RES_LR_SPACE,TRUE, &pItem) )
4631 const SvxLRSpaceItem *pLRItem =
4632 (const SvxLRSpaceItem *)pItem;
4634 sal_Int32 nLeft = pLRItem->GetTxtLeft();
4635 sal_Int32 nRight = pLRItem->GetRight();
4636 nFirstLineIndent = pLRItem->GetTxtFirstLineOfst();
4638 // In Definitions-Listen enthalten die Abstaende auch die der
4639 // vorhergehenden Level
4640 if( RES_POOLCOLL_HTML_DD == nTopColl )
4642 const SvxLRSpaceItem& rDTLRSpace = pCSS1Parser
4643 ->GetTxtFmtColl( RES_POOLCOLL_HTML_DT, aEmptyStr )
4644 ->GetLRSpace();
4645 nLeft -= rDTLRSpace.GetTxtLeft();
4646 nRight -= rDTLRSpace.GetRight();
4648 else if( RES_POOLCOLL_HTML_DT == nTopColl )
4650 nLeft = 0;
4651 nRight = 0;
4654 // die Absatz-Abstaende addieren sich
4655 nLeftMargin = nLeftMargin + static_cast< sal_uInt16 >(nLeft);
4656 nRightMargin = nRightMargin + static_cast< sal_uInt16 >(nRight);
4658 pContext->SetMargins( nLeftMargin, nRightMargin,
4659 nFirstLineIndent );
4661 if( SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,TRUE, &pItem) )
4663 const SvxULSpaceItem *pULItem =
4664 (const SvxULSpaceItem *)pItem;
4665 pContext->SetULSpace( pULItem->GetUpper(), pULItem->GetLower() );
4669 // wenn gar keine Vorlage im Kontext gesetzt ist, Textkoerper nehmen
4670 if( !pCollToSet )
4672 pCollToSet = pCSS1Parser->GetTxtCollFromPool( nDfltColl );
4673 const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4674 if( !nLeftMargin )
4675 nLeftMargin = static_cast< sal_uInt16 >(rLRItem.GetTxtLeft());
4676 if( !nRightMargin )
4677 nRightMargin = static_cast< sal_uInt16 >(rLRItem.GetRight());
4678 if( !nFirstLineIndent )
4679 nFirstLineIndent = rLRItem.GetTxtFirstLineOfst();
4682 // bisherige harte Attributierung des Absatzes entfernen
4683 if( aParaAttrs.Count() )
4685 for( i=0; i<aParaAttrs.Count(); i++ )
4686 aParaAttrs[i]->Invalidate();
4688 aParaAttrs.Remove( 0, aParaAttrs.Count() );
4691 // Die Vorlage setzen
4692 pDoc->SetTxtFmtColl( *pPam, pCollToSet );
4694 // ggf. noch den Absatz-Einzug korrigieren
4695 const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4696 BOOL bSetLRSpace;
4698 bSetLRSpace = nLeftMargin != rLRItem.GetTxtLeft() ||
4699 nFirstLineIndent != rLRItem.GetTxtFirstLineOfst() ||
4700 nRightMargin != rLRItem.GetRight();
4702 if( bSetLRSpace )
4704 SvxLRSpaceItem aLRItem( rLRItem );
4705 aLRItem.SetTxtLeft( nLeftMargin );
4706 aLRItem.SetRight( nRightMargin );
4707 aLRItem.SetTxtFirstLineOfst( nFirstLineIndent );
4708 if( pItemSet )
4709 pItemSet->Put( aLRItem );
4710 else
4712 NewAttr( &aAttrTab.pLRSpace, aLRItem );
4713 aAttrTab.pLRSpace->SetLikePara();
4714 aParaAttrs.Insert( aAttrTab.pLRSpace, aParaAttrs.Count() );
4715 EndAttr( aAttrTab.pLRSpace, 0, FALSE );
4719 // und nun noch die Attribute setzen
4720 if( pItemSet )
4722 InsertParaAttrs( *pItemSet );
4723 delete pItemSet;
4727 /* \f */
4729 void SwHTMLParser::NewCharFmt( int nToken )
4731 String aId, aStyle, aClass, aLang, aDir;
4733 const HTMLOptions *pHTMLOptions = GetOptions();
4734 for( USHORT i = pHTMLOptions->Count(); i; )
4736 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4737 switch( pOption->GetToken() )
4739 case HTML_O_ID:
4740 aId = pOption->GetString();
4741 break;
4742 case HTML_O_STYLE:
4743 aStyle = pOption->GetString();
4744 break;
4745 case HTML_O_CLASS:
4746 aClass = pOption->GetString();
4747 break;
4748 case HTML_O_LANG:
4749 aLang = pOption->GetString();
4750 break;
4751 case HTML_O_DIR:
4752 aDir = pOption->GetString();
4753 break;
4757 // einen neuen Kontext anlegen
4758 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
4760 // die Vorlage setzen und im Kontext merken
4761 SwCharFmt* pCFmt = pCSS1Parser->GetChrFmt( static_cast< sal_uInt16 >(nToken), aClass );
4762 ASSERT( pCFmt, "keine Zeichenvorlage zu Token gefunden" );
4765 // Styles parsen (zu Class siehe auch NewPara)
4766 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4768 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4769 SvxCSS1PropertyInfo aPropInfo;
4771 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4773 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4774 "Class wird nicht beruecksichtigt" );
4775 DoPositioning( aItemSet, aPropInfo, pCntxt );
4776 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
4780 // Zeichen-Vorlagen werden in einem eigenen Stack gehalten und
4781 // koennen nie durch Styles eingefuegt werden. Das Attribut ist deshalb
4782 // auch gar nicht im CSS1-Which-Range enthalten
4783 if( pCFmt )
4784 InsertAttr( &aAttrTab.pCharFmts, SwFmtCharFmt( pCFmt ), pCntxt );
4786 // den Kontext merken
4787 PushContext( pCntxt );
4791 /* \f */
4793 void SwHTMLParser::InsertSpacer()
4795 // und es ggf. durch die Optionen veraendern
4796 String aId;
4797 sal_Int16 eVertOri = text::VertOrientation::TOP;
4798 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
4799 Size aSize( 0, 0);
4800 long nSize = 0;
4801 BOOL bPrcWidth = FALSE;
4802 BOOL bPrcHeight = FALSE;
4803 USHORT nType = HTML_SPTYPE_HORI;
4805 const HTMLOptions *pHTMLOptions = GetOptions();
4806 for( USHORT i = pHTMLOptions->Count(); i; )
4808 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4809 switch( pOption->GetToken() )
4811 case HTML_O_ID:
4812 aId = pOption->GetString();
4813 break;
4814 case HTML_O_TYPE:
4815 pOption->GetEnum( nType, aHTMLSpacerTypeTable );
4816 break;
4817 case HTML_O_ALIGN:
4818 eVertOri =
4819 pOption->GetEnum( aHTMLImgVAlignTable,
4820 eVertOri );
4821 eHoriOri =
4822 pOption->GetEnum( aHTMLImgHAlignTable,
4823 eHoriOri );
4824 break;
4825 case HTML_O_WIDTH:
4826 // erstmal nur als Pixelwerte merken!
4827 bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4828 aSize.Width() = (long)pOption->GetNumber();
4829 break;
4830 case HTML_O_HEIGHT:
4831 // erstmal nur als Pixelwerte merken!
4832 bPrcHeight = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4833 aSize.Height() = (long)pOption->GetNumber();
4834 break;
4835 case HTML_O_SIZE:
4836 // erstmal nur als Pixelwerte merken!
4837 nSize = pOption->GetNumber();
4838 break;
4842 switch( nType )
4844 case HTML_SPTYPE_BLOCK:
4846 // einen leeren Textrahmen anlegen
4848 // den Itemset holen
4849 SfxItemSet aFrmSet( pDoc->GetAttrPool(),
4850 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
4851 if( !IsNewDoc() )
4852 Reader::ResetFrmFmtAttrs( aFrmSet );
4854 // den Anker und die Ausrichtung setzen
4855 SetAnchorAndAdjustment( eVertOri, eHoriOri, aFrmSet );
4857 // und noch die Groesse des Rahmens
4858 Size aDfltSz( MINFLY, MINFLY );
4859 Size aSpace( 0, 0 );
4860 SfxItemSet aDummyItemSet( pDoc->GetAttrPool(),
4861 pCSS1Parser->GetWhichMap() );
4862 SvxCSS1PropertyInfo aDummyPropInfo;
4864 SetFixSize( aSize, aDfltSz, bPrcWidth, bPrcHeight,
4865 aDummyItemSet, aDummyPropInfo, aFrmSet );
4866 SetSpace( aSpace, aDummyItemSet, aDummyPropInfo, aFrmSet );
4868 // den Inhalt schuetzen
4869 SvxProtectItem aProtectItem( RES_PROTECT) ;
4870 aProtectItem.SetCntntProtect( TRUE );
4871 aFrmSet.Put( aProtectItem );
4873 // der Rahmen anlegen
4874 RndStdIds eAnchorId =
4875 ((const SwFmtAnchor &)aFrmSet.Get(RES_ANCHOR)).GetAnchorId();
4876 SwFrmFmt *pFlyFmt = pDoc->MakeFlySection( eAnchorId,
4877 pPam->GetPoint(), &aFrmSet );
4878 // Ggf Frames anlegen und auto-geb. Rahmen registrieren
4879 RegisterFlyFrm( pFlyFmt );
4881 break;
4882 case HTML_SPTYPE_VERT:
4883 if( nSize > 0 )
4885 if( nSize && Application::GetDefaultDevice() )
4887 nSize = Application::GetDefaultDevice()
4888 ->PixelToLogic( Size(0,nSize),
4889 MapMode(MAP_TWIP) ).Height();
4892 // einen Absatz-Abstand setzen
4893 SwTxtNode *pTxtNode = 0;
4894 if( !pPam->GetPoint()->nContent.GetIndex() )
4896 // den unteren Absatz-Abstand des vorherigen Nodes aendern,
4897 // wenn moeglich
4899 SetAttr(); // noch offene Absatz-Attribute setzen
4901 pTxtNode = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()-1]
4902 ->GetTxtNode();
4904 // Wenn der Abstz davor kein Txtenode ist, dann wird jetzt
4905 // ein leere Absatz angelegt, der eh schon eine Zeilenhoehe
4906 // Abstand erzeugt.
4907 if( !pTxtNode )
4908 nSize = nSize>HTML_PARSPACE ? nSize-HTML_PARSPACE : 0;
4911 if( pTxtNode )
4913 SvxULSpaceItem aULSpace( (const SvxULSpaceItem&)pTxtNode
4914 ->SwCntntNode::GetAttr( RES_UL_SPACE ) );
4915 aULSpace.SetLower( aULSpace.GetLower() + (USHORT)nSize );
4916 pTxtNode->SetAttr( aULSpace );
4918 else
4920 NewAttr( &aAttrTab.pULSpace, SvxULSpaceItem( 0, (USHORT)nSize, RES_UL_SPACE ) );
4921 EndAttr( aAttrTab.pULSpace, 0, FALSE );
4923 AppendTxtNode(); // nicht am Abstand drehen!
4926 break;
4927 case HTML_SPTYPE_HORI:
4928 if( nSize > 0 )
4930 // wenn der Absatz noch leer ist, einen Erstzeilen-Einzug
4931 // setzen, sondern Sperrschrift ueber einem Space aufspannen
4933 if( nSize && Application::GetDefaultDevice() )
4935 nSize = Application::GetDefaultDevice()
4936 ->PixelToLogic( Size(nSize,0),
4937 MapMode(MAP_TWIP) ).Width();
4940 if( !pPam->GetPoint()->nContent.GetIndex() )
4942 USHORT nLeft=0, nRight=0;
4943 short nIndent = 0;
4945 GetMarginsFromContextWithNumBul( nLeft, nRight, nIndent );
4946 nIndent = nIndent + (short)nSize;
4948 SvxLRSpaceItem aLRItem( RES_LR_SPACE );
4949 aLRItem.SetTxtLeft( nLeft );
4950 aLRItem.SetRight( nRight );
4951 aLRItem.SetTxtFirstLineOfst( nIndent );
4953 NewAttr( &aAttrTab.pLRSpace, aLRItem );
4954 EndAttr( aAttrTab.pLRSpace, 0, FALSE );
4956 else
4958 NewAttr( &aAttrTab.pKerning, SvxKerningItem( (short)nSize, RES_CHRATR_KERNING ) );
4959 String aTmp( ' ' );
4960 pDoc->Insert( *pPam, aTmp /*, CHARSET_ANSI*/, true );
4961 EndAttr( aAttrTab.pKerning );
4967 USHORT SwHTMLParser::ToTwips( USHORT nPixel ) const
4969 if( nPixel && Application::GetDefaultDevice() )
4971 long nTwips = Application::GetDefaultDevice()->PixelToLogic(
4972 Size( nPixel, nPixel ), MapMode( MAP_TWIP ) ).Width();
4973 return nTwips <= USHRT_MAX ? (USHORT)nTwips : USHRT_MAX;
4975 else
4976 return nPixel;
4979 SwTwips SwHTMLParser::GetCurrentBrowseWidth()
4981 SwTwips nWidth = SwHTMLTableLayout::GetBrowseWidth( *pDoc );
4982 if( nWidth )
4983 return nWidth;
4985 if( !aHTMLPageSize.Width() )
4987 const SwFrmFmt& rPgFmt = pCSS1Parser->GetMasterPageDesc()->GetMaster();
4989 const SwFmtFrmSize& rSz = rPgFmt.GetFrmSize();
4990 const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace();
4991 const SvxULSpaceItem& rUL = rPgFmt.GetULSpace();
4992 const SwFmtCol& rCol = rPgFmt.GetCol();
4994 aHTMLPageSize.Width() = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight();
4995 aHTMLPageSize.Height() = rSz.GetHeight() - rUL.GetUpper() - rUL.GetLower();
4997 if( 1 < rCol.GetNumCols() )
4998 aHTMLPageSize.Width() /= rCol.GetNumCols();
5001 return aHTMLPageSize.Width();
5005 /* \f */
5007 void SwHTMLParser::InsertIDOption()
5009 String aId;
5010 const HTMLOptions *pHTMLOptions = GetOptions();
5011 for( USHORT i = pHTMLOptions->Count(); i; )
5013 const HTMLOption *pOption = (*pHTMLOptions)[--i];
5014 if( HTML_O_ID==pOption->GetToken() )
5016 aId = pOption->GetString();
5017 break;
5021 if( aId.Len() )
5022 InsertBookmark( aId );
5026 /* \f */
5029 void SwHTMLParser::InsertLineBreak()
5031 // <BR CLEAR=xxx> wird wie folgt behandelt:
5032 // 1.) Es werden nur nur absatzgebundene Rahmen betrachtet, die
5033 // im aktuellen Absatz verankert sind.
5034 // 2.) Fuer linksbuendig ausgerichtete Rahmen wird bei CLEAR=LEFT
5035 // oder ALL und auf rechtsbuendige ausgerichtete Rahmen bei
5036 // CLEAR=RIGHT oder ALL der Durchlauf wie folgt geaendert:
5037 // 3.) Wenn der Absatz keinen Text enthaelt, bekommt der Rahmen keinen
5038 // Umlauf
5039 // 4.) sonst erhaelt ein links ausgerichteter Rahmen eine rechten
5040 // "nur Anker" Umlauf und recht rechst ausg. Rahmen einen linken
5041 // "nur Anker" Umlauf.
5042 // 5.) wenn in einem nicht-leeren Absatz der Umlauf eines Rahmens
5043 // geaendert wird, wird ein neuer Absatz aufgemacht
5044 // 6.) Wenn von keinem Rahmen der Umlauf geaendert wird, wird ein
5045 // harter Zeilenumbruch eingefuegt
5047 String aId, aStyle, aClass; // die ID der Bookmark
5048 BOOL bClearLeft = FALSE, bClearRight = FALSE;
5049 BOOL bCleared = FALSE; // wurde ein CLEAR ausgefuehrt?
5051 // dann holen wir mal die Optionen
5052 const HTMLOptions *pHTMLOptions = GetOptions();
5053 for( USHORT i = pHTMLOptions->Count(); i; )
5055 const HTMLOption *pOption = (*pHTMLOptions)[--i];
5056 switch( pOption->GetToken() )
5058 case HTML_O_CLEAR:
5060 const String &aClear = pOption->GetString();
5061 if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_all ) )
5063 bClearLeft = TRUE;
5064 bClearRight = TRUE;
5066 else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) )
5067 bClearLeft = TRUE;
5068 else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) )
5069 bClearRight = TRUE;
5071 break;
5072 case HTML_O_ID:
5073 aId = pOption->GetString();
5074 break;
5075 case HTML_O_STYLE:
5076 aStyle = pOption->GetString();
5077 break;
5078 case HTML_O_CLASS:
5079 aClass = pOption->GetString();
5080 break;
5084 // CLEAR wird nur fuer den aktuellen Absaetz unterstuetzt
5085 if( bClearLeft || bClearRight )
5087 SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
5088 SwTxtNode* pTxtNd = rNodeIdx.GetNode().GetTxtNode();
5089 if( pTxtNd )
5091 SwFrmFmt* pFmt;
5092 const SwFmtAnchor* pAnchor;
5093 const SwPosition* pAPos;
5094 const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
5096 for( USHORT i=0; i<rFrmFmtTbl.Count(); i++ )
5098 pFmt = rFrmFmtTbl[i];
5099 pAnchor = &pFmt->GetAnchor();
5100 if( 0 != ( pAPos = pAnchor->GetCntntAnchor()) &&
5101 (FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
5102 FLY_AUTO_CNTNT == pAnchor->GetAnchorId()) &&
5103 pAPos->nNode == rNodeIdx &&
5104 pFmt->GetSurround().GetSurround() != SURROUND_NONE )
5106 sal_Int16 eHori = RES_DRAWFRMFMT == pFmt->Which()
5107 ? text::HoriOrientation::LEFT
5108 : pFmt->GetHoriOrient().GetHoriOrient();
5110 SwSurround eSurround = SURROUND_PARALLEL;
5111 if( pPam->GetPoint()->nContent.GetIndex() )
5113 if( bClearLeft && text::HoriOrientation::LEFT==eHori )
5114 eSurround = SURROUND_RIGHT;
5115 else if( bClearRight && text::HoriOrientation::RIGHT==eHori )
5116 eSurround = SURROUND_LEFT;
5118 else if( (bClearLeft && text::HoriOrientation::LEFT==eHori) ||
5119 (bClearRight && text::HoriOrientation::RIGHT==eHori) )
5121 eSurround = SURROUND_NONE;
5124 if( SURROUND_PARALLEL != eSurround )
5126 SwFmtSurround aSurround( eSurround );
5127 if( SURROUND_NONE != eSurround )
5128 aSurround.SetAnchorOnly( TRUE );
5129 pFmt->SetFmtAttr( aSurround );
5130 bCleared = TRUE;
5132 } // Anker ist nicht im Node
5133 } // Schleife ueber Fly-Frames
5134 } // kein Text-Node
5135 } // kein CLEAR
5137 // Styles parsen
5138 SvxFmtBreakItem aBreakItem( SVX_BREAK_NONE, RES_BREAK );
5139 BOOL bBreakItem = FALSE;
5140 if( HasStyleOptions( aStyle, aId, aClass ) )
5142 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
5143 SvxCSS1PropertyInfo aPropInfo;
5145 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) )
5147 if( pCSS1Parser->SetFmtBreak( aItemSet, aPropInfo ) )
5149 aBreakItem = (const SvxFmtBreakItem &)aItemSet.Get( RES_BREAK );
5150 bBreakItem = TRUE;
5152 if( aPropInfo.aId.Len() )
5153 InsertBookmark( aPropInfo.aId );
5157 if( bBreakItem && SVX_BREAK_PAGE_AFTER==aBreakItem.GetBreak() )
5159 NewAttr( &aAttrTab.pBreak, aBreakItem );
5160 EndAttr( aAttrTab.pBreak, 0, FALSE );
5163 if( !bCleared && !bBreakItem )
5165 // wenn kein CLEAR ausgefuehrt werden sollte oder konnte, wird
5166 // ein Zeilenumbruch eingef?gt
5167 String sTmp( (sal_Unicode)0x0a ); // make the Mac happy :-)
5168 pDoc->Insert( *pPam, sTmp, true );
5170 else if( pPam->GetPoint()->nContent.GetIndex() )
5172 // wenn ein Claer in einem nicht-leeren Absatz ausgefuehrt wurde,
5173 // muss anschliessen ein neuer Absatz aufgemacht werden
5174 // MIB 21.02.97: Eigentlich muesste man hier den unteren Absatz-
5175 // Absatnd auf 0 drehen. Das geht aber bei sowas wie <BR ..><P>
5176 // schief (>Netacpe). Deshalb lassen wir das erstmal.
5177 AppendTxtNode( AM_NOSPACE );
5179 if( bBreakItem && SVX_BREAK_PAGE_BEFORE==aBreakItem.GetBreak() )
5181 NewAttr( &aAttrTab.pBreak, aBreakItem );
5182 EndAttr( aAttrTab.pBreak, 0, FALSE );
5186 void SwHTMLParser::InsertHorzRule()
5188 USHORT nSize = 0;
5189 USHORT nWidth = 0;
5191 SvxAdjust eAdjust = SVX_ADJUST_END;
5193 BOOL bPrcWidth = FALSE;
5194 BOOL bNoShade = FALSE;
5195 BOOL bColor = FALSE;
5197 Color aColor;
5198 String aId;
5200 // dann holen wir mal die Optionen
5201 const HTMLOptions *pHTMLOptions = GetOptions();
5202 for( USHORT i = pHTMLOptions->Count(); i; )
5204 const HTMLOption *pOption = (*pHTMLOptions)[--i];
5205 switch( pOption->GetToken() )
5207 case HTML_O_ID:
5208 aId = pOption->GetString();
5209 break;
5210 case HTML_O_SIZE:
5211 nSize = (USHORT)pOption->GetNumber();
5212 break;
5213 case HTML_O_WIDTH:
5214 bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
5215 nWidth = (USHORT)pOption->GetNumber();
5216 if( bPrcWidth && nWidth>=100 )
5218 // 100%-Linien sind der default-Fall (keine Attrs neotig)
5219 nWidth = 0;
5220 bPrcWidth = FALSE;
5222 break;
5223 case HTML_O_ALIGN:
5224 eAdjust =
5225 (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eAdjust) );
5226 break;
5227 case HTML_O_NOSHADE:
5228 bNoShade = TRUE;
5229 break;
5230 case HTML_O_COLOR:
5231 pOption->GetColor( aColor );
5232 bColor = TRUE;
5233 break;
5237 if( pPam->GetPoint()->nContent.GetIndex() )
5238 AppendTxtNode( AM_NOSPACE );
5239 if( nOpenParaToken )
5240 EndPara();
5241 AppendTxtNode();
5242 pPam->Move( fnMoveBackward );
5244 // ... und in einem Kontext merken
5245 _HTMLAttrContext *pCntxt =
5246 new _HTMLAttrContext( HTML_HORZRULE, RES_POOLCOLL_HTML_HR, aEmptyStr );
5248 PushContext( pCntxt );
5250 // die neue Vorlage setzen
5251 SetTxtCollAttrs( pCntxt );
5253 // die harten Attribute an diesem Absatz werden nie mehr ungueltig
5254 if( aParaAttrs.Count() )
5255 aParaAttrs.Remove( 0, aParaAttrs.Count() );
5257 if( nSize>0 || bColor || bNoShade )
5259 // Farbe und/oder Breite der Linie setzen
5260 if( !bColor )
5261 aColor.SetColor( COL_GRAY );
5263 SvxBorderLine aBorderLine( &aColor );
5264 if( nSize )
5266 long nPWidth = 0;
5267 long nPHeight = (long)nSize;
5268 SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
5269 SvxCSS1Parser::SetBorderWidth( aBorderLine, (USHORT)nPHeight,
5270 !bNoShade );
5272 else if( bNoShade )
5274 aBorderLine.SetOutWidth( DEF_LINE_WIDTH_2 );
5276 else
5278 aBorderLine.SetOutWidth( DEF_DOUBLE_LINE0_OUT );
5279 aBorderLine.SetInWidth( DEF_DOUBLE_LINE0_IN );
5280 aBorderLine.SetDistance( DEF_DOUBLE_LINE0_DIST );
5283 SvxBoxItem aBoxItem(RES_BOX);
5284 aBoxItem.SetLine( &aBorderLine, BOX_LINE_BOTTOM );
5285 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aBoxItem );
5286 aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5288 if( nWidth )
5290 // Wenn wir in keiner Tabelle sind, wird die Breitenangabe durch
5291 // Absatz-Einzuege "getuerkt". In einer Tabelle macht das wenig
5292 // Sinn. Um zu Vermeiden, dass die Linie bei der Breitenberechnung
5293 // beruecksichtigt wird, bekommt sie aber trotzdem entsprechendes
5294 // LRSpace-Item verpasst.
5295 #ifdef FIX41370
5296 const SwFmtColl *pColl = GetCurrFmtColl();
5297 SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5298 #endif
5299 if( !pTable )
5301 // Laenge und Ausrichtung der Linie ueber Absatz-Einzuege "tuerken"
5302 long nBrowseWidth = GetCurrentBrowseWidth();
5303 nWidth = bPrcWidth ? (USHORT)((nWidth*nBrowseWidth) / 100)
5304 : ToTwips( (USHORT)nBrowseWidth );
5305 if( nWidth < MINLAY )
5306 nWidth = MINLAY;
5308 if( (long)nWidth < nBrowseWidth )
5310 #ifndef FIX41370
5311 const SwFmtColl *pColl = GetCurrFmtColl();
5312 SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5313 #endif
5314 long nDist = nBrowseWidth - nWidth;
5316 switch( eAdjust )
5318 case SVX_ADJUST_RIGHT:
5319 aLRItem.SetTxtLeft( (USHORT)nDist );
5320 break;
5321 case SVX_ADJUST_LEFT:
5322 aLRItem.SetRight( (USHORT)nDist );
5323 break;
5324 case SVX_ADJUST_CENTER:
5325 default:
5326 nDist /= 2;
5327 aLRItem.SetTxtLeft( (USHORT)nDist );
5328 aLRItem.SetRight( (USHORT)nDist );
5329 break;
5332 #ifndef FIX41370
5333 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5334 aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5335 #endif
5339 #ifdef FIX41370
5340 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5341 aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5342 #endif
5345 // Bookmarks koennen nicht in Hyperlinks eingefueht werden
5346 if( aId.Len() )
5347 InsertBookmark( aId );
5349 // den aktuellen Kontext vom Stack holen
5350 _HTMLAttrContext *pPoppedContext = PopContext( HTML_HORZRULE );
5351 ASSERT( pPoppedContext==pCntxt, "wo kommt denn da ein HR-Kontext her?" );
5352 delete pPoppedContext;
5354 pPam->Move( fnMoveForward );
5356 // und im Absatz danach die dort aktuelle Vorlage setzen
5357 SetTxtCollAttrs();
5360 void SwHTMLParser::ParseMoreMetaOptions()
5362 String aName, aContent;
5363 BOOL bHTTPEquiv = FALSE;
5365 const HTMLOptions *pHTMLOptions = GetOptions();
5366 for( USHORT i = pHTMLOptions->Count(); i; )
5368 const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
5369 switch( pOption->GetToken() )
5371 case HTML_O_NAME:
5372 aName = pOption->GetString();
5373 bHTTPEquiv = FALSE;
5374 break;
5375 case HTML_O_HTTPEQUIV:
5376 aName = pOption->GetString();
5377 bHTTPEquiv = TRUE;
5378 break;
5379 case HTML_O_CONTENT:
5380 aContent = pOption->GetString();
5381 break;
5385 // Hier wird es etwas tricky: Wir wissen genau, da? die Dok-Info
5386 // nicht geaendert wurde. Deshalb genuegt es, auf Generator und
5387 // auf refresh abzufragen, um noch nicht verarbeitete Token zu finden,
5388 // denn das sind die einzigen, die die Dok-Info nicht modifizieren.
5389 if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_generator ) ||
5390 aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_refresh ) ||
5391 aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_type ) ||
5392 aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_script_type ) )
5393 return;
5395 aContent.EraseAllChars( _CR );
5396 aContent.EraseAllChars( _LF );
5398 if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdendnote ) )
5400 FillEndNoteInfo( aContent );
5401 return;
5404 if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdfootnote ) )
5406 FillFootNoteInfo( aContent );
5407 return;
5410 String sText(
5411 String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
5412 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_meta) );
5413 sText.Append( ' ' );
5414 if( bHTTPEquiv )
5415 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_httpequiv) );
5416 else
5417 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_name) );
5418 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5419 sText.Append( aName );
5420 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\" ") );
5421 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_content) );
5422 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5423 sText.Append( aContent );
5424 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\">") );
5426 SwPostItField aPostItFld(
5427 (SwPostItFieldType*)pDoc->GetSysFldType( RES_POSTITFLD ),
5428 aEmptyStr, sText, DateTime() );
5429 SwFmtFld aFmtFld( aPostItFld );
5430 InsertAttr( aFmtFld );
5433 /* \f */
5435 _HTMLAttr::_HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem,
5436 _HTMLAttr **ppHd ) :
5437 nSttPara( rPos.nNode ),
5438 nEndPara( rPos.nNode ),
5439 nSttCntnt( rPos.nContent.GetIndex() ),
5440 nEndCntnt(rPos.nContent.GetIndex() ),
5441 bInsAtStart( TRUE ),
5442 bLikePara( FALSE ),
5443 bValid( TRUE ),
5444 nCount( 1 ),
5445 pNext( 0 ),
5446 pPrev( 0 ),
5447 ppHead( ppHd )
5449 pItem = rItem.Clone();
5452 _HTMLAttr::_HTMLAttr( const _HTMLAttr &rAttr, const SwNodeIndex &rEndPara,
5453 USHORT nEndCnt, _HTMLAttr **ppHd ) :
5454 nSttPara( rAttr.nSttPara ),
5455 nEndPara( rEndPara ),
5456 nSttCntnt( rAttr.nSttCntnt ),
5457 nEndCntnt( nEndCnt ),
5458 bInsAtStart( rAttr.bInsAtStart ),
5459 bLikePara( rAttr.bLikePara ),
5460 bValid( rAttr.bValid ),
5461 nCount( rAttr.nCount ),
5462 pNext( 0 ),
5463 pPrev( 0 ),
5464 ppHead( ppHd )
5466 pItem = rAttr.pItem->Clone();
5469 _HTMLAttr::~_HTMLAttr()
5471 delete pItem;
5474 _HTMLAttr *_HTMLAttr::Clone( const SwNodeIndex& rEndPara, USHORT nEndCnt ) const
5476 // das Attribut mit der alten Start-Position neu anlegen
5477 _HTMLAttr *pNew = new _HTMLAttr( *this, rEndPara, nEndCnt, ppHead );
5479 // die Previous-Liste muss uebernommen werden, die Next-Liste nicht!
5480 pNew->pPrev = pPrev;
5482 return pNew;
5485 void _HTMLAttr::Reset( const SwNodeIndex& rSttPara, USHORT nSttCnt,
5486 _HTMLAttr **ppHd )
5488 // den Anfang (und das Ende) neu setzen
5489 nSttPara = rSttPara;
5490 nSttCntnt = nSttCnt;
5491 nEndPara = rSttPara;
5492 nEndCntnt = nSttCnt;
5494 // den Head korrigieren und die Verkettungen aufheben
5495 pNext = 0;
5496 pPrev = 0;
5497 ppHead = ppHd;
5500 void _HTMLAttr::InsertPrev( _HTMLAttr *pPrv )
5502 ASSERT( !pPrv->pNext || pPrv->pNext == this,
5503 "_HTMLAttr::InsertPrev: pNext falsch" );
5504 pPrv->pNext = 0;
5506 ASSERT( 0 == pPrv->ppHead || ppHead == pPrv->ppHead,
5507 "_HTMLAttr::InsertPrev: ppHead falsch" );
5508 pPrv->ppHead = 0;
5510 _HTMLAttr *pAttr = this;
5511 while( pAttr->GetPrev() )
5512 pAttr = pAttr->GetPrev();
5514 pAttr->pPrev = pPrv;
5517 bool SwHTMLParser::ParseMetaOptions(
5518 const uno::Reference<document::XDocumentProperties> & i_xDocProps,
5519 SvKeyValueIterator *i_pHeader )
5521 // always call base ParseMetaOptions, it sets the encoding (#i96700#)
5522 bool ret( HTMLParser::ParseMetaOptions(i_xDocProps, i_pHeader) );
5523 if (!ret && IsNewDoc())
5525 ParseMoreMetaOptions();
5527 return ret;
5530 // override so we can parse DOCINFO field subtypes INFO[1-4]
5531 void SwHTMLParser::AddMetaUserDefined( ::rtl::OUString const & i_rMetaName )
5533 // unless we already have 4 names, append the argument to m_InfoNames
5534 ::rtl::OUString* pName // the first empty string in m_InfoNames
5535 (!m_InfoNames[0].getLength() ? &m_InfoNames[0] :
5536 (!m_InfoNames[1].getLength() ? &m_InfoNames[1] :
5537 (!m_InfoNames[2].getLength() ? &m_InfoNames[2] :
5538 (!m_InfoNames[3].getLength() ? &m_InfoNames[3] : 0 ))));
5539 if (pName)
5541 (*pName) = i_rMetaName;