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