merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / html / swhtml.cxx
bloba883fa42075469165c83b8e3b87f2c8c921e0276
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 <txtfld.hxx>
83 #include <fmtanchr.hxx>
84 #include <fmtsrnd.hxx>
85 #include <fmtfsize.hxx>
86 #include <fmtclds.hxx>
87 #include <fchrfmt.hxx>
88 #include <fmtinfmt.hxx>
89 #include <docary.hxx>
90 #include <docstat.hxx>
91 #include <doc.hxx>
92 #include <pam.hxx>
93 #include <ndtxt.hxx>
94 #include <mdiexp.hxx> // ...Percent()
95 #include <expfld.hxx>
96 #include <poolfmt.hxx>
97 #include <pagedesc.hxx>
98 #include <IMark.hxx> // fuer SwBookmark ...
99 #include <docsh.hxx>
100 #include <editsh.hxx> // fuer Start/EndAction
101 #include <docufld.hxx>
102 #include <swcss1.hxx>
103 #include <htmlvsh.hxx>
104 #include <fltini.hxx>
105 #include <htmltbl.hxx>
106 #include <htmlnum.hxx>
107 #include <swhtml.hxx>
108 #include <linkenum.hxx>
109 #include <breakit.hxx>
110 #include <SwAppletImpl.hxx>
112 #include <sfx2/viewfrm.hxx>
114 #ifndef _STATSTR_HRC
115 #include <statstr.hrc> // ResId fuer Statusleiste
116 #endif
117 #include <swerror.h>
119 #define FONTSIZE_MASK 7
120 #define FONTCOLOR_MASK (1<<15)
121 #define FONT_MASK (1<<14)
123 #define HTML_ESC_PROP 80
124 #define HTML_ESC_SUPER DFLT_ESC_SUPER
125 #define HTML_ESC_SUB DFLT_ESC_SUB
127 #define HTML_SPTYPE_NONE 0
128 #define HTML_SPTYPE_BLOCK 1
129 #define HTML_SPTYPE_HORI 2
130 #define HTML_SPTYPE_VERT 3
132 #ifndef TOOLS_CONSTASCII_STRINGPARAM
133 #define TOOLS_CONSTASCII_STRINGPARAM( constAsciiStr ) constAsciiStr, sizeof( constAsciiStr )-1
134 #endif
136 using namespace ::com::sun::star;
138 // <P ALIGN=xxx>, <Hn ALIGN=xxx>, <TD ALIGN=xxx> usw.
139 HTMLOptionEnum __FAR_DATA aHTMLPAlignTable[] =
141 { OOO_STRING_SVTOOLS_HTML_AL_left, SVX_ADJUST_LEFT },
142 { OOO_STRING_SVTOOLS_HTML_AL_center, SVX_ADJUST_CENTER },
143 { OOO_STRING_SVTOOLS_HTML_AL_middle, SVX_ADJUST_CENTER }, // Netscape
144 { OOO_STRING_SVTOOLS_HTML_AL_right, SVX_ADJUST_RIGHT },
145 { OOO_STRING_SVTOOLS_HTML_AL_justify, SVX_ADJUST_BLOCK },
146 { OOO_STRING_SVTOOLS_HTML_AL_char, SVX_ADJUST_LEFT },
147 { 0, 0 }
150 // <SPACER TYPE=...>
151 static HTMLOptionEnum __FAR_DATA aHTMLSpacerTypeTable[] =
153 { OOO_STRING_SVTOOLS_HTML_SPTYPE_block, HTML_SPTYPE_BLOCK },
154 { OOO_STRING_SVTOOLS_HTML_SPTYPE_horizontal, HTML_SPTYPE_HORI },
155 { OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical, HTML_SPTYPE_VERT },
156 { 0, 0 }
159 SV_IMPL_PTRARR( _HTMLAttrs, _HTMLAttrPtr )
161 HTMLReader::HTMLReader()
163 bTmplBrowseMode = TRUE;
166 String HTMLReader::GetTemplateName() const
168 String sTemplate(
169 String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("internal")) );
170 sTemplate += INET_PATH_TOKEN;
171 sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("html") );
172 String sTemplateWithoutExt( sTemplate );
173 #ifndef MAC_WITHOUT_EXT
174 // --> OD 2005-01-26 - first search for OpenDocument Writer/Web template
175 sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".oth") );
176 // <--
177 #endif
179 SvtPathOptions aPathOpt;
180 // OpenDocument Writer/Web template (extension .oth)
181 BOOL bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
183 #ifndef MAC_WITHOUT_EXT
184 if( !bSet )
186 // 6.0 (extension .stw)
187 sTemplate = sTemplateWithoutExt;
188 // --> OD 2005-01-26 - no OpenDocument Writer/Web template found.
189 // search for OpenOffice.org Writer/Web template
190 sTemplate.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(".stw") );
191 // <--
192 bSet = aPathOpt.SearchFile( sTemplate, SvtPathOptions::PATH_TEMPLATE );
194 #endif
196 if( !bSet )
198 sTemplate.Erase();
199 ASSERT( !this,
200 "Die html.vor befindet sich nicht mehr im definierten Directory!");
203 return sTemplate;
206 int HTMLReader::SetStrmStgPtr()
208 ASSERT( pMedium, "Wo ist das Medium??" );
210 if( pMedium->IsRemote() || !pMedium->IsStorage() )
212 pStrm = pMedium->GetInStream();
213 return TRUE;
215 return FALSE;
219 // Aufruf fuer die allg. Reader-Schnittstelle
220 ULONG HTMLReader::Read( SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & rName )
222 if( !pStrm )
224 ASSERT( pStrm, "HTML-Read ohne Stream" );
225 return ERR_SWG_READ_ERROR;
228 if( !bInsertMode )
230 Reader::SetNoOutlineNum( rDoc );
231 Reader::ResetFrmFmts( rDoc );
233 // Die HTML-Seitenvorlage setzen, wenn des kein HTML-Dokument ist,
234 // sonst ist sie schon gesetzt.
235 if( !rDoc.get(IDocumentSettingAccess::HTML_MODE) )
237 rDoc.InsertPoolItem( rPam, SwFmtPageDesc(
238 rDoc.GetPageDescFromPool( RES_POOLPAGE_HTML, false )), 0 );
242 // damit keiner das Doc klaut!
243 rDoc.acquire();
244 ULONG nRet = 0;
245 SvParserRef xParser = new SwHTMLParser( &rDoc, rPam, *pStrm,
246 rName, rBaseURL, !bInsertMode, pMedium,
247 IsReadUTF8(),
248 bIgnoreHTMLComments );
250 SvParserState eState = xParser->CallParser();
252 if( SVPAR_PENDING == eState )
253 pStrm->ResetError();
254 else if( SVPAR_ACCEPTED != eState )
256 String sErr( String::CreateFromInt32((sal_Int32)xParser->GetLineNr()));
257 sErr += ',';
258 sErr += String::CreateFromInt32((sal_Int32)xParser->GetLinePos());
260 // den Stream als Fehlernummer Transporter benutzen
261 nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr,
262 ERRCODE_BUTTON_OK | ERRCODE_MSG_ERROR );
266 return nRet;
270 /* \f */
272 SwHTMLParser::SwHTMLParser( SwDoc* pD, const SwPaM& rCrsr, SvStream& rIn,
273 const String& rPath,
274 const String& rBaseURL,
275 int bReadNewDoc,
276 SfxMedium* pMed, BOOL bReadUTF8,
277 sal_Bool bNoHTMLComments )
278 : SfxHTMLParser( rIn, static_cast< BOOL >(bReadNewDoc), pMed ),
279 SwClient( 0 ),
280 aPathToFile( rPath ),
281 sBaseURL( rBaseURL ),
282 pAppletImpl( 0 ),
283 pCSS1Parser( 0 ),
284 pNumRuleInfo( new SwHTMLNumRuleInfo ),
285 pPendStack( 0 ),
286 pDoc( pD ),
287 pActionViewShell( 0 ),
288 pSttNdIdx( 0 ),
289 pTable(0),
290 pFormImpl( 0 ),
291 pMarquee( 0 ),
292 pField( 0 ),
293 pImageMap( 0 ),
294 pImageMaps( 0 ),
295 pFootEndNoteImpl( 0 ),
296 nScriptStartLineNr( 0 ),
297 nBaseFontStMin( 0 ),
298 nFontStMin( 0 ),
299 nDefListDeep( 0 ),
300 nFontStHeadStart( 0 ),
301 nSBModuleCnt( 0 ),
302 nMissingImgMaps( 0 ),
303 nParaCnt( 5 ),
304 // --> OD 2007-10-26 #i83625#
305 nContextStMin( 0 ),
306 nContextStAttrMin( 0 ),
307 // <--
308 nOpenParaToken( 0 ),
309 eJumpTo( JUMPTO_NONE ),
310 #ifndef PRODUCT
311 nContinue( 0 ),
312 #endif
313 eParaAdjust( SVX_ADJUST_END ),
314 bDocInitalized( FALSE ),
315 bSetModEnabled( FALSE ),
316 bInFloatingFrame( FALSE ),
317 bInField( FALSE ),
318 bCallNextToken( FALSE ),
319 bIgnoreRawData( FALSE ),
320 bNoParSpace( FALSE ),
321 bInNoEmbed( FALSE ),
322 bInTitle( FALSE ),
323 bUpdateDocStat( FALSE ),
324 bFixSelectWidth( FALSE ),
325 bFixSelectHeight( FALSE ),
326 bTextArea( FALSE ),
327 bSelect( FALSE ),
328 bInFootEndNoteAnchor( FALSE ),
329 bInFootEndNoteSymbol( FALSE ),
330 // bIgnoreHTMLComments( bNoHTMLComments )
331 bIgnoreHTMLComments( bNoHTMLComments ),
332 bRemoveHidden( FALSE ),
333 pTempViewFrame(0)
335 nEventId = 0;
336 bUpperSpace = bViewCreated = bChkJumpMark =
337 bSetCrsr = FALSE;
339 eScriptLang = HTML_SL_UNKNOWN;
340 bAnyStarBasic = TRUE;
342 pPam = new SwPaM( *rCrsr.GetPoint() );
343 memset( &aAttrTab, 0, sizeof( _HTMLAttrTable ));
345 // Die Font-Groessen 1-7 aus der INI-Datei lesen
346 SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get();
347 aFontHeights[0] = pHtmlOptions->GetFontSize( 0 ) * 20;
348 aFontHeights[1] = pHtmlOptions->GetFontSize( 1 ) * 20;
349 aFontHeights[2] = pHtmlOptions->GetFontSize( 2 ) * 20;
350 aFontHeights[3] = pHtmlOptions->GetFontSize( 3 ) * 20;
351 aFontHeights[4] = pHtmlOptions->GetFontSize( 4 ) * 20;
352 aFontHeights[5] = pHtmlOptions->GetFontSize( 5 ) * 20;
353 aFontHeights[6] = pHtmlOptions->GetFontSize( 6 ) * 20;
355 bKeepUnknown = pHtmlOptions->IsImportUnknown();
357 if(bReadNewDoc)
359 SvxFontHeightItem aFontHeight(aFontHeights[2], 100, RES_CHRATR_FONTSIZE);
360 pDoc->SetDefault( aFontHeight );
361 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
362 pDoc->SetDefault( aFontHeight );
363 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
364 pDoc->SetDefault( aFontHeight );
367 // Waehrend des Imports in den HTML-Modus schalten, damit die
368 // richrigen Vorlagen angelegt werden
369 bOldIsHTMLMode = pDoc->get(IDocumentSettingAccess::HTML_MODE);
370 pDoc->set(IDocumentSettingAccess::HTML_MODE, true);
372 pCSS1Parser = new SwCSS1Parser( pDoc, aFontHeights, sBaseURL, IsNewDoc() );
373 pCSS1Parser->SetIgnoreFontFamily( pHtmlOptions->IsIgnoreFontFamily() );
375 if( bReadUTF8 )
377 SetSrcEncoding( RTL_TEXTENCODING_UTF8 );
379 else
381 SwDocShell *pDocSh = pDoc->GetDocShell();
382 SvKeyValueIterator *pHeaderAttrs =
383 pDocSh->GetHeaderAttributes();
384 if( pHeaderAttrs )
385 SetEncodingByHTTPHeader( pHeaderAttrs );
387 pCSS1Parser->SetDfltEncoding( gsl_getSystemTextEncoding() );
389 // Timer nur bei ganz normalen Dokumenten aufsetzen!
390 SwDocShell* pDocSh = pDoc->GetDocShell();
391 if( pDocSh )
393 bViewCreated = TRUE; // nicht, synchron laden
395 // es ist ein Sprungziel vorgegeben.
397 if( pMed )
399 sJmpMark = pMed->GetURLObject().GetMark();
400 if( sJmpMark.Len() )
402 eJumpTo = JUMPTO_MARK;
403 String sCmp;
404 xub_StrLen nLastPos, nPos = 0;
405 while( STRING_NOTFOUND != ( nLastPos =
406 sJmpMark.Search( cMarkSeperator, nPos + 1 )) )
407 nPos = nLastPos;
409 if( nPos && ( sCmp = sJmpMark.Copy( nPos + 1 ) ).
410 EraseAllChars().Len() )
412 sCmp.ToLowerAscii();
413 if( sCmp.EqualsAscii( pMarkToRegion ) )
414 eJumpTo = JUMPTO_REGION;
415 else if( sCmp.EqualsAscii( pMarkToTable ) )
416 eJumpTo = JUMPTO_TABLE;
417 else if( sCmp.EqualsAscii( pMarkToGraphic ) )
418 eJumpTo = JUMPTO_GRAPHIC;
419 else if( sCmp.EqualsAscii( pMarkToOutline ) ||
420 sCmp.EqualsAscii( pMarkToText ) ||
421 sCmp.EqualsAscii( pMarkToFrame ) )
422 eJumpTo = JUMPTO_NONE; // das ist nichts gueltiges!
423 else
424 // ansonsten ist das ein normaler (Book)Mark
425 nPos = STRING_LEN;
427 else
428 nPos = STRING_LEN;
430 sJmpMark.Erase( nPos );
431 if( !sJmpMark.Len() )
432 eJumpTo = JUMPTO_NONE;
438 __EXPORT SwHTMLParser::~SwHTMLParser()
440 #ifndef PRODUCT
441 ASSERT( !nContinue, "DTOR im Continue - Das geht schief!!!" );
442 #endif
443 BOOL bAsync = pDoc->IsInLoadAsynchron();
444 pDoc->SetInLoadAsynchron( FALSE );
445 pDoc->set(IDocumentSettingAccess::HTML_MODE, bOldIsHTMLMode);
447 if( pDoc->GetDocShell() && nEventId )
448 Application::RemoveUserEvent( nEventId );
450 // das DocumentDetected kann ggfs. die DocShells loeschen, darum nochmals
451 // abfragen
452 if( pDoc->GetDocShell() )
454 // Gelinkte Bereiche updaten
455 USHORT nLinkMode = pDoc->getLinkUpdateMode( true );
456 if( nLinkMode != NEVER && bAsync &&
457 SFX_CREATE_MODE_INTERNAL!=pDoc->GetDocShell()->GetCreateMode() )
458 pDoc->GetLinkManager().UpdateAllLinks( nLinkMode == MANUAL,
459 TRUE, FALSE );
461 if ( pDoc->GetDocShell()->IsLoading() )
463 // --> OD 2006-11-07 #i59688#
464 pDoc->GetDocShell()->LoadingFinished();
468 delete pSttNdIdx;
470 if( aSetAttrTab.Count() )
472 ASSERT( !aSetAttrTab.Count(),"Es stehen noch Attribute auf dem Stack" );
473 aSetAttrTab.DeleteAndDestroy( 0, aSetAttrTab.Count() );
476 delete pPam;
477 delete pCSS1Parser;
478 delete pNumRuleInfo;
479 DeleteFormImpl();
480 DeleteFootEndNoteImpl();
482 ASSERT( !pTable, "Es existiert noch eine offene Tabelle" );
483 delete pImageMaps;
484 //delete pTable;
486 ASSERT( !pPendStack,
487 "SwHTMLParser::~SwHTMLParser: Hier sollte es keinen Pending-Stack mehr geben" );
488 while( pPendStack )
490 SwPendingStack* pTmp = pPendStack;
491 pPendStack = pPendStack->pNext;
492 delete pTmp->pData;
493 delete pTmp;
496 if( !pDoc->release() )
498 // keiner will mehr das Doc haben, also weg damit
499 delete pDoc;
500 pDoc = NULL;
503 if ( pTempViewFrame )
505 pTempViewFrame->DoClose();
507 // the temporary view frame is hidden, so the hidden flag might need to be removed
508 if ( bRemoveHidden && pDoc && pDoc->GetDocShell() && pDoc->GetDocShell()->GetMedium() )
509 pDoc->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN );
513 IMPL_LINK( SwHTMLParser, AsyncCallback, void*, /*pVoid*/ )
515 nEventId=0;
517 // --> FME 2005-08-18 #i47907# If the document has already been destructed,
518 // the parser should be aware of this:
519 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
520 || 1 == pDoc->getReferenceCount() )
522 // wurde der Import vom SFX abgebrochen?
523 eState = SVPAR_ERROR;
525 // <--
527 GetAsynchCallLink().Call(0);
528 return 0;
531 SvParserState __EXPORT SwHTMLParser::CallParser()
533 // einen temporaeren Index anlegen, auf Pos 0 so wird er nicht bewegt!
534 pSttNdIdx = new SwNodeIndex( pDoc->GetNodes() );
535 if( !IsNewDoc() ) // in ein Dokument einfuegen ?
537 const SwPosition* pPos = pPam->GetPoint();
539 pDoc->SplitNode( *pPos, false );
541 *pSttNdIdx = pPos->nNode.GetIndex()-1;
542 pDoc->SplitNode( *pPos, false );
544 SwPaM aInsertionRangePam( *pPos );
546 pPam->Move( fnMoveBackward );
548 // #106634# split any redline over the insertion point
549 aInsertionRangePam.SetMark();
550 *aInsertionRangePam.GetPoint() = *pPam->GetPoint();
551 aInsertionRangePam.Move( fnMoveBackward );
552 pDoc->SplitRedline( aInsertionRangePam );
554 pDoc->SetTxtFmtColl( *pPam,
555 pCSS1Parser->GetTxtCollFromPool( RES_POOLCOLL_STANDARD ));
558 if( GetMedium() )
560 if( !bViewCreated )
562 nEventId = Application::PostUserEvent( LINK( this, SwHTMLParser, AsyncCallback ), 0 );
564 else
566 bViewCreated = TRUE;
567 nEventId = 0;
571 // Laufbalken anzeigen
572 else if( !GetMedium() || !GetMedium()->IsRemote() )
574 rInput.Seek(STREAM_SEEK_TO_END);
575 rInput.ResetError();
576 ::StartProgress( STR_STATSTR_W4WREAD, 0, rInput.Tell(),
577 pDoc->GetDocShell() );
578 rInput.Seek(STREAM_SEEK_TO_BEGIN);
579 rInput.ResetError();
582 SwPageDesc& rDesc = pDoc->_GetPageDesc( 0 );
583 rDesc.Add( this );
585 SvParserState eRet = HTMLParser::CallParser();
586 return eRet;
589 void __EXPORT SwHTMLParser::Continue( int nToken )
591 #ifndef PRODUCT
592 ASSERT( !nContinue, "Continue im Continue - Das sollte doch nicht sein, oder?" );
593 nContinue++;
594 #endif
596 // Wenn der Import (vom SFX) abgebrochen wurde, wird ein Fehler
597 // gesetzt aber trotzdem noch weiter gemacht, damit vernuenftig
598 // aufgeraeumt wird.
599 ASSERT( SVPAR_ERROR!=eState,
600 "SwHTMLParser::Continue: bereits ein Fehler gesetzt" );
601 if( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
602 eState = SVPAR_ERROR;
604 // Die ViewShell vom Dokument holen, merken und als aktuelle setzen.
605 ViewShell *pInitVSh = CallStartAction();
607 if( SVPAR_ERROR != eState && GetMedium() && !bViewCreated )
609 // Beim ersten Aufruf erstmal returnen, Doc anzeigen
610 // und auf Timer Callback warten.
611 // An dieser Stelle wurde im CallParser gerade mal ein Zeichen
612 // gelesen und ein SaveState(0) gerufen.
613 eState = SVPAR_PENDING;
614 bViewCreated = TRUE;
615 pDoc->SetInLoadAsynchron( TRUE );
617 #ifndef PRODUCT
618 nContinue--;
619 #endif
621 return;
624 bSetModEnabled = FALSE;
625 if( pDoc->GetDocShell() &&
626 0 != (bSetModEnabled = pDoc->GetDocShell()->IsEnableSetModified()) )
628 pDoc->GetDocShell()->EnableSetModified( FALSE );
631 // waehrend des einlesens kein OLE-Modified rufen
632 Link aOLELink( pDoc->GetOle2Link() );
633 pDoc->SetOle2Link( Link() );
635 BOOL bModified = pDoc->IsModified();
636 BOOL bWasUndo = pDoc->DoesUndo();
637 pDoc->DoUndo( FALSE );
639 // Wenn der Import abgebrochen wird, kein Continue mehr rufen.
640 // Falls ein Pending-Stack existiert aber durch einen Aufruf
641 // von NextToken dafuer sorgen, dass der Pending-Stack noch
642 // beendet wird.
643 if( SVPAR_ERROR == eState )
645 ASSERT( !pPendStack || pPendStack->nToken,
646 "SwHTMLParser::Continue: Pending-Stack ohne Token" );
647 if( pPendStack && pPendStack->nToken )
648 NextToken( pPendStack->nToken );
649 ASSERT( !pPendStack,
650 "SwHTMLParser::Continue: Es gibt wieder einen Pend-Stack" );
652 else
654 HTMLParser::Continue( pPendStack ? pPendStack->nToken : nToken );
657 // Laufbalken wieder abschalten
658 EndProgress( pDoc->GetDocShell() );
660 BOOL bLFStripped = FALSE;
661 if( SVPAR_PENDING != GetStatus() )
663 // noch die letzten Attribute setzen
665 if( aScriptSource.Len() )
667 SwScriptFieldType *pType =
668 (SwScriptFieldType*)pDoc->GetSysFldType( RES_SCRIPTFLD );
670 SwScriptField aFld( pType, aScriptType, aScriptSource,
671 FALSE );
672 InsertAttr( SwFmtFld( aFld ) );
675 if( pAppletImpl )
677 if( pAppletImpl->GetApplet().is() )
678 EndApplet();
679 else
680 EndObject();
683 // ggf. ein noch vorhandes LF hinter dem letzen Absatz entfernen
684 if( IsNewDoc() )
685 bLFStripped = StripTrailingLF() > 0;
687 // noch offene Nummerierungen beenden.
688 while( GetNumInfo().GetNumRule() )
689 EndNumBulList();
691 ASSERT( !nContextStMin, "Es gibt geschuetzte Kontexte" );
692 nContextStMin = 0;
693 while( aContexts.Count() )
695 _HTMLAttrContext *pCntxt = PopContext();
696 if( pCntxt )
698 EndContext( pCntxt );
699 delete pCntxt;
703 if( aParaAttrs.Count() )
704 aParaAttrs.Remove( 0, aParaAttrs.Count() );
706 SetAttr( FALSE );
708 // Noch die erst verzoegert gesetzten Styles setzen
709 pCSS1Parser->SetDelayedStyles();
712 // den Start wieder korrigieren
713 if( !IsNewDoc() && pSttNdIdx->GetIndex() )
715 SwTxtNode* pTxtNode = pSttNdIdx->GetNode().GetTxtNode();
716 SwNodeIndex aNxtIdx( *pSttNdIdx );
717 if( pTxtNode && pTxtNode->CanJoinNext( &aNxtIdx ))
719 xub_StrLen nStt = pTxtNode->GetTxt().Len();
720 // wenn der Cursor noch in dem Node steht, dann setze in an das Ende
721 if( pPam->GetPoint()->nNode == aNxtIdx )
723 pPam->GetPoint()->nNode = *pSttNdIdx;
724 pPam->GetPoint()->nContent.Assign( pTxtNode, nStt );
727 #ifndef PRODUCT
728 // !!! sollte nicht moeglich sein, oder ??
729 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( TRUE ).nNode.GetIndex(),
730 "Pam.Bound1 steht noch im Node" );
731 ASSERT( pSttNdIdx->GetIndex()+1 != pPam->GetBound( FALSE ).nNode.GetIndex(),
732 "Pam.Bound2 steht noch im Node" );
734 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( TRUE ).nNode.GetIndex() )
736 xub_StrLen nCntPos = pPam->GetBound( TRUE ).nContent.GetIndex();
737 pPam->GetBound( TRUE ).nContent.Assign( pTxtNode,
738 pTxtNode->GetTxt().Len() + nCntPos );
740 if( pSttNdIdx->GetIndex()+1 == pPam->GetBound( FALSE ).nNode.GetIndex() )
742 xub_StrLen nCntPos = pPam->GetBound( FALSE ).nContent.GetIndex();
743 pPam->GetBound( FALSE ).nContent.Assign( pTxtNode,
744 pTxtNode->GetTxt().Len() + nCntPos );
746 #endif
747 // Zeichen Attribute beibehalten!
748 SwTxtNode* pDelNd = aNxtIdx.GetNode().GetTxtNode();
749 if( pTxtNode->GetTxt().Len() )
750 pDelNd->FmtToTxtAttr( pTxtNode );
751 else
752 pTxtNode->ChgFmtColl( pDelNd->GetTxtColl() );
753 pTxtNode->JoinNext();
758 if( SVPAR_ACCEPTED == eState )
760 if( nMissingImgMaps )
762 // es fehlen noch ein paar Image-Map zuordungen.
763 // vielleicht sind die Image-Maps ja jetzt da?
764 ConnectImageMaps();
767 // jetzt noch den letzten ueberfluessigen Absatz loeschen
768 SwPosition* pPos = pPam->GetPoint();
769 if( !pPos->nContent.GetIndex() && !bLFStripped )
771 SwTxtNode* pAktNd;
772 ULONG nNodeIdx = pPos->nNode.GetIndex();
774 BOOL bHasFlysOrMarks =
775 HasCurrentParaFlys() || HasCurrentParaBookmarks( TRUE );
777 if( IsNewDoc() )
779 const SwNode *pPrev = pDoc->GetNodes()[nNodeIdx -1];
780 if( !pPam->GetPoint()->nContent.GetIndex() &&
781 ( pPrev->IsCntntNode() ||
782 (pPrev->IsEndNode() &&
783 pPrev->StartOfSectionNode()->IsSectionNode()) ) )
785 SwCntntNode* pCNd = pPam->GetCntntNode();
786 if( pCNd && pCNd->StartOfSectionIndex()+2 <
787 pCNd->EndOfSectionIndex() && !bHasFlysOrMarks )
789 ViewShell *pVSh = CheckActionViewShell();
790 SwCrsrShell *pCrsrSh = pVSh && pVSh->ISA(SwCrsrShell)
791 ? static_cast < SwCrsrShell * >( pVSh )
792 : 0;
793 if( pCrsrSh &&
794 pCrsrSh->GetCrsr()->GetPoint()
795 ->nNode.GetIndex() == nNodeIdx )
797 pCrsrSh->MovePara(fnParaPrev, fnParaEnd );
798 pCrsrSh->SetMark();
799 pCrsrSh->ClearMark();
801 pPam->GetBound(TRUE).nContent.Assign( 0, 0 );
802 pPam->GetBound(FALSE).nContent.Assign( 0, 0 );
803 pDoc->GetNodes().Delete( pPam->GetPoint()->nNode );
807 else if( 0 != ( pAktNd = pDoc->GetNodes()[ nNodeIdx ]->GetTxtNode()) && !bHasFlysOrMarks )
809 if( pAktNd->CanJoinNext( &pPos->nNode ))
811 SwTxtNode* pNextNd = pPos->nNode.GetNode().GetTxtNode();
812 pPos->nContent.Assign( pNextNd, 0 );
813 pPam->SetMark(); pPam->DeleteMark();
814 pNextNd->JoinPrev();
816 else if( !pAktNd->GetTxt().Len() )
818 pPos->nContent.Assign( 0, 0 );
819 pPam->SetMark(); pPam->DeleteMark();
820 pDoc->GetNodes().Delete( pPos->nNode, 1 );
821 pPam->Move( fnMoveBackward );
826 // nun noch das SplitNode vom Anfang aufheben
827 else if( !IsNewDoc() )
829 if( pPos->nContent.GetIndex() ) // dann gabs am Ende kein <P>,
830 pPam->Move( fnMoveForward, fnGoNode ); // als zum naechsten Node
831 SwTxtNode* pTxtNode = pPos->nNode.GetNode().GetTxtNode();
832 SwNodeIndex aPrvIdx( pPos->nNode );
833 if( pTxtNode && pTxtNode->CanJoinPrev( &aPrvIdx ) &&
834 *pSttNdIdx <= aPrvIdx )
836 // eigentlich muss hier ein JoinNext erfolgen, aber alle Cursor
837 // usw. sind im pTxtNode angemeldet, so dass der bestehen
838 // bleiben MUSS.
840 // Absatz in Zeichen-Attribute umwandeln, aus dem Prev die
841 // Absatzattribute und die Vorlage uebernehmen!
842 SwTxtNode* pPrev = aPrvIdx.GetNode().GetTxtNode();
843 pTxtNode->ChgFmtColl( pPrev->GetTxtColl() );
844 pTxtNode->FmtToTxtAttr( pPrev );
845 pTxtNode->ResetAllAttr();
847 if( pPrev->HasSwAttrSet() )
848 pTxtNode->SetAttr( *pPrev->GetpSwAttrSet() );
850 if( &pPam->GetBound(TRUE).nNode.GetNode() == pPrev )
851 pPam->GetBound(TRUE).nContent.Assign( pTxtNode, 0 );
852 if( &pPam->GetBound(FALSE).nNode.GetNode() == pPrev )
853 pPam->GetBound(FALSE).nContent.Assign( pTxtNode, 0 );
855 pTxtNode->JoinPrev();
859 // und noch die DocumentInfo aufbereiten
860 if( IsNewDoc() )
862 SwDocShell *pDocShell(pDoc->GetDocShell());
863 DBG_ASSERT(pDocShell, "no SwDocShell");
864 if (pDocShell) {
865 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
866 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
867 uno::Reference<document::XDocumentProperties> xDocProps(
868 xDPS->getDocumentProperties());
869 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
870 if ( xDocProps.is() && (xDocProps->getAutoloadSecs() > 0) &&
871 xDocProps->getAutoloadURL().equalsAscii("") )
873 xDocProps->setAutoloadURL(aPathToFile);
878 if( bUpdateDocStat )
880 SwDocStat aStat( pDoc->GetDocStat() );
881 pDoc->UpdateDocStat( aStat );
885 if( SVPAR_PENDING != GetStatus() )
886 delete pSttNdIdx, pSttNdIdx = 0;
888 // sollte der Parser der Letzte sein, der das Doc haelt, dann braucht
889 // man hier auch nichts mehr tun, Doc wird gleich zerstoert!
890 if( 1 < pDoc->getReferenceCount() )
892 if( bWasUndo )
894 pDoc->DelAllUndoObj();
895 pDoc->DoUndo( TRUE );
897 else if( !pInitVSh )
899 // Wenn zu Beginn des Continue keine Shell vorhanden war,
900 // kann trotzdem mitlerweile eine angelegt worden sein.
901 // In dieses Fall stimmt das bWasUndo-Flag nicht und
902 // wir muessen das Undo noch anschalten.
903 ViewShell *pTmpVSh = CheckActionViewShell();
904 if( pTmpVSh )
905 pDoc->DoUndo( TRUE );
908 pDoc->SetOle2Link( aOLELink );
909 if( !bModified )
910 pDoc->ResetModified();
911 if( bSetModEnabled && pDoc->GetDocShell() )
913 pDoc->GetDocShell()->EnableSetModified( TRUE );
914 bSetModEnabled = FALSE; // this is unnecessary here
919 // Wenn die Dokuemnt-ViewShell noch existiert und eine Action
920 // offen ist (muss bei Abbruch nicht sein), die Action beenden,
921 // uns von der Shell abmelden und schliesslich die alte Shell
922 // wieder rekonstruieren.
923 CallEndAction( TRUE );
925 #ifndef PRODUCT
926 nContinue--;
927 #endif
930 void SwHTMLParser::Modify( SfxPoolItem *pOld, SfxPoolItem *pNew )
932 switch( pOld ? pOld->Which() : pNew ? pNew->Which() : 0 )
934 case RES_OBJECTDYING:
935 if( ((SwPtrMsgPoolItem *)pOld)->pObject == pRegisteredIn )
937 // dann uns selbst beenden
938 pRegisteredIn->Remove( this );
939 ReleaseRef(); // ansonsten sind wir fertig!
941 break;
945 void SwHTMLParser::DocumentDetected()
947 ASSERT( !bDocInitalized, "DocumentDetected mehrfach aufgerufen" );
948 bDocInitalized = TRUE;
949 if( IsNewDoc() )
951 if( IsInHeader() )
952 FinishHeader( TRUE );
954 CallEndAction( TRUE, TRUE );
956 pDoc->DoUndo( FALSE );
957 // Durch das DocumentDetected wurde im allgemeinen eine
958 // ViewShell angelegt. Es kann aber auch sein, dass sie
959 // erst spaeter angelegt wird, naemlich dann, wenn die UI
960 // gecaptured ist.
961 CallStartAction();
965 // wird fuer jedes Token gerufen, das in CallParser erkannt wird
966 void __EXPORT SwHTMLParser::NextToken( int nToken )
968 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
969 || 1 == pDoc->getReferenceCount() )
971 // wurde der Import vom SFX abgebrochen? Wenn ein Pending-Stack
972 // existiert den noch aufraumen
973 eState = SVPAR_ERROR;
974 ASSERT( !pPendStack || pPendStack->nToken,
975 "SwHTMLParser::NextToken: Pending-Stack ohne Token" );
976 if( 1 == pDoc->getReferenceCount() || !pPendStack )
977 return ;
980 #ifndef PRODUCT
981 if( pPendStack )
983 switch( nToken )
985 // Tabellen werden ueber rekusive Methodenaufrufe gelesen
986 case HTML_TABLE_ON:
987 // Bei CSS-Deklarationen muss evtl. noch auf das
988 // Ende eines File-Downloads gewartet werden.
989 case HTML_LINK:
990 // Bei Controls muss evtl. noch die Groesse gesetzt werden.
991 case HTML_INPUT:
992 case HTML_TEXTAREA_ON:
993 case HTML_SELECT_ON:
994 case HTML_SELECT_OFF:
995 break;
996 default:
997 ASSERT( !pPendStack, "Unbekanntes Token fuer Pending-Stack" );
998 break;
1001 #endif
1003 // Die folgeneden Spezialfaelle muessen vor der Filter-Detection behandelt
1004 // werden, denn der Inhalt des Titels, etc. wird auch in Netcape nicht
1005 // zur Filter-Detection herangezogen.
1006 if( !pPendStack )
1008 if( bInTitle )
1010 switch( nToken )
1012 case HTML_TITLE_OFF:
1013 if( IsNewDoc() && sTitle.Len() )
1015 if( pDoc->GetDocShell() ) {
1016 uno::Reference<document::XDocumentPropertiesSupplier>
1017 xDPS(pDoc->GetDocShell()->GetModel(),
1018 uno::UNO_QUERY_THROW);
1019 uno::Reference<document::XDocumentProperties> xDocProps(
1020 xDPS->getDocumentProperties());
1021 DBG_ASSERT(xDocProps.is(), "no DocumentProperties");
1022 if (xDocProps.is()) {
1023 xDocProps->setTitle(sTitle);
1026 pDoc->GetDocShell()->SetTitle( sTitle );
1029 bInTitle = FALSE;
1030 sTitle.Erase();
1031 break;
1033 case HTML_NONBREAKSPACE:
1034 sTitle += ' ';
1035 break;
1037 case HTML_SOFTHYPH:
1038 sTitle += '-';
1039 break;
1041 case HTML_TEXTTOKEN:
1042 sTitle += aToken;
1043 break;
1045 default:
1046 sTitle += '<';
1047 if( (HTML_TOKEN_ONOFF & nToken) && (1 & nToken) )
1048 sTitle += '/';
1049 sTitle += sSaveToken;
1050 if( aToken.Len() )
1052 sTitle += ' ';
1053 sTitle += aToken;
1055 sTitle += '>';
1056 break;
1059 return;
1063 // Wenn wir noch nicht wissen, was fuer ein Dokument wir vor uns haben,
1064 // versuchen wir das erstmal rauszufinden. Das muss fuer Controls in
1065 // Fall vor dem Einfuegen des Controls passieren, weil beim Einfuegen
1066 // bereits eine View benoetigt wird.
1067 if( !bDocInitalized )
1068 DocumentDetected();
1070 BOOL bGetIDOption = FALSE, bInsertUnknown = FALSE;
1071 BOOL bUpperSpaceSave = bUpperSpace;
1072 bUpperSpace = FALSE;
1074 // Die folgenden Speziallfaelle muessen oder koennen nach der
1075 // Filter-Detection erfolgen.
1076 if( !pPendStack )
1078 if( bInFloatingFrame )
1080 // <SCRIPT> wird hier (von uns) ignoriert, weil es auch in
1081 // Applets ignoriert wird!
1082 if( HTML_IFRAME_OFF == nToken )
1084 bCallNextToken = FALSE;
1085 EndFloatingFrame();
1088 return;
1090 else if( bInNoEmbed )
1092 switch( nToken )
1094 case HTML_NOEMBED_OFF:
1095 aContents.ConvertLineEnd();
1096 InsertComment( aContents, OOO_STRING_SVTOOLS_HTML_noembed );
1097 aContents.Erase();
1098 bCallNextToken = FALSE;
1099 bInNoEmbed = FALSE;
1100 break;
1102 case HTML_RAWDATA:
1103 InsertCommentText( OOO_STRING_SVTOOLS_HTML_noembed );
1104 break;
1106 default:
1107 ASSERT( !this, "SwHTMLParser::NextToken: ungueltiges Tag" );
1108 break;
1111 return;
1113 else if( pAppletImpl )
1115 // in einem Applet interessieren uns (erstmal) nur <PARAM>-Tags
1116 // und das </APPLET>.
1117 // <SCRIPT> wird hier (von Netscape) ignoriert!
1119 switch( nToken )
1121 case HTML_APPLET_OFF:
1122 bCallNextToken = FALSE;
1123 EndApplet();
1124 break;
1125 case HTML_OBJECT_OFF:
1126 bCallNextToken = FALSE;
1127 EndObject();
1128 break;
1130 case HTML_PARAM:
1131 InsertParam();
1132 break;
1135 return;
1137 else if( bTextArea )
1139 // in einer TextArea wird alles bis zum </TEXTAREA> als Text
1140 // eingefuegt
1141 // <SCRIPT> wird hier (von Netscape) ignoriert!
1143 switch( nToken )
1145 case HTML_TEXTAREA_OFF:
1146 bCallNextToken = FALSE;
1147 EndTextArea();
1148 break;
1150 default:
1151 InsertTextAreaText( static_cast< sal_uInt16 >(nToken) );
1152 break;
1155 return;
1157 else if( bSelect )
1159 // MUSS nach bNoScript kommen!
1160 switch( nToken )
1162 case HTML_SELECT_OFF:
1163 bCallNextToken = FALSE;
1164 EndSelect();
1165 return;
1167 case HTML_OPTION:
1168 InsertSelectOption();
1169 return;
1171 case HTML_TEXTTOKEN:
1172 InsertSelectText();
1173 return;
1175 case HTML_INPUT:
1176 case HTML_SCRIPT_ON:
1177 case HTML_SCRIPT_OFF:
1178 case HTML_NOSCRIPT_ON:
1179 case HTML_NOSCRIPT_OFF:
1180 case HTML_RAWDATA:
1181 // im normalen switch bahandeln
1182 break;
1184 default:
1185 // ignorieren
1186 return;
1189 else if( pMarquee )
1191 // in einer TextArea wird alles bis zum </TEXTAREA> als Text
1192 // eingefuegt
1193 // Die <SCRIPT>-Tags werden vom MS-IE ignoriert, von uns das
1194 // geasmte Script
1195 switch( nToken )
1197 case HTML_MARQUEE_OFF:
1198 bCallNextToken = FALSE;
1199 EndMarquee();
1200 break;
1202 case HTML_TEXTTOKEN:
1203 InsertMarqueeText();
1204 break;
1207 return;
1209 else if( bInField )
1211 switch( nToken )
1213 case HTML_SDFIELD_OFF:
1214 bCallNextToken = FALSE;
1215 EndField();
1216 break;
1218 case HTML_TEXTTOKEN:
1219 InsertFieldText();
1220 break;
1223 return;
1225 else if( bInFootEndNoteAnchor || bInFootEndNoteSymbol )
1227 switch( nToken )
1229 case HTML_ANCHOR_OFF:
1230 EndAnchor();
1231 bCallNextToken = FALSE;
1232 break;
1234 case HTML_TEXTTOKEN:
1235 InsertFootEndNoteText();
1236 break;
1238 return;
1240 else if( aUnknownToken.Len() )
1242 // Unbekannte Token im Header werden nur durch ein passendes
1243 // End-Token, </HEAD> oder <BODY> wieder beendet. Darin wird Text
1244 // ignoriert.
1245 switch( nToken )
1247 case HTML_UNKNOWNCONTROL_OFF:
1248 if( aUnknownToken.CompareTo(sSaveToken) != COMPARE_EQUAL )
1249 return;
1250 case HTML_FRAMESET_ON:
1251 case HTML_HEAD_OFF:
1252 case HTML_BODY_ON:
1253 case HTML_IMAGE: // Warum auch immer Netscape das tut.
1254 aUnknownToken.Erase();
1255 break;
1256 case HTML_TEXTTOKEN:
1257 return;
1258 default:
1259 break;
1264 switch( nToken )
1266 case HTML_BODY_ON:
1267 if( aStyleSource.Len() )
1269 pCSS1Parser->ParseStyleSheet( aStyleSource );
1270 aStyleSource.Erase();
1272 if( IsNewDoc() )
1274 InsertBodyOptions();
1275 // Falls es eine Vorlage fuer die erste oder rechte Seite gibt,
1276 // setzen wir die hier.
1277 const SwPageDesc *pPageDesc = 0;
1278 if( pCSS1Parser->IsSetFirstPageDesc() )
1279 pPageDesc = pCSS1Parser->GetFirstPageDesc();
1280 else if( pCSS1Parser->IsSetRightPageDesc() )
1281 pPageDesc = pCSS1Parser->GetRightPageDesc();
1283 if( pPageDesc )
1285 pDoc->InsertPoolItem( *pPam, SwFmtPageDesc( pPageDesc ), 0 );
1288 break;
1290 case HTML_LINK:
1291 InsertLink();
1292 break;
1294 case HTML_BASE:
1296 const HTMLOptions *pHTMLOptions = GetOptions();
1297 for( USHORT i = pHTMLOptions->Count(); i; )
1299 const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1300 switch( pOption->GetToken() )
1302 case HTML_O_HREF:
1303 sBaseURL = pOption->GetString();
1304 break;
1305 case HTML_O_TARGET:
1306 if( IsNewDoc() )
1308 SwDocShell *pDocShell(pDoc->GetDocShell());
1309 DBG_ASSERT(pDocShell, "no SwDocShell");
1310 if (pDocShell) {
1311 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1312 pDocShell->GetModel(), uno::UNO_QUERY_THROW);
1313 uno::Reference<document::XDocumentProperties>
1314 xDocProps(xDPS->getDocumentProperties());
1315 DBG_ASSERT(xDocProps.is(),"no DocumentProperties");
1316 if (xDocProps.is()) {
1317 xDocProps->setDefaultTarget(
1318 pOption->GetString());
1322 break;
1326 break;
1328 case HTML_META:
1330 SvKeyValueIterator *pHTTPHeader = 0;
1331 if( IsNewDoc() )
1333 SwDocShell *pDocSh = pDoc->GetDocShell();
1334 if( pDocSh )
1335 pHTTPHeader = pDocSh->GetHeaderAttributes();
1337 SwDocShell *pDocShell(pDoc->GetDocShell());
1338 DBG_ASSERT(pDocShell, "no SwDocShell");
1339 if (pDocShell)
1341 uno::Reference<document::XDocumentProperties> xDocProps;
1342 if (IsNewDoc())
1344 const uno::Reference<document::XDocumentPropertiesSupplier>
1345 xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW );
1346 xDocProps = xDPS->getDocumentProperties();
1347 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
1349 ParseMetaOptions( xDocProps, pHTTPHeader );
1352 break;
1354 case HTML_TITLE_ON:
1355 bInTitle = TRUE;
1356 break;
1358 case HTML_SCRIPT_ON:
1359 NewScript();
1360 break;
1362 case HTML_SCRIPT_OFF:
1363 EndScript();
1364 break;
1366 case HTML_NOSCRIPT_ON:
1367 case HTML_NOSCRIPT_OFF:
1368 bInsertUnknown = TRUE;
1369 break;
1371 case HTML_STYLE_ON:
1372 NewStyle();
1373 break;
1375 case HTML_STYLE_OFF:
1376 EndStyle();
1377 break;
1379 case HTML_RAWDATA:
1380 if( !bIgnoreRawData )
1382 if( IsReadScript() )
1384 AddScriptSource();
1386 else if( IsReadStyle() )
1388 if( aStyleSource.Len() )
1389 aStyleSource += '\n';
1390 aStyleSource += aToken;
1393 break;
1395 case HTML_OBJECT_ON:
1396 #ifdef SOLAR_JAVA
1397 NewObject();
1398 bCallNextToken = pAppletImpl!=0 && pTable!=0;
1399 #endif
1400 break;
1402 case HTML_APPLET_ON:
1403 #ifdef SOLAR_JAVA
1404 InsertApplet();
1405 bCallNextToken = pAppletImpl!=0 && pTable!=0;
1406 #endif
1407 break;
1409 case HTML_IFRAME_ON:
1410 InsertFloatingFrame();
1411 bCallNextToken = bInFloatingFrame && pTable!=0;
1412 break;
1414 case HTML_LINEBREAK:
1415 if( !IsReadPRE() )
1417 InsertLineBreak();
1418 break;
1420 else
1421 bGetIDOption = TRUE;
1422 // <BR>s in <PRE> aehneln echten LFs, deshalb kein break
1424 case HTML_NEWPARA:
1425 // CR in PRE/LISTING/XMP
1427 if( HTML_NEWPARA==nToken ||
1428 pPam->GetPoint()->nContent.GetIndex() )
1430 AppendTxtNode(); // lf gibts hier nicht, deshalb unkritisch
1431 SetTxtCollAttrs();
1433 // Laufbalkenanzeige
1434 if( !GetMedium() || !GetMedium()->IsRemote() )
1435 ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
1437 break;
1439 case HTML_NONBREAKSPACE:
1440 pDoc->InsertString( *pPam, CHAR_HARDBLANK );
1441 break;
1443 case HTML_SOFTHYPH:
1444 pDoc->InsertString( *pPam, CHAR_SOFTHYPHEN );
1445 break;
1447 case HTML_LINEFEEDCHAR:
1448 if( pPam->GetPoint()->nContent.GetIndex() )
1449 AppendTxtNode();
1450 if( !pTable && !pDoc->IsInHeaderFooter( pPam->GetPoint()->nNode ) )
1452 NewAttr( &aAttrTab.pBreak, SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK) );
1453 EndAttr( aAttrTab.pBreak, 0, FALSE );
1455 break;
1457 case HTML_TEXTTOKEN:
1458 // dann fuege den String ein, ohne das Attribute am Ende
1459 // aufgespannt werden.
1460 if( aToken.Len() && ' '==aToken.GetChar(0) && !IsReadPRE() )
1462 xub_StrLen nPos = pPam->GetPoint()->nContent.GetIndex();
1463 if( nPos )
1465 const String& rText =
1466 pDoc->GetNodes()[ pPam->GetPoint()->nNode ]->GetTxtNode()
1467 ->GetTxt();
1468 sal_Unicode cLast = rText.GetChar(--nPos);
1469 if( ' ' == cLast || '\x0a' == cLast)
1470 aToken.Erase(0,1);
1472 else
1473 aToken.Erase(0,1);
1475 if( !aToken.Len() )
1477 bUpperSpace = bUpperSpaceSave;
1478 break;
1482 if( aToken.Len() )
1484 if( !bDocInitalized )
1485 DocumentDetected();
1486 pDoc->InsertString( *pPam, aToken );
1488 // wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber
1489 // nicht leer ist, dann sind die Absatz-Attribute entgueltig.
1490 if( aParaAttrs.Count() )
1491 aParaAttrs.Remove( 0, aParaAttrs.Count() );
1493 SetAttr();
1495 break;
1497 case HTML_HORZRULE:
1498 InsertHorzRule();
1499 break;
1501 case HTML_IMAGE:
1502 InsertImage();
1503 // sollte der Parser der Letzte sein, der das Doc haelt, dann kann
1504 // man hier abbrechen und einen Fehler setzen.
1505 if( 1 == pDoc->getReferenceCount() )
1507 eState = SVPAR_ERROR;
1509 break;
1511 case HTML_SPACER:
1512 InsertSpacer();
1513 break;
1515 case HTML_EMBED:
1516 InsertEmbed();
1517 break;
1519 case HTML_NOEMBED_ON:
1520 bInNoEmbed = TRUE;
1521 bCallNextToken = pTable!=0;
1522 ReadRawData( OOO_STRING_SVTOOLS_HTML_noembed );
1523 break;
1525 case HTML_DEFLIST_ON:
1526 if( nOpenParaToken )
1527 EndPara();
1528 NewDefList();
1529 break;
1530 case HTML_DEFLIST_OFF:
1531 if( nOpenParaToken )
1532 EndPara();
1533 EndDefListItem( 0, FALSE, 1==nDefListDeep );
1534 EndDefList();
1535 break;
1537 case HTML_DD_ON:
1538 case HTML_DT_ON:
1539 if( nOpenParaToken )
1540 EndPara();
1541 EndDefListItem( 0, FALSE );// <DD>/<DT> beenden und keine Vorl. setzen
1542 NewDefListItem( nToken );
1543 break;
1545 case HTML_DD_OFF:
1546 case HTML_DT_OFF:
1547 // siehe HTML_LI_OFF
1548 // eigentlich muesste man ein DD/DT jetzt beenden. Da aber sowhl
1549 // Netscape als auch Microsoft das nicht tun, machen wir das eben
1550 // auch nicht.
1551 EndDefListItem( nToken, FALSE );
1552 break;
1554 // Bereiche
1555 case HTML_DIVISION_ON:
1556 case HTML_CENTER_ON:
1557 if( nOpenParaToken )
1559 if( IsReadPRE() )
1560 nOpenParaToken = 0;
1561 else
1562 EndPara();
1564 NewDivision( nToken );
1565 break;
1567 case HTML_DIVISION_OFF:
1568 case HTML_CENTER_OFF:
1569 if( nOpenParaToken )
1571 if( IsReadPRE() )
1572 nOpenParaToken = 0;
1573 else
1574 EndPara();
1576 EndDivision( nToken );
1577 break;
1579 case HTML_MULTICOL_ON:
1580 if( nOpenParaToken )
1581 EndPara();
1582 NewMultiCol();
1583 break;
1585 case HTML_MULTICOL_OFF:
1586 if( nOpenParaToken )
1587 EndPara();
1588 EndTag( HTML_MULTICOL_ON );
1589 break;
1591 case HTML_MARQUEE_ON:
1592 NewMarquee();
1593 bCallNextToken = pMarquee!=0 && pTable!=0;
1594 break;
1596 case HTML_FORM_ON:
1597 NewForm();
1598 break;
1599 case HTML_FORM_OFF:
1600 EndForm();
1601 break;
1603 // Vorlagen:
1604 case HTML_PARABREAK_ON:
1605 if( nOpenParaToken )
1606 EndPara( TRUE );
1607 NewPara();
1608 break;
1610 case HTML_PARABREAK_OFF:
1611 EndPara( TRUE );
1612 break;
1614 case HTML_ADDRESS_ON:
1615 if( nOpenParaToken )
1616 EndPara();
1617 NewTxtFmtColl( HTML_ADDRESS_ON, RES_POOLCOLL_SENDADRESS );
1618 break;
1620 case HTML_ADDRESS_OFF:
1621 if( nOpenParaToken )
1622 EndPara();
1623 EndTxtFmtColl( HTML_ADDRESS_OFF );
1624 break;
1626 case HTML_BLOCKQUOTE_ON:
1627 case HTML_BLOCKQUOTE30_ON:
1628 if( nOpenParaToken )
1629 EndPara();
1630 NewTxtFmtColl( HTML_BLOCKQUOTE_ON, RES_POOLCOLL_HTML_BLOCKQUOTE );
1631 break;
1633 case HTML_BLOCKQUOTE_OFF:
1634 case HTML_BLOCKQUOTE30_OFF:
1635 if( nOpenParaToken )
1636 EndPara();
1637 EndTxtFmtColl( HTML_BLOCKQUOTE_ON );
1638 break;
1640 case HTML_PREFORMTXT_ON:
1641 case HTML_LISTING_ON:
1642 case HTML_XMP_ON:
1643 if( nOpenParaToken )
1644 EndPara();
1645 NewTxtFmtColl( nToken, RES_POOLCOLL_HTML_PRE );
1646 break;
1648 case HTML_PREFORMTXT_OFF:
1649 bNoParSpace = TRUE; // der letzte PRE-Absatz muss einen Zeilenabstand bekommen
1650 EndTxtFmtColl( HTML_PREFORMTXT_OFF );
1651 break;
1653 case HTML_LISTING_OFF:
1654 case HTML_XMP_OFF:
1655 EndTxtFmtColl( nToken );
1656 break;
1658 case HTML_HEAD1_ON:
1659 case HTML_HEAD2_ON:
1660 case HTML_HEAD3_ON:
1661 case HTML_HEAD4_ON:
1662 case HTML_HEAD5_ON:
1663 case HTML_HEAD6_ON:
1664 if( nOpenParaToken )
1666 if( IsReadPRE() )
1667 nOpenParaToken = 0;
1668 else
1669 EndPara();
1671 NewHeading( nToken );
1672 break;
1674 case HTML_HEAD1_OFF:
1675 case HTML_HEAD2_OFF:
1676 case HTML_HEAD3_OFF:
1677 case HTML_HEAD4_OFF:
1678 case HTML_HEAD5_OFF:
1679 case HTML_HEAD6_OFF:
1680 EndHeading();
1681 break;
1683 case HTML_TABLE_ON:
1684 if( pPendStack )
1685 BuildTable( SVX_ADJUST_END );
1686 else
1688 if( nOpenParaToken )
1689 EndPara();
1690 ASSERT( !pTable, "Tabelle in Tabelle darf hier nicht vorkommen" );
1691 if( !pTable && (IsNewDoc() || !pPam->GetNode()->FindTableNode()) &&
1692 (pPam->GetPoint()->nNode.GetIndex() >
1693 pDoc->GetNodes().GetEndOfExtras().GetIndex() ||
1694 !pPam->GetNode()->FindFootnoteStartNode() ) )
1696 if ( nParaCnt < 5 )
1697 Show(); // bis hierhin schon mal anzeigen
1699 SvxAdjust eAdjust = aAttrTab.pAdjust
1700 ? ((const SvxAdjustItem&)aAttrTab.pAdjust->GetItem()).
1701 GetAdjust()
1702 : SVX_ADJUST_END;
1703 BuildTable( eAdjust );
1705 else
1706 bInsertUnknown = bKeepUnknown;
1708 break;
1710 // Listen
1711 case HTML_DIRLIST_ON:
1712 case HTML_MENULIST_ON:
1713 case HTML_ORDERLIST_ON:
1714 case HTML_UNORDERLIST_ON:
1715 if( nOpenParaToken )
1716 EndPara();
1717 NewNumBulList( nToken );
1718 break;
1720 case HTML_DIRLIST_OFF:
1721 case HTML_MENULIST_OFF:
1722 case HTML_ORDERLIST_OFF:
1723 case HTML_UNORDERLIST_OFF:
1724 if( nOpenParaToken )
1725 EndPara();
1726 EndNumBulListItem( 0, TRUE, GetNumInfo().GetDepth()==1 );
1727 EndNumBulList( nToken );
1728 break;
1730 case HTML_LI_ON:
1731 case HTML_LISTHEADER_ON:
1732 if( nOpenParaToken &&
1733 (pPam->GetPoint()->nContent.GetIndex()
1734 || HTML_PARABREAK_ON==nOpenParaToken) )
1736 // nure bei <P><LI> den Absatz beenden, aber nicht bei <DD><LI>
1737 EndPara();
1740 EndNumBulListItem( 0, FALSE );// <LI>/<LH> beenden und keine Vorl. setzen
1741 NewNumBulListItem( nToken );
1742 break;
1744 case HTML_LI_OFF:
1745 case HTML_LISTHEADER_OFF:
1746 EndNumBulListItem( nToken, FALSE );
1747 break;
1749 // Attribute :
1750 case HTML_ITALIC_ON:
1752 SvxPostureItem aPosture( ITALIC_NORMAL, RES_CHRATR_POSTURE );
1753 SvxPostureItem aPostureCJK( ITALIC_NORMAL, RES_CHRATR_CJK_POSTURE );
1754 SvxPostureItem aPostureCTL( ITALIC_NORMAL, RES_CHRATR_CTL_POSTURE );
1755 NewStdAttr( HTML_ITALIC_ON,
1756 &aAttrTab.pItalic, aPosture,
1757 &aAttrTab.pItalicCJK, &aPostureCJK,
1758 &aAttrTab.pItalicCTL, &aPostureCTL );
1760 break;
1762 case HTML_BOLD_ON:
1764 SvxWeightItem aWeight( WEIGHT_BOLD, RES_CHRATR_WEIGHT );
1765 SvxWeightItem aWeightCJK( WEIGHT_BOLD, RES_CHRATR_CJK_WEIGHT );
1766 SvxWeightItem aWeightCTL( WEIGHT_BOLD, RES_CHRATR_CTL_WEIGHT );
1767 NewStdAttr( HTML_BOLD_ON,
1768 &aAttrTab.pBold, aWeight,
1769 &aAttrTab.pBoldCJK, &aWeightCJK,
1770 &aAttrTab.pBoldCTL, &aWeightCTL );
1772 break;
1775 case HTML_STRIKE_ON:
1776 case HTML_STRIKETHROUGH_ON:
1778 NewStdAttr( HTML_STRIKE_ON, &aAttrTab.pStrike,
1779 SvxCrossedOutItem(STRIKEOUT_SINGLE, RES_CHRATR_CROSSEDOUT) );
1781 break;
1783 case HTML_UNDERLINE_ON:
1785 NewStdAttr( HTML_UNDERLINE_ON, &aAttrTab.pUnderline,
1786 SvxUnderlineItem(UNDERLINE_SINGLE, RES_CHRATR_UNDERLINE) );
1788 break;
1790 case HTML_SUPERSCRIPT_ON:
1792 NewStdAttr( HTML_SUPERSCRIPT_ON, &aAttrTab.pEscapement,
1793 SvxEscapementItem(HTML_ESC_SUPER,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1795 break;
1797 case HTML_SUBSCRIPT_ON:
1799 NewStdAttr( HTML_SUBSCRIPT_ON, &aAttrTab.pEscapement,
1800 SvxEscapementItem(HTML_ESC_SUB,HTML_ESC_PROP, RES_CHRATR_ESCAPEMENT) );
1802 break;
1804 case HTML_BLINK_ON:
1806 NewStdAttr( HTML_BLINK_ON, &aAttrTab.pBlink,
1807 SvxBlinkItem( TRUE, RES_CHRATR_BLINK ) );
1809 break;
1811 case HTML_SPAN_ON:
1812 NewStdAttr( HTML_SPAN_ON );
1813 break;
1816 case HTML_ITALIC_OFF:
1817 case HTML_BOLD_OFF:
1818 case HTML_STRIKE_OFF:
1819 case HTML_UNDERLINE_OFF:
1820 case HTML_SUPERSCRIPT_OFF:
1821 case HTML_SUBSCRIPT_OFF:
1822 case HTML_BLINK_OFF:
1823 case HTML_SPAN_OFF:
1824 EndTag( nToken );
1825 break;
1827 case HTML_STRIKETHROUGH_OFF:
1828 EndTag( HTML_STRIKE_OFF );
1829 break;
1831 case HTML_BASEFONT_ON:
1832 NewBasefontAttr();
1833 break;
1834 case HTML_BASEFONT_OFF:
1835 EndBasefontAttr();
1836 break;
1837 case HTML_FONT_ON:
1838 case HTML_BIGPRINT_ON:
1839 case HTML_SMALLPRINT_ON:
1840 NewFontAttr( nToken );
1841 break;
1842 case HTML_FONT_OFF:
1843 case HTML_BIGPRINT_OFF:
1844 case HTML_SMALLPRINT_OFF:
1845 EndFontAttr( nToken );
1846 break;
1848 case HTML_EMPHASIS_ON:
1849 case HTML_CITIATION_ON:
1850 case HTML_STRONG_ON:
1851 case HTML_CODE_ON:
1852 case HTML_SAMPLE_ON:
1853 case HTML_KEYBOARD_ON:
1854 case HTML_VARIABLE_ON:
1855 case HTML_DEFINSTANCE_ON:
1856 case HTML_SHORTQUOTE_ON:
1857 case HTML_LANGUAGE_ON:
1858 case HTML_AUTHOR_ON:
1859 case HTML_PERSON_ON:
1860 case HTML_ACRONYM_ON:
1861 case HTML_ABBREVIATION_ON:
1862 case HTML_INSERTEDTEXT_ON:
1863 case HTML_DELETEDTEXT_ON:
1865 case HTML_TELETYPE_ON:
1866 NewCharFmt( nToken );
1867 break;
1869 case HTML_SDFIELD_ON:
1870 NewField();
1871 bCallNextToken = bInField && pTable!=0;
1872 break;
1874 case HTML_EMPHASIS_OFF:
1875 case HTML_CITIATION_OFF:
1876 case HTML_STRONG_OFF:
1877 case HTML_CODE_OFF:
1878 case HTML_SAMPLE_OFF:
1879 case HTML_KEYBOARD_OFF:
1880 case HTML_VARIABLE_OFF:
1881 case HTML_DEFINSTANCE_OFF:
1882 case HTML_SHORTQUOTE_OFF:
1883 case HTML_LANGUAGE_OFF:
1884 case HTML_AUTHOR_OFF:
1885 case HTML_PERSON_OFF:
1886 case HTML_ACRONYM_OFF:
1887 case HTML_ABBREVIATION_OFF:
1888 case HTML_INSERTEDTEXT_OFF:
1889 case HTML_DELETEDTEXT_OFF:
1891 case HTML_TELETYPE_OFF:
1892 EndTag( nToken );
1893 break;
1895 case HTML_HEAD_OFF:
1896 if( aStyleSource.Len() )
1898 pCSS1Parser->ParseStyleSheet( aStyleSource );
1899 aStyleSource.Erase();
1901 break;
1903 case HTML_DOCTYPE:
1904 case HTML_BODY_OFF:
1905 case HTML_HTML_OFF:
1906 case HTML_HEAD_ON:
1907 case HTML_TITLE_OFF:
1908 break; // nicht weiter auswerten, oder???
1909 case HTML_HTML_ON:
1911 const HTMLOptions *pHTMLOptions = GetOptions();
1912 for( USHORT i = pHTMLOptions->Count(); i; )
1914 const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
1915 if( HTML_O_DIR == pOption->GetToken() )
1917 const String& rDir = pOption->GetString();
1918 SfxItemSet aItemSet( pDoc->GetAttrPool(),
1919 pCSS1Parser->GetWhichMap() );
1920 SvxCSS1PropertyInfo aPropInfo;
1921 String aDummy;
1922 ParseStyleOptions( aDummy, aDummy, aDummy, aItemSet,
1923 aPropInfo, 0, &rDir );
1925 pCSS1Parser->SetPageDescAttrs( 0, &aItemSet );
1926 break;
1930 break;
1932 case HTML_INPUT:
1933 InsertInput();
1934 break;
1936 case HTML_TEXTAREA_ON:
1937 NewTextArea();
1938 bCallNextToken = bTextArea && pTable!=0;
1939 break;
1941 case HTML_SELECT_ON:
1942 NewSelect();
1943 bCallNextToken = bSelect && pTable!=0;
1944 break;
1946 case HTML_ANCHOR_ON:
1947 NewAnchor();
1948 break;
1950 case HTML_ANCHOR_OFF:
1951 EndAnchor();
1952 break;
1954 case HTML_COMMENT:
1955 if( ( aToken.Len() > 5 ) && ( ! bIgnoreHTMLComments ) )
1957 // als Post-It einfuegen
1958 // MIB 8.12.2000: If there are no space characters right behind
1959 // the <!-- and on front of the -->, leave the comment untouched.
1960 if( ' ' == aToken.GetChar( 3 ) &&
1961 ' ' == aToken.GetChar( aToken.Len()-3 ) )
1963 String aComment( aToken.Copy( 3, aToken.Len()-5 ) );
1964 aComment.EraseLeadingChars().EraseTrailingChars();
1965 InsertComment( aComment );
1967 else
1969 String aComment( '<' );
1970 (aComment += aToken) += '>';
1971 InsertComment( aComment );
1974 break;
1976 case HTML_MAP_ON:
1977 // Image Maps werden asynchron gelesen: Zunaechst wird nur eine
1978 // ImageMap angelegt. Die Bereiche kommen spaeter. Trozdem wird
1979 // die ImageMap schon in das IMap-Array eingetragen, denn sie
1980 // koennte ja schon verwendet werden.
1981 pImageMap = new ImageMap;
1982 if( ParseMapOptions( pImageMap) )
1984 if( !pImageMaps )
1985 pImageMaps = new ImageMaps;
1986 pImageMaps->Insert( pImageMap, pImageMaps->Count() );
1988 else
1990 delete pImageMap;
1991 pImageMap = 0;
1993 break;
1995 case HTML_MAP_OFF:
1996 // jetzt gibt es keine ImageMap mehr (IMap nicht Loeschen, denn
1997 // die stckt ja schon in dem Array!)
1998 pImageMap = 0;
1999 break;
2001 case HTML_AREA:
2002 if( pImageMap )
2003 ParseAreaOptions( pImageMap, sBaseURL, SFX_EVENT_MOUSEOVER_OBJECT,
2004 SFX_EVENT_MOUSEOUT_OBJECT );
2005 break;
2007 case HTML_FRAMESET_ON:
2008 bInsertUnknown = bKeepUnknown;
2009 break;
2011 case HTML_NOFRAMES_ON:
2012 if( IsInHeader() )
2013 FinishHeader( TRUE );
2014 bInsertUnknown = bKeepUnknown;
2015 break;
2017 case HTML_UNKNOWNCONTROL_ON:
2018 // Im Header muss der Inhalt von unbekannten Token ignoriert werden,
2019 // es sei denn, das Token faengt mit einem '!' an.
2020 if( IsInHeader() && !IsReadPRE() && !aUnknownToken.Len() &&
2021 sSaveToken.Len() && '!' != sSaveToken.GetChar(0) &&
2022 '%' != sSaveToken.GetChar(0) )
2023 aUnknownToken = sSaveToken;
2024 // kein break
2026 default:
2027 bInsertUnknown = bKeepUnknown;
2028 break;
2031 if( bGetIDOption )
2032 InsertIDOption();
2034 if( bInsertUnknown )
2036 String aComment(
2037 String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
2038 if( (HTML_TOKEN_ONOFF & nToken) != 0 && (1 & nToken) != 0 )
2039 aComment += '/';
2040 aComment += sSaveToken;
2041 if( aToken.Len() )
2043 UnescapeToken();
2044 (aComment += ' ') += aToken;
2046 aComment += '>';
2047 InsertComment( aComment );
2050 // wenn es noch vorlaefige Absatz-Attribute gibt, der Absatz aber
2051 // nicht leer ist, dann sind die Absatz-Attribute entgueltig.
2052 if( aParaAttrs.Count() && pPam->GetPoint()->nContent.GetIndex() )
2053 aParaAttrs.Remove( 0, aParaAttrs.Count() );
2056 /* \f */
2058 extern BOOL lcl_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 );
2060 void lcl_swhtml_getItemInfo( const _HTMLAttr& rAttr,
2061 sal_Bool& rScriptDependent, sal_Bool& rFont,
2062 sal_uInt16& rScriptType )
2064 sal_uInt16 nWhich = rAttr.GetItem().Which();
2065 switch( nWhich )
2067 case RES_CHRATR_FONT:
2068 rFont = sal_True;
2069 case RES_CHRATR_FONTSIZE:
2070 case RES_CHRATR_LANGUAGE:
2071 case RES_CHRATR_POSTURE:
2072 case RES_CHRATR_WEIGHT:
2073 rScriptType = i18n::ScriptType::LATIN;
2074 rScriptDependent = sal_True;
2075 break;
2076 case RES_CHRATR_CJK_FONT:
2077 rFont = sal_True;
2078 case RES_CHRATR_CJK_FONTSIZE:
2079 case RES_CHRATR_CJK_LANGUAGE:
2080 case RES_CHRATR_CJK_POSTURE:
2081 case RES_CHRATR_CJK_WEIGHT:
2082 rScriptType = i18n::ScriptType::ASIAN;
2083 rScriptDependent = sal_True;
2084 break;
2085 case RES_CHRATR_CTL_FONT:
2086 rFont = sal_True;
2087 case RES_CHRATR_CTL_FONTSIZE:
2088 case RES_CHRATR_CTL_LANGUAGE:
2089 case RES_CHRATR_CTL_POSTURE:
2090 case RES_CHRATR_CTL_WEIGHT:
2091 rScriptType = i18n::ScriptType::COMPLEX;
2092 rScriptDependent = sal_True;
2093 break;
2094 default:
2095 rScriptDependent = sal_False;
2096 rFont = sal_False;
2097 break;
2101 BOOL SwHTMLParser::AppendTxtNode( SwHTMLAppendMode eMode, BOOL bUpdateNum )
2103 // Ein harter Zeilen-Umbruch am Ende muss immer entfernt werden.
2104 // Einen zweiten ersetzen wir durch einen Absatz-Abstand.
2105 xub_StrLen nLFStripped = StripTrailingLF();
2106 if( (AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode) && nLFStripped > 1 )
2107 eMode = AM_SPACE;
2109 // die harten Attribute an diesem Absatz werden nie mehr ungueltig
2110 if( aParaAttrs.Count() )
2111 aParaAttrs.Remove( 0, aParaAttrs.Count() );
2113 if( AM_SPACE==eMode || AM_NOSPACE==eMode )
2115 SwTxtNode *pTxtNode =
2116 pDoc->GetNodes()[pPam->GetPoint()->nNode]->GetTxtNode();
2118 const SvxULSpaceItem& rULSpace =
2119 (const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2121 BOOL bChange = AM_NOSPACE==eMode ? rULSpace.GetLower() > 0
2122 : rULSpace.GetLower() == 0;
2124 if( bChange )
2126 const SvxULSpaceItem& rCollULSpace =
2127 pTxtNode->GetAnyFmtColl().GetULSpace();
2129 BOOL bMayReset = AM_NOSPACE==eMode ? rCollULSpace.GetLower() == 0
2130 : rCollULSpace.GetLower() > 0;
2132 if( bMayReset &&
2133 rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2135 pTxtNode->ResetAttr( RES_UL_SPACE );
2137 else
2139 pTxtNode->SetAttr(
2140 SvxULSpaceItem( rULSpace.GetUpper(),
2141 AM_NOSPACE==eMode ? 0 : HTML_PARSPACE, RES_UL_SPACE ) );
2145 bNoParSpace = AM_NOSPACE==eMode || AM_SOFTNOSPACE==eMode;
2147 SwPosition aOldPos( *pPam->GetPoint() );
2149 BOOL bRet = pDoc->AppendTxtNode( *pPam->GetPoint() );
2151 // Zeichen-Attribute aufspalten und ggf keine setzen, die ueber den
2152 // ganzen Absatz gesetzt sind
2153 const SwNodeIndex& rEndIdx = aOldPos.nNode;
2154 xub_StrLen nEndCnt = aOldPos.nContent.GetIndex();
2155 const SwPosition& rPos = *pPam->GetPoint();
2157 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
2158 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
2159 nCnt--; ++pTbl )
2161 _HTMLAttr *pAttr = *pTbl;
2162 if( pAttr && pAttr->GetItem().Which() < RES_PARATR_BEGIN )
2164 BOOL bWholePara = FALSE;
2166 while( pAttr )
2168 _HTMLAttr *pNext = pAttr->GetNext();
2169 if( pAttr->GetSttParaIdx() < rEndIdx.GetIndex() ||
2170 (!bWholePara &&
2171 pAttr->GetSttPara() == rEndIdx &&
2172 pAttr->GetSttCnt() != nEndCnt) )
2174 bWholePara =
2175 pAttr->GetSttPara() == rEndIdx &&
2176 pAttr->GetSttCnt() == 0;
2178 xub_StrLen nStt = pAttr->nSttCntnt;
2179 sal_Bool bScript = sal_False, bFont = sal_False;
2180 sal_uInt16 nScriptItem;
2181 sal_Bool bInsert = sal_True;
2182 lcl_swhtml_getItemInfo( *pAttr, bScript, bFont,
2183 nScriptItem );
2184 // den besehrigen Teil setzen
2185 if( bInsert && bScript )
2187 const SwTxtNode *pTxtNd =
2188 pAttr->GetSttPara().GetNode().GetTxtNode();
2189 ASSERT( pTxtNd, "No text node" );
2190 if( pTxtNd )
2192 const String& rText = pTxtNd->GetTxt();
2193 sal_uInt16 nScriptTxt =
2194 pBreakIt->GetBreakIter()->getScriptType(
2195 rText, pAttr->GetSttCnt() );
2196 xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2197 ->endOfScript( rText, nStt, nScriptTxt );
2198 while( nScriptEnd < nEndCnt )
2200 if( nScriptItem == nScriptTxt )
2202 _HTMLAttr *pSetAttr =
2203 pAttr->Clone( rEndIdx, nScriptEnd );
2204 pSetAttr->nSttCntnt = nStt;
2205 pSetAttr->ClearPrev();
2206 if( !pNext || bWholePara )
2208 USHORT nTmp = pSetAttr->bInsAtStart ? 0
2209 : aSetAttrTab.Count();
2210 aSetAttrTab.Insert( pSetAttr, nTmp );
2212 else
2213 pNext->InsertPrev( pSetAttr );
2215 nStt = nScriptEnd;
2216 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
2217 rText, nStt );
2218 nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
2219 ->endOfScript( rText, nStt, nScriptTxt );
2221 bInsert = nScriptItem == nScriptTxt;
2224 if( bInsert )
2226 _HTMLAttr *pSetAttr =
2227 pAttr->Clone( rEndIdx, nEndCnt );
2228 pSetAttr->nSttCntnt = nStt;
2230 // Wenn das Attribut den gesamten Absatz umspannt, werden
2231 // alle auesseren Attribute nicht mehr beachtet. Deshalb
2232 // darf es auch nicht in die Prev-Liste eines ausseren
2233 // Attributs eingetragen werden, denn dieses wird ja
2234 // erstmal nicht gesetzt. Das fuehrt zu verschiebenungen,
2235 // wenn Felder ins Rennen kommen (siehe #51020#)
2236 if( !pNext || bWholePara )
2238 USHORT nTmp = pSetAttr->bInsAtStart ? 0
2239 : aSetAttrTab.Count();
2240 aSetAttrTab.Insert( pSetAttr, nTmp );
2242 else
2243 pNext->InsertPrev( pSetAttr );
2245 else
2247 _HTMLAttr *pPrev = pAttr->GetPrev();
2248 if( pPrev )
2250 // Die Previous-Attribute muessen trotzdem gesetzt werden.
2251 if( !pNext || bWholePara )
2253 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
2254 aSetAttrTab.Insert( pPrev, nTmp );
2256 else
2257 pNext->InsertPrev( pPrev );
2260 pAttr->ClearPrev();
2263 pAttr->SetStart( rPos );
2264 pAttr = pNext;
2269 if( bUpdateNum )
2271 if( GetNumInfo().GetDepth() )
2273 BYTE nLvl = GetNumInfo().GetLevel();
2274 // --> OD 2008-04-02 #refactorlists#
2275 // SetNoNum (&nLvl, TRUE);
2276 // SetNodeNum( nLvl);
2277 SetNodeNum( nLvl, false );
2278 // <--
2280 else
2281 pPam->GetNode()->GetTxtNode()->ResetAttr( RES_PARATR_NUMRULE );
2284 // Attrubute im Absatz davor sollte man jetzt setzen (wegen JavaScript)
2285 SetAttr();
2287 // Now it is time to get rid of all script dependent hints that are
2288 // equal to the settings in the style
2289 SwTxtNode *pTxtNd = rEndIdx.GetNode().GetTxtNode();
2290 ASSERT( pTxtNd, "There is the txt node" );
2291 sal_uInt16 nCntAttr = (pTxtNd && pTxtNd->GetpSwpHints())
2292 ? pTxtNd->GetSwpHints().Count() : 0;
2293 if( nCntAttr )
2295 // These are the end position of all script depenent hints.
2296 // If we find a hint that starts before the current end position,
2297 // we have to set it. If we finf a hint that start behind or at
2298 // that position, we have to take the hint's value into account.
2299 // If it is equal to the style, or in fact the paragarph's value
2300 // for that hint, the hint is removed. Otherwise it's end position
2301 // is remembered.
2302 xub_StrLen aEndPos[15] =
2303 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
2304 SwpHints& rHints = pTxtNd->GetSwpHints();
2305 for( sal_uInt16 i=0; i < nCntAttr; i++ )
2307 SwTxtAttr *pHt = rHints.GetTextHint( i );
2308 sal_uInt16 nWhich = pHt->Which();
2309 sal_Int16 nIdx = -1;
2310 if( RES_CHRATR_CJK_FONT <= nWhich &&
2311 nWhich <= RES_CHRATR_CTL_WEIGHT )
2313 nIdx = static_cast< USHORT >(nWhich - RES_CHRATR_CJK_FONT + 5);
2315 else switch( nWhich )
2317 case RES_CHRATR_FONT: nIdx = 0; break;
2318 case RES_CHRATR_FONTSIZE: nIdx = 1; break;
2319 case RES_CHRATR_LANGUAGE: nIdx = 2; break;
2320 case RES_CHRATR_POSTURE: nIdx = 3; break;
2321 case RES_CHRATR_WEIGHT: nIdx = 4; break;
2323 if( nIdx != -1 )
2325 xub_StrLen nStt = *pHt->GetStart();
2326 if( nStt >= aEndPos[nIdx] )
2328 sal_Bool bFont = (nIdx % 5) == 0;
2329 const SfxPoolItem& rItem =
2330 ((const SwCntntNode *)pTxtNd)->GetAttr( nWhich );
2331 if( bFont ? lcl_css1atr_equalFontItems(rItem,pHt->GetAttr())
2332 : rItem == pHt->GetAttr() )
2334 // The hint is the same as set in the paragraph and
2335 // therfor, it can be deleted
2336 // CAUTION!!! This WILL delete the hint and it MAY
2337 // also delete the SwpHints!!! To avoid any trouble
2338 // we leave the loop immediately if this is the last
2339 // hint.
2340 pTxtNd->DeleteAttribute( pHt );
2341 if( 1 == nCntAttr )
2342 break;
2343 i--;
2344 nCntAttr--;
2346 else
2348 // The hint is deifferent. Therfor all hints within that
2349 // hint have to be ignored.
2350 aEndPos[nIdx] = pHt->GetEnd() ? *pHt->GetEnd() : nStt;
2353 else
2355 // The hint starts before another one ends.
2356 // The hint in this case is not deleted
2357 ASSERT( pHt->GetEnd() && *pHt->GetEnd() <= aEndPos[nIdx],
2358 "hints aren't nested properly!" );
2365 if( !pTable && !--nParaCnt )
2366 Show();
2368 return bRet;
2371 void SwHTMLParser::AddParSpace()
2373 if( !bNoParSpace )
2374 return;
2376 bNoParSpace = FALSE;
2378 ULONG nNdIdx = pPam->GetPoint()->nNode.GetIndex() - 1;
2380 SwTxtNode *pTxtNode = pDoc->GetNodes()[nNdIdx]->GetTxtNode();
2381 if( !pTxtNode )
2382 return;
2384 SvxULSpaceItem rULSpace =
2385 (const SvxULSpaceItem&)pTxtNode->SwCntntNode::GetAttr( RES_UL_SPACE );
2386 if( !rULSpace.GetLower() )
2388 const SvxULSpaceItem& rCollULSpace =
2389 pTxtNode->GetAnyFmtColl().GetULSpace();
2390 if( rCollULSpace.GetLower() &&
2391 rCollULSpace.GetUpper() == rULSpace.GetUpper() )
2393 pTxtNode->ResetAttr( RES_UL_SPACE );
2395 else
2397 pTxtNode->SetAttr(
2398 SvxULSpaceItem( rULSpace.GetUpper(), HTML_PARSPACE, RES_UL_SPACE ) );
2404 void SwHTMLParser::Show()
2406 // Hier wird
2407 // - ein EndAction gerufen, damit formatiert wird
2408 // - ein Reschedule gerufen,
2409 // - die eiegen View-Shell wieder gesetzt
2410 // - und Start-Action gerufen
2412 ASSERT( SVPAR_WORKING==eState, "Show nicht im Working-State - Das kann ins Auge gehen" );
2413 ViewShell *pOldVSh = CallEndAction();
2415 GetpApp()->Reschedule();
2417 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2418 || 1 == pDoc->getReferenceCount() )
2420 // wurde der Import vom SFX abgebrochen?
2421 eState = SVPAR_ERROR;
2424 // Die ViewShell nochmal holen, denn sie koennte im Reschedule
2425 // zerstoert wirden sein.
2426 ViewShell *pVSh = CallStartAction( pOldVSh );
2428 // ist der aktuelle Node nicht mehr sichtbar, dann benutzen wir
2429 // eine groessere Schrittweite
2430 if( pVSh )
2431 nParaCnt = pDoc->GetNodes()[pPam->GetPoint()->nNode]
2432 ->IsInVisibleArea(pVSh) ? 5 : 50;
2435 void SwHTMLParser::ShowStatline()
2437 // Hier wird
2438 // - ein Reschedule gerufen, damit gescrollt werden kann
2439 // - die eiegen View-Shell wieder gesetzt
2440 // - ein Start/End-Action gerufen, wenn gescrollt wurde.
2442 ASSERT( SVPAR_WORKING==eState, "ShowStatLine nicht im Working-State - Das kann ins Auge gehen" );
2444 // Laufbalkenanzeige
2445 if( !GetMedium() || !GetMedium()->IsRemote() )
2447 ::SetProgressState( rInput.Tell(), pDoc->GetDocShell() );
2448 CheckActionViewShell();
2450 else
2452 GetpApp()->Reschedule();
2454 if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
2455 || 1 == pDoc->getReferenceCount() )
2456 // wurde der Import vom SFX abgebrochen?
2457 eState = SVPAR_ERROR;
2459 ViewShell *pVSh = CheckActionViewShell();
2460 if( pVSh && pVSh->HasInvalidRect() )
2462 CallEndAction( FALSE, FALSE );
2463 CallStartAction( pVSh, FALSE );
2468 ViewShell *SwHTMLParser::CallStartAction( ViewShell *pVSh, BOOL bChkPtr )
2470 ASSERT( !pActionViewShell, "CallStartAction: ViewShell schon gesetzt" );
2472 if( !pVSh || bChkPtr )
2474 #ifndef PRODUCT
2475 ViewShell *pOldVSh = pVSh;
2476 #endif
2477 pDoc->GetEditShell( &pVSh );
2478 ASSERT( !pVSh || !pOldVSh || pOldVSh == pVSh, "CallStartAction: Wer hat die ViewShell ausgetauscht?" );
2479 #ifndef PRODUCT
2480 if( pOldVSh && !pVSh )
2481 pVSh = 0;
2482 #endif
2484 pActionViewShell = pVSh;
2486 if( pActionViewShell )
2488 if( pActionViewShell->ISA( SwEditShell ) )
2489 ((SwEditShell*)pActionViewShell)->StartAction();
2490 else
2491 pActionViewShell->StartAction();
2494 return pActionViewShell;
2497 ViewShell *SwHTMLParser::CallEndAction( BOOL bChkAction, BOOL bChkPtr )
2499 if( bChkPtr )
2501 ViewShell *pVSh = 0;
2502 pDoc->GetEditShell( &pVSh );
2503 ASSERT( !pVSh || pActionViewShell == pVSh,
2504 "CallEndAction: Wer hat die ViewShell ausgetauscht?" );
2505 #if OSL_DEBUG_LEVEL > 1
2506 if( pActionViewShell && !pVSh )
2507 pVSh = 0;
2508 #endif
2509 if( pVSh != pActionViewShell )
2510 pActionViewShell = 0;
2513 if( !pActionViewShell || (bChkAction && !pActionViewShell->ActionPend()) )
2514 return pActionViewShell;
2516 if( bSetCrsr )
2518 // an allen CrsrEditShells die Cursor auf den Doc-Anfang setzen
2519 ViewShell *pSh = pActionViewShell;
2520 do {
2521 if( pSh->IsA( TYPE( SwCrsrShell ) ) )
2522 ((SwCrsrShell*)pSh)->SttEndDoc(TRUE);
2523 pSh = (ViewShell *)pSh->GetNext();
2524 } while( pSh != pActionViewShell );
2526 bSetCrsr = FALSE;
2528 if( pActionViewShell->ISA( SwEditShell ) )
2530 //Schon gescrollt?, dann dafuer sorgen, dass die View sich nicht bewegt!
2531 const BOOL bOldLock = pActionViewShell->IsViewLocked();
2532 pActionViewShell->LockView( TRUE );
2533 const BOOL bOldEndActionByVirDev = pActionViewShell->IsEndActionByVirDev();
2534 pActionViewShell->SetEndActionByVirDev( TRUE );;
2535 ((SwEditShell*)pActionViewShell)->EndAction();
2536 pActionViewShell->SetEndActionByVirDev( bOldEndActionByVirDev );
2537 pActionViewShell->LockView( bOldLock );
2539 // bChkJumpMark ist nur gesetzt, wenn das Object auch gefunden wurde
2540 if( bChkJumpMark )
2542 const Point aVisSttPos( DOCUMENTBORDER, DOCUMENTBORDER );
2543 if( GetMedium() && aVisSttPos == pActionViewShell->VisArea().Pos() )
2544 ::JumpToSwMark( pActionViewShell,
2545 GetMedium()->GetURLObject().GetMark() );
2546 bChkJumpMark = FALSE;
2549 else
2550 pActionViewShell->EndAction();
2552 // sollte der Parser der Letzte sein, der das Doc haelt, dann kann
2553 // man hier abbrechen und einen Fehler setzen.
2554 if( 1 == pDoc->getReferenceCount() )
2556 eState = SVPAR_ERROR;
2559 ViewShell *pVSh = pActionViewShell;
2560 pActionViewShell = 0;
2562 return pVSh;
2565 ViewShell *SwHTMLParser::CheckActionViewShell()
2567 ViewShell *pVSh = 0;
2568 pDoc->GetEditShell( &pVSh );
2569 ASSERT( !pVSh || pActionViewShell == pVSh,
2570 "CheckActionViewShell: Wer hat die ViewShell ausgetauscht?" );
2571 #if OSL_DEBUG_LEVEL > 1
2572 if( pActionViewShell && !pVSh )
2573 pVSh = 0;
2574 #endif
2575 if( pVSh != pActionViewShell )
2576 pActionViewShell = 0;
2578 return pActionViewShell;
2581 /* \f */
2583 void SwHTMLParser::_SetAttr( BOOL bChkEnd, BOOL bBeforeTable,
2584 _HTMLAttrs *pPostIts )
2586 SwPaM* pAttrPam = new SwPaM( *pPam->GetPoint() );
2587 const SwNodeIndex& rEndIdx = pPam->GetPoint()->nNode;
2588 xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2589 _HTMLAttr* pAttr;
2590 SwCntntNode* pCNd;
2591 USHORT n;
2593 _HTMLAttrs aFields( 5, 5 );
2595 for( n = aSetAttrTab.Count(); n; )
2597 pAttr = aSetAttrTab[ --n ];
2598 USHORT nWhich = pAttr->pItem->Which();
2600 ULONG nEndParaIdx = pAttr->GetEndParaIdx();
2601 BOOL bSetAttr;
2602 if( bChkEnd )
2604 // fix #42192#: Zechen-Attribute mit Ende moeglich frueh,
2605 // also noch im aktuellen Absatz setzen (wegen JavaScript
2606 // und diversen Chats). das darf man aber nicht fuer Attribute,
2607 // die ueber den ganzen Absatz aufgspannt werden sollen, weil
2608 // sie aus Absatzvorlgen stammen, die nicht gesetzt werden
2609 // koennen. Weil die Attribute mit SETATTR_DONTREPLACE
2610 // eingefuegt werden, sollte man sie auch anchtraeglich
2611 // noch setzen koennen.
2612 bSetAttr = ( nEndParaIdx < rEndIdx.GetIndex() &&
2613 (RES_LR_SPACE != nWhich || !GetNumInfo().GetNumRule()) ) ||
2614 ( !pAttr->IsLikePara() &&
2615 nEndParaIdx == rEndIdx.GetIndex() &&
2616 pAttr->GetEndCnt() < nEndCnt &&
2617 (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)) ) ||
2618 ( bBeforeTable &&
2619 nEndParaIdx == rEndIdx.GetIndex() &&
2620 !pAttr->GetEndCnt() );
2622 else
2624 // Attribiute im Content-Bereich duerfen nicht gesetzt
2625 // werden, wenn wir in einem Sonderbereich stehen, aber
2626 // umgekekehrt schon.
2627 ULONG nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2628 bSetAttr = nEndParaIdx < rEndIdx.GetIndex() ||
2629 rEndIdx.GetIndex() > nEndOfIcons ||
2630 nEndParaIdx <= nEndOfIcons;
2633 if( bSetAttr )
2635 // Das Attribute darf nicht in der liste der vorlaeufigen
2636 // Absatz-Attribute stehen, weil es sonst geloescht wurde.
2637 USHORT ii = aParaAttrs.Count();
2638 while( ii-- )
2640 ASSERT( pAttr != aParaAttrs[ii],
2641 "SetAttr: Attribut duerfte noch nicht gesetzt werden" );
2642 aParaAttrs.Remove( ii );
2646 // dann also setzen
2647 aSetAttrTab.Remove( n, 1 );
2649 while( pAttr )
2651 _HTMLAttr *pPrev = pAttr->GetPrev();
2652 if( !pAttr->bValid )
2654 // ungueltige Attribute koennen gloescht werden
2655 delete pAttr;
2656 pAttr = pPrev;
2657 continue; //break;
2661 pCNd = pDoc->GetNodes()[ pAttr->nSttPara ]->GetCntntNode();
2662 if( !pCNd )
2664 // durch die elende Loescherei von Nodes kann auch mal
2665 // ein Index auf einen End-Node zeigen :-(
2666 if ( (pAttr->GetSttPara() == pAttr->GetEndPara()) &&
2667 !isTXTATR_NOEND(nWhich) )
2669 // wenn der End-Index auch auf den Node zeigt
2670 // brauchen wir auch kein Attribut mehr zu setzen,
2671 // es sei denn, es ist ein Text-Attribut.
2672 delete pAttr;
2673 pAttr = pPrev;
2674 continue; //break;
2676 pCNd = pDoc->GetNodes().GoNext( &(pAttr->nSttPara) );
2677 if( pCNd )
2678 pAttr->nSttCntnt = 0;
2679 else
2681 ASSERT( !this, "SetAttr: GoNext() failed!" );
2682 delete pAttr;
2683 pAttr = pPrev;
2684 continue; // break;
2687 pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2691 // durch das Loeschen von BRs kann der Start-Index
2692 // auch mal hinter das Ende des Textes zeigen
2693 if( pAttr->nSttCntnt > pCNd->Len() )
2694 pAttr->nSttCntnt = pCNd->Len();
2695 pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2697 pAttrPam->SetMark();
2698 if ( (pAttr->GetSttPara() != pAttr->GetEndPara()) &&
2699 !isTXTATR_NOEND(nWhich) )
2701 pCNd = pDoc->GetNodes()[ pAttr->nEndPara ]->GetCntntNode();
2702 if( !pCNd )
2704 pCNd = pDoc->GetNodes().GoPrevious( &(pAttr->nEndPara) );
2705 if( pCNd )
2706 pAttr->nEndCntnt = pCNd->Len();
2707 else
2709 ASSERT( !this, "SetAttr: GoPrevious() failed!" );
2710 pAttrPam->DeleteMark();
2711 delete pAttr;
2712 pAttr = pPrev;
2713 continue; // break;
2717 pAttrPam->GetPoint()->nNode = pAttr->nEndPara;
2719 else if( pAttr->IsLikePara() )
2721 pAttr->nEndCntnt = pCNd->Len();
2724 // durch das Loeschen von BRs kann der End-Index
2725 // auch mal hinter das Ende des Textes zeigen
2726 if( pAttr->nEndCntnt > pCNd->Len() )
2727 pAttr->nEndCntnt = pCNd->Len();
2729 pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nEndCntnt );
2730 if( bBeforeTable &&
2731 pAttrPam->GetPoint()->nNode.GetIndex() ==
2732 rEndIdx.GetIndex() )
2734 // wenn wir vor dem Einfuegen einer Tabelle stehen
2735 // und das Attribut im aktuellen Node beendet wird,
2736 // muessen wir es im Node davor beenden oder wegschmeissen,
2737 // wenn es erst in dem Node beginnt
2738 if( nWhich != RES_BREAK && nWhich != RES_PAGEDESC &&
2739 !isTXTATR_NOEND(nWhich) )
2741 if( pAttrPam->GetMark()->nNode.GetIndex() !=
2742 rEndIdx.GetIndex() )
2744 ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2745 "Content-Position vor Tabelle nicht 0???" );
2746 pAttrPam->Move( fnMoveBackward );
2748 else
2750 pAttrPam->DeleteMark();
2751 delete pAttr;
2752 pAttr = pPrev;
2753 continue;
2758 switch( nWhich )
2760 case RES_FLTR_BOOKMARK: // insert bookmark
2762 const String sName( ((SfxStringItem*)pAttr->pItem)->GetValue() );
2763 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
2764 IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark( sName );
2765 if( ppBkmk != pMarkAccess->getMarksEnd() &&
2766 ppBkmk->get()->GetMarkStart() == *pAttrPam->GetPoint() )
2767 break; // do not generate duplicates on this position
2768 pAttrPam->DeleteMark();
2769 const ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark(
2770 *pAttrPam,
2771 sName,
2772 IDocumentMarkAccess::BOOKMARK );
2774 // jump to bookmark
2775 if( JUMPTO_MARK == eJumpTo && pNewMark->GetName() == ::rtl::OUString(sJmpMark) )
2777 bChkJumpMark = TRUE;
2778 eJumpTo = JUMPTO_NONE;
2781 break;
2782 case RES_TXTATR_FIELD:
2784 USHORT nFldWhich =
2785 pPostIts ? ((const SwFmtFld *)pAttr->pItem)
2786 ->GetFld()->GetTyp()->Which() : 0;
2787 if( pPostIts && (RES_POSTITFLD == nFldWhich ||
2788 RES_SCRIPTFLD == nFldWhich) )
2790 pPostIts->Insert( pAttr, 0 );
2792 else
2794 aFields.Insert( pAttr, aFields.Count() );
2797 pAttrPam->DeleteMark();
2798 pAttr = pPrev;
2799 continue;
2801 case RES_LR_SPACE:
2802 if( pAttrPam->GetPoint()->nNode.GetIndex() ==
2803 pAttrPam->GetMark()->nNode.GetIndex() &&
2804 pCNd )
2806 // wegen Numerierungen dieses Attribut direkt
2807 // am Node setzen
2808 pCNd->SetAttr( *pAttr->pItem );
2809 break;
2811 ASSERT( !this,
2812 "LRSpace ueber mehrere Absaetze gesetzt!" );
2813 // kein break (hier sollen wir trotzdem nie hinkommen;
2814 default:
2816 // ggfs. ein Bookmark anspringen
2817 if( RES_TXTATR_INETFMT == nWhich &&
2818 JUMPTO_MARK == eJumpTo &&
2819 sJmpMark == ((SwFmtINetFmt*)pAttr->pItem)->GetName() )
2821 bChkJumpMark = TRUE;
2822 eJumpTo = JUMPTO_NONE;
2825 pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, nsSetAttrMode::SETATTR_DONTREPLACE );
2827 pAttrPam->DeleteMark();
2829 delete pAttr;
2830 pAttr = pPrev;
2835 for( n = aMoveFlyFrms.Count(); n; )
2837 SwFrmFmt *pFrmFmt = aMoveFlyFrms[ --n ];
2839 const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
2840 ASSERT( FLY_AT_CNTNT==rAnchor.GetAnchorId(),
2841 "Nur Auto-Rahmen brauchen eine Spezialbehandlung" );
2842 const SwPosition *pFlyPos = rAnchor.GetCntntAnchor();
2843 ULONG nFlyParaIdx = pFlyPos->nNode.GetIndex();
2844 BOOL bMoveFly;
2845 if( bChkEnd )
2847 bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2848 ( nFlyParaIdx == rEndIdx.GetIndex() &&
2849 aMoveFlyCnts[n] < nEndCnt );
2851 else
2853 ULONG nEndOfIcons = pDoc->GetNodes().GetEndOfExtras().GetIndex();
2854 bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() ||
2855 rEndIdx.GetIndex() > nEndOfIcons ||
2856 nFlyParaIdx <= nEndOfIcons;
2858 if( bMoveFly )
2860 pFrmFmt->DelFrms();
2861 *pAttrPam->GetPoint() = *pFlyPos;
2862 pAttrPam->GetPoint()->nContent.Assign( pAttrPam->GetCntntNode(),
2863 aMoveFlyCnts[n] );
2864 SwFmtAnchor aAnchor( rAnchor );
2865 aAnchor.SetType( FLY_AUTO_CNTNT );
2866 aAnchor.SetAnchor( pAttrPam->GetPoint() );
2867 pFrmFmt->SetFmtAttr( aAnchor );
2869 const SwFmtHoriOrient& rHoriOri = pFrmFmt->GetHoriOrient();
2870 if( text::HoriOrientation::LEFT == rHoriOri.GetHoriOrient() )
2872 SwFmtHoriOrient aHoriOri( rHoriOri );
2873 aHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2874 pFrmFmt->SetFmtAttr( aHoriOri );
2876 const SwFmtVertOrient& rVertOri = pFrmFmt->GetVertOrient();
2877 if( text::VertOrientation::TOP == rVertOri.GetVertOrient() )
2879 SwFmtVertOrient aVertOri( rVertOri );
2880 aVertOri.SetRelationOrient( text::RelOrientation::CHAR );
2881 pFrmFmt->SetFmtAttr( aVertOri );
2884 pFrmFmt->MakeFrms();
2885 aMoveFlyFrms.Remove( n, 1 );
2886 aMoveFlyCnts.Remove( n, 1 );
2889 while( aFields.Count() )
2891 pAttr = aFields[0];
2893 pCNd = pDoc->GetNodes()[ pAttr->nSttPara ]->GetCntntNode();
2894 pAttrPam->GetPoint()->nNode = pAttr->nSttPara;
2895 pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->nSttCntnt );
2897 if( bBeforeTable &&
2898 pAttrPam->GetPoint()->nNode.GetIndex() == rEndIdx.GetIndex() )
2900 ASSERT( !bBeforeTable, "Aha, der Fall tritt also doch ein" );
2901 ASSERT( !pAttrPam->GetPoint()->nContent.GetIndex(),
2902 "Content-Position vor Tabelle nicht 0???" );
2903 // !!!
2904 pAttrPam->Move( fnMoveBackward );
2907 pDoc->InsertPoolItem( *pAttrPam, *pAttr->pItem, 0 );
2909 aFields.Remove( 0, 1 );
2910 delete pAttr;
2913 delete pAttrPam;
2916 void SwHTMLParser::NewAttr( _HTMLAttr **ppAttr, const SfxPoolItem& rItem )
2918 // Font-Hoehen und -Farben- sowie Escapement-Attribute duerfen nicht
2919 // zusammengefasst werden. Sie werden deshalb in einer Liste gespeichert,
2920 // in der das zuletzt aufgespannte Attribut vorne steht und der Count
2921 // immer 1 ist. Fuer alle anderen Attribute wird der Count einfach
2922 // hochgezaehlt.
2923 if( *ppAttr )
2925 _HTMLAttr *pAttr = new _HTMLAttr( *pPam->GetPoint(), rItem,
2926 ppAttr );
2927 pAttr->InsertNext( *ppAttr );
2928 (*ppAttr) = pAttr;
2930 else
2931 (*ppAttr) = new _HTMLAttr( *pPam->GetPoint(), rItem, ppAttr );
2935 void SwHTMLParser::EndAttr( _HTMLAttr* pAttr, _HTMLAttr **ppDepAttr,
2936 BOOL bChkEmpty )
2938 ASSERT( !ppDepAttr, "SwHTMLParser::EndAttr: ppDepAttr-Feature ungetestet?" );
2939 // Der Listenkopf ist im Attribut gespeichert
2940 _HTMLAttr **ppHead = pAttr->ppHead;
2942 ASSERT( ppHead, "keinen Attributs-Listenkopf gefunden!" );
2944 // die aktuelle Psoition als Ende-Position merken
2945 const SwNodeIndex* pEndIdx = &pPam->GetPoint()->nNode;
2946 xub_StrLen nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2948 // WIrd das zueltzt gestartete oder ein frueher gestartetes Attribut
2949 // beendet?
2950 _HTMLAttr *pLast = 0;
2951 if( ppHead && pAttr != *ppHead )
2953 // Es wird nicht das zuletzt gestartete Attribut beendet
2955 // Dann suche wir das unmittelbar danach gestartete Attribut, das
2956 // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
2957 // mehr in der Liste
2958 pLast = *ppHead;
2959 while( pLast && pLast->GetNext() != pAttr )
2960 pLast = pLast->GetNext();
2962 ASSERT( pLast, "Attribut nicht in eigener Liste gefunden!" );
2964 // das Attribut nicht an der PaM-Psoition beenden, sondern da,
2965 // wo das danch gestartete Attribut anfing???
2966 //pEndIdx = &pPrev->GetSttPara();
2967 //nEndCnt = pPrev->GetSttCnt();
2970 BOOL bMoveBack = FALSE;
2971 USHORT nWhich = pAttr->pItem->Which();
2972 if( /*!pLast &&*/ !nEndCnt && RES_PARATR_BEGIN <= nWhich &&
2973 *pEndIdx != pAttr->GetSttPara() )
2975 // dann eine Cntntnt Position zurueck!
2976 bMoveBack = pPam->Move( fnMoveBackward );
2977 nEndCnt = pPam->GetPoint()->nContent.GetIndex();
2980 // nun das Attrubut beenden
2981 _HTMLAttr *pNext = pAttr->GetNext();
2984 sal_Bool bInsert;
2985 sal_uInt16 nScriptItem = 0;
2986 sal_Bool bScript = sal_False, bFont = sal_False;
2987 // ein Bereich ??
2988 if( !bChkEmpty || (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
2989 RES_PAGEDESC == nWhich || RES_BREAK == nWhich ||
2990 *pEndIdx != pAttr->GetSttPara() ||
2991 nEndCnt != pAttr->GetSttCnt() )
2993 bInsert = sal_True;
2994 // We do some optimization for script depenedent attribtes here.
2995 if( *pEndIdx == pAttr->GetSttPara() )
2997 lcl_swhtml_getItemInfo( *pAttr, bScript, bFont, nScriptItem );
3000 else
3002 bInsert = sal_False;
3005 if( bInsert && bScript )
3007 const SwTxtNode *pTxtNd = pAttr->GetSttPara().GetNode()
3008 .GetTxtNode();
3009 ASSERT( pTxtNd, "No text node" );
3010 const String& rText = pTxtNd->GetTxt();
3011 sal_uInt16 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
3012 rText, pAttr->GetSttCnt() );
3013 xub_StrLen nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
3014 ->endOfScript( rText, pAttr->GetSttCnt(), nScriptTxt );
3015 while( nScriptEnd < nEndCnt )
3017 if( nScriptItem == nScriptTxt )
3019 _HTMLAttr *pSetAttr = pAttr->Clone( *pEndIdx, nScriptEnd );
3020 pSetAttr->ClearPrev();
3021 if( pNext )
3022 pNext->InsertPrev( pSetAttr );
3023 else
3025 USHORT nTmp = pSetAttr->bInsAtStart ? 0
3026 : aSetAttrTab.Count();
3027 aSetAttrTab.Insert( pSetAttr, nTmp );
3030 pAttr->nSttCntnt = nScriptEnd;
3031 nScriptTxt = pBreakIt->GetBreakIter()->getScriptType(
3032 rText, nScriptEnd );
3033 nScriptEnd = (xub_StrLen)pBreakIt->GetBreakIter()
3034 ->endOfScript( rText, nScriptEnd, nScriptTxt );
3036 bInsert = nScriptItem == nScriptTxt;
3038 if( bInsert )
3040 pAttr->nEndPara = *pEndIdx;
3041 pAttr->nEndCntnt = nEndCnt;
3042 pAttr->bInsAtStart = RES_TXTATR_INETFMT != nWhich &&
3043 RES_TXTATR_CHARFMT != nWhich;
3045 if( !pNext )
3047 // keine offenen Attribute dieses Typs mehr da,
3048 // dann koennen alle gesetzt werden, es sei denn
3049 // sie haengen noch von einem anderen Attribut ab,
3050 // dann werden sie dort angehaengt
3051 if( ppDepAttr && *ppDepAttr )
3052 (*ppDepAttr)->InsertPrev( pAttr );
3053 else
3055 USHORT nTmp = pAttr->bInsAtStart ? 0 : aSetAttrTab.Count();
3056 aSetAttrTab.Insert( pAttr, nTmp );
3059 else
3061 // es gibt noch andere offene Attribute des Typs,
3062 // daher muss das Setzen zurueckgestellt werden.
3063 // das aktuelle Attribut wird deshalb hinten an die
3064 // Previous-Liste des Nachfolgers angehaengt
3065 pNext->InsertPrev( pAttr );
3068 else
3070 // dann nicht einfuegen, sondern Loeschen. Durch das "tuerken" von
3071 // Vorlagen durch harte Attributierung koennen sich auch mal andere
3072 // leere Attribute in der Prev-Liste befinden, die dann trotzdem
3073 // gesetzt werden muessen
3074 _HTMLAttr *pPrev = pAttr->GetPrev();
3075 delete pAttr;
3077 if( pPrev )
3079 // Die Previous-Attribute muessen trotzdem gesetzt werden.
3080 if( pNext )
3081 pNext->InsertPrev( pPrev );
3082 else
3084 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3085 aSetAttrTab.Insert( pPrev, nTmp );
3091 // wenn das erste Attribut der Liste gesetzt wurde muss noch der
3092 // Listenkopf korrigiert werden.
3093 if( pLast )
3094 pLast->pNext = pNext;
3095 else if( ppHead )
3096 *ppHead = pNext;
3098 if( bMoveBack )
3099 pPam->Move( fnMoveForward );
3102 void SwHTMLParser::DeleteAttr( _HTMLAttr* pAttr )
3104 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3105 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3106 ASSERT( !aParaAttrs.Count(),
3107 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3108 if( aParaAttrs.Count() )
3109 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3111 // Der Listenkopf ist im Attribut gespeichert
3112 _HTMLAttr **ppHead = pAttr->ppHead;
3114 ASSERT( ppHead, "keinen Attributs-Listenkopf gefunden!" );
3116 // Wird das zueltzt gestartete oder ein frueher gestartetes Attribut
3117 // entfernt?
3118 _HTMLAttr *pLast = 0;
3119 if( ppHead && pAttr != *ppHead )
3121 // Es wird nicht das zuletzt gestartete Attribut beendet
3123 // Dann suche wir das unmittelbar danach gestartete Attribut, das
3124 // ja ebenfalls noch nicht beendet wurde (sonst stuende es nicht
3125 // mehr in der Liste
3126 pLast = *ppHead;
3127 while( pLast && pLast->GetNext() != pAttr )
3128 pLast = pLast->GetNext();
3130 ASSERT( pLast, "Attribut nicht in eigener Liste gefunden!" );
3133 // nun das Attrubut entfernen
3134 _HTMLAttr *pNext = pAttr->GetNext();
3135 _HTMLAttr *pPrev = pAttr->GetPrev();
3136 delete pAttr;
3138 if( pPrev )
3140 // Die Previous-Attribute muessen trotzdem gesetzt werden.
3141 if( pNext )
3142 pNext->InsertPrev( pPrev );
3143 else
3145 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3146 aSetAttrTab.Insert( pPrev, nTmp );
3150 // wenn das erste Attribut der Liste entfernt wurde muss noch der
3151 // Listenkopf korrigiert werden.
3152 if( pLast )
3153 pLast->pNext = pNext;
3154 else if( ppHead )
3155 *ppHead = pNext;
3158 void SwHTMLParser::SaveAttrTab( _HTMLAttrTable& rNewAttrTab )
3160 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3161 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3162 ASSERT( !aParaAttrs.Count(),
3163 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3164 if( aParaAttrs.Count() )
3165 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3167 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3168 _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3170 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3171 nCnt--; (++pTbl, ++pSaveTbl) )
3173 *pSaveTbl = *pTbl;
3175 _HTMLAttr *pAttr = *pSaveTbl;
3176 while( pAttr )
3178 pAttr->SetHead( pSaveTbl );
3179 pAttr = pAttr->GetNext();
3182 *pTbl = 0;
3186 void SwHTMLParser::SplitAttrTab( _HTMLAttrTable& rNewAttrTab,
3187 BOOL bMoveEndBack )
3189 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3190 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3191 ASSERT( !aParaAttrs.Count(),
3192 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3193 if( aParaAttrs.Count() )
3194 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3196 const SwNodeIndex& nSttIdx = pPam->GetPoint()->nNode;
3197 SwNodeIndex nEndIdx( nSttIdx );
3199 // alle noch offenen Attribute beenden und hinter der Tabelle
3200 // neu aufspannen
3201 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3202 _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3203 BOOL bSetAttr = TRUE;
3204 xub_StrLen nSttCnt = pPam->GetPoint()->nContent.GetIndex();
3205 xub_StrLen nEndCnt = nSttCnt;
3207 if( bMoveEndBack )
3209 ULONG nOldEnd = nEndIdx.GetIndex();
3210 ULONG nTmpIdx;
3211 if( ( nTmpIdx = pDoc->GetNodes().GetEndOfExtras().GetIndex()) >= nOldEnd ||
3212 ( nTmpIdx = pDoc->GetNodes().GetEndOfAutotext().GetIndex()) >= nOldEnd )
3214 nTmpIdx = pDoc->GetNodes().GetEndOfInserts().GetIndex();
3216 SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious(&nEndIdx);
3218 // keine Attribute setzen, wenn der PaM aus dem Content-Bereich
3219 // herausgeschoben wurde.
3220 bSetAttr = pCNd && nTmpIdx < nEndIdx.GetIndex();
3222 nEndCnt = (bSetAttr ? pCNd->Len() : 0);
3224 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3225 nCnt--; (++pTbl, ++pSaveTbl) )
3227 _HTMLAttr *pAttr = *pTbl;
3228 *pSaveTbl = 0;
3229 while( pAttr )
3231 _HTMLAttr *pNext = pAttr->GetNext();
3232 _HTMLAttr *pPrev = pAttr->GetPrev();
3234 if( bSetAttr &&
3235 ( pAttr->GetSttParaIdx() < nEndIdx.GetIndex() ||
3236 (pAttr->GetSttPara() == nEndIdx &&
3237 pAttr->GetSttCnt() != nEndCnt) ) )
3239 // das Attribut muss vor der Liste gesetzt werden. Da wir
3240 // das Original noch brauchen, weil Zeiger auf das Attribut
3241 // noch in den Kontexten existieren, muessen wir es clonen.
3242 // Die Next-Liste geht dabei verloren, aber die
3243 // Previous-Liste bleibt erhalten
3244 _HTMLAttr *pSetAttr = pAttr->Clone( nEndIdx, nEndCnt );
3246 if( pNext )
3247 pNext->InsertPrev( pSetAttr );
3248 else
3250 USHORT nTmp = pSetAttr->bInsAtStart ? 0
3251 : aSetAttrTab.Count();
3252 aSetAttrTab.Insert( pSetAttr, nTmp );
3255 else if( pPrev )
3257 // Wenn das Attribut nicht gesetzt vor der Tabelle
3258 // gesetzt werden muss, muessen der Previous-Attribute
3259 // trotzdem gesetzt werden.
3260 if( pNext )
3261 pNext->InsertPrev( pPrev );
3262 else
3264 USHORT nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
3265 aSetAttrTab.Insert( pPrev, nTmp );
3269 // den Start des Attributs neu setzen und die Verkettungen
3270 // aufbrechen
3271 pAttr->Reset( nSttIdx, nSttCnt, pSaveTbl );
3273 if( *pSaveTbl )
3275 _HTMLAttr *pSAttr = *pSaveTbl;
3276 while( pSAttr->GetNext() )
3277 pSAttr = pSAttr->GetNext();
3278 pSAttr->InsertNext( pAttr );
3280 else
3281 *pSaveTbl = pAttr;
3283 pAttr = pNext;
3286 *pTbl = 0;
3290 void SwHTMLParser::RestoreAttrTab( const _HTMLAttrTable& rNewAttrTab,
3291 BOOL bSetNewStart )
3293 // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
3294 // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
3295 ASSERT( !aParaAttrs.Count(),
3296 "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
3297 if( aParaAttrs.Count() )
3298 aParaAttrs.Remove( 0, aParaAttrs.Count() );
3300 _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
3301 _HTMLAttr** pSaveTbl = (_HTMLAttr**)&rNewAttrTab;
3303 for( USHORT nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3304 nCnt--; (++pTbl, ++pSaveTbl) )
3306 ASSERT( !*pTbl, "Die Attribut-Tabelle ist nicht leer!" );
3308 const SwPosition *pPos = pPam->GetPoint();
3309 const SwNodeIndex& rSttPara = pPos->nNode;
3310 xub_StrLen nSttCnt = pPos->nContent.GetIndex();
3312 *pTbl = *pSaveTbl;
3314 _HTMLAttr *pAttr = *pTbl;
3315 while( pAttr )
3317 ASSERT( !pAttr->GetPrev() || !pAttr->GetPrev()->ppHead,
3318 "Previous-Attribut hat noch einen Header" );
3319 pAttr->SetHead( pTbl );
3320 if( bSetNewStart )
3322 pAttr->nSttPara = rSttPara;
3323 pAttr->nEndPara = rSttPara;
3324 pAttr->nSttCntnt = nSttCnt;
3325 pAttr->nEndCntnt = nSttCnt;
3327 pAttr = pAttr->GetNext();
3330 *pSaveTbl = 0;
3334 void SwHTMLParser::InsertAttr( const SfxPoolItem& rItem, BOOL bLikePara,
3335 BOOL bInsAtStart )
3337 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(),
3338 rItem );
3339 if( bLikePara )
3340 pTmp->SetLikePara();
3341 USHORT nTmp = bInsAtStart ? 0 : aSetAttrTab.Count();
3342 aSetAttrTab.Insert( pTmp, nTmp );
3345 void SwHTMLParser::InsertAttrs( _HTMLAttrs& rAttrs )
3347 while( rAttrs.Count() )
3349 _HTMLAttr *pAttr = rAttrs[0];
3350 InsertAttr( pAttr->GetItem() );
3351 rAttrs.Remove( 0, 1 );
3352 delete pAttr;
3356 /* \f */
3358 void SwHTMLParser::NewStdAttr( int nToken )
3360 String aId, aStyle, aClass, aLang, aDir;
3362 const HTMLOptions *pHTMLOptions = GetOptions();
3363 for( USHORT i = pHTMLOptions->Count(); i; )
3365 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3366 switch( pOption->GetToken() )
3368 case HTML_O_ID:
3369 aId = pOption->GetString();
3370 break;
3371 case HTML_O_STYLE:
3372 aStyle = pOption->GetString();
3373 break;
3374 case HTML_O_CLASS:
3375 aClass = pOption->GetString();
3376 break;
3377 case HTML_O_LANG:
3378 aLang = pOption->GetString();
3379 break;
3380 case HTML_O_DIR:
3381 aDir = pOption->GetString();
3382 break;
3386 // einen neuen Kontext anlegen
3387 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3389 // Styles parsen
3390 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3392 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3393 SvxCSS1PropertyInfo aPropInfo;
3395 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3397 if( HTML_SPAN_ON != nToken || !aClass.Len() ||
3398 !CreateContainer( aClass, aItemSet, aPropInfo, pCntxt ) )
3399 DoPositioning( aItemSet, aPropInfo, pCntxt );
3400 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3404 // den Kontext merken
3405 PushContext( pCntxt );
3408 void SwHTMLParser::NewStdAttr( int nToken,
3409 _HTMLAttr **ppAttr, const SfxPoolItem & rItem,
3410 _HTMLAttr **ppAttr2, const SfxPoolItem *pItem2,
3411 _HTMLAttr **ppAttr3, const SfxPoolItem *pItem3 )
3413 String aId, aStyle, aClass, aLang, aDir;
3415 const HTMLOptions *pHTMLOptions = GetOptions();
3416 for( USHORT i = pHTMLOptions->Count(); i; )
3418 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3419 switch( pOption->GetToken() )
3421 case HTML_O_ID:
3422 aId = pOption->GetString();
3423 break;
3424 case HTML_O_STYLE:
3425 aStyle = pOption->GetString();
3426 break;
3427 case HTML_O_CLASS:
3428 aClass = pOption->GetString();
3429 break;
3430 case HTML_O_LANG:
3431 aLang = pOption->GetString();
3432 break;
3433 case HTML_O_DIR:
3434 aDir = pOption->GetString();
3435 break;
3439 // einen neuen Kontext anlegen
3440 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3442 // Styles parsen
3443 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3445 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3446 SvxCSS1PropertyInfo aPropInfo;
3448 aItemSet.Put( rItem );
3449 if( pItem2 )
3450 aItemSet.Put( *pItem2 );
3451 if( pItem3 )
3452 aItemSet.Put( *pItem3 );
3454 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3455 DoPositioning( aItemSet, aPropInfo, pCntxt );
3457 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3459 else
3461 InsertAttr( ppAttr ,rItem, pCntxt );
3462 if( pItem2 )
3464 ASSERT( ppAttr2, "missing table entry for item2" );
3465 InsertAttr( ppAttr2, *pItem2, pCntxt );
3467 if( pItem3 )
3469 ASSERT( ppAttr3, "missing table entry for item3" );
3470 InsertAttr( ppAttr3, *pItem3, pCntxt );
3474 // den Kontext merken
3475 PushContext( pCntxt );
3478 void SwHTMLParser::EndTag( int nToken )
3480 // den Kontext holen
3481 _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
3482 if( pCntxt )
3484 // und ggf. die Attribute beenden
3485 EndContext( pCntxt );
3486 delete pCntxt;
3491 void SwHTMLParser::NewBasefontAttr()
3493 String aId, aStyle, aClass, aLang, aDir;
3494 USHORT nSize = 3;
3496 const HTMLOptions *pHTMLOptions = GetOptions();
3497 for( USHORT i = pHTMLOptions->Count(); i; )
3499 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3500 switch( pOption->GetToken() )
3502 case HTML_O_SIZE:
3503 nSize = (USHORT)pOption->GetNumber();
3504 break;
3505 case HTML_O_ID:
3506 aId = pOption->GetString();
3507 break;
3508 case HTML_O_STYLE:
3509 aStyle = pOption->GetString();
3510 break;
3511 case HTML_O_CLASS:
3512 aClass = pOption->GetString();
3513 break;
3514 case HTML_O_LANG:
3515 aLang = pOption->GetString();
3516 break;
3517 case HTML_O_DIR:
3518 aDir = pOption->GetString();
3519 break;
3523 if( nSize < 1 )
3524 nSize = 1;
3526 if( nSize > 7 )
3527 nSize = 7;
3529 // einen neuen Kontext anlegen
3530 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_BASEFONT_ON );
3532 // Styles parsen
3533 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3535 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3536 SvxCSS1PropertyInfo aPropInfo;
3538 SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3539 aItemSet.Put( aFontHeight );
3540 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3541 aItemSet.Put( aFontHeight );
3542 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3543 aItemSet.Put( aFontHeight );
3545 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3546 DoPositioning( aItemSet, aPropInfo, pCntxt );
3548 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3550 else
3552 SvxFontHeightItem aFontHeight( aFontHeights[nSize-1], 100, RES_CHRATR_FONTSIZE );
3553 InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3554 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3555 InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3556 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3557 InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3560 // den Kontext merken
3561 PushContext( pCntxt );
3563 // die Font-Size merken
3564 aBaseFontStack.Insert( nSize, aBaseFontStack.Count() );
3567 void SwHTMLParser::EndBasefontAttr()
3569 EndTag( HTML_BASEFONT_ON );
3571 // Stack-Unterlauf in Tabellen vermeiden
3572 if( aBaseFontStack.Count() > nBaseFontStMin )
3573 aBaseFontStack.Remove( aBaseFontStack.Count()-1, 1 );
3576 void SwHTMLParser::NewFontAttr( int nToken )
3578 USHORT nBaseSize =
3579 ( aBaseFontStack.Count() > nBaseFontStMin
3580 ? (aBaseFontStack[aBaseFontStack.Count()-1] & FONTSIZE_MASK)
3581 : 3 );
3582 USHORT nFontSize =
3583 ( aFontStack.Count() > nFontStMin
3584 ? (aFontStack[aFontStack.Count()-1] & FONTSIZE_MASK)
3585 : nBaseSize );
3587 String aFace, aId, aStyle, aClass, aLang, aDir;
3588 Color aColor;
3589 ULONG nFontHeight = 0; // tatsaechlich einzustellende Font-Hoehe
3590 USHORT nSize = 0; // Fontgroesse in Netscape-Notation (1-7)
3591 BOOL bColor = FALSE;
3593 const HTMLOptions *pHTMLOptions = GetOptions();
3594 for( USHORT i = pHTMLOptions->Count(); i; )
3596 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3597 switch( pOption->GetToken() )
3599 case HTML_O_SIZE:
3600 if( HTML_FONT_ON==nToken && pOption->GetString().Len() )
3602 INT32 nSSize;
3603 if( '+' == pOption->GetString().GetChar(0) ||
3604 '-' == pOption->GetString().GetChar(0) )
3605 nSSize = nBaseSize + pOption->GetSNumber();
3606 else
3607 nSSize = (INT32)pOption->GetNumber();
3609 if( nSSize < 1 )
3610 nSSize = 1;
3611 else if( nSSize > 7 )
3612 nSSize = 7;
3614 nSize = (USHORT)nSSize;
3615 nFontHeight = aFontHeights[nSize-1];
3617 break;
3618 case HTML_O_COLOR:
3619 if( HTML_FONT_ON==nToken )
3621 pOption->GetColor( aColor );
3622 bColor = TRUE;
3624 break;
3625 case HTML_O_FACE:
3626 if( HTML_FONT_ON==nToken )
3627 aFace = pOption->GetString();
3628 break;
3629 case HTML_O_ID:
3630 aId = pOption->GetString();
3631 break;
3632 case HTML_O_STYLE:
3633 aStyle = pOption->GetString();
3634 break;
3635 case HTML_O_CLASS:
3636 aClass = pOption->GetString();
3637 break;
3638 case HTML_O_LANG:
3639 aLang = pOption->GetString();
3640 break;
3641 case HTML_O_DIR:
3642 aDir = pOption->GetString();
3643 break;
3647 if( HTML_FONT_ON != nToken )
3649 // HTML_BIGPRINT_ON oder HTML_SMALLPRINT_ON
3651 // in Ueberschriften bestimmt die aktuelle Ueberschrift
3652 // die Font-Hoehe und nicht BASEFONT
3653 USHORT nPoolId = GetCurrFmtColl()->GetPoolFmtId();
3654 if( (nPoolId>=RES_POOLCOLL_HEADLINE1 &&
3655 nPoolId<=RES_POOLCOLL_HEADLINE6) )
3657 // wenn die Schriftgroesse in der Ueberschrift noch
3658 // nicht veraendert ist, die aus der Vorlage nehmen
3659 if( nFontStHeadStart==aFontStack.Count() )
3660 nFontSize = static_cast< USHORT >(6 - (nPoolId - RES_POOLCOLL_HEADLINE1));
3662 else
3663 nPoolId = 0;
3665 if( HTML_BIGPRINT_ON == nToken )
3666 nSize = ( nFontSize<7 ? nFontSize+1 : 7 );
3667 else
3668 nSize = ( nFontSize>1 ? nFontSize-1 : 1 );
3670 // in Ueberschriften wird die neue Fonthoehe wenn moeglich aus
3671 // den Vorlagen geholt.
3672 if( nPoolId && nSize>=1 && nSize <=6 )
3673 nFontHeight =
3674 pCSS1Parser->GetTxtCollFromPool(
3675 RES_POOLCOLL_HEADLINE1+6-nSize )->GetSize().GetHeight();
3676 else
3677 nFontHeight = aFontHeights[nSize-1];
3680 ASSERT( !nSize == !nFontHeight, "HTML-Font-Size != Font-Height" );
3682 String aFontName, aStyleName;
3683 FontFamily eFamily = FAMILY_DONTKNOW; // Family und Pitch,
3684 FontPitch ePitch = PITCH_DONTKNOW; // falls nicht gefunden
3685 rtl_TextEncoding eEnc = gsl_getSystemTextEncoding();
3687 if( aFace.Len() && !pCSS1Parser->IsIgnoreFontFamily() )
3689 const FontList *pFList = 0;
3690 SwDocShell *pDocSh = pDoc->GetDocShell();
3691 if( pDocSh )
3693 const SvxFontListItem *pFListItem =
3694 (const SvxFontListItem *)pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST);
3695 if( pFListItem )
3696 pFList = pFListItem->GetFontList();
3699 BOOL bFound = FALSE;
3700 xub_StrLen nStrPos = 0;
3701 while( nStrPos!=STRING_NOTFOUND )
3703 String aFName = aFace.GetToken( 0, ',', nStrPos );
3704 aFName.EraseTrailingChars().EraseLeadingChars();
3705 if( aFName.Len() )
3707 if( !bFound && pFList )
3709 sal_Handle hFont = pFList->GetFirstFontInfo( aFName );
3710 if( 0 != hFont )
3712 const FontInfo& rFInfo = pFList->GetFontInfo( hFont );
3713 if( RTL_TEXTENCODING_DONTKNOW != rFInfo.GetCharSet() )
3715 bFound = TRUE;
3716 if( RTL_TEXTENCODING_SYMBOL == rFInfo.GetCharSet() )
3717 eEnc = RTL_TEXTENCODING_SYMBOL;
3721 if( aFontName.Len() )
3722 aFontName += ';';
3723 aFontName += aFName;
3729 // einen neuen Kontext anlegen
3730 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
3732 // Styles parsen
3733 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3735 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3736 SvxCSS1PropertyInfo aPropInfo;
3738 if( nFontHeight )
3740 SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3741 aItemSet.Put( aFontHeight );
3742 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3743 aItemSet.Put( aFontHeight );
3744 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3745 aItemSet.Put( aFontHeight );
3747 if( bColor )
3748 aItemSet.Put( SvxColorItem(aColor, RES_CHRATR_COLOR) );
3749 if( aFontName.Len() )
3751 SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3752 aItemSet.Put( aFont );
3753 aFont.SetWhich( RES_CHRATR_CJK_FONT );
3754 aItemSet.Put( aFont );
3755 aFont.SetWhich( RES_CHRATR_CTL_FONT );
3756 aItemSet.Put( aFont );
3760 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
3761 DoPositioning( aItemSet, aPropInfo, pCntxt );
3763 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
3765 else
3767 if( nFontHeight )
3769 SvxFontHeightItem aFontHeight( nFontHeight, 100, RES_CHRATR_FONTSIZE );
3770 InsertAttr( &aAttrTab.pFontHeight, aFontHeight, pCntxt );
3771 aFontHeight.SetWhich( RES_CHRATR_CJK_FONTSIZE );
3772 InsertAttr( &aAttrTab.pFontHeightCJK, aFontHeight, pCntxt );
3773 aFontHeight.SetWhich( RES_CHRATR_CTL_FONTSIZE );
3774 InsertAttr( &aAttrTab.pFontHeightCTL, aFontHeight, pCntxt );
3776 if( bColor )
3777 InsertAttr( &aAttrTab.pFontColor, SvxColorItem(aColor, RES_CHRATR_COLOR), pCntxt );
3778 if( aFontName.Len() )
3780 SvxFontItem aFont( eFamily, aFontName, aStyleName, ePitch, eEnc, RES_CHRATR_FONT );
3781 InsertAttr( &aAttrTab.pFont, aFont, pCntxt );
3782 aFont.SetWhich( RES_CHRATR_CJK_FONT );
3783 InsertAttr( &aAttrTab.pFontCJK, aFont, pCntxt );
3784 aFont.SetWhich( RES_CHRATR_CTL_FONT );
3785 InsertAttr( &aAttrTab.pFontCTL, aFont, pCntxt );
3789 // den Kontext merken
3790 PushContext( pCntxt );
3792 aFontStack.Insert( nSize, aFontStack.Count() );
3795 void SwHTMLParser::EndFontAttr( int nToken )
3797 EndTag( nToken );
3799 // Stack-Unterlauf in Tabellen vermeiden
3800 if( aFontStack.Count() > nFontStMin )
3801 aFontStack.Remove( aFontStack.Count()-1, 1 );
3804 /* \f */
3806 void SwHTMLParser::NewPara()
3808 if( pPam->GetPoint()->nContent.GetIndex() )
3809 AppendTxtNode( AM_SPACE );
3810 else
3811 AddParSpace();
3813 eParaAdjust = SVX_ADJUST_END;
3814 String aId, aStyle, aClass, aLang, aDir;
3816 const HTMLOptions *pHTMLOptions = GetOptions();
3817 for( USHORT i = pHTMLOptions->Count(); i; )
3819 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3820 switch( pOption->GetToken() )
3822 case HTML_O_ID:
3823 aId = pOption->GetString();
3824 break;
3825 case HTML_O_ALIGN:
3826 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3827 break;
3828 case HTML_O_STYLE:
3829 aStyle = pOption->GetString();
3830 break;
3831 case HTML_O_CLASS:
3832 aClass = pOption->GetString();
3833 break;
3834 case HTML_O_LANG:
3835 aLang = pOption->GetString();
3836 break;
3837 case HTML_O_DIR:
3838 aDir = pOption->GetString();
3839 break;
3843 // einen neuen Kontext anlegen
3844 _HTMLAttrContext *pCntxt =
3845 aClass.Len() ? new _HTMLAttrContext( HTML_PARABREAK_ON,
3846 RES_POOLCOLL_TEXT, aClass )
3847 : new _HTMLAttrContext( HTML_PARABREAK_ON );
3849 // Styles parsen (Class nicht beruecksichtigen. Das geht nur, solange
3850 // keine der CSS1-Properties der Klasse hart formatiert werden muss!!!)
3851 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
3853 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3854 SvxCSS1PropertyInfo aPropInfo;
3856 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
3858 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
3859 "Class wird nicht beruecksichtigt" );
3860 DoPositioning( aItemSet, aPropInfo, pCntxt );
3861 InsertAttrs( aItemSet, aPropInfo, pCntxt );
3865 if( SVX_ADJUST_END != eParaAdjust )
3866 InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
3868 // und auf den Stack packen
3869 PushContext( pCntxt );
3871 // die aktuelle Vorlage oder deren Attribute setzen
3872 SetTxtCollAttrs( aClass.Len() ? pCntxt : 0 );
3874 // Laufbalkenanzeige
3875 ShowStatline();
3877 ASSERT( !nOpenParaToken, "Jetzt geht ein offenes Absatz-Element verloren" );
3878 nOpenParaToken = HTML_PARABREAK_ON;
3881 void SwHTMLParser::EndPara( BOOL bReal )
3883 if( HTML_LI_ON==nOpenParaToken && pTable )
3885 #ifndef PRODUCT
3886 const SwNumRule *pNumRule = pPam->GetNode()->GetTxtNode()->GetNumRule();
3887 #endif
3888 ASSERT( pNumRule, "Wo ist die Numrule geblieben" );
3891 // leere Absaetze werden von Netscape uebersprungen, von uns jetzt auch
3892 if( bReal )
3894 if( pPam->GetPoint()->nContent.GetIndex() )
3895 AppendTxtNode( AM_SPACE );
3896 else
3897 AddParSpace();
3900 // wenn ein DD oder DT offen war, handelt es sich um eine
3901 // implizite Def-Liste, die jetzt beendet werden muss
3902 if( (nOpenParaToken==HTML_DT_ON || nOpenParaToken==HTML_DD_ON) &&
3903 nDefListDeep)
3905 nDefListDeep--;
3908 // den Kontext vom Stack holen. Er kann auch von einer implizit
3909 // geoeffneten Definitionsliste kommen
3910 _HTMLAttrContext *pCntxt =
3911 PopContext( static_cast< sal_uInt16 >(nOpenParaToken ? (nOpenParaToken & ~1)
3912 : HTML_PARABREAK_ON) );
3914 // Attribute beenden
3915 if( pCntxt )
3917 EndContext( pCntxt );
3918 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
3919 delete pCntxt;
3922 // und die bisherige Vorlage neu setzen
3923 if( bReal )
3924 SetTxtCollAttrs();
3926 nOpenParaToken = 0;
3930 void SwHTMLParser::NewHeading( int nToken )
3932 eParaAdjust = SVX_ADJUST_END;
3934 String aId, aStyle, aClass, aLang, aDir;
3936 const HTMLOptions *pHTMLOptions = GetOptions();
3937 for( USHORT i = pHTMLOptions->Count(); i; )
3939 const HTMLOption *pOption = (*pHTMLOptions)[--i];
3940 switch( pOption->GetToken() )
3942 case HTML_O_ID:
3943 aId = pOption->GetString();
3944 break;
3945 case HTML_O_ALIGN:
3946 eParaAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eParaAdjust) );
3947 break;
3948 case HTML_O_STYLE:
3949 aStyle = pOption->GetString();
3950 break;
3951 case HTML_O_CLASS:
3952 aClass = pOption->GetString();
3953 break;
3954 case HTML_O_LANG:
3955 aLang = pOption->GetString();
3956 break;
3957 case HTML_O_DIR:
3958 aDir = pOption->GetString();
3959 break;
3963 // einen neuen Absatz aufmachen
3964 if( pPam->GetPoint()->nContent.GetIndex() )
3965 AppendTxtNode( AM_SPACE );
3966 else
3967 AddParSpace();
3969 // die passende Vorlage suchen
3970 USHORT nTxtColl;
3971 switch( nToken )
3973 case HTML_HEAD1_ON: nTxtColl = RES_POOLCOLL_HEADLINE1; break;
3974 case HTML_HEAD2_ON: nTxtColl = RES_POOLCOLL_HEADLINE2; break;
3975 case HTML_HEAD3_ON: nTxtColl = RES_POOLCOLL_HEADLINE3; break;
3976 case HTML_HEAD4_ON: nTxtColl = RES_POOLCOLL_HEADLINE4; break;
3977 case HTML_HEAD5_ON: nTxtColl = RES_POOLCOLL_HEADLINE5; break;
3978 case HTML_HEAD6_ON: nTxtColl = RES_POOLCOLL_HEADLINE6; break;
3979 default: nTxtColl = RES_POOLCOLL_STANDARD; break;
3982 // den Kontext anlegen
3983 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nTxtColl, aClass );
3985 // Styles parsen (zu Class siehe auch NewPara)
3986 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
3988 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
3989 SvxCSS1PropertyInfo aPropInfo;
3991 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
3993 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
3994 "Class wird nicht beruecksichtigt" );
3995 DoPositioning( aItemSet, aPropInfo, pCntxt );
3996 InsertAttrs( aItemSet, aPropInfo, pCntxt );
4000 if( SVX_ADJUST_END != eParaAdjust )
4001 InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eParaAdjust, RES_PARATR_ADJUST), pCntxt );
4003 // udn auf den Stack packen
4004 PushContext( pCntxt );
4006 // und die Vorlage oder deren Attribute setzen
4007 SetTxtCollAttrs( pCntxt );
4009 nFontStHeadStart = aFontStack.Count();
4011 // Laufbalkenanzeige
4012 ShowStatline();
4015 void SwHTMLParser::EndHeading()
4017 // einen neuen Absatz aufmachen
4018 if( pPam->GetPoint()->nContent.GetIndex() )
4019 AppendTxtNode( AM_SPACE );
4020 else
4021 AddParSpace();
4023 // Kontext zu dem Token suchen und vom Stack holen
4024 _HTMLAttrContext *pCntxt = 0;
4025 USHORT nPos = aContexts.Count();
4026 while( !pCntxt && nPos>nContextStMin )
4028 switch( aContexts[--nPos]->GetToken() )
4030 case HTML_HEAD1_ON:
4031 case HTML_HEAD2_ON:
4032 case HTML_HEAD3_ON:
4033 case HTML_HEAD4_ON:
4034 case HTML_HEAD5_ON:
4035 case HTML_HEAD6_ON:
4036 pCntxt = aContexts[nPos];
4037 aContexts.Remove( nPos, 1 );
4038 break;
4042 // und noch Attribute beenden
4043 if( pCntxt )
4045 EndContext( pCntxt );
4046 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4047 delete pCntxt;
4050 // die bisherige Vorlage neu setzen
4051 SetTxtCollAttrs();
4053 nFontStHeadStart = nFontStMin;
4056 /* \f */
4058 void SwHTMLParser::NewTxtFmtColl( int nToken, USHORT nColl )
4060 String aId, aStyle, aClass, aLang, aDir;
4062 const HTMLOptions *pHTMLOptions = GetOptions();
4063 for( USHORT i = pHTMLOptions->Count(); i; )
4065 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4066 switch( pOption->GetToken() )
4068 case HTML_O_ID:
4069 aId = pOption->GetString();
4070 break;
4071 case HTML_O_STYLE:
4072 aStyle = pOption->GetString();
4073 break;
4074 case HTML_O_CLASS:
4075 aClass = pOption->GetString();
4076 break;
4077 case HTML_O_LANG:
4078 aLang = pOption->GetString();
4079 break;
4080 case HTML_O_DIR:
4081 aDir = pOption->GetString();
4082 break;
4086 // einen neuen Absatz aufmachen
4087 SwHTMLAppendMode eMode = AM_NORMAL;
4088 switch( nToken )
4090 case HTML_LISTING_ON:
4091 case HTML_XMP_ON:
4092 // Diese beiden Tags werden jetzt auf die PRE-Vorlage gemappt.
4093 // Fuer dem Fall, dass ein CLASS angegeben ist, loeschen wir
4094 // es damit wir nicht die CLASS der PRE-Vorlage bekommen.
4095 aClass = aEmptyStr;
4096 case HTML_BLOCKQUOTE_ON:
4097 case HTML_BLOCKQUOTE30_ON:
4098 case HTML_PREFORMTXT_ON:
4099 eMode = AM_SPACE;
4100 break;
4101 case HTML_ADDRESS_ON:
4102 eMode = AM_NOSPACE; // ADDRESS kann auf einen <P> ohne </P> folgen
4103 break;
4104 case HTML_DT_ON:
4105 case HTML_DD_ON:
4106 eMode = AM_SOFTNOSPACE;
4107 break;
4108 default:
4109 ASSERT( !this, "unbekannte Vorlage" );
4110 break;
4112 if( pPam->GetPoint()->nContent.GetIndex() )
4113 AppendTxtNode( eMode );
4114 else if( AM_SPACE==eMode )
4115 AddParSpace();
4117 // ... und in einem Kontext merken
4118 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken), nColl, aClass );
4120 // Styles parsen (zu Class siehe auch NewPara)
4121 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4123 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4124 SvxCSS1PropertyInfo aPropInfo;
4126 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4128 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4129 "Class wird nicht beruecksichtigt" );
4130 DoPositioning( aItemSet, aPropInfo, pCntxt );
4131 InsertAttrs( aItemSet, aPropInfo, pCntxt );
4135 PushContext( pCntxt );
4137 // die neue Vorlage setzen
4138 SetTxtCollAttrs( pCntxt );
4140 // Laufbalkenanzeige aktualisieren
4141 ShowStatline();
4144 void SwHTMLParser::EndTxtFmtColl( int nToken )
4146 SwHTMLAppendMode eMode = AM_NORMAL;
4147 switch( nToken & ~1 )
4149 case HTML_BLOCKQUOTE_ON:
4150 case HTML_BLOCKQUOTE30_ON:
4151 case HTML_PREFORMTXT_ON:
4152 case HTML_LISTING_ON:
4153 case HTML_XMP_ON:
4154 eMode = AM_SPACE;
4155 break;
4156 case HTML_ADDRESS_ON:
4157 case HTML_DT_ON:
4158 case HTML_DD_ON:
4159 eMode = AM_SOFTNOSPACE;
4160 break;
4161 default:
4162 ASSERT( !this, "unbekannte Vorlage" );
4163 break;
4165 if( pPam->GetPoint()->nContent.GetIndex() )
4166 AppendTxtNode( eMode );
4167 else if( AM_SPACE==eMode )
4168 AddParSpace();
4170 // den aktuellen Kontext vom Stack holen
4171 _HTMLAttrContext *pCntxt = PopContext( static_cast< sal_uInt16 >(nToken & ~1) );
4173 // und noch Attribute beenden
4174 if( pCntxt )
4176 EndContext( pCntxt );
4177 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4178 delete pCntxt;
4181 // und die bisherige Vorlage setzen
4182 SetTxtCollAttrs();
4185 /* \f */
4187 void SwHTMLParser::NewDefList()
4189 String aId, aStyle, aClass, aLang, aDir;
4191 const HTMLOptions *pHTMLOptions = GetOptions();
4192 for( USHORT i = pHTMLOptions->Count(); i; )
4194 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4195 switch( pOption->GetToken() )
4197 case HTML_O_ID:
4198 aId = pOption->GetString();
4199 break;
4200 case HTML_O_STYLE:
4201 aStyle = pOption->GetString();
4202 break;
4203 case HTML_O_CLASS:
4204 aClass = pOption->GetString();
4205 break;
4206 case HTML_O_LANG:
4207 aLang = pOption->GetString();
4208 break;
4209 case HTML_O_DIR:
4210 aDir = pOption->GetString();
4211 break;
4215 // einen neuen Absatz aufmachen
4216 BOOL bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 0;
4217 if( pPam->GetPoint()->nContent.GetIndex() )
4218 AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4219 else if( bSpace )
4220 AddParSpace();
4222 // ein Level mehr
4223 nDefListDeep++;
4226 BOOL bInDD = FALSE, bNotInDD = FALSE;
4227 USHORT nPos = aContexts.Count();
4228 while( !bInDD && !bNotInDD && nPos>nContextStMin )
4230 USHORT nCntxtToken = aContexts[--nPos]->GetToken();
4231 switch( nCntxtToken )
4233 case HTML_DEFLIST_ON:
4234 case HTML_DIRLIST_ON:
4235 case HTML_MENULIST_ON:
4236 case HTML_ORDERLIST_ON:
4237 case HTML_UNORDERLIST_ON:
4238 bNotInDD = TRUE;
4239 break;
4240 case HTML_DD_ON:
4241 bInDD = TRUE;
4242 break;
4247 // ... und in einem Kontext merken
4248 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_DEFLIST_ON );
4250 // darin auch die Raender merken
4251 sal_uInt16 nLeft=0, nRight=0;
4252 short nIndent=0;
4253 GetMarginsFromContext( nLeft, nRight, nIndent );
4255 // Die Einrueckung, die sich schon aus einem DL-ergibt, entspricht der
4256 // eines DT auf dem aktuellen Level, und die entspricht der eines
4257 // DD auf dem Level davor. Fue einen Level >=2 muss also ein DD-Abstand
4258 // hinzugefuegt werden
4259 if( !bInDD && nDefListDeep > 1 )
4262 // und den der DT-Vorlage des aktuellen Levels
4263 SvxLRSpaceItem rLRSpace =
4264 pCSS1Parser->GetTxtFmtColl( RES_POOLCOLL_HTML_DD, aEmptyStr )
4265 ->GetLRSpace();
4266 nLeft = nLeft + static_cast< sal_uInt16 >(rLRSpace.GetTxtLeft());
4269 pCntxt->SetMargins( nLeft, nRight, nIndent );
4271 // Styles parsen
4272 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
4274 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4275 SvxCSS1PropertyInfo aPropInfo;
4277 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo, &aLang, &aDir ) )
4279 DoPositioning( aItemSet, aPropInfo, pCntxt );
4280 InsertAttrs( aItemSet, aPropInfo, pCntxt );
4284 PushContext( pCntxt );
4286 // die Attribute der neuen Vorlage setzen
4287 if( nDefListDeep > 1 )
4288 SetTxtCollAttrs( pCntxt );
4291 void SwHTMLParser::EndDefList()
4293 BOOL bSpace = (GetNumInfo().GetDepth() + nDefListDeep) == 1;
4294 if( pPam->GetPoint()->nContent.GetIndex() )
4295 AppendTxtNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE );
4296 else if( bSpace )
4297 AddParSpace();
4299 // ein Level weniger
4300 if( nDefListDeep > 0 )
4301 nDefListDeep--;
4303 // den aktuellen Kontext vom Stack holen
4304 _HTMLAttrContext *pCntxt = PopContext( HTML_DEFLIST_ON );
4306 // und noch Attribute beenden
4307 if( pCntxt )
4309 EndContext( pCntxt );
4310 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4311 delete pCntxt;
4314 // und Vorlage setzen
4315 SetTxtCollAttrs();
4318 void SwHTMLParser::NewDefListItem( int nToken )
4320 // festellen, ob das DD/DT in einer DL vorkommt
4321 BOOL bInDefList = FALSE, bNotInDefList = FALSE;
4322 USHORT nPos = aContexts.Count();
4323 while( !bInDefList && !bNotInDefList && nPos>nContextStMin )
4325 USHORT nCntxtToken = aContexts[--nPos]->GetToken();
4326 switch( nCntxtToken )
4328 case HTML_DEFLIST_ON:
4329 bInDefList = TRUE;
4330 break;
4331 case HTML_DIRLIST_ON:
4332 case HTML_MENULIST_ON:
4333 case HTML_ORDERLIST_ON:
4334 case HTML_UNORDERLIST_ON:
4335 bNotInDefList = TRUE;
4336 break;
4340 // wenn nicht, implizit eine neue DL aufmachen
4341 if( !bInDefList )
4343 nDefListDeep++;
4344 ASSERT( !nOpenParaToken,
4345 "Jetzt geht ein offenes Absatz-Element verloren" );
4346 nOpenParaToken = static_cast< sal_uInt16 >(nToken);
4349 NewTxtFmtColl( nToken, static_cast< USHORT >(nToken==HTML_DD_ON ? RES_POOLCOLL_HTML_DD
4350 : RES_POOLCOLL_HTML_DT) );
4353 void SwHTMLParser::EndDefListItem( int nToken, BOOL bSetColl,
4354 BOOL /*bLastPara*/ )
4356 // einen neuen Absatz aufmachen
4357 if( !nToken && pPam->GetPoint()->nContent.GetIndex() )
4358 AppendTxtNode( AM_SOFTNOSPACE );
4360 // Kontext zu dem Token suchen und vom Stack holen
4361 nToken &= ~1;
4362 _HTMLAttrContext *pCntxt = 0;
4363 USHORT nPos = aContexts.Count();
4364 while( !pCntxt && nPos>nContextStMin )
4366 USHORT nCntxtToken = aContexts[--nPos]->GetToken();
4367 switch( nCntxtToken )
4369 case HTML_DD_ON:
4370 case HTML_DT_ON:
4371 if( !nToken || nToken == nCntxtToken )
4373 pCntxt = aContexts[nPos];
4374 aContexts.Remove( nPos, 1 );
4376 break;
4377 case HTML_DEFLIST_ON:
4378 // keine DD/DT ausserhalb der aktuelen DefListe betrachten
4379 case HTML_DIRLIST_ON:
4380 case HTML_MENULIST_ON:
4381 case HTML_ORDERLIST_ON:
4382 case HTML_UNORDERLIST_ON:
4383 // und auch nicht ausserhalb einer anderen Liste
4384 nPos = nContextStMin;
4385 break;
4389 // und noch Attribute beenden
4390 if( pCntxt )
4392 EndContext( pCntxt );
4393 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
4394 delete pCntxt;
4397 // und die bisherige Vorlage setzen
4398 if( bSetColl )
4399 SetTxtCollAttrs();
4402 /* \f */
4404 BOOL SwHTMLParser::HasCurrentParaFlys( BOOL bNoSurroundOnly,
4405 BOOL bSurroundOnly ) const
4407 // bNoSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
4408 // ohne Umlauf
4409 // bSurroundOnly: Der Absatz enthaelt mindestens einen Rahmen
4410 // mit Umlauf aber keinen ohne Umlauf
4411 // sonst: Der Absatz enthaelt irgendeinen Rahmen
4412 SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
4414 SwFrmFmt* pFmt;
4415 const SwFmtAnchor* pAnchor;
4416 const SwPosition* pAPos;
4417 const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
4419 USHORT i;
4420 BOOL bFound = FALSE;
4421 for( i=0; i<rFrmFmtTbl.Count(); i++ )
4423 pFmt = rFrmFmtTbl[i];
4424 pAnchor = &pFmt->GetAnchor();
4425 // Ein Rahmen wurde gefunden, wenn
4426 // - er absatzgebunden ist, und
4427 // - im aktuellen Absatz verankert ist, und
4428 // - jeder absatzgebunene Rahmen zaehlt, oder
4429 // - (nur Rahmen oder umlauf zaehlen und ) der Rahmen keinen
4430 // Umlauf besitzt
4432 if( 0 != ( pAPos = pAnchor->GetCntntAnchor()) &&
4433 (FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
4434 FLY_AUTO_CNTNT == pAnchor->GetAnchorId()) &&
4435 pAPos->nNode == rNodeIdx )
4437 if( !(bNoSurroundOnly || bSurroundOnly) )
4439 bFound = TRUE;
4440 break;
4442 else
4444 // fix #42282#: Wenn Rahmen mit Umlauf gesucht sind,
4445 // auch keine mit Durchlauf beachten. Dabei handelt es
4446 // sich (noch) um HIDDEN-Controls, und denen weicht man
4447 // besser auch nicht aus.
4448 SwSurround eSurround = pFmt->GetSurround().GetSurround();
4449 if( bNoSurroundOnly )
4451 if( SURROUND_NONE==eSurround )
4453 bFound = TRUE;
4454 break;
4457 if( bSurroundOnly )
4459 if( SURROUND_NONE==eSurround )
4461 bFound = FALSE;
4462 break;
4464 else if( SURROUND_THROUGHT!=eSurround )
4466 bFound = TRUE;
4467 // weitersuchen: Es koennten ja noch welche ohne
4468 // Umlauf kommen ...
4475 return bFound;
4478 /* \f */
4480 // die speziellen Methoden zum Einfuegen von Objecten
4482 const SwFmtColl *SwHTMLParser::GetCurrFmtColl() const
4484 const SwCntntNode* pCNd = pPam->GetCntntNode();
4485 return &pCNd->GetAnyFmtColl();
4489 void SwHTMLParser::SetTxtCollAttrs( _HTMLAttrContext *pContext )
4491 SwTxtFmtColl *pCollToSet = 0; // die zu setzende Vorlage
4492 SfxItemSet *pItemSet = 0; // der Set fuer harte Attrs
4493 USHORT nTopColl = pContext ? pContext->GetTxtFmtColl() : 0;
4494 const String& rTopClass = pContext ? pContext->GetClass() : (const String&) aEmptyStr;
4495 USHORT nDfltColl = RES_POOLCOLL_TEXT;
4497 BOOL bInPRE=FALSE; // etwas Kontext Info
4499 USHORT nLeftMargin = 0, nRightMargin = 0; // die Einzuege und
4500 short nFirstLineIndent = 0; // Abstaende
4501 USHORT i;
4503 for( i = nContextStAttrMin; i < aContexts.Count(); i++ )
4505 const _HTMLAttrContext *pCntxt = aContexts[i];
4507 USHORT nColl = pCntxt->GetTxtFmtColl();
4508 if( nColl )
4510 // Es gibt eine Vorlage, die zu setzen ist. Dann
4511 // muss zunaechst einmal entschieden werden,
4512 // ob die Vorlage auch gesetzt werden kann
4513 BOOL bSetThis = TRUE;
4514 switch( nColl )
4516 case USHORT(RES_POOLCOLL_HTML_PRE):
4517 bInPRE = TRUE;
4518 break;
4519 case USHORT(RES_POOLCOLL_TEXT):
4520 // <TD><P CLASS=xxx> muss TD.xxx werden
4521 if( nDfltColl==RES_POOLCOLL_TABLE ||
4522 nDfltColl==RES_POOLCOLL_TABLE_HDLN )
4523 nColl = nDfltColl;
4524 break;
4525 case USHORT(RES_POOLCOLL_HTML_HR):
4526 // <HR> auch in <PRE> als Vorlage setzen, sonst kann man sie
4527 // nicht mehr exportieren
4528 break;
4529 default:
4530 if( bInPRE )
4531 bSetThis = FALSE;
4532 break;
4535 SwTxtFmtColl *pNewColl =
4536 pCSS1Parser->GetTxtFmtColl( nColl, pCntxt->GetClass() );
4538 if( bSetThis )
4540 // wenn jetzt eine andere Vorlage gesetzt werden soll als
4541 // bisher, muss die bishere Vorlage durch harte Attributierung
4542 // ersetzt werden
4544 if( pCollToSet )
4546 // die Attribute, die die bisherige Vorlage setzt
4547 // hart einfuegen
4548 if( !pItemSet )
4549 pItemSet = new SfxItemSet( pCollToSet->GetAttrSet() );
4550 else
4552 const SfxItemSet& rCollSet = pCollToSet->GetAttrSet();
4553 SfxItemSet aItemSet( *rCollSet.GetPool(),
4554 rCollSet.GetRanges() );
4555 aItemSet.Set( rCollSet );
4556 pItemSet->Put( aItemSet );
4558 // aber die Attribute, die aktuelle Vorlage setzt
4559 // entfernen, weil sie sonst spaeter ueberschrieben
4560 // werden
4561 pItemSet->Differentiate( pNewColl->GetAttrSet() );
4564 pCollToSet = pNewColl;
4566 else
4568 // hart Attributieren
4569 if( !pItemSet )
4570 pItemSet = new SfxItemSet( pNewColl->GetAttrSet() );
4571 else
4573 const SfxItemSet& rCollSet = pNewColl->GetAttrSet();
4574 SfxItemSet aItemSet( *rCollSet.GetPool(),
4575 rCollSet.GetRanges() );
4576 aItemSet.Set( rCollSet );
4577 pItemSet->Put( aItemSet );
4581 else
4583 // vielliecht gibt es ja eine Default-Vorlage?
4584 nColl = pCntxt->GetDfltTxtFmtColl();
4585 if( nColl )
4586 nDfltColl = nColl;
4589 // ggf. neue Absatz-Einzuege holen
4590 if( pCntxt->IsLRSpaceChanged() )
4592 USHORT nLeft=0, nRight=0;
4594 pCntxt->GetMargins( nLeft, nRight, nFirstLineIndent );
4595 nLeftMargin = nLeft;
4596 nRightMargin = nRight;
4600 // wenn im aktuellen Kontext eine neue Vorlage gesetzt werden soll,
4601 // muessen deren Absatz-Abstaende noch in den Kontext eingetragen werden
4602 if( pContext && nTopColl )
4604 // <TD><P CLASS=xxx> muss TD.xxx werden
4605 if( nTopColl==RES_POOLCOLL_TEXT &&
4606 (nDfltColl==RES_POOLCOLL_TABLE ||
4607 nDfltColl==RES_POOLCOLL_TABLE_HDLN) )
4608 nTopColl = nDfltColl;
4610 const SwTxtFmtColl *pTopColl =
4611 pCSS1Parser->GetTxtFmtColl( nTopColl, rTopClass );
4612 const SfxItemSet& rItemSet = pTopColl->GetAttrSet();
4613 const SfxPoolItem *pItem;
4614 if( SFX_ITEM_SET == rItemSet.GetItemState(RES_LR_SPACE,TRUE, &pItem) )
4616 const SvxLRSpaceItem *pLRItem =
4617 (const SvxLRSpaceItem *)pItem;
4619 sal_Int32 nLeft = pLRItem->GetTxtLeft();
4620 sal_Int32 nRight = pLRItem->GetRight();
4621 nFirstLineIndent = pLRItem->GetTxtFirstLineOfst();
4623 // In Definitions-Listen enthalten die Abstaende auch die der
4624 // vorhergehenden Level
4625 if( RES_POOLCOLL_HTML_DD == nTopColl )
4627 const SvxLRSpaceItem& rDTLRSpace = pCSS1Parser
4628 ->GetTxtFmtColl( RES_POOLCOLL_HTML_DT, aEmptyStr )
4629 ->GetLRSpace();
4630 nLeft -= rDTLRSpace.GetTxtLeft();
4631 nRight -= rDTLRSpace.GetRight();
4633 else if( RES_POOLCOLL_HTML_DT == nTopColl )
4635 nLeft = 0;
4636 nRight = 0;
4639 // die Absatz-Abstaende addieren sich
4640 nLeftMargin = nLeftMargin + static_cast< sal_uInt16 >(nLeft);
4641 nRightMargin = nRightMargin + static_cast< sal_uInt16 >(nRight);
4643 pContext->SetMargins( nLeftMargin, nRightMargin,
4644 nFirstLineIndent );
4646 if( SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,TRUE, &pItem) )
4648 const SvxULSpaceItem *pULItem =
4649 (const SvxULSpaceItem *)pItem;
4650 pContext->SetULSpace( pULItem->GetUpper(), pULItem->GetLower() );
4654 // wenn gar keine Vorlage im Kontext gesetzt ist, Textkoerper nehmen
4655 if( !pCollToSet )
4657 pCollToSet = pCSS1Parser->GetTxtCollFromPool( nDfltColl );
4658 const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4659 if( !nLeftMargin )
4660 nLeftMargin = static_cast< sal_uInt16 >(rLRItem.GetTxtLeft());
4661 if( !nRightMargin )
4662 nRightMargin = static_cast< sal_uInt16 >(rLRItem.GetRight());
4663 if( !nFirstLineIndent )
4664 nFirstLineIndent = rLRItem.GetTxtFirstLineOfst();
4667 // bisherige harte Attributierung des Absatzes entfernen
4668 if( aParaAttrs.Count() )
4670 for( i=0; i<aParaAttrs.Count(); i++ )
4671 aParaAttrs[i]->Invalidate();
4673 aParaAttrs.Remove( 0, aParaAttrs.Count() );
4676 // Die Vorlage setzen
4677 pDoc->SetTxtFmtColl( *pPam, pCollToSet );
4679 // ggf. noch den Absatz-Einzug korrigieren
4680 const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace();
4681 BOOL bSetLRSpace;
4683 bSetLRSpace = nLeftMargin != rLRItem.GetTxtLeft() ||
4684 nFirstLineIndent != rLRItem.GetTxtFirstLineOfst() ||
4685 nRightMargin != rLRItem.GetRight();
4687 if( bSetLRSpace )
4689 SvxLRSpaceItem aLRItem( rLRItem );
4690 aLRItem.SetTxtLeft( nLeftMargin );
4691 aLRItem.SetRight( nRightMargin );
4692 aLRItem.SetTxtFirstLineOfst( nFirstLineIndent );
4693 if( pItemSet )
4694 pItemSet->Put( aLRItem );
4695 else
4697 NewAttr( &aAttrTab.pLRSpace, aLRItem );
4698 aAttrTab.pLRSpace->SetLikePara();
4699 aParaAttrs.Insert( aAttrTab.pLRSpace, aParaAttrs.Count() );
4700 EndAttr( aAttrTab.pLRSpace, 0, FALSE );
4704 // und nun noch die Attribute setzen
4705 if( pItemSet )
4707 InsertParaAttrs( *pItemSet );
4708 delete pItemSet;
4712 /* \f */
4714 void SwHTMLParser::NewCharFmt( int nToken )
4716 String aId, aStyle, aClass, aLang, aDir;
4718 const HTMLOptions *pHTMLOptions = GetOptions();
4719 for( USHORT i = pHTMLOptions->Count(); i; )
4721 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4722 switch( pOption->GetToken() )
4724 case HTML_O_ID:
4725 aId = pOption->GetString();
4726 break;
4727 case HTML_O_STYLE:
4728 aStyle = pOption->GetString();
4729 break;
4730 case HTML_O_CLASS:
4731 aClass = pOption->GetString();
4732 break;
4733 case HTML_O_LANG:
4734 aLang = pOption->GetString();
4735 break;
4736 case HTML_O_DIR:
4737 aDir = pOption->GetString();
4738 break;
4742 // einen neuen Kontext anlegen
4743 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
4745 // die Vorlage setzen und im Kontext merken
4746 SwCharFmt* pCFmt = pCSS1Parser->GetChrFmt( static_cast< sal_uInt16 >(nToken), aClass );
4747 ASSERT( pCFmt, "keine Zeichenvorlage zu Token gefunden" );
4750 // Styles parsen (zu Class siehe auch NewPara)
4751 if( HasStyleOptions( aStyle, aId, aEmptyStr, &aLang, &aDir ) )
4753 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
4754 SvxCSS1PropertyInfo aPropInfo;
4756 if( ParseStyleOptions( aStyle, aId, aEmptyStr, aItemSet, aPropInfo, &aLang, &aDir ) )
4758 ASSERT( !aClass.Len() || !pCSS1Parser->GetClass( aClass ),
4759 "Class wird nicht beruecksichtigt" );
4760 DoPositioning( aItemSet, aPropInfo, pCntxt );
4761 InsertAttrs( aItemSet, aPropInfo, pCntxt, TRUE );
4765 // Zeichen-Vorlagen werden in einem eigenen Stack gehalten und
4766 // koennen nie durch Styles eingefuegt werden. Das Attribut ist deshalb
4767 // auch gar nicht im CSS1-Which-Range enthalten
4768 if( pCFmt )
4769 InsertAttr( &aAttrTab.pCharFmts, SwFmtCharFmt( pCFmt ), pCntxt );
4771 // den Kontext merken
4772 PushContext( pCntxt );
4776 /* \f */
4778 void SwHTMLParser::InsertSpacer()
4780 // und es ggf. durch die Optionen veraendern
4781 String aId;
4782 sal_Int16 eVertOri = text::VertOrientation::TOP;
4783 sal_Int16 eHoriOri = text::HoriOrientation::NONE;
4784 Size aSize( 0, 0);
4785 long nSize = 0;
4786 BOOL bPrcWidth = FALSE;
4787 BOOL bPrcHeight = FALSE;
4788 USHORT nType = HTML_SPTYPE_HORI;
4790 const HTMLOptions *pHTMLOptions = GetOptions();
4791 for( USHORT i = pHTMLOptions->Count(); i; )
4793 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4794 switch( pOption->GetToken() )
4796 case HTML_O_ID:
4797 aId = pOption->GetString();
4798 break;
4799 case HTML_O_TYPE:
4800 pOption->GetEnum( nType, aHTMLSpacerTypeTable );
4801 break;
4802 case HTML_O_ALIGN:
4803 eVertOri =
4804 pOption->GetEnum( aHTMLImgVAlignTable,
4805 eVertOri );
4806 eHoriOri =
4807 pOption->GetEnum( aHTMLImgHAlignTable,
4808 eHoriOri );
4809 break;
4810 case HTML_O_WIDTH:
4811 // erstmal nur als Pixelwerte merken!
4812 bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4813 aSize.Width() = (long)pOption->GetNumber();
4814 break;
4815 case HTML_O_HEIGHT:
4816 // erstmal nur als Pixelwerte merken!
4817 bPrcHeight = (pOption->GetString().Search('%') != STRING_NOTFOUND);
4818 aSize.Height() = (long)pOption->GetNumber();
4819 break;
4820 case HTML_O_SIZE:
4821 // erstmal nur als Pixelwerte merken!
4822 nSize = pOption->GetNumber();
4823 break;
4827 switch( nType )
4829 case HTML_SPTYPE_BLOCK:
4831 // einen leeren Textrahmen anlegen
4833 // den Itemset holen
4834 SfxItemSet aFrmSet( pDoc->GetAttrPool(),
4835 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
4836 if( !IsNewDoc() )
4837 Reader::ResetFrmFmtAttrs( aFrmSet );
4839 // den Anker und die Ausrichtung setzen
4840 SetAnchorAndAdjustment( eVertOri, eHoriOri, aFrmSet );
4842 // und noch die Groesse des Rahmens
4843 Size aDfltSz( MINFLY, MINFLY );
4844 Size aSpace( 0, 0 );
4845 SfxItemSet aDummyItemSet( pDoc->GetAttrPool(),
4846 pCSS1Parser->GetWhichMap() );
4847 SvxCSS1PropertyInfo aDummyPropInfo;
4849 SetFixSize( aSize, aDfltSz, bPrcWidth, bPrcHeight,
4850 aDummyItemSet, aDummyPropInfo, aFrmSet );
4851 SetSpace( aSpace, aDummyItemSet, aDummyPropInfo, aFrmSet );
4853 // den Inhalt schuetzen
4854 SvxProtectItem aProtectItem( RES_PROTECT) ;
4855 aProtectItem.SetCntntProtect( TRUE );
4856 aFrmSet.Put( aProtectItem );
4858 // der Rahmen anlegen
4859 RndStdIds eAnchorId =
4860 ((const SwFmtAnchor &)aFrmSet.Get(RES_ANCHOR)).GetAnchorId();
4861 SwFrmFmt *pFlyFmt = pDoc->MakeFlySection( eAnchorId,
4862 pPam->GetPoint(), &aFrmSet );
4863 // Ggf Frames anlegen und auto-geb. Rahmen registrieren
4864 RegisterFlyFrm( pFlyFmt );
4866 break;
4867 case HTML_SPTYPE_VERT:
4868 if( nSize > 0 )
4870 if( nSize && Application::GetDefaultDevice() )
4872 nSize = Application::GetDefaultDevice()
4873 ->PixelToLogic( Size(0,nSize),
4874 MapMode(MAP_TWIP) ).Height();
4877 // einen Absatz-Abstand setzen
4878 SwTxtNode *pTxtNode = 0;
4879 if( !pPam->GetPoint()->nContent.GetIndex() )
4881 // den unteren Absatz-Abstand des vorherigen Nodes aendern,
4882 // wenn moeglich
4884 SetAttr(); // noch offene Absatz-Attribute setzen
4886 pTxtNode = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()-1]
4887 ->GetTxtNode();
4889 // Wenn der Abstz davor kein Txtenode ist, dann wird jetzt
4890 // ein leere Absatz angelegt, der eh schon eine Zeilenhoehe
4891 // Abstand erzeugt.
4892 if( !pTxtNode )
4893 nSize = nSize>HTML_PARSPACE ? nSize-HTML_PARSPACE : 0;
4896 if( pTxtNode )
4898 SvxULSpaceItem aULSpace( (const SvxULSpaceItem&)pTxtNode
4899 ->SwCntntNode::GetAttr( RES_UL_SPACE ) );
4900 aULSpace.SetLower( aULSpace.GetLower() + (USHORT)nSize );
4901 pTxtNode->SetAttr( aULSpace );
4903 else
4905 NewAttr( &aAttrTab.pULSpace, SvxULSpaceItem( 0, (USHORT)nSize, RES_UL_SPACE ) );
4906 EndAttr( aAttrTab.pULSpace, 0, FALSE );
4908 AppendTxtNode(); // nicht am Abstand drehen!
4911 break;
4912 case HTML_SPTYPE_HORI:
4913 if( nSize > 0 )
4915 // wenn der Absatz noch leer ist, einen Erstzeilen-Einzug
4916 // setzen, sondern Sperrschrift ueber einem Space aufspannen
4918 if( nSize && Application::GetDefaultDevice() )
4920 nSize = Application::GetDefaultDevice()
4921 ->PixelToLogic( Size(nSize,0),
4922 MapMode(MAP_TWIP) ).Width();
4925 if( !pPam->GetPoint()->nContent.GetIndex() )
4927 USHORT nLeft=0, nRight=0;
4928 short nIndent = 0;
4930 GetMarginsFromContextWithNumBul( nLeft, nRight, nIndent );
4931 nIndent = nIndent + (short)nSize;
4933 SvxLRSpaceItem aLRItem( RES_LR_SPACE );
4934 aLRItem.SetTxtLeft( nLeft );
4935 aLRItem.SetRight( nRight );
4936 aLRItem.SetTxtFirstLineOfst( nIndent );
4938 NewAttr( &aAttrTab.pLRSpace, aLRItem );
4939 EndAttr( aAttrTab.pLRSpace, 0, FALSE );
4941 else
4943 NewAttr( &aAttrTab.pKerning, SvxKerningItem( (short)nSize, RES_CHRATR_KERNING ) );
4944 String aTmp( ' ' );
4945 pDoc->InsertString( *pPam, aTmp );
4946 EndAttr( aAttrTab.pKerning );
4952 USHORT SwHTMLParser::ToTwips( USHORT nPixel ) const
4954 if( nPixel && Application::GetDefaultDevice() )
4956 long nTwips = Application::GetDefaultDevice()->PixelToLogic(
4957 Size( nPixel, nPixel ), MapMode( MAP_TWIP ) ).Width();
4958 return nTwips <= USHRT_MAX ? (USHORT)nTwips : USHRT_MAX;
4960 else
4961 return nPixel;
4964 SwTwips SwHTMLParser::GetCurrentBrowseWidth()
4966 SwTwips nWidth = SwHTMLTableLayout::GetBrowseWidth( *pDoc );
4967 if( nWidth )
4968 return nWidth;
4970 if( !aHTMLPageSize.Width() )
4972 const SwFrmFmt& rPgFmt = pCSS1Parser->GetMasterPageDesc()->GetMaster();
4974 const SwFmtFrmSize& rSz = rPgFmt.GetFrmSize();
4975 const SvxLRSpaceItem& rLR = rPgFmt.GetLRSpace();
4976 const SvxULSpaceItem& rUL = rPgFmt.GetULSpace();
4977 const SwFmtCol& rCol = rPgFmt.GetCol();
4979 aHTMLPageSize.Width() = rSz.GetWidth() - rLR.GetLeft() - rLR.GetRight();
4980 aHTMLPageSize.Height() = rSz.GetHeight() - rUL.GetUpper() - rUL.GetLower();
4982 if( 1 < rCol.GetNumCols() )
4983 aHTMLPageSize.Width() /= rCol.GetNumCols();
4986 return aHTMLPageSize.Width();
4990 /* \f */
4992 void SwHTMLParser::InsertIDOption()
4994 String aId;
4995 const HTMLOptions *pHTMLOptions = GetOptions();
4996 for( USHORT i = pHTMLOptions->Count(); i; )
4998 const HTMLOption *pOption = (*pHTMLOptions)[--i];
4999 if( HTML_O_ID==pOption->GetToken() )
5001 aId = pOption->GetString();
5002 break;
5006 if( aId.Len() )
5007 InsertBookmark( aId );
5011 /* \f */
5014 void SwHTMLParser::InsertLineBreak()
5016 // <BR CLEAR=xxx> wird wie folgt behandelt:
5017 // 1.) Es werden nur nur absatzgebundene Rahmen betrachtet, die
5018 // im aktuellen Absatz verankert sind.
5019 // 2.) Fuer linksbuendig ausgerichtete Rahmen wird bei CLEAR=LEFT
5020 // oder ALL und auf rechtsbuendige ausgerichtete Rahmen bei
5021 // CLEAR=RIGHT oder ALL der Durchlauf wie folgt geaendert:
5022 // 3.) Wenn der Absatz keinen Text enthaelt, bekommt der Rahmen keinen
5023 // Umlauf
5024 // 4.) sonst erhaelt ein links ausgerichteter Rahmen eine rechten
5025 // "nur Anker" Umlauf und recht rechst ausg. Rahmen einen linken
5026 // "nur Anker" Umlauf.
5027 // 5.) wenn in einem nicht-leeren Absatz der Umlauf eines Rahmens
5028 // geaendert wird, wird ein neuer Absatz aufgemacht
5029 // 6.) Wenn von keinem Rahmen der Umlauf geaendert wird, wird ein
5030 // harter Zeilenumbruch eingefuegt
5032 String aId, aStyle, aClass; // die ID der Bookmark
5033 BOOL bClearLeft = FALSE, bClearRight = FALSE;
5034 BOOL bCleared = FALSE; // wurde ein CLEAR ausgefuehrt?
5036 // dann holen wir mal die Optionen
5037 const HTMLOptions *pHTMLOptions = GetOptions();
5038 for( USHORT i = pHTMLOptions->Count(); i; )
5040 const HTMLOption *pOption = (*pHTMLOptions)[--i];
5041 switch( pOption->GetToken() )
5043 case HTML_O_CLEAR:
5045 const String &aClear = pOption->GetString();
5046 if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_all ) )
5048 bClearLeft = TRUE;
5049 bClearRight = TRUE;
5051 else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_left ) )
5052 bClearLeft = TRUE;
5053 else if( aClear.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) )
5054 bClearRight = TRUE;
5056 break;
5057 case HTML_O_ID:
5058 aId = pOption->GetString();
5059 break;
5060 case HTML_O_STYLE:
5061 aStyle = pOption->GetString();
5062 break;
5063 case HTML_O_CLASS:
5064 aClass = pOption->GetString();
5065 break;
5069 // CLEAR wird nur fuer den aktuellen Absaetz unterstuetzt
5070 if( bClearLeft || bClearRight )
5072 SwNodeIndex& rNodeIdx = pPam->GetPoint()->nNode;
5073 SwTxtNode* pTxtNd = rNodeIdx.GetNode().GetTxtNode();
5074 if( pTxtNd )
5076 SwFrmFmt* pFmt;
5077 const SwFmtAnchor* pAnchor;
5078 const SwPosition* pAPos;
5079 const SwSpzFrmFmts& rFrmFmtTbl = *pDoc->GetSpzFrmFmts();
5081 for( USHORT i=0; i<rFrmFmtTbl.Count(); i++ )
5083 pFmt = rFrmFmtTbl[i];
5084 pAnchor = &pFmt->GetAnchor();
5085 if( 0 != ( pAPos = pAnchor->GetCntntAnchor()) &&
5086 (FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
5087 FLY_AUTO_CNTNT == pAnchor->GetAnchorId()) &&
5088 pAPos->nNode == rNodeIdx &&
5089 pFmt->GetSurround().GetSurround() != SURROUND_NONE )
5091 sal_Int16 eHori = RES_DRAWFRMFMT == pFmt->Which()
5092 ? text::HoriOrientation::LEFT
5093 : pFmt->GetHoriOrient().GetHoriOrient();
5095 SwSurround eSurround = SURROUND_PARALLEL;
5096 if( pPam->GetPoint()->nContent.GetIndex() )
5098 if( bClearLeft && text::HoriOrientation::LEFT==eHori )
5099 eSurround = SURROUND_RIGHT;
5100 else if( bClearRight && text::HoriOrientation::RIGHT==eHori )
5101 eSurround = SURROUND_LEFT;
5103 else if( (bClearLeft && text::HoriOrientation::LEFT==eHori) ||
5104 (bClearRight && text::HoriOrientation::RIGHT==eHori) )
5106 eSurround = SURROUND_NONE;
5109 if( SURROUND_PARALLEL != eSurround )
5111 SwFmtSurround aSurround( eSurround );
5112 if( SURROUND_NONE != eSurround )
5113 aSurround.SetAnchorOnly( TRUE );
5114 pFmt->SetFmtAttr( aSurround );
5115 bCleared = TRUE;
5117 } // Anker ist nicht im Node
5118 } // Schleife ueber Fly-Frames
5119 } // kein Text-Node
5120 } // kein CLEAR
5122 // Styles parsen
5123 SvxFmtBreakItem aBreakItem( SVX_BREAK_NONE, RES_BREAK );
5124 BOOL bBreakItem = FALSE;
5125 if( HasStyleOptions( aStyle, aId, aClass ) )
5127 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
5128 SvxCSS1PropertyInfo aPropInfo;
5130 if( ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ) )
5132 if( pCSS1Parser->SetFmtBreak( aItemSet, aPropInfo ) )
5134 aBreakItem = (const SvxFmtBreakItem &)aItemSet.Get( RES_BREAK );
5135 bBreakItem = TRUE;
5137 if( aPropInfo.aId.Len() )
5138 InsertBookmark( aPropInfo.aId );
5142 if( bBreakItem && SVX_BREAK_PAGE_AFTER==aBreakItem.GetBreak() )
5144 NewAttr( &aAttrTab.pBreak, aBreakItem );
5145 EndAttr( aAttrTab.pBreak, 0, FALSE );
5148 if( !bCleared && !bBreakItem )
5150 // wenn kein CLEAR ausgefuehrt werden sollte oder konnte, wird
5151 // ein Zeilenumbruch eingef?gt
5152 String sTmp( (sal_Unicode)0x0a ); // make the Mac happy :-)
5153 pDoc->InsertString( *pPam, sTmp );
5155 else if( pPam->GetPoint()->nContent.GetIndex() )
5157 // wenn ein Claer in einem nicht-leeren Absatz ausgefuehrt wurde,
5158 // muss anschliessen ein neuer Absatz aufgemacht werden
5159 // MIB 21.02.97: Eigentlich muesste man hier den unteren Absatz-
5160 // Absatnd auf 0 drehen. Das geht aber bei sowas wie <BR ..><P>
5161 // schief (>Netacpe). Deshalb lassen wir das erstmal.
5162 AppendTxtNode( AM_NOSPACE );
5164 if( bBreakItem && SVX_BREAK_PAGE_BEFORE==aBreakItem.GetBreak() )
5166 NewAttr( &aAttrTab.pBreak, aBreakItem );
5167 EndAttr( aAttrTab.pBreak, 0, FALSE );
5171 void SwHTMLParser::InsertHorzRule()
5173 USHORT nSize = 0;
5174 USHORT nWidth = 0;
5176 SvxAdjust eAdjust = SVX_ADJUST_END;
5178 BOOL bPrcWidth = FALSE;
5179 BOOL bNoShade = FALSE;
5180 BOOL bColor = FALSE;
5182 Color aColor;
5183 String aId;
5185 // dann holen wir mal die Optionen
5186 const HTMLOptions *pHTMLOptions = GetOptions();
5187 for( USHORT i = pHTMLOptions->Count(); i; )
5189 const HTMLOption *pOption = (*pHTMLOptions)[--i];
5190 switch( pOption->GetToken() )
5192 case HTML_O_ID:
5193 aId = pOption->GetString();
5194 break;
5195 case HTML_O_SIZE:
5196 nSize = (USHORT)pOption->GetNumber();
5197 break;
5198 case HTML_O_WIDTH:
5199 bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
5200 nWidth = (USHORT)pOption->GetNumber();
5201 if( bPrcWidth && nWidth>=100 )
5203 // 100%-Linien sind der default-Fall (keine Attrs neotig)
5204 nWidth = 0;
5205 bPrcWidth = FALSE;
5207 break;
5208 case HTML_O_ALIGN:
5209 eAdjust =
5210 (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable, static_cast< sal_uInt16 >(eAdjust) );
5211 break;
5212 case HTML_O_NOSHADE:
5213 bNoShade = TRUE;
5214 break;
5215 case HTML_O_COLOR:
5216 pOption->GetColor( aColor );
5217 bColor = TRUE;
5218 break;
5222 if( pPam->GetPoint()->nContent.GetIndex() )
5223 AppendTxtNode( AM_NOSPACE );
5224 if( nOpenParaToken )
5225 EndPara();
5226 AppendTxtNode();
5227 pPam->Move( fnMoveBackward );
5229 // ... und in einem Kontext merken
5230 _HTMLAttrContext *pCntxt =
5231 new _HTMLAttrContext( HTML_HORZRULE, RES_POOLCOLL_HTML_HR, aEmptyStr );
5233 PushContext( pCntxt );
5235 // die neue Vorlage setzen
5236 SetTxtCollAttrs( pCntxt );
5238 // die harten Attribute an diesem Absatz werden nie mehr ungueltig
5239 if( aParaAttrs.Count() )
5240 aParaAttrs.Remove( 0, aParaAttrs.Count() );
5242 if( nSize>0 || bColor || bNoShade )
5244 // Farbe und/oder Breite der Linie setzen
5245 if( !bColor )
5246 aColor.SetColor( COL_GRAY );
5248 SvxBorderLine aBorderLine( &aColor );
5249 if( nSize )
5251 long nPWidth = 0;
5252 long nPHeight = (long)nSize;
5253 SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
5254 SvxCSS1Parser::SetBorderWidth( aBorderLine, (USHORT)nPHeight,
5255 !bNoShade );
5257 else if( bNoShade )
5259 aBorderLine.SetOutWidth( DEF_LINE_WIDTH_2 );
5261 else
5263 aBorderLine.SetOutWidth( DEF_DOUBLE_LINE0_OUT );
5264 aBorderLine.SetInWidth( DEF_DOUBLE_LINE0_IN );
5265 aBorderLine.SetDistance( DEF_DOUBLE_LINE0_DIST );
5268 SvxBoxItem aBoxItem(RES_BOX);
5269 aBoxItem.SetLine( &aBorderLine, BOX_LINE_BOTTOM );
5270 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aBoxItem );
5271 aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5273 if( nWidth )
5275 // Wenn wir in keiner Tabelle sind, wird die Breitenangabe durch
5276 // Absatz-Einzuege "getuerkt". In einer Tabelle macht das wenig
5277 // Sinn. Um zu Vermeiden, dass die Linie bei der Breitenberechnung
5278 // beruecksichtigt wird, bekommt sie aber trotzdem entsprechendes
5279 // LRSpace-Item verpasst.
5280 #ifdef FIX41370
5281 const SwFmtColl *pColl = GetCurrFmtColl();
5282 SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5283 #endif
5284 if( !pTable )
5286 // Laenge und Ausrichtung der Linie ueber Absatz-Einzuege "tuerken"
5287 long nBrowseWidth = GetCurrentBrowseWidth();
5288 nWidth = bPrcWidth ? (USHORT)((nWidth*nBrowseWidth) / 100)
5289 : ToTwips( (USHORT)nBrowseWidth );
5290 if( nWidth < MINLAY )
5291 nWidth = MINLAY;
5293 if( (long)nWidth < nBrowseWidth )
5295 #ifndef FIX41370
5296 const SwFmtColl *pColl = GetCurrFmtColl();
5297 SvxLRSpaceItem aLRItem( pColl->GetLRSpace() );
5298 #endif
5299 long nDist = nBrowseWidth - nWidth;
5301 switch( eAdjust )
5303 case SVX_ADJUST_RIGHT:
5304 aLRItem.SetTxtLeft( (USHORT)nDist );
5305 break;
5306 case SVX_ADJUST_LEFT:
5307 aLRItem.SetRight( (USHORT)nDist );
5308 break;
5309 case SVX_ADJUST_CENTER:
5310 default:
5311 nDist /= 2;
5312 aLRItem.SetTxtLeft( (USHORT)nDist );
5313 aLRItem.SetRight( (USHORT)nDist );
5314 break;
5317 #ifndef FIX41370
5318 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5319 aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5320 #endif
5324 #ifdef FIX41370
5325 _HTMLAttr* pTmp = new _HTMLAttr( *pPam->GetPoint(), aLRItem );
5326 aSetAttrTab.Insert( pTmp, aSetAttrTab.Count() );
5327 #endif
5330 // Bookmarks koennen nicht in Hyperlinks eingefueht werden
5331 if( aId.Len() )
5332 InsertBookmark( aId );
5334 // den aktuellen Kontext vom Stack holen
5335 _HTMLAttrContext *pPoppedContext = PopContext( HTML_HORZRULE );
5336 ASSERT( pPoppedContext==pCntxt, "wo kommt denn da ein HR-Kontext her?" );
5337 delete pPoppedContext;
5339 pPam->Move( fnMoveForward );
5341 // und im Absatz danach die dort aktuelle Vorlage setzen
5342 SetTxtCollAttrs();
5345 void SwHTMLParser::ParseMoreMetaOptions()
5347 String aName, aContent;
5348 BOOL bHTTPEquiv = FALSE;
5350 const HTMLOptions *pHTMLOptions = GetOptions();
5351 for( USHORT i = pHTMLOptions->Count(); i; )
5353 const HTMLOption *pOption = (*pHTMLOptions)[ --i ];
5354 switch( pOption->GetToken() )
5356 case HTML_O_NAME:
5357 aName = pOption->GetString();
5358 bHTTPEquiv = FALSE;
5359 break;
5360 case HTML_O_HTTPEQUIV:
5361 aName = pOption->GetString();
5362 bHTTPEquiv = TRUE;
5363 break;
5364 case HTML_O_CONTENT:
5365 aContent = pOption->GetString();
5366 break;
5370 // Hier wird es etwas tricky: Wir wissen genau, da? die Dok-Info
5371 // nicht geaendert wurde. Deshalb genuegt es, auf Generator und
5372 // auf refresh abzufragen, um noch nicht verarbeitete Token zu finden,
5373 // denn das sind die einzigen, die die Dok-Info nicht modifizieren.
5374 if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_generator ) ||
5375 aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_refresh ) ||
5376 aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_type ) ||
5377 aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_content_script_type ) )
5378 return;
5380 aContent.EraseAllChars( _CR );
5381 aContent.EraseAllChars( _LF );
5383 if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdendnote ) )
5385 FillEndNoteInfo( aContent );
5386 return;
5389 if( aName.EqualsIgnoreCaseAscii( OOO_STRING_SVTOOLS_HTML_META_sdfootnote ) )
5391 FillFootNoteInfo( aContent );
5392 return;
5395 String sText(
5396 String::CreateFromAscii(TOOLS_CONSTASCII_STRINGPARAM("HTML: <")) );
5397 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_meta) );
5398 sText.Append( ' ' );
5399 if( bHTTPEquiv )
5400 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_httpequiv) );
5401 else
5402 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_name) );
5403 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5404 sText.Append( aName );
5405 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\" ") );
5406 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM(OOO_STRING_SVTOOLS_HTML_O_content) );
5407 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("=\"") );
5408 sText.Append( aContent );
5409 sText.AppendAscii( TOOLS_CONSTASCII_STRINGPARAM("\">") );
5411 SwPostItField aPostItFld(
5412 (SwPostItFieldType*)pDoc->GetSysFldType( RES_POSTITFLD ),
5413 aEmptyStr, sText, DateTime() );
5414 SwFmtFld aFmtFld( aPostItFld );
5415 InsertAttr( aFmtFld );
5418 /* \f */
5420 _HTMLAttr::_HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem,
5421 _HTMLAttr **ppHd ) :
5422 nSttPara( rPos.nNode ),
5423 nEndPara( rPos.nNode ),
5424 nSttCntnt( rPos.nContent.GetIndex() ),
5425 nEndCntnt(rPos.nContent.GetIndex() ),
5426 bInsAtStart( TRUE ),
5427 bLikePara( FALSE ),
5428 bValid( TRUE ),
5429 nCount( 1 ),
5430 pNext( 0 ),
5431 pPrev( 0 ),
5432 ppHead( ppHd )
5434 pItem = rItem.Clone();
5437 _HTMLAttr::_HTMLAttr( const _HTMLAttr &rAttr, const SwNodeIndex &rEndPara,
5438 USHORT nEndCnt, _HTMLAttr **ppHd ) :
5439 nSttPara( rAttr.nSttPara ),
5440 nEndPara( rEndPara ),
5441 nSttCntnt( rAttr.nSttCntnt ),
5442 nEndCntnt( nEndCnt ),
5443 bInsAtStart( rAttr.bInsAtStart ),
5444 bLikePara( rAttr.bLikePara ),
5445 bValid( rAttr.bValid ),
5446 nCount( rAttr.nCount ),
5447 pNext( 0 ),
5448 pPrev( 0 ),
5449 ppHead( ppHd )
5451 pItem = rAttr.pItem->Clone();
5454 _HTMLAttr::~_HTMLAttr()
5456 delete pItem;
5459 _HTMLAttr *_HTMLAttr::Clone( const SwNodeIndex& rEndPara, USHORT nEndCnt ) const
5461 // das Attribut mit der alten Start-Position neu anlegen
5462 _HTMLAttr *pNew = new _HTMLAttr( *this, rEndPara, nEndCnt, ppHead );
5464 // die Previous-Liste muss uebernommen werden, die Next-Liste nicht!
5465 pNew->pPrev = pPrev;
5467 return pNew;
5470 void _HTMLAttr::Reset( const SwNodeIndex& rSttPara, USHORT nSttCnt,
5471 _HTMLAttr **ppHd )
5473 // den Anfang (und das Ende) neu setzen
5474 nSttPara = rSttPara;
5475 nSttCntnt = nSttCnt;
5476 nEndPara = rSttPara;
5477 nEndCntnt = nSttCnt;
5479 // den Head korrigieren und die Verkettungen aufheben
5480 pNext = 0;
5481 pPrev = 0;
5482 ppHead = ppHd;
5485 void _HTMLAttr::InsertPrev( _HTMLAttr *pPrv )
5487 ASSERT( !pPrv->pNext || pPrv->pNext == this,
5488 "_HTMLAttr::InsertPrev: pNext falsch" );
5489 pPrv->pNext = 0;
5491 ASSERT( 0 == pPrv->ppHead || ppHead == pPrv->ppHead,
5492 "_HTMLAttr::InsertPrev: ppHead falsch" );
5493 pPrv->ppHead = 0;
5495 _HTMLAttr *pAttr = this;
5496 while( pAttr->GetPrev() )
5497 pAttr = pAttr->GetPrev();
5499 pAttr->pPrev = pPrv;
5502 bool SwHTMLParser::ParseMetaOptions(
5503 const uno::Reference<document::XDocumentProperties> & i_xDocProps,
5504 SvKeyValueIterator *i_pHeader )
5506 // always call base ParseMetaOptions, it sets the encoding (#i96700#)
5507 bool ret( HTMLParser::ParseMetaOptions(i_xDocProps, i_pHeader) );
5508 if (!ret && IsNewDoc())
5510 ParseMoreMetaOptions();
5512 return ret;
5515 // override so we can parse DOCINFO field subtypes INFO[1-4]
5516 void SwHTMLParser::AddMetaUserDefined( ::rtl::OUString const & i_rMetaName )
5518 // unless we already have 4 names, append the argument to m_InfoNames
5519 ::rtl::OUString* pName // the first empty string in m_InfoNames
5520 (!m_InfoNames[0].getLength() ? &m_InfoNames[0] :
5521 (!m_InfoNames[1].getLength() ? &m_InfoNames[1] :
5522 (!m_InfoNames[2].getLength() ? &m_InfoNames[2] :
5523 (!m_InfoNames[3].getLength() ? &m_InfoNames[3] : 0 ))));
5524 if (pName)
5526 (*pName) = i_rMetaName;