Update ooo320-m1
[ooovba.git] / svx / source / editeng / eehtml.cxx
bloba497b8a5c35e0ee7fe9586888131c406333bff1f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: eehtml.cxx,v $
10 * $Revision: 1.20 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <eeng_pch.hxx>
36 #include <eehtml.hxx>
37 #include <impedit.hxx>
38 #include <svx/adjitem.hxx>
39 #include <svx/flditem.hxx>
40 #include <tools/urlobj.hxx>
41 #include <svx/fhgtitem.hxx>
42 #include "fontitem.hxx"
43 #include <svx/ulspitem.hxx>
44 #include <svx/wghtitem.hxx>
45 #include <svtools/htmltokn.h>
46 #include <svtools/htmlkywd.hxx>
49 #define ACTION_INSERTTEXT 1
50 #define ACTION_INSERTPARABRK 2
52 #define STYLE_PRE 101
54 EditHTMLParser::EditHTMLParser( SvStream& rIn, const String& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs )
55 : SfxHTMLParser( rIn, true )
56 , aBaseURL( rBaseURL )
58 pImpEditEngine = 0;
59 pCurAnchor = 0;
60 bInPara = FALSE;
61 bWasInPara = FALSE;
62 nInTable = 0;
63 nInCell = 0;
64 nDefListLevel = 0;
65 nBulletLevel = 0;
66 nNumberingLevel = 0;
67 bFieldsInserted = FALSE;
69 if ( pHTTPHeaderAttrs )
70 SetEncodingByHTTPHeader( pHTTPHeaderAttrs );
73 EditHTMLParser::~EditHTMLParser()
75 delete pCurAnchor;
78 SvParserState EditHTMLParser::CallParser( ImpEditEngine* pImpEE, const EditPaM& rPaM )
80 DBG_ASSERT( pImpEE, "CallParser: ImpEditEngine ?!" );
81 pImpEditEngine = pImpEE;
82 SvParserState _eState = SVPAR_NOTSTARTED;
83 if ( pImpEditEngine )
85 // Umbrechmimik vom RTF-Import einbauen?
86 aCurSel = EditSelection( rPaM, rPaM );
88 if ( pImpEditEngine->aImportHdl.IsSet() )
90 ImportInfo aImportInfo( HTMLIMP_START, this, pImpEditEngine->CreateESel( aCurSel ) );
91 pImpEditEngine->aImportHdl.Call( &aImportInfo );
94 ImpSetStyleSheet( 0 );
95 _eState = HTMLParser::CallParser();
97 if ( pImpEditEngine->aImportHdl.IsSet() )
99 ImportInfo aImportInfo( HTMLIMP_END, this, pImpEditEngine->CreateESel( aCurSel ) );
100 pImpEditEngine->aImportHdl.Call( &aImportInfo );
103 if ( bFieldsInserted )
104 pImpEditEngine->UpdateFields();
106 return _eState;
109 void EditHTMLParser::NextToken( int nToken )
111 #ifdef DBG_UTIL
112 HTML_TOKEN_IDS xID = (HTML_TOKEN_IDS)nToken;
113 (void)xID;
114 #endif
116 switch( nToken )
118 case HTML_META:
120 const HTMLOptions *_pOptions = GetOptions();
121 USHORT nArrLen = _pOptions->Count();
122 BOOL bEquiv = FALSE;
123 for ( USHORT i = 0; i < nArrLen; i++ )
125 const HTMLOption *pOption = (*_pOptions)[i];
126 switch( pOption->GetToken() )
128 case HTML_O_HTTPEQUIV:
130 bEquiv = TRUE;
132 break;
133 case HTML_O_CONTENT:
135 if ( bEquiv )
137 rtl_TextEncoding eEnc = GetEncodingByMIME( pOption->GetString() );
138 if ( eEnc != RTL_TEXTENCODING_DONTKNOW )
139 SetSrcEncoding( eEnc );
142 break;
147 break;
148 case HTML_PLAINTEXT_ON:
149 case HTML_PLAINTEXT2_ON:
150 bInPara = TRUE;
151 break;
152 case HTML_PLAINTEXT_OFF:
153 case HTML_PLAINTEXT2_OFF:
154 bInPara = FALSE;
155 break;
157 case HTML_LINEBREAK:
158 case HTML_NEWPARA:
160 if ( ( bInPara || nInTable ) &&
161 ( ( nToken == HTML_LINEBREAK ) || HasTextInCurrentPara() ) )
163 ImpInsertParaBreak();
166 break;
167 case HTML_HORZRULE:
169 if ( HasTextInCurrentPara() )
170 ImpInsertParaBreak();
171 ImpInsertParaBreak();
173 case HTML_NONBREAKSPACE:
175 if ( bInPara )
177 ImpInsertText( String( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
180 break;
181 case HTML_TEXTTOKEN:
183 if ( !bInPara )
184 StartPara( FALSE );
186 // if ( bInPara || pCurAnchor )
188 String aText = aToken;
189 if ( aText.Len() && ( aText.GetChar( 0 ) == ' ' )
190 && ThrowAwayBlank() && !IsReadPRE() )
191 aText.Erase( 0, 1 );
193 if ( pCurAnchor )
195 pCurAnchor->aText += aText;
197 else
199 // Nur bis HTML mit 319 geschrieben ?!
200 if ( IsReadPRE() )
202 USHORT nTabPos = aText.Search( '\t', 0 );
203 while ( nTabPos != STRING_NOTFOUND )
205 aText.Erase( nTabPos, 1 );
206 aText.Insert( String( RTL_CONSTASCII_USTRINGPARAM( " " ) ), nTabPos );
207 nTabPos = aText.Search( '\t', nTabPos+8 );
210 ImpInsertText( aText );
214 break;
216 case HTML_CENTER_ON:
217 case HTML_CENTER_OFF: // if ( bInPara )
219 USHORT nNode = pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() );
220 SfxItemSet aItems( aCurSel.Max().GetNode()->GetContentAttribs().GetItems() );
221 aItems.ClearItem( EE_PARA_JUST );
222 if ( nToken == HTML_CENTER_ON )
223 aItems.Put( SvxAdjustItem( SVX_ADJUST_CENTER, EE_PARA_JUST ) );
224 pImpEditEngine->SetParaAttribs( nNode, aItems );
226 break;
228 case HTML_ANCHOR_ON: AnchorStart();
229 break;
230 case HTML_ANCHOR_OFF: AnchorEnd();
231 break;
233 case HTML_PARABREAK_ON:
234 if( bInPara && HasTextInCurrentPara() )
235 EndPara( TRUE );
236 StartPara( TRUE );
237 break;
239 case HTML_PARABREAK_OFF:
240 if( bInPara )
241 EndPara( TRUE );
242 break;
244 case HTML_HEAD1_ON:
245 case HTML_HEAD2_ON:
246 case HTML_HEAD3_ON:
247 case HTML_HEAD4_ON:
248 case HTML_HEAD5_ON:
249 case HTML_HEAD6_ON:
251 HeadingStart( nToken );
253 break;
255 case HTML_HEAD1_OFF:
256 case HTML_HEAD2_OFF:
257 case HTML_HEAD3_OFF:
258 case HTML_HEAD4_OFF:
259 case HTML_HEAD5_OFF:
260 case HTML_HEAD6_OFF:
262 HeadingEnd( nToken );
264 break;
266 case HTML_PREFORMTXT_ON:
267 case HTML_XMP_ON:
268 case HTML_LISTING_ON:
270 StartPara( TRUE );
271 ImpSetStyleSheet( STYLE_PRE );
273 break;
275 case HTML_DEFLIST_ON:
277 nDefListLevel++;
279 break;
281 case HTML_DEFLIST_OFF:
283 if( nDefListLevel )
284 nDefListLevel--;
286 break;
288 case HTML_TABLE_ON: nInTable++;
289 break;
290 case HTML_TABLE_OFF: DBG_ASSERT( nInTable, "Nicht in Table, aber TABLE_OFF?" );
291 nInTable--;
292 break;
294 case HTML_TABLEHEADER_ON:
295 case HTML_TABLEDATA_ON:
296 nInCell++;
297 // fallthru
298 case HTML_BLOCKQUOTE_ON:
299 case HTML_BLOCKQUOTE_OFF:
300 case HTML_BLOCKQUOTE30_ON:
301 case HTML_BLOCKQUOTE30_OFF:
302 case HTML_LISTHEADER_ON:
303 case HTML_LI_ON:
304 case HTML_DD_ON:
305 case HTML_DT_ON:
306 case HTML_ORDERLIST_ON:
307 case HTML_UNORDERLIST_ON:
309 BOOL bHasText = HasTextInCurrentPara();
310 if ( bHasText )
311 ImpInsertParaBreak();
312 StartPara( FALSE );
314 break;
316 case HTML_TABLEHEADER_OFF:
317 case HTML_TABLEDATA_OFF:
319 if ( nInCell )
320 nInCell--;
322 // fallthru
323 case HTML_LISTHEADER_OFF:
324 case HTML_LI_OFF:
325 case HTML_DD_OFF:
326 case HTML_DT_OFF:
327 case HTML_ORDERLIST_OFF:
328 case HTML_UNORDERLIST_OFF: EndPara( FALSE );
329 break;
331 case HTML_TABLEROW_ON:
332 case HTML_TABLEROW_OFF: // Nur nach einem CELL ein RETURN, fuer Calc
334 case HTML_COL_ON:
335 case HTML_COLGROUP_ON:
336 case HTML_COLGROUP_OFF: break;
338 case HTML_FONT_ON: // ...
339 break;
340 case HTML_FONT_OFF: // ...
341 break;
344 // #58335# kein SkipGroup on/off auf inline markup etc.
346 // globals
347 case HTML_HTML_ON:
348 case HTML_HTML_OFF:
349 case HTML_BODY_ON:
350 case HTML_BODY_OFF:
351 case HTML_HEAD_ON:
352 case HTML_HEAD_OFF:
353 case HTML_FORM_ON:
354 case HTML_FORM_OFF:
355 case HTML_THEAD_ON:
356 case HTML_THEAD_OFF:
357 case HTML_TBODY_ON:
358 case HTML_TBODY_OFF:
359 case HTML_TITLE_ON:
360 case HTML_TITLE_OFF:
361 // inline elements, structural markup
362 // HTML 3.0
363 case HTML_BANNER_ON:
364 case HTML_BANNER_OFF:
365 case HTML_DIVISION_ON:
366 case HTML_DIVISION_OFF:
367 // case HTML_LISTHEADER_ON: //! special handling
368 // case HTML_LISTHEADER_OFF:
369 case HTML_NOTE_ON:
370 case HTML_NOTE_OFF:
371 // inline elements, logical markup
372 // HTML 2.0
373 case HTML_ADDRESS_ON:
374 case HTML_ADDRESS_OFF:
375 // case HTML_BLOCKQUOTE_ON: //! extra Behandlung
376 // case HTML_BLOCKQUOTE_OFF:
377 case HTML_CITIATION_ON:
378 case HTML_CITIATION_OFF:
379 case HTML_CODE_ON:
380 case HTML_CODE_OFF:
381 case HTML_DEFINSTANCE_ON:
382 case HTML_DEFINSTANCE_OFF:
383 case HTML_EMPHASIS_ON:
384 case HTML_EMPHASIS_OFF:
385 case HTML_KEYBOARD_ON:
386 case HTML_KEYBOARD_OFF:
387 case HTML_SAMPLE_ON:
388 case HTML_SAMPLE_OFF:
389 case HTML_STRIKE_ON:
390 case HTML_STRIKE_OFF:
391 case HTML_STRONG_ON:
392 case HTML_STRONG_OFF:
393 case HTML_VARIABLE_ON:
394 case HTML_VARIABLE_OFF:
395 // HTML 3.0
396 case HTML_ABBREVIATION_ON:
397 case HTML_ABBREVIATION_OFF:
398 case HTML_ACRONYM_ON:
399 case HTML_ACRONYM_OFF:
400 case HTML_AUTHOR_ON:
401 case HTML_AUTHOR_OFF:
402 // case HTML_BLOCKQUOTE30_ON: //! extra Behandlung
403 // case HTML_BLOCKQUOTE30_OFF:
404 case HTML_DELETEDTEXT_ON:
405 case HTML_DELETEDTEXT_OFF:
406 case HTML_INSERTEDTEXT_ON:
407 case HTML_INSERTEDTEXT_OFF:
408 case HTML_LANGUAGE_ON:
409 case HTML_LANGUAGE_OFF:
410 case HTML_PERSON_ON:
411 case HTML_PERSON_OFF:
412 case HTML_SHORTQUOTE_ON:
413 case HTML_SHORTQUOTE_OFF:
414 case HTML_SUBSCRIPT_ON:
415 case HTML_SUBSCRIPT_OFF:
416 case HTML_SUPERSCRIPT_ON:
417 case HTML_SUPERSCRIPT_OFF:
418 // inline elements, visual markup
419 // HTML 2.0
420 case HTML_BOLD_ON:
421 case HTML_BOLD_OFF:
422 case HTML_ITALIC_ON:
423 case HTML_ITALIC_OFF:
424 case HTML_TELETYPE_ON:
425 case HTML_TELETYPE_OFF:
426 case HTML_UNDERLINE_ON:
427 case HTML_UNDERLINE_OFF:
428 // HTML 3.0
429 case HTML_BIGPRINT_ON:
430 case HTML_BIGPRINT_OFF:
431 case HTML_STRIKETHROUGH_ON:
432 case HTML_STRIKETHROUGH_OFF:
433 case HTML_SMALLPRINT_ON:
434 case HTML_SMALLPRINT_OFF:
435 // figures
436 case HTML_FIGURE_ON:
437 case HTML_FIGURE_OFF:
438 case HTML_CAPTION_ON:
439 case HTML_CAPTION_OFF:
440 case HTML_CREDIT_ON:
441 case HTML_CREDIT_OFF:
442 // misc
443 case HTML_DIRLIST_ON:
444 case HTML_DIRLIST_OFF:
445 case HTML_FOOTNOTE_ON: //! landen so im Text
446 case HTML_FOOTNOTE_OFF:
447 case HTML_MENULIST_ON:
448 case HTML_MENULIST_OFF:
449 // case HTML_PLAINTEXT_ON: //! extra Behandlung
450 // case HTML_PLAINTEXT_OFF:
451 // case HTML_PREFORMTXT_ON: //! extra Behandlung
452 // case HTML_PREFORMTXT_OFF:
453 case HTML_SPAN_ON:
454 case HTML_SPAN_OFF:
455 // obsolete
456 // case HTML_XMP_ON: //! extra Behandlung
457 // case HTML_XMP_OFF:
458 // case HTML_LISTING_ON: //! extra Behandlung
459 // case HTML_LISTING_OFF:
460 // Netscape
461 case HTML_BLINK_ON:
462 case HTML_BLINK_OFF:
463 case HTML_NOBR_ON:
464 case HTML_NOBR_OFF:
465 case HTML_NOEMBED_ON:
466 case HTML_NOEMBED_OFF:
467 case HTML_NOFRAMES_ON:
468 case HTML_NOFRAMES_OFF:
469 // Internet Explorer
470 case HTML_MARQUEE_ON:
471 case HTML_MARQUEE_OFF:
472 // case HTML_PLAINTEXT2_ON: //! extra Behandlung
473 // case HTML_PLAINTEXT2_OFF:
474 break;
476 default:
478 if ( nToken & HTML_TOKEN_ONOFF )
480 if ( ( nToken == HTML_UNKNOWNCONTROL_ON ) || ( nToken == HTML_UNKNOWNCONTROL_OFF ) )
484 else if ( !(nToken & 1) )
486 DBG_ASSERT( !( nToken & 1 ), "Kein Start-Token ?!" );
487 SkipGroup( nToken + 1 );
491 } // SWITCH
493 if ( pImpEditEngine->aImportHdl.IsSet() )
495 ImportInfo aImportInfo( HTMLIMP_NEXTTOKEN, this, pImpEditEngine->CreateESel( aCurSel ) );
496 aImportInfo.nToken = nToken;
497 aImportInfo.nTokenValue = (short)nTokenValue;
498 if ( nToken == HTML_TEXTTOKEN )
499 aImportInfo.aText = aToken;
500 pImpEditEngine->aImportHdl.Call( &aImportInfo );
505 void EditHTMLParser::ImpInsertParaBreak()
507 if ( pImpEditEngine->aImportHdl.IsSet() )
509 ImportInfo aImportInfo( HTMLIMP_INSERTPARA, this, pImpEditEngine->CreateESel( aCurSel ) );
510 pImpEditEngine->aImportHdl.Call( &aImportInfo );
512 aCurSel = pImpEditEngine->ImpInsertParaBreak( aCurSel );
513 nLastAction = ACTION_INSERTPARABRK;
516 void EditHTMLParser::ImpSetAttribs( const SfxItemSet& rItems, EditSelection* pSel )
518 // pSel, wenn Zeichenattribute, sonst Absatzattribute fuer den
519 // aktuellen Absatz.
520 DBG_ASSERT( pSel || ( aCurSel.Min().GetNode() == aCurSel.Max().GetNode() ), "ImpInsertAttribs: Selektion?" );
522 EditPaM aStartPaM( pSel ? pSel->Min() : aCurSel.Min() );
523 EditPaM aEndPaM( pSel ? pSel->Max() : aCurSel.Max() );
525 if ( !pSel )
527 aStartPaM.SetIndex( 0 );
528 aEndPaM.SetIndex( aEndPaM.GetNode()->Len() );
531 if ( pImpEditEngine->aImportHdl.IsSet() )
533 EditSelection aSel( aStartPaM, aEndPaM );
534 ImportInfo aImportInfo( HTMLIMP_SETATTR, this, pImpEditEngine->CreateESel( aSel ) );
535 aImportInfo.pAttrs = (void*)&rItems;
536 pImpEditEngine->aImportHdl.Call( &aImportInfo );
539 ContentNode* pSN = aStartPaM.GetNode();
540 USHORT nStartNode = pImpEditEngine->GetEditDoc().GetPos( pSN );
542 // Wenn ein Attribut von 0 bis aktuelle Absatzlaenge geht,
543 // soll es ein Absatz-Attribut sein!
545 // Achtung: Selektion kann ueber mehrere Absaetze gehen.
546 // Alle vollstaendigen Absaetze sind Absatzattribute...
548 // HTML eigentlich nicht:
549 #ifdef DBG_UTIL
550 ContentNode* pEN = aEndPaM.GetNode();
551 USHORT nEndNode = pImpEditEngine->GetEditDoc().GetPos( pEN );
552 DBG_ASSERT( nStartNode == nEndNode, "ImpSetAttribs: Mehrere Absaetze?" );
553 #endif
556 for ( USHORT z = nStartNode+1; z < nEndNode; z++ )
558 DBG_ASSERT( pImpEditEngine->GetEditDoc().SaveGetObject( z ), "Node existiert noch nicht(RTF)" );
559 pImpEditEngine->SetParaAttribs( z, rSet.GetAttrSet() );
562 if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
564 // Den Rest des StartNodes...
565 if ( aStartPaM.GetIndex() == 0 )
566 pImpEditEngine->SetParaAttribs( nStartNode, rSet.GetAttrSet() );
567 else
568 pImpEditEngine->SetAttribs( EditSelection( aStartPaM, EditPaM( aStartPaM.GetNode(), aStartPaM.GetNode()->Len() ) ), rSet.GetAttrSet() );
570 // Den Anfang des EndNodes....
571 if ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() )
572 pImpEditEngine->SetParaAttribs( nEndNode, rSet.GetAttrSet() );
573 else
574 pImpEditEngine->SetAttribs( EditSelection( EditPaM( aEndPaM.GetNode(), 0 ), aEndPaM ), rSet.GetAttrSet() );
576 else
579 if ( ( aStartPaM.GetIndex() == 0 ) && ( aEndPaM.GetIndex() == aEndPaM.GetNode()->Len() ) )
581 // Muesse gemergt werden:
582 SfxItemSet aItems( pImpEditEngine->GetParaAttribs( nStartNode ) );
583 aItems.Put( rItems );
584 pImpEditEngine->SetParaAttribs( nStartNode, aItems );
586 else
587 pImpEditEngine->SetAttribs( EditSelection( aStartPaM, aEndPaM ), rItems );
591 void EditHTMLParser::ImpSetStyleSheet( USHORT nHLevel )
594 nHLevel: 0: Ausschalten
595 1-6: Heading
596 STYLE_PRE: Preformatted
599 // if ( pImpEditEngine->GetStatus().DoImportRTFStyleSheets() )
600 // {
601 // SvxRTFStyleType* pS = GetStyleTbl().Get( rSet.StyleNo() );
602 // DBG_ASSERT( pS, "Vorlage in RTF nicht definiert!" );
603 // if ( pS )
604 // pImpEditEngine->SetStyleSheet( EditSelection( aStartPaM, aEndPaM ), pS->sName, SFX_STYLE_FAMILY_ALL );
605 // }
606 // else
608 // Harte Attribute erzeugen...
609 // Reicht fuer Calc, bei StyleSheets muesste noch geklaert werden,
610 // dass diese auch in der App liegen sollten, damit sie beim
611 // fuettern in eine andere Engine auch noch da sind...
613 USHORT nNode = pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() );
614 // SfxItemSet aItems( pImpEditEngine->GetEmptyItemSet() );
615 SfxItemSet aItems( aCurSel.Max().GetNode()->GetContentAttribs().GetItems() );
617 aItems.ClearItem( EE_PARA_ULSPACE );
618 aItems.ClearItem( EE_CHAR_FONTHEIGHT );
619 aItems.ClearItem( EE_CHAR_FONTINFO );
620 aItems.ClearItem( EE_CHAR_WEIGHT );
622 // Fett in den ersten 3 Headings
623 if ( ( nHLevel >= 1 ) && ( nHLevel <= 3 ) )
625 SvxWeightItem aWeightItem( WEIGHT_BOLD, EE_CHAR_WEIGHT );
626 aItems.Put( aWeightItem );
629 // Fonthoehe und Abstaende, wenn LogicToLogic moeglich:
630 MapUnit eUnit = pImpEditEngine->GetRefMapMode().GetMapUnit();
631 if ( ( eUnit != MAP_PIXEL ) && ( eUnit != MAP_SYSFONT ) &&
632 ( eUnit != MAP_APPFONT ) && ( eUnit != MAP_RELATIVE ) )
634 long nPoints = 10;
635 if ( nHLevel == 1 )
636 nPoints = 22;
637 else if ( nHLevel == 2 )
638 nPoints = 16;
639 else if ( nHLevel == 3 )
640 nPoints = 12;
641 else if ( nHLevel == 4 )
642 nPoints = 11;
644 nPoints = OutputDevice::LogicToLogic( nPoints, MAP_POINT, eUnit );
645 SvxFontHeightItem aHeightItem( nPoints, 100, EE_CHAR_FONTHEIGHT );
646 aItems.Put( aHeightItem );
648 // Absatzabstaende, wenn Heading:
649 if ( !nHLevel || ((nHLevel >= 1) && (nHLevel <= 6)) )
651 SvxULSpaceItem aULSpaceItem( EE_PARA_ULSPACE );
652 aULSpaceItem.SetUpper( (USHORT)OutputDevice::LogicToLogic( 42, MAP_10TH_MM, eUnit ) );
653 aULSpaceItem.SetLower( (USHORT)OutputDevice::LogicToLogic( 35, MAP_10TH_MM, eUnit ) );
654 aItems.Put( aULSpaceItem );
658 // Bei Pre einen proportionalen Font waehlen
659 if ( nHLevel == STYLE_PRE )
661 Font aFont = OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, LANGUAGE_SYSTEM, 0 );
662 SvxFontItem aFontItem( aFont.GetFamily(), aFont.GetName(), XubString(), aFont.GetPitch(), aFont.GetCharSet(), EE_CHAR_FONTINFO );
663 aItems.Put( aFontItem );
666 pImpEditEngine->SetParaAttribs( nNode, aItems );
670 void EditHTMLParser::ImpInsertText( const String& rText )
672 String aText( rText );
673 if ( pImpEditEngine->aImportHdl.IsSet() )
675 ImportInfo aImportInfo( HTMLIMP_INSERTTEXT, this, pImpEditEngine->CreateESel( aCurSel ) );
676 aImportInfo.aText = aText;
677 pImpEditEngine->aImportHdl.Call( &aImportInfo );
680 aCurSel = pImpEditEngine->ImpInsertText( aCurSel, aText );
681 nLastAction = ACTION_INSERTTEXT;
684 void EditHTMLParser::SkipGroup( int nEndToken )
686 // #69109# groups in cells are closed upon leaving the cell, because those
687 // ******* web authors don't know their job
688 // for example: <td><form></td> lacks a closing </form>
689 BYTE nCellLevel = nInCell;
690 int nToken;
691 while( nCellLevel <= nInCell && ( (nToken = GetNextToken() ) != nEndToken ) && nToken )
693 switch ( nToken )
695 case HTML_TABLEHEADER_ON:
696 case HTML_TABLEDATA_ON:
697 nInCell++;
698 break;
699 case HTML_TABLEHEADER_OFF:
700 case HTML_TABLEDATA_OFF:
701 if ( nInCell )
702 nInCell--;
703 break;
708 void EditHTMLParser::StartPara( BOOL bReal )
710 if ( bReal )
712 const HTMLOptions *_pOptions = GetOptions();
713 USHORT nArrLen = _pOptions->Count();
714 SvxAdjust eAdjust = SVX_ADJUST_LEFT;
715 for ( USHORT i = 0; i < nArrLen; i++ )
717 const HTMLOption *pOption = (*_pOptions)[i];
718 switch( pOption->GetToken() )
720 case HTML_O_ALIGN:
722 if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_right ) == COMPARE_EQUAL )
723 eAdjust = SVX_ADJUST_RIGHT;
724 else if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_middle ) == COMPARE_EQUAL )
725 eAdjust = SVX_ADJUST_CENTER;
726 else if ( pOption->GetString().CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_AL_center ) == COMPARE_EQUAL )
727 eAdjust = SVX_ADJUST_CENTER;
728 else
729 eAdjust = SVX_ADJUST_LEFT;
731 break;
734 SfxItemSet aItemSet( pImpEditEngine->GetEmptyItemSet() );
735 aItemSet.Put( SvxAdjustItem( eAdjust, EE_PARA_JUST ) );
736 ImpSetAttribs( aItemSet );
738 bInPara = TRUE;
741 void EditHTMLParser::EndPara( BOOL )
743 if ( bInPara )
745 BOOL bHasText = HasTextInCurrentPara();
746 if ( bHasText )
747 ImpInsertParaBreak();
748 // Nur, wenn ohne Absatzabstaende gearbeitet wird...
749 // if ( !nInTable && bReal && (nNumberingLevel<=1) && (nBulletLevel<=1) )
750 // ImpInsertParaBreak();
752 bInPara = FALSE;
755 BOOL EditHTMLParser::ThrowAwayBlank()
757 // Ein Blank muss weggeschmissen werden, wenn der neue Text mit einem
758 // Blank beginnt und der aktuelle Absatz leer ist oder mit einem
759 // Blank endet...
760 ContentNode* pNode = aCurSel.Max().GetNode();
761 if ( pNode->Len() && ( pNode->GetChar( pNode->Len()-1 ) != ' ' ) )
762 return FALSE;
763 return TRUE;
766 BOOL EditHTMLParser::HasTextInCurrentPara()
768 return aCurSel.Max().GetNode()->Len() ? TRUE : FALSE;
771 void EditHTMLParser::AnchorStart()
773 // Anker im Anker ignoriern
774 if ( !pCurAnchor )
776 const HTMLOptions* _pOptions = GetOptions();
777 USHORT nArrLen = _pOptions->Count();
779 String aRef;
781 for ( USHORT i = 0; i < nArrLen; i++ )
783 const HTMLOption* pOption = (*_pOptions)[i];
784 switch( pOption->GetToken() )
786 case HTML_O_HREF:
787 aRef = pOption->GetString();
788 break;
792 if ( aRef.Len() )
794 String aURL = aRef;
795 if ( aURL.Len() && ( aURL.GetChar( 0 ) != '#' ) )
797 INetURLObject aTargetURL;
798 INetURLObject aRootURL( aBaseURL );
799 aRootURL.GetNewAbsURL( aRef, &aTargetURL );
800 aURL = aTargetURL.GetMainURL( INetURLObject::DECODE_TO_IURI );
802 pCurAnchor = new AnchorInfo;
803 pCurAnchor->aHRef = aURL;
808 void EditHTMLParser::AnchorEnd()
810 if ( pCurAnchor )
812 // Als URL-Feld einfuegen...
813 SvxFieldItem aFld( SvxURLField( pCurAnchor->aHRef, pCurAnchor->aText, SVXURLFORMAT_REPR ), EE_FEATURE_FIELD );
814 aCurSel = pImpEditEngine->InsertField( aCurSel, aFld );
815 bFieldsInserted = TRUE;
816 delete pCurAnchor;
817 pCurAnchor = 0;
819 if ( pImpEditEngine->aImportHdl.IsSet() )
821 ImportInfo aImportInfo( HTMLIMP_INSERTFIELD, this, pImpEditEngine->CreateESel( aCurSel ) );
822 pImpEditEngine->aImportHdl.Call( &aImportInfo );
827 void EditHTMLParser::HeadingStart( int nToken )
829 bWasInPara = bInPara;
830 StartPara( FALSE );
832 if ( bWasInPara && HasTextInCurrentPara() )
833 ImpInsertParaBreak();
835 USHORT nId = sal::static_int_cast< USHORT >(
836 1 + ( ( nToken - HTML_HEAD1_ON ) / 2 ) );
837 DBG_ASSERT( (nId >= 1) && (nId <= 9), "HeadingStart: ID kann nicht stimmen!" );
838 ImpSetStyleSheet( nId );
841 void EditHTMLParser::HeadingEnd( int )
843 EndPara( FALSE );
844 ImpSetStyleSheet( 0 );
846 if ( bWasInPara )
848 bInPara = TRUE;
849 bWasInPara = FALSE;