merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / html / htmlsect.cxx
blob293a7f8a644516d610477d5be73f68e91e52f54d
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: htmlsect.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_sw.hxx"
37 #include "hintids.hxx"
39 #ifndef _APP_HXX //autogen
40 #include <vcl/svapp.hxx>
41 #endif
42 #ifndef _WRKWIN_HXX //autogen
43 #include <vcl/wrkwin.hxx>
44 #endif
45 #include <svx/adjitem.hxx>
46 #include <svx/ulspitem.hxx>
47 #include <svx/brkitem.hxx>
48 #include <svtools/htmltokn.h>
49 #ifndef _HTMLKYWD_H
50 #include <svtools/htmlkywd.hxx>
51 #endif
52 #include <sfx2/linkmgr.hxx>
53 #include <rtl/uri.hxx>
54 #include <fmtornt.hxx>
55 #include <fmthdft.hxx>
56 #include <fmtcntnt.hxx>
57 #include <fmtfsize.hxx>
58 #include <fmtclds.hxx>
59 #include <fmtanchr.hxx>
60 #include <fmtpdsc.hxx>
61 #include <fmtsrnd.hxx>
62 #include <fmtflcnt.hxx>
63 #include "frmatr.hxx"
64 #include "doc.hxx"
65 #include "pam.hxx"
66 #include "ndtxt.hxx"
67 #include "shellio.hxx"
68 #include "section.hxx"
69 #include "poolfmt.hxx"
70 #include "pagedesc.hxx"
71 #include "swtable.hxx"
72 #include "viewsh.hxx"
73 #include "swcss1.hxx"
74 #include "swhtml.hxx"
75 #include <svtools/urihelper.hxx>
77 #define CONTEXT_FLAGS_MULTICOL (HTML_CNTXT_STRIP_PARA | \
78 HTML_CNTXT_KEEP_NUMRULE | \
79 HTML_CNTXT_KEEP_ATTRS)
80 //#define CONTEXT_FLAGS_HDRFTR (HTML_CNTXT_STRIP_PARA|HTML_CNTXT_PROTECT_STACK)
81 #define CONTEXT_FLAGS_HDRFTR (CONTEXT_FLAGS_MULTICOL)
82 #define CONTEXT_FLAGS_FTN (CONTEXT_FLAGS_MULTICOL)
85 using namespace ::com::sun::star;
88 /* \f */
90 void SwHTMLParser::NewDivision( int nToken )
92 String aId, aHRef, aStyle, aClass, aLang, aDir;
93 SvxAdjust eAdjust = HTML_CENTER_ON==nToken ? SVX_ADJUST_CENTER
94 : SVX_ADJUST_END;
96 sal_Bool bHeader=sal_False, bFooter=sal_False;
97 const HTMLOptions *pHTMLOptions = GetOptions();
98 for( sal_uInt16 i = pHTMLOptions->Count(); i; )
100 const HTMLOption *pOption = (*pHTMLOptions)[--i];
101 switch( pOption->GetToken() )
103 case HTML_O_ID:
104 aId = pOption->GetString();
105 break;
106 case HTML_O_ALIGN:
107 if( HTML_DIVISION_ON==nToken )
108 eAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable,
109 static_cast< sal_uInt16 >(eAdjust) );
110 break;
111 case HTML_O_STYLE:
112 aStyle = pOption->GetString();
113 break;
114 case HTML_O_CLASS:
115 aClass = pOption->GetString();
116 break;
117 case HTML_O_LANG:
118 aLang = pOption->GetString();
119 break;
120 case HTML_O_DIR:
121 aDir = pOption->GetString();
122 break;
123 case HTML_O_HREF:
124 aHRef = pOption->GetString();
125 break;
126 case HTML_O_TYPE:
128 const String& rType = pOption->GetString();
129 if( rType.EqualsIgnoreCaseAscii( "HEADER" ) )
130 bHeader = sal_True;
131 else if( rType.EqualsIgnoreCaseAscii( "FOOTER" ) )
132 bFooter = sal_True;
137 sal_Bool bAppended = sal_False;
138 if( pPam->GetPoint()->nContent.GetIndex() )
140 AppendTxtNode( bHeader||bFooter||aId.Len()||aHRef.Len() ? AM_NORMAL
141 : AM_NOSPACE );
142 bAppended = sal_True;
145 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
147 sal_Bool bStyleParsed = sal_False, bPositioned = sal_False;
148 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
149 SvxCSS1PropertyInfo aPropInfo;
150 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
152 bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
153 aItemSet, aPropInfo, &aLang, &aDir );
154 if( bStyleParsed )
156 bPositioned = HTML_DIVISION_ON == nToken && aClass.Len() &&
157 CreateContainer( aClass, aItemSet, aPropInfo,
158 pCntxt );
159 if( !bPositioned )
160 bPositioned = DoPositioning( aItemSet, aPropInfo, pCntxt );
164 if( !bPositioned && (bHeader || bFooter) && IsNewDoc() )
166 SwPageDesc *pPageDesc = pCSS1Parser->GetMasterPageDesc();
167 SwFrmFmt& rPageFmt = pPageDesc->GetMaster();
169 SwFrmFmt *pHdFtFmt;
170 sal_Bool bNew = sal_False;
171 sal_uInt16 nFlags = CONTEXT_FLAGS_HDRFTR;
172 if( bHeader )
174 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt();
175 if( !pHdFtFmt )
177 // noch keine Header, dann erzeuge einen.
178 rPageFmt.SetFmtAttr( SwFmtHeader( sal_True ));
179 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt();
180 bNew = sal_True;
182 nFlags |= HTML_CNTXT_HEADER_DIST;
184 else
186 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt();
187 if( !pHdFtFmt )
189 // noch keine Footer, dann erzeuge einen.
190 rPageFmt.SetFmtAttr( SwFmtFooter( sal_True ));
191 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt();
192 bNew = sal_True;
194 nFlags |= HTML_CNTXT_FOOTER_DIST;
197 const SwFmtCntnt& rFlyCntnt = pHdFtFmt->GetCntnt();
198 const SwNodeIndex& rCntntStIdx = *rFlyCntnt.GetCntntIdx();
199 SwCntntNode *pCNd;
201 if( bNew )
203 pCNd = pDoc->GetNodes()[rCntntStIdx.GetIndex()+1]
204 ->GetCntntNode();
206 else
208 // Einen neuen Node zu Beginn der Section anlegen
209 SwNodeIndex aSttIdx( rCntntStIdx, 1 );
210 pCNd = pDoc->GetNodes().MakeTxtNode( aSttIdx,
211 pCSS1Parser->GetTxtCollFromPool(RES_POOLCOLL_TEXT));
213 // Den bisherigen Inhalt der Section loeschen
214 SwPaM aDelPam( aSttIdx );
215 aDelPam.SetMark();
217 const SwStartNode *pStNd =
218 (const SwStartNode *)pDoc->GetNodes()[rCntntStIdx];
219 aDelPam.GetPoint()->nNode = pStNd->EndOfSectionIndex() - 1;
221 pDoc->DelFullPara( aDelPam );
223 // Die Seitenvorlage aktualisieren
224 for( sal_uInt16 i=0; i < pDoc->GetPageDescCnt(); i++ )
226 if( RES_POOLPAGE_HTML==const_cast<const SwDoc *>(pDoc)
227 ->GetPageDesc(i).GetPoolFmtId() )
229 pDoc->ChgPageDesc( i, *pPageDesc );
230 break;
235 SwPosition aNewPos( SwNodeIndex( rCntntStIdx, 1 ), SwIndex( pCNd, 0 ) );
236 SaveDocContext( pCntxt, nFlags, &aNewPos );
238 else if( !bPositioned && aId.Len() > 9 &&
239 ('s' == aId.GetChar(0) || 'S' == aId.GetChar(0) ) &&
240 ('d' == aId.GetChar(1) || 'D' == aId.GetChar(1) ) )
242 sal_Bool bEndNote = sal_False, bFootNote = sal_False;
243 if( aId.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_sdendnote, 9 ) == COMPARE_EQUAL )
244 bEndNote = sal_True;
245 else if( aId.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_sdfootnote, 10 ) == COMPARE_EQUAL )
246 bFootNote = sal_True;
247 if( bFootNote || bEndNote )
249 SwNodeIndex *pStartNdIdx = GetFootEndNoteSection( aId );
250 if( pStartNdIdx )
252 SwCntntNode *pCNd =
253 pDoc->GetNodes()[pStartNdIdx->GetIndex()+1]->GetCntntNode();
254 SwNodeIndex aTmpSwNodeIndex = SwNodeIndex(*pCNd);
255 SwPosition aNewPos( aTmpSwNodeIndex, SwIndex( pCNd, 0 ) );
256 SaveDocContext( pCntxt, CONTEXT_FLAGS_FTN, &aNewPos );
257 aId = aPropInfo.aId = aEmptyStr;
262 // Bereiche fuegen wir in Rahmen nur dann ein, wenn der Bereich gelinkt ist.
263 if( (aId.Len() && !bPositioned) || aHRef.Len() )
265 // Bereich einfuegen (muss vor dem Setzten von Attributen erfolgen,
266 // weil die Section vor der PaM-Position eingefuegt.
268 // wenn wir im ersten Node einer Section stehen, wir die neue
269 // Section nicht in der aktuellen, sondern vor der aktuellen
270 // Section eingefuegt. Deshalb muessen wir dann einen Node
271 // einfuegen. UND IN LOESCHEN!!!
272 if( !bAppended )
274 SwNodeIndex aPrvNdIdx( pPam->GetPoint()->nNode, -1 );
275 if( (pDoc->GetNodes()[aPrvNdIdx])->IsSectionNode() )
277 AppendTxtNode();
278 bAppended = sal_True;
281 _HTMLAttrs *pPostIts = bAppended ? 0 : new _HTMLAttrs;
282 SetAttr( sal_True, sal_True, pPostIts );
284 // Namen der Section eindeutig machen
285 String aName( pDoc->GetUniqueSectionName( aId.Len() ? &aId : 0 ) );
287 if( aHRef.Len() )
289 sal_Unicode cDelim = 255U;
290 String aURL;
291 xub_StrLen nPos = aHRef.SearchBackward( cDelim );
292 xub_StrLen nPos2 = STRING_NOTFOUND;
293 if( STRING_NOTFOUND != nPos )
295 nPos2 = aHRef.SearchBackward( cDelim, nPos );
296 if( STRING_NOTFOUND != nPos2 )
298 xub_StrLen nTmp = nPos;
299 nPos = nPos2;
300 nPos2 = nTmp;
303 if( STRING_NOTFOUND == nPos )
305 aURL = URIHelper::SmartRel2Abs(INetURLObject( sBaseURL ), aHRef, Link(), false);
307 else
309 aURL = URIHelper::SmartRel2Abs(INetURLObject( sBaseURL ), aHRef.Copy( 0, nPos ), Link(), false );
310 aURL += sfx2::cTokenSeperator;
311 if( STRING_NOTFOUND == nPos2 )
313 aURL += aHRef.Copy( nPos+1 );
315 else
317 aURL += aHRef.Copy( nPos+1, nPos2 - (nPos+1) );
318 aURL += sfx2::cTokenSeperator;
319 aURL += String(rtl::Uri::decode( aHRef.Copy( nPos2+1 ),
320 rtl_UriDecodeWithCharset,
321 RTL_TEXTENCODING_ISO_8859_1 ));
324 aHRef = aURL;
327 SwSection aSection( aHRef.Len() ? FILE_LINK_SECTION
328 : CONTENT_SECTION, aName );
329 if( aHRef.Len() )
331 aSection.SetLinkFileName( aHRef );
332 aSection.SetProtect();
335 SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
336 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
337 if( !IsNewDoc() )
338 Reader::ResetFrmFmtAttrs(aFrmItemSet );
340 const SfxPoolItem *pItem;
341 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_BACKGROUND, sal_False,
342 &pItem ) )
344 aFrmItemSet.Put( *pItem );
345 aItemSet.ClearItem( RES_BACKGROUND );
347 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_FRAMEDIR, sal_False,
348 &pItem ) )
350 aFrmItemSet.Put( *pItem );
351 aItemSet.ClearItem( RES_FRAMEDIR );
354 pDoc->InsertSwSection( *pPam, aSection, &aFrmItemSet, false );
356 // ggfs. einen Bereich anspringen
357 if( JUMPTO_REGION == eJumpTo && aName == sJmpMark )
359 bChkJumpMark = sal_True;
360 eJumpTo = JUMPTO_NONE;
363 SwTxtNode* pOldTxtNd =
364 bAppended ? 0 : pDoc->GetNodes()[pPam->GetPoint()->nNode]
365 ->GetTxtNode();
367 pPam->Move( fnMoveBackward );
369 // PageDesc- und SwFmtBreak Attribute vom aktuellen Node in den
370 // (ersten) Node des Bereich verschieben.
371 if( pOldTxtNd )
372 MovePageDescAttrs( pOldTxtNd, pPam->GetPoint()->nNode.GetIndex(),
373 sal_True );
375 if( pPostIts )
377 // noch vorhandene PostIts in den ersten Absatz
378 // der Tabelle setzen
379 InsertAttrs( *pPostIts );
380 delete pPostIts;
381 pPostIts = 0;
384 pCntxt->SetSpansSection( sal_True );
386 // keine text::Bookmarks mit dem gleichen Namen wie Bereiche einfuegen
387 if( aPropInfo.aId.Len() && aPropInfo.aId==aName )
388 aPropInfo.aId.Erase();
390 else
392 pCntxt->SetAppendMode( AM_NOSPACE );
395 if( SVX_ADJUST_END != eAdjust )
397 InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eAdjust, RES_PARATR_ADJUST), pCntxt );
400 // Style parsen
401 if( bStyleParsed )
402 InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
404 PushContext( pCntxt );
407 void SwHTMLParser::EndDivision( int /*nToken*/ )
409 // Stack-Eintrag zu dem Token suchen (weil wir noch den Div-Stack
410 // haben unterscheiden wir erst einmal nicht zwischen DIV und CENTER
411 _HTMLAttrContext *pCntxt = 0;
412 sal_uInt16 nPos = aContexts.Count();
413 while( !pCntxt && nPos>nContextStMin )
415 switch( aContexts[--nPos]->GetToken() )
417 case HTML_CENTER_ON:
418 case HTML_DIVISION_ON:
419 pCntxt = aContexts[nPos];
420 aContexts.Remove( nPos, 1 );
421 break;
425 if( pCntxt )
427 // Attribute beenden
428 EndContext( pCntxt );
429 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
431 delete pCntxt;
435 void SwHTMLParser::FixHeaderFooterDistance( sal_Bool bHeader,
436 const SwPosition *pOldPos )
438 SwPageDesc *pPageDesc = pCSS1Parser->GetMasterPageDesc();
439 SwFrmFmt& rPageFmt = pPageDesc->GetMaster();
441 SwFrmFmt *pHdFtFmt =
442 bHeader ? (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt()
443 : (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt();
444 ASSERT( pHdFtFmt, "Doch keine Kopf- oder Fusszeile" );
446 const SwFmtCntnt& rFlyCntnt = pHdFtFmt->GetCntnt();
447 const SwNodeIndex& rCntntStIdx = *rFlyCntnt.GetCntntIdx();
449 ULONG nPrvNxtIdx;
450 if( bHeader )
452 nPrvNxtIdx = pDoc->GetNodes()[rCntntStIdx]->EndOfSectionIndex()-1;
454 else
456 nPrvNxtIdx = pOldPos->nNode.GetIndex() - 1;
459 sal_uInt16 nSpace = 0;
460 SwTxtNode *pTxtNode = pDoc->GetNodes()[nPrvNxtIdx]->GetTxtNode();
461 if( pTxtNode )
463 const SvxULSpaceItem& rULSpace =
464 ((const SvxULSpaceItem&)pTxtNode
465 ->SwCntntNode::GetAttr( RES_UL_SPACE ));
467 // Der untere Absatz-Abstand wird zum Abstand zur
468 // Kopf- oder Fusszeile
469 nSpace = rULSpace.GetLower();
471 // und anschliessend auf einen vernuenftigen Wert
472 // gesetzt
473 const SvxULSpaceItem& rCollULSpace =
474 pTxtNode->GetAnyFmtColl().GetULSpace();
475 if( rCollULSpace.GetUpper() == rULSpace.GetUpper() )
476 pTxtNode->ResetAttr( RES_UL_SPACE );
477 else
478 pTxtNode->SetAttr(
479 SvxULSpaceItem( rULSpace.GetUpper(),
480 rCollULSpace.GetLower(), RES_UL_SPACE ) );
483 if( bHeader )
485 nPrvNxtIdx = pOldPos->nNode.GetIndex();
487 else
489 nPrvNxtIdx = rCntntStIdx.GetIndex() + 1;
492 pTxtNode = pDoc->GetNodes()[nPrvNxtIdx]
493 ->GetTxtNode();
494 if( pTxtNode )
496 const SvxULSpaceItem& rULSpace =
497 ((const SvxULSpaceItem&)pTxtNode
498 ->SwCntntNode::GetAttr( RES_UL_SPACE ));
500 // Der obere Absatz-Abstand wird zum Abstand zur
501 // Kopf- oder Fusszeile, wenn er groesser ist als
502 // der untere vom Absatz davor
503 if( rULSpace.GetUpper() > nSpace )
504 nSpace = rULSpace.GetUpper();
506 // und anschliessend auf einen vernuenftigen Wert gesetzt
507 const SvxULSpaceItem& rCollULSpace =
508 pTxtNode->GetAnyFmtColl().GetULSpace();
509 if( rCollULSpace.GetLower() == rULSpace.GetLower() )
510 pTxtNode->ResetAttr( RES_UL_SPACE );
511 else
512 pTxtNode->SetAttr(
513 SvxULSpaceItem( rCollULSpace.GetUpper(),
514 rULSpace.GetLower(), RES_UL_SPACE ) );
517 SvxULSpaceItem aULSpace( RES_UL_SPACE );
518 if( bHeader )
519 aULSpace.SetLower( nSpace );
520 else
521 aULSpace.SetUpper( nSpace );
523 pHdFtFmt->SetFmtAttr( aULSpace );
526 sal_Bool SwHTMLParser::EndSection( sal_Bool bLFStripped )
528 SwEndNode *pEndNd = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()+1]
529 ->GetEndNode();
530 if( pEndNd && pEndNd->StartOfSectionNode()->IsSectionNode() )
532 // den Bereich beenden
533 if( !bLFStripped )
534 StripTrailingPara();
535 pPam->Move( fnMoveForward );
536 return sal_True;
539 ASSERT( !this, "Falsche PaM Position Beenden eines Bereichs" );
541 return sal_False;
544 sal_Bool SwHTMLParser::EndSections( sal_Bool bLFStripped )
546 sal_Bool bSectionClosed = sal_False;
547 sal_uInt16 nPos = aContexts.Count();
548 while( nPos>nContextStMin )
550 _HTMLAttrContext *pCntxt = aContexts[--nPos];
551 if( pCntxt->GetSpansSection() && EndSection( bLFStripped ) )
553 bSectionClosed = sal_True;
554 pCntxt->SetSpansSection( sal_False );
555 bLFStripped = sal_False;
559 return bSectionClosed;
562 /* \f */
564 void SwHTMLParser::NewMultiCol()
566 String aId, aStyle, aClass, aLang, aDir;
567 long nWidth = 100;
568 sal_uInt16 nCols = 0, nGutter = 10;
569 sal_Bool bPrcWidth = sal_True;
571 const HTMLOptions *pHTMLOptions = GetOptions();
572 sal_uInt16 i;
574 for( i = pHTMLOptions->Count(); i; )
576 const HTMLOption *pOption = (*pHTMLOptions)[--i];
577 switch( pOption->GetToken() )
579 case HTML_O_ID:
580 aId = pOption->GetString();
581 break;
582 case HTML_O_STYLE:
583 aStyle = pOption->GetString();
584 break;
585 case HTML_O_CLASS:
586 aClass = pOption->GetString();
587 break;
588 case HTML_O_LANG:
589 aLang = pOption->GetString();
590 break;
591 case HTML_O_DIR:
592 aDir = pOption->GetString();
593 break;
594 case HTML_O_COLS:
595 nCols = (sal_uInt16)pOption->GetNumber();
596 break;
597 case HTML_O_WIDTH:
598 nWidth = pOption->GetNumber();
599 bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
600 if( bPrcWidth && nWidth>100 )
601 nWidth = 100;
602 break;
603 case HTML_O_GUTTER:
604 nGutter = (sal_uInt16)pOption->GetNumber();
605 break;
610 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_MULTICOL_ON );
612 //.is the multicol elememt contained in a container? That may be the
613 // case for 5.0 documents.
614 sal_Bool bInCntnr = sal_False;
615 i = aContexts.Count();
616 while( !bInCntnr && i > nContextStMin )
617 bInCntnr = 0 != aContexts[--i]->GetFrmItemSet();
619 // Parse style sheets, but don't position anything by now.
620 sal_Bool bStyleParsed = sal_False;
621 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
622 SvxCSS1PropertyInfo aPropInfo;
623 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
624 bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
625 aItemSet, aPropInfo, &aLang, &aDir );
627 // Calculate width.
628 sal_uInt8 nPrcWidth = bPrcWidth ? (sal_uInt8)nWidth : 0;
629 sal_uInt16 nTwipWidth = 0;
630 if( !bPrcWidth && nWidth && Application::GetDefaultDevice() )
632 nTwipWidth = (sal_uInt16)Application::GetDefaultDevice()
633 ->PixelToLogic( Size(nWidth, 0),
634 MapMode(MAP_TWIP) ).Width();
637 if( !nPrcWidth && nTwipWidth < MINFLY )
638 nTwipWidth = MINFLY;
640 // Do positioning.
641 sal_Bool bPositioned = sal_False;
642 if( bInCntnr || pCSS1Parser->MayBePositioned( aPropInfo, sal_True ) )
644 SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
645 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
646 if( !IsNewDoc() )
647 Reader::ResetFrmFmtAttrs(aFrmItemSet );
649 SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, aItemSet, aPropInfo,
650 aFrmItemSet );
652 // The width is either the WIDTH attribute's value or contained
653 // in some style option.
654 SetVarSize( aItemSet, aPropInfo, aFrmItemSet, nTwipWidth, nPrcWidth );
656 SetSpace( Size(0,0), aItemSet, aPropInfo, aFrmItemSet );
658 // Set some other frame attributes. If the background is set, its
659 // it will be cleared here. That for, it won't be set at the section,
660 // too.
661 SetFrmFmtAttrs( aItemSet, aPropInfo,
662 HTML_FF_BOX|HTML_FF_BACKGROUND|HTML_FF_PADDING|HTML_FF_DIRECTION,
663 aFrmItemSet );
665 // Insert fly frame. If the are columns, the fly frame's name is not
666 // the sections name but a generated one.
667 String aFlyName( aEmptyStr );
668 if( nCols < 2 )
670 aFlyName = aId;
671 aPropInfo.aId.Erase();
674 InsertFlyFrame( aFrmItemSet, pCntxt, aFlyName, CONTEXT_FLAGS_ABSPOS );
676 pCntxt->SetPopStack( sal_True );
677 bPositioned = sal_True;
680 sal_Bool bAppended = sal_False;
681 if( !bPositioned )
683 if( pPam->GetPoint()->nContent.GetIndex() )
685 AppendTxtNode( AM_SPACE );
686 bAppended = sal_True;
688 else
690 AddParSpace();
694 // If there are less then 2 columns, no section is inserted.
695 if( nCols >= 2 )
697 if( !bAppended )
699 // If the pam is at the start of a section, a additional text
700 // node must be inserted. Otherwise, the new section will be
701 // inserted in front of the old one.
702 SwNodeIndex aPrvNdIdx( pPam->GetPoint()->nNode, -1 );
703 if( (pDoc->GetNodes()[aPrvNdIdx])->IsSectionNode() )
705 AppendTxtNode();
706 bAppended = sal_True;
709 _HTMLAttrs *pPostIts = bAppended ? 0 : new _HTMLAttrs;
710 SetAttr( sal_True, sal_True, pPostIts );
712 // Make section name unique.
713 String aName( pDoc->GetUniqueSectionName( aId.Len() ? &aId : 0 ) );
714 SwSection aSection( CONTENT_SECTION, aName );
716 SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
717 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
718 if( !IsNewDoc() )
719 Reader::ResetFrmFmtAttrs(aFrmItemSet );
721 if( nGutter && Application::GetDefaultDevice() )
723 nGutter = (sal_uInt16)Application::GetDefaultDevice()
724 ->PixelToLogic( Size(nGutter, 0),
725 MapMode(MAP_TWIP) ).Width();
728 SwFmtCol aFmtCol;
729 #ifndef WIDTH_SUPPORTED_BY_SECTIONS
730 nPrcWidth = 100;
731 #endif
733 aFmtCol.Init( nCols, nGutter, nPrcWidth ? USHRT_MAX : nTwipWidth );
734 aFrmItemSet.Put( aFmtCol );
736 const SfxPoolItem *pItem;
737 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_BACKGROUND, sal_False,
738 &pItem ) )
740 aFrmItemSet.Put( *pItem );
741 aItemSet.ClearItem( RES_BACKGROUND );
743 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_FRAMEDIR, sal_False,
744 &pItem ) )
746 aFrmItemSet.Put( *pItem );
747 aItemSet.ClearItem( RES_FRAMEDIR );
749 pDoc->InsertSwSection( *pPam, aSection, &aFrmItemSet, false );
751 // Jump to section, if this is requested.
752 if( JUMPTO_REGION == eJumpTo && aName == sJmpMark )
754 bChkJumpMark = sal_True;
755 eJumpTo = JUMPTO_NONE;
758 SwTxtNode* pOldTxtNd =
759 bAppended ? 0 : pDoc->GetNodes()[pPam->GetPoint()->nNode]
760 ->GetTxtNode();
762 pPam->Move( fnMoveBackward );
764 // Move PageDesc and SwFmtBreak attributes of the current node
765 // to the section's first node.
766 if( pOldTxtNd )
767 MovePageDescAttrs( pOldTxtNd, pPam->GetPoint()->nNode.GetIndex(),
768 sal_True );
770 if( pPostIts )
772 // Move pending PostIts into the section.
773 InsertAttrs( *pPostIts );
774 delete pPostIts;
775 pPostIts = 0;
778 pCntxt->SetSpansSection( sal_True );
780 // Insert a bookmark if its name differs from the section's name only.
781 if( aPropInfo.aId.Len() && aPropInfo.aId==aName )
782 aPropInfo.aId.Erase();
785 // Additional attributes must be set as hard ones.
786 if( bStyleParsed )
787 InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
789 PushContext( pCntxt );
792 /* \f */
794 void SwHTMLParser::InsertFlyFrame( const SfxItemSet& rItemSet,
795 _HTMLAttrContext *pCntxt,
796 const String& rName,
797 sal_uInt16 nFlags )
799 RndStdIds eAnchorId =
800 ((const SwFmtAnchor&)rItemSet.Get( RES_ANCHOR )).GetAnchorId();
802 // Den Rahmen anlegen
803 SwFlyFrmFmt* pFlyFmt = pDoc->MakeFlySection( eAnchorId, pPam->GetPoint(),
804 &rItemSet );
805 // Ggf. den Namen setzen
806 if( rName.Len() )
807 pFlyFmt->SetName( rName );
809 RegisterFlyFrm( pFlyFmt );
811 const SwFmtCntnt& rFlyCntnt = pFlyFmt->GetCntnt();
812 const SwNodeIndex& rFlyCntIdx = *rFlyCntnt.GetCntntIdx();
813 SwCntntNode *pCNd = pDoc->GetNodes()[rFlyCntIdx.GetIndex()+1]
814 ->GetCntntNode();
816 SwPosition aNewPos( SwNodeIndex( rFlyCntIdx, 1 ), SwIndex( pCNd, 0 ) );
817 SaveDocContext( pCntxt, nFlags, &aNewPos );
821 /* \f */
823 void SwHTMLParser::MovePageDescAttrs( SwNode *pSrcNd,
824 ULONG nDestIdx,
825 sal_Bool bFmtBreak )
827 SwCntntNode* pDestCntntNd =
828 pDoc->GetNodes()[nDestIdx]->GetCntntNode();
830 ASSERT( pDestCntntNd, "Wieso ist das Ziel kein Content-Node?" );
832 if( pSrcNd->IsCntntNode() )
834 SwCntntNode* pSrcCntntNd = pSrcNd->GetCntntNode();
836 const SfxPoolItem* pItem;
837 if( SFX_ITEM_SET == pSrcCntntNd->GetSwAttrSet()
838 .GetItemState( RES_PAGEDESC, sal_False, &pItem ) &&
839 ((SwFmtPageDesc *)pItem)->GetPageDesc() )
841 pDestCntntNd->SetAttr( *pItem );
842 pSrcCntntNd->ResetAttr( RES_PAGEDESC );
844 if( SFX_ITEM_SET == pSrcCntntNd->GetSwAttrSet()
845 .GetItemState( RES_BREAK, sal_False, &pItem ) )
847 switch( ((SvxFmtBreakItem *)pItem)->GetBreak() )
849 case SVX_BREAK_PAGE_BEFORE:
850 case SVX_BREAK_PAGE_AFTER:
851 case SVX_BREAK_PAGE_BOTH:
852 if( bFmtBreak )
853 pDestCntntNd->SetAttr( *pItem );
854 pSrcCntntNd->ResetAttr( RES_BREAK );
855 default:
860 else if( pSrcNd->IsTableNode() )
862 SwFrmFmt *pFrmFmt = pSrcNd->GetTableNode()->GetTable().GetFrmFmt();
864 const SfxPoolItem* pItem;
865 if( SFX_ITEM_SET == pFrmFmt->GetAttrSet().
866 GetItemState( RES_PAGEDESC, sal_False, &pItem ) )
868 pDestCntntNd->SetAttr( *pItem );
869 pFrmFmt->ResetFmtAttr( RES_PAGEDESC );