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