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 #include <rtl/uri.hxx>
28
29 #include <svl/urihelper.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/wrkwin.hxx>
32 #include <editeng/adjitem.hxx>
33 #include <editeng/ulspitem.hxx>
34 #include <editeng/brkitem.hxx>
35 #include <svtools/htmltokn.h>
36 #include <svtools/htmlkywd.hxx>
37 #include <sfx2/linkmgr.hxx>
38
39 #include "hintids.hxx"
40 #include <fmtornt.hxx>
41 #include <fmthdft.hxx>
42 #include <fmtcntnt.hxx>
43 #include <fmtfsize.hxx>
44 #include <fmtclds.hxx>
45 #include <fmtanchr.hxx>
46 #include <fmtpdsc.hxx>
47 #include <fmtsrnd.hxx>
48 #include <fmtflcnt.hxx>
49 #include "frmatr.hxx"
50 #include "doc.hxx"
51 #include "pam.hxx"
52 #include "ndtxt.hxx"
53 #include "shellio.hxx"
54 #include "section.hxx"
55 #include "poolfmt.hxx"
56 #include "pagedesc.hxx"
57 #include "swtable.hxx"
58 #include "viewsh.hxx"
59 #include "swcss1.hxx"
60 #include "swhtml.hxx"
61
62 #define CONTEXT_FLAGS_MULTICOL (HTML_CNTXT_STRIP_PARA | \
63 HTML_CNTXT_KEEP_NUMRULE | \
64 HTML_CNTXT_KEEP_ATTRS)
65 //#define CONTEXT_FLAGS_HDRFTR (HTML_CNTXT_STRIP_PARA|HTML_CNTXT_PROTECT_STACK)
66 #define CONTEXT_FLAGS_HDRFTR (CONTEXT_FLAGS_MULTICOL)
67 #define CONTEXT_FLAGS_FTN (CONTEXT_FLAGS_MULTICOL)
68
69
70 using namespace ::com::sun::star;
71
72
73 /* */
74
NewDivision(int nToken)75 void SwHTMLParser::NewDivision( int nToken )
76 {
77 String aId, aHRef, aStyle, aClass, aLang, aDir;
78 SvxAdjust eAdjust = HTML_CENTER_ON==nToken ? SVX_ADJUST_CENTER
79 : SVX_ADJUST_END;
80
81 sal_Bool bHeader=sal_False, bFooter=sal_False;
82 const HTMLOptions *pHTMLOptions = GetOptions();
83 for( sal_uInt16 i = pHTMLOptions->Count(); i; )
84 {
85 const HTMLOption *pOption = (*pHTMLOptions)[--i];
86 switch( pOption->GetToken() )
87 {
88 case HTML_O_ID:
89 aId = pOption->GetString();
90 break;
91 case HTML_O_ALIGN:
92 if( HTML_DIVISION_ON==nToken )
93 eAdjust = (SvxAdjust)pOption->GetEnum( aHTMLPAlignTable,
94 static_cast< sal_uInt16 >(eAdjust) );
95 break;
96 case HTML_O_STYLE:
97 aStyle = pOption->GetString();
98 break;
99 case HTML_O_CLASS:
100 aClass = pOption->GetString();
101 break;
102 case HTML_O_LANG:
103 aLang = pOption->GetString();
104 break;
105 case HTML_O_DIR:
106 aDir = pOption->GetString();
107 break;
108 case HTML_O_HREF:
109 aHRef = pOption->GetString();
110 break;
111 case HTML_O_TYPE:
112 {
113 const String& rType = pOption->GetString();
114 if( rType.EqualsIgnoreCaseAscii( "HEADER" ) )
115 bHeader = sal_True;
116 else if( rType.EqualsIgnoreCaseAscii( "FOOTER" ) )
117 bFooter = sal_True;
118 }
119 }
120 }
121
122 sal_Bool bAppended = sal_False;
123 if( pPam->GetPoint()->nContent.GetIndex() )
124 {
125 AppendTxtNode( bHeader||bFooter||aId.Len()||aHRef.Len() ? AM_NORMAL
126 : AM_NOSPACE );
127 bAppended = sal_True;
128 }
129
130 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( static_cast< sal_uInt16 >(nToken) );
131
132 sal_Bool bStyleParsed = sal_False, bPositioned = sal_False;
133 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
134 SvxCSS1PropertyInfo aPropInfo;
135 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
136 {
137 bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
138 aItemSet, aPropInfo, &aLang, &aDir );
139 if( bStyleParsed )
140 {
141 bPositioned = HTML_DIVISION_ON == nToken && aClass.Len() &&
142 CreateContainer( aClass, aItemSet, aPropInfo,
143 pCntxt );
144 if( !bPositioned )
145 bPositioned = DoPositioning( aItemSet, aPropInfo, pCntxt );
146 }
147 }
148
149 if( !bPositioned && (bHeader || bFooter) && IsNewDoc() )
150 {
151 SwPageDesc *pPageDesc = pCSS1Parser->GetMasterPageDesc();
152 SwFrmFmt& rPageFmt = pPageDesc->GetMaster();
153
154 SwFrmFmt *pHdFtFmt;
155 sal_Bool bNew = sal_False;
156 sal_uInt16 nFlags = CONTEXT_FLAGS_HDRFTR;
157 if( bHeader )
158 {
159 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt();
160 if( !pHdFtFmt )
161 {
162 // noch keine Header, dann erzeuge einen.
163 rPageFmt.SetFmtAttr( SwFmtHeader( sal_True ));
164 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt();
165 bNew = sal_True;
166 }
167 nFlags |= HTML_CNTXT_HEADER_DIST;
168 }
169 else
170 {
171 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt();
172 if( !pHdFtFmt )
173 {
174 // noch keine Footer, dann erzeuge einen.
175 rPageFmt.SetFmtAttr( SwFmtFooter( sal_True ));
176 pHdFtFmt = (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt();
177 bNew = sal_True;
178 }
179 nFlags |= HTML_CNTXT_FOOTER_DIST;
180 }
181
182 const SwFmtCntnt& rFlyCntnt = pHdFtFmt->GetCntnt();
183 const SwNodeIndex& rCntntStIdx = *rFlyCntnt.GetCntntIdx();
184 SwCntntNode *pCNd;
185
186 if( bNew )
187 {
188 pCNd = pDoc->GetNodes()[rCntntStIdx.GetIndex()+1]
189 ->GetCntntNode();
190 }
191 else
192 {
193 // Einen neuen Node zu Beginn der Section anlegen
194 SwNodeIndex aSttIdx( rCntntStIdx, 1 );
195 pCNd = pDoc->GetNodes().MakeTxtNode( aSttIdx,
196 pCSS1Parser->GetTxtCollFromPool(RES_POOLCOLL_TEXT));
197
198 // Den bisherigen Inhalt der Section loeschen
199 SwPaM aDelPam( aSttIdx );
200 aDelPam.SetMark();
201
202 const SwStartNode *pStNd =
203 (const SwStartNode *) &rCntntStIdx.GetNode();
204 aDelPam.GetPoint()->nNode = pStNd->EndOfSectionIndex() - 1;
205
206 pDoc->DelFullPara( aDelPam );
207
208 // Die Seitenvorlage aktualisieren
209 for( sal_uInt16 i=0; i < pDoc->GetPageDescCnt(); i++ )
210 {
211 if( RES_POOLPAGE_HTML==const_cast<const SwDoc *>(pDoc)
212 ->GetPageDesc(i).GetPoolFmtId() )
213 {
214 pDoc->ChgPageDesc( i, *pPageDesc );
215 break;
216 }
217 }
218 }
219
220 SwPosition aNewPos( SwNodeIndex( rCntntStIdx, 1 ), SwIndex( pCNd, 0 ) );
221 SaveDocContext( pCntxt, nFlags, &aNewPos );
222 }
223 else if( !bPositioned && aId.Len() > 9 &&
224 ('s' == aId.GetChar(0) || 'S' == aId.GetChar(0) ) &&
225 ('d' == aId.GetChar(1) || 'D' == aId.GetChar(1) ) )
226 {
227 sal_Bool bEndNote = sal_False, bFootNote = sal_False;
228 if( aId.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_sdendnote, 9 ) == COMPARE_EQUAL )
229 bEndNote = sal_True;
230 else if( aId.CompareIgnoreCaseToAscii( OOO_STRING_SVTOOLS_HTML_sdfootnote, 10 ) == COMPARE_EQUAL )
231 bFootNote = sal_True;
232 if( bFootNote || bEndNote )
233 {
234 SwNodeIndex *pStartNdIdx = GetFootEndNoteSection( aId );
235 if( pStartNdIdx )
236 {
237 SwCntntNode *pCNd =
238 pDoc->GetNodes()[pStartNdIdx->GetIndex()+1]->GetCntntNode();
239 SwNodeIndex aTmpSwNodeIndex = SwNodeIndex(*pCNd);
240 SwPosition aNewPos( aTmpSwNodeIndex, SwIndex( pCNd, 0 ) );
241 SaveDocContext( pCntxt, CONTEXT_FLAGS_FTN, &aNewPos );
242 aId = aPropInfo.aId = aEmptyStr;
243 }
244 }
245 }
246
247 // Bereiche fuegen wir in Rahmen nur dann ein, wenn der Bereich gelinkt ist.
248 if( (aId.Len() && !bPositioned) || aHRef.Len() )
249 {
250 // Bereich einfuegen (muss vor dem Setzten von Attributen erfolgen,
251 // weil die Section vor der PaM-Position eingefuegt.
252
253 // wenn wir im ersten Node einer Section stehen, wir die neue
254 // Section nicht in der aktuellen, sondern vor der aktuellen
255 // Section eingefuegt. Deshalb muessen wir dann einen Node
256 // einfuegen. UND IN LOESCHEN!!!
257 if( !bAppended )
258 {
259 SwNodeIndex aPrvNdIdx( pPam->GetPoint()->nNode, -1 );
260 if (aPrvNdIdx.GetNode().IsSectionNode())
261 {
262 AppendTxtNode();
263 bAppended = sal_True;
264 }
265 }
266 _HTMLAttrs *pPostIts = bAppended ? 0 : new _HTMLAttrs;
267 SetAttr( sal_True, sal_True, pPostIts );
268
269 // Namen der Section eindeutig machen
270 String aName( pDoc->GetUniqueSectionName( aId.Len() ? &aId : 0 ) );
271
272 if( aHRef.Len() )
273 {
274 sal_Unicode cDelim = 255U;
275 String aURL;
276 xub_StrLen nPos = aHRef.SearchBackward( cDelim );
277 xub_StrLen nPos2 = STRING_NOTFOUND;
278 if( STRING_NOTFOUND != nPos )
279 {
280 nPos2 = aHRef.SearchBackward( cDelim, nPos );
281 if( STRING_NOTFOUND != nPos2 )
282 {
283 xub_StrLen nTmp = nPos;
284 nPos = nPos2;
285 nPos2 = nTmp;
286 }
287 }
288 if( STRING_NOTFOUND == nPos )
289 {
290 aURL = URIHelper::SmartRel2Abs(INetURLObject( sBaseURL ), aHRef, Link(), false);
291 }
292 else
293 {
294 aURL = URIHelper::SmartRel2Abs(INetURLObject( sBaseURL ), aHRef.Copy( 0, nPos ), Link(), false );
295 aURL += sfx2::cTokenSeperator;
296 if( STRING_NOTFOUND == nPos2 )
297 {
298 aURL += aHRef.Copy( nPos+1 );
299 }
300 else
301 {
302 aURL += aHRef.Copy( nPos+1, nPos2 - (nPos+1) );
303 aURL += sfx2::cTokenSeperator;
304 aURL += String(rtl::Uri::decode( aHRef.Copy( nPos2+1 ),
305 rtl_UriDecodeWithCharset,
306 RTL_TEXTENCODING_ISO_8859_1 ));
307 }
308 }
309 aHRef = aURL;
310 }
311
312 SwSectionData aSection( (aHRef.Len()) ? FILE_LINK_SECTION
313 : CONTENT_SECTION, aName );
314 if( aHRef.Len() )
315 {
316 aSection.SetLinkFileName( aHRef );
317 aSection.SetProtectFlag(true);
318 }
319
320 SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
321 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
322 if( !IsNewDoc() )
323 Reader::ResetFrmFmtAttrs(aFrmItemSet );
324
325 const SfxPoolItem *pItem;
326 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_BACKGROUND, sal_False,
327 &pItem ) )
328 {
329 aFrmItemSet.Put( *pItem );
330 aItemSet.ClearItem( RES_BACKGROUND );
331 }
332 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_FRAMEDIR, sal_False,
333 &pItem ) )
334 {
335 aFrmItemSet.Put( *pItem );
336 aItemSet.ClearItem( RES_FRAMEDIR );
337 }
338
339 pDoc->InsertSwSection( *pPam, aSection, 0, &aFrmItemSet, false );
340
341 // ggfs. einen Bereich anspringen
342 if( JUMPTO_REGION == eJumpTo && aName == sJmpMark )
343 {
344 bChkJumpMark = sal_True;
345 eJumpTo = JUMPTO_NONE;
346 }
347
348 SwTxtNode* pOldTxtNd =
349 (bAppended) ? 0 : pPam->GetPoint()->nNode.GetNode().GetTxtNode();
350
351 pPam->Move( fnMoveBackward );
352
353 // PageDesc- und SwFmtBreak Attribute vom aktuellen Node in den
354 // (ersten) Node des Bereich verschieben.
355 if( pOldTxtNd )
356 MovePageDescAttrs( pOldTxtNd, pPam->GetPoint()->nNode.GetIndex(),
357 sal_True );
358
359 if( pPostIts )
360 {
361 // noch vorhandene PostIts in den ersten Absatz
362 // der Tabelle setzen
363 InsertAttrs( *pPostIts );
364 delete pPostIts;
365 pPostIts = 0;
366 }
367
368 pCntxt->SetSpansSection( sal_True );
369
370 // keine text::Bookmarks mit dem gleichen Namen wie Bereiche einfuegen
371 if( aPropInfo.aId.Len() && aPropInfo.aId==aName )
372 aPropInfo.aId.Erase();
373 }
374 else
375 {
376 pCntxt->SetAppendMode( AM_NOSPACE );
377 }
378
379 if( SVX_ADJUST_END != eAdjust )
380 {
381 InsertAttr( &aAttrTab.pAdjust, SvxAdjustItem(eAdjust, RES_PARATR_ADJUST), pCntxt );
382 }
383
384 // Style parsen
385 if( bStyleParsed )
386 InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
387
388 PushContext( pCntxt );
389 }
390
EndDivision(int)391 void SwHTMLParser::EndDivision( int /*nToken*/ )
392 {
393 // Stack-Eintrag zu dem Token suchen (weil wir noch den Div-Stack
394 // haben unterscheiden wir erst einmal nicht zwischen DIV und CENTER
395 _HTMLAttrContext *pCntxt = 0;
396 sal_uInt16 nPos = aContexts.Count();
397 while( !pCntxt && nPos>nContextStMin )
398 {
399 switch( aContexts[--nPos]->GetToken() )
400 {
401 case HTML_CENTER_ON:
402 case HTML_DIVISION_ON:
403 pCntxt = aContexts[nPos];
404 aContexts.Remove( nPos, 1 );
405 break;
406 }
407 }
408
409 if( pCntxt )
410 {
411 // Attribute beenden
412 EndContext( pCntxt );
413 SetAttr(); // Absatz-Atts wegen JavaScript moeglichst schnell setzen
414
415 delete pCntxt;
416 }
417 }
418
FixHeaderFooterDistance(sal_Bool bHeader,const SwPosition * pOldPos)419 void SwHTMLParser::FixHeaderFooterDistance( sal_Bool bHeader,
420 const SwPosition *pOldPos )
421 {
422 SwPageDesc *pPageDesc = pCSS1Parser->GetMasterPageDesc();
423 SwFrmFmt& rPageFmt = pPageDesc->GetMaster();
424
425 SwFrmFmt *pHdFtFmt =
426 bHeader ? (SwFrmFmt*)rPageFmt.GetHeader().GetHeaderFmt()
427 : (SwFrmFmt*)rPageFmt.GetFooter().GetFooterFmt();
428 ASSERT( pHdFtFmt, "Doch keine Kopf- oder Fusszeile" );
429
430 const SwFmtCntnt& rFlyCntnt = pHdFtFmt->GetCntnt();
431 const SwNodeIndex& rCntntStIdx = *rFlyCntnt.GetCntntIdx();
432
433 sal_uLong nPrvNxtIdx;
434 if( bHeader )
435 {
436 nPrvNxtIdx = rCntntStIdx.GetNode().EndOfSectionIndex()-1;
437 }
438 else
439 {
440 nPrvNxtIdx = pOldPos->nNode.GetIndex() - 1;
441 }
442
443 sal_uInt16 nSpace = 0;
444 SwTxtNode *pTxtNode = pDoc->GetNodes()[nPrvNxtIdx]->GetTxtNode();
445 if( pTxtNode )
446 {
447 const SvxULSpaceItem& rULSpace =
448 ((const SvxULSpaceItem&)pTxtNode
449 ->SwCntntNode::GetAttr( RES_UL_SPACE ));
450
451 // Der untere Absatz-Abstand wird zum Abstand zur
452 // Kopf- oder Fusszeile
453 nSpace = rULSpace.GetLower();
454
455 // und anschliessend auf einen vernuenftigen Wert
456 // gesetzt
457 const SvxULSpaceItem& rCollULSpace =
458 pTxtNode->GetAnyFmtColl().GetULSpace();
459 if( rCollULSpace.GetUpper() == rULSpace.GetUpper() )
460 pTxtNode->ResetAttr( RES_UL_SPACE );
461 else
462 pTxtNode->SetAttr(
463 SvxULSpaceItem( rULSpace.GetUpper(),
464 rCollULSpace.GetLower(), RES_UL_SPACE ) );
465 }
466
467 if( bHeader )
468 {
469 nPrvNxtIdx = pOldPos->nNode.GetIndex();
470 }
471 else
472 {
473 nPrvNxtIdx = rCntntStIdx.GetIndex() + 1;
474 }
475
476 pTxtNode = pDoc->GetNodes()[nPrvNxtIdx]
477 ->GetTxtNode();
478 if( pTxtNode )
479 {
480 const SvxULSpaceItem& rULSpace =
481 ((const SvxULSpaceItem&)pTxtNode
482 ->SwCntntNode::GetAttr( RES_UL_SPACE ));
483
484 // Der obere Absatz-Abstand wird zum Abstand zur
485 // Kopf- oder Fusszeile, wenn er groesser ist als
486 // der untere vom Absatz davor
487 if( rULSpace.GetUpper() > nSpace )
488 nSpace = rULSpace.GetUpper();
489
490 // und anschliessend auf einen vernuenftigen Wert gesetzt
491 const SvxULSpaceItem& rCollULSpace =
492 pTxtNode->GetAnyFmtColl().GetULSpace();
493 if( rCollULSpace.GetLower() == rULSpace.GetLower() )
494 pTxtNode->ResetAttr( RES_UL_SPACE );
495 else
496 pTxtNode->SetAttr(
497 SvxULSpaceItem( rCollULSpace.GetUpper(),
498 rULSpace.GetLower(), RES_UL_SPACE ) );
499 }
500
501 SvxULSpaceItem aULSpace( RES_UL_SPACE );
502 if( bHeader )
503 aULSpace.SetLower( nSpace );
504 else
505 aULSpace.SetUpper( nSpace );
506
507 pHdFtFmt->SetFmtAttr( aULSpace );
508 }
509
EndSection(sal_Bool bLFStripped)510 sal_Bool SwHTMLParser::EndSection( sal_Bool bLFStripped )
511 {
512 SwEndNode *pEndNd = pDoc->GetNodes()[pPam->GetPoint()->nNode.GetIndex()+1]
513 ->GetEndNode();
514 if( pEndNd && pEndNd->StartOfSectionNode()->IsSectionNode() )
515 {
516 // den Bereich beenden
517 if( !bLFStripped )
518 StripTrailingPara();
519 pPam->Move( fnMoveForward );
520 return sal_True;
521 }
522
523 ASSERT( sal_False, "Wrong PaM position ending a range" );
524
525 return sal_False;
526 }
527
EndSections(sal_Bool bLFStripped)528 sal_Bool SwHTMLParser::EndSections( sal_Bool bLFStripped )
529 {
530 sal_Bool bSectionClosed = sal_False;
531 sal_uInt16 nPos = aContexts.Count();
532 while( nPos>nContextStMin )
533 {
534 _HTMLAttrContext *pCntxt = aContexts[--nPos];
535 if( pCntxt->GetSpansSection() && EndSection( bLFStripped ) )
536 {
537 bSectionClosed = sal_True;
538 pCntxt->SetSpansSection( sal_False );
539 bLFStripped = sal_False;
540 }
541 }
542
543 return bSectionClosed;
544 }
545
546 /* */
547
NewMultiCol()548 void SwHTMLParser::NewMultiCol()
549 {
550 String aId, aStyle, aClass, aLang, aDir;
551 long nWidth = 100;
552 sal_uInt16 nCols = 0, nGutter = 10;
553 sal_Bool bPrcWidth = sal_True;
554
555 const HTMLOptions *pHTMLOptions = GetOptions();
556 sal_uInt16 i;
557
558 for( i = pHTMLOptions->Count(); i; )
559 {
560 const HTMLOption *pOption = (*pHTMLOptions)[--i];
561 switch( pOption->GetToken() )
562 {
563 case HTML_O_ID:
564 aId = pOption->GetString();
565 break;
566 case HTML_O_STYLE:
567 aStyle = pOption->GetString();
568 break;
569 case HTML_O_CLASS:
570 aClass = pOption->GetString();
571 break;
572 case HTML_O_LANG:
573 aLang = pOption->GetString();
574 break;
575 case HTML_O_DIR:
576 aDir = pOption->GetString();
577 break;
578 case HTML_O_COLS:
579 nCols = (sal_uInt16)pOption->GetNumber();
580 break;
581 case HTML_O_WIDTH:
582 nWidth = pOption->GetNumber();
583 bPrcWidth = (pOption->GetString().Search('%') != STRING_NOTFOUND);
584 if( bPrcWidth && nWidth>100 )
585 nWidth = 100;
586 break;
587 case HTML_O_GUTTER:
588 nGutter = (sal_uInt16)pOption->GetNumber();
589 break;
590
591 }
592 }
593
594 _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_MULTICOL_ON );
595
596 //.is the multicol elememt contained in a container? That may be the
597 // case for 5.0 documents.
598 sal_Bool bInCntnr = sal_False;
599 i = aContexts.Count();
600 while( !bInCntnr && i > nContextStMin )
601 bInCntnr = 0 != aContexts[--i]->GetFrmItemSet();
602
603 // Parse style sheets, but don't position anything by now.
604 sal_Bool bStyleParsed = sal_False;
605 SfxItemSet aItemSet( pDoc->GetAttrPool(), pCSS1Parser->GetWhichMap() );
606 SvxCSS1PropertyInfo aPropInfo;
607 if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
608 bStyleParsed = ParseStyleOptions( aStyle, aId, aClass,
609 aItemSet, aPropInfo, &aLang, &aDir );
610
611 // Calculate width.
612 sal_uInt8 nPrcWidth = bPrcWidth ? (sal_uInt8)nWidth : 0;
613 sal_uInt16 nTwipWidth = 0;
614 if( !bPrcWidth && nWidth && Application::GetDefaultDevice() )
615 {
616 nTwipWidth = (sal_uInt16)Application::GetDefaultDevice()
617 ->PixelToLogic( Size(nWidth, 0),
618 MapMode(MAP_TWIP) ).Width();
619 }
620
621 if( !nPrcWidth && nTwipWidth < MINFLY )
622 nTwipWidth = MINFLY;
623
624 // Do positioning.
625 sal_Bool bPositioned = sal_False;
626 if( bInCntnr || pCSS1Parser->MayBePositioned( aPropInfo, sal_True ) )
627 {
628 SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
629 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
630 if( !IsNewDoc() )
631 Reader::ResetFrmFmtAttrs(aFrmItemSet );
632
633 SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, aItemSet, aPropInfo,
634 aFrmItemSet );
635
636 // The width is either the WIDTH attribute's value or contained
637 // in some style option.
638 SetVarSize( aItemSet, aPropInfo, aFrmItemSet, nTwipWidth, nPrcWidth );
639
640 SetSpace( Size(0,0), aItemSet, aPropInfo, aFrmItemSet );
641
642 // Set some other frame attributes. If the background is set, its
643 // it will be cleared here. That for, it won't be set at the section,
644 // too.
645 SetFrmFmtAttrs( aItemSet, aPropInfo,
646 HTML_FF_BOX|HTML_FF_BACKGROUND|HTML_FF_PADDING|HTML_FF_DIRECTION,
647 aFrmItemSet );
648
649 // Insert fly frame. If the are columns, the fly frame's name is not
650 // the sections name but a generated one.
651 String aFlyName( aEmptyStr );
652 if( nCols < 2 )
653 {
654 aFlyName = aId;
655 aPropInfo.aId.Erase();
656 }
657
658 InsertFlyFrame( aFrmItemSet, pCntxt, aFlyName, CONTEXT_FLAGS_ABSPOS );
659
660 pCntxt->SetPopStack( sal_True );
661 bPositioned = sal_True;
662 }
663
664 sal_Bool bAppended = sal_False;
665 if( !bPositioned )
666 {
667 if( pPam->GetPoint()->nContent.GetIndex() )
668 {
669 AppendTxtNode( AM_SPACE );
670 bAppended = sal_True;
671 }
672 else
673 {
674 AddParSpace();
675 }
676 }
677
678 // If there are less then 2 columns, no section is inserted.
679 if( nCols >= 2 )
680 {
681 if( !bAppended )
682 {
683 // If the pam is at the start of a section, a additional text
684 // node must be inserted. Otherwise, the new section will be
685 // inserted in front of the old one.
686 SwNodeIndex aPrvNdIdx( pPam->GetPoint()->nNode, -1 );
687 if (aPrvNdIdx.GetNode().IsSectionNode())
688 {
689 AppendTxtNode();
690 bAppended = sal_True;
691 }
692 }
693 _HTMLAttrs *pPostIts = bAppended ? 0 : new _HTMLAttrs;
694 SetAttr( sal_True, sal_True, pPostIts );
695
696 // Make section name unique.
697 String aName( pDoc->GetUniqueSectionName( aId.Len() ? &aId : 0 ) );
698 SwSectionData aSection( CONTENT_SECTION, aName );
699
700 SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
701 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
702 if( !IsNewDoc() )
703 Reader::ResetFrmFmtAttrs(aFrmItemSet );
704
705 if( nGutter && Application::GetDefaultDevice() )
706 {
707 nGutter = (sal_uInt16)Application::GetDefaultDevice()
708 ->PixelToLogic( Size(nGutter, 0),
709 MapMode(MAP_TWIP) ).Width();
710 }
711
712 SwFmtCol aFmtCol;
713 #ifndef WIDTH_SUPPORTED_BY_SECTIONS
714 nPrcWidth = 100;
715 #endif
716
717 aFmtCol.Init( nCols, nGutter, nPrcWidth ? USHRT_MAX : nTwipWidth );
718 aFrmItemSet.Put( aFmtCol );
719
720 const SfxPoolItem *pItem;
721 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_BACKGROUND, sal_False,
722 &pItem ) )
723 {
724 aFrmItemSet.Put( *pItem );
725 aItemSet.ClearItem( RES_BACKGROUND );
726 }
727 if( SFX_ITEM_SET == aItemSet.GetItemState( RES_FRAMEDIR, sal_False,
728 &pItem ) )
729 {
730 aFrmItemSet.Put( *pItem );
731 aItemSet.ClearItem( RES_FRAMEDIR );
732 }
733 pDoc->InsertSwSection( *pPam, aSection, 0, &aFrmItemSet, false );
734
735 // Jump to section, if this is requested.
736 if( JUMPTO_REGION == eJumpTo && aName == sJmpMark )
737 {
738 bChkJumpMark = sal_True;
739 eJumpTo = JUMPTO_NONE;
740 }
741
742 SwTxtNode* pOldTxtNd =
743 (bAppended) ? 0 : pPam->GetPoint()->nNode.GetNode().GetTxtNode();
744
745 pPam->Move( fnMoveBackward );
746
747 // Move PageDesc and SwFmtBreak attributes of the current node
748 // to the section's first node.
749 if( pOldTxtNd )
750 MovePageDescAttrs( pOldTxtNd, pPam->GetPoint()->nNode.GetIndex(),
751 sal_True );
752
753 if( pPostIts )
754 {
755 // Move pending PostIts into the section.
756 InsertAttrs( *pPostIts );
757 delete pPostIts;
758 pPostIts = 0;
759 }
760
761 pCntxt->SetSpansSection( sal_True );
762
763 // Insert a bookmark if its name differs from the section's name only.
764 if( aPropInfo.aId.Len() && aPropInfo.aId==aName )
765 aPropInfo.aId.Erase();
766 }
767
768 // Additional attributes must be set as hard ones.
769 if( bStyleParsed )
770 InsertAttrs( aItemSet, aPropInfo, pCntxt, sal_True );
771
772 PushContext( pCntxt );
773 }
774
775 /* */
776
InsertFlyFrame(const SfxItemSet & rItemSet,_HTMLAttrContext * pCntxt,const String & rName,sal_uInt16 nFlags)777 void SwHTMLParser::InsertFlyFrame( const SfxItemSet& rItemSet,
778 _HTMLAttrContext *pCntxt,
779 const String& rName,
780 sal_uInt16 nFlags )
781 {
782 RndStdIds eAnchorId =
783 ((const SwFmtAnchor&)rItemSet.Get( RES_ANCHOR )).GetAnchorId();
784
785 // Den Rahmen anlegen
786 SwFlyFrmFmt* pFlyFmt = pDoc->MakeFlySection( eAnchorId, pPam->GetPoint(),
787 &rItemSet );
788 // Ggf. den Namen setzen
789 if( rName.Len() )
790 pFlyFmt->SetName( rName );
791
792 RegisterFlyFrm( pFlyFmt );
793
794 const SwFmtCntnt& rFlyCntnt = pFlyFmt->GetCntnt();
795 const SwNodeIndex& rFlyCntIdx = *rFlyCntnt.GetCntntIdx();
796 SwCntntNode *pCNd = pDoc->GetNodes()[rFlyCntIdx.GetIndex()+1]
797 ->GetCntntNode();
798
799 SwPosition aNewPos( SwNodeIndex( rFlyCntIdx, 1 ), SwIndex( pCNd, 0 ) );
800 SaveDocContext( pCntxt, nFlags, &aNewPos );
801 }
802
803
804 /* */
805
MovePageDescAttrs(SwNode * pSrcNd,sal_uLong nDestIdx,sal_Bool bFmtBreak)806 void SwHTMLParser::MovePageDescAttrs( SwNode *pSrcNd,
807 sal_uLong nDestIdx,
808 sal_Bool bFmtBreak )
809 {
810 SwCntntNode* pDestCntntNd =
811 pDoc->GetNodes()[nDestIdx]->GetCntntNode();
812
813 ASSERT( pDestCntntNd, "Wieso ist das Ziel kein Content-Node?" );
814
815 if( pSrcNd->IsCntntNode() )
816 {
817 SwCntntNode* pSrcCntntNd = pSrcNd->GetCntntNode();
818
819 const SfxPoolItem* pItem;
820 if( SFX_ITEM_SET == pSrcCntntNd->GetSwAttrSet()
821 .GetItemState( RES_PAGEDESC, sal_False, &pItem ) &&
822 ((SwFmtPageDesc *)pItem)->GetPageDesc() )
823 {
824 pDestCntntNd->SetAttr( *pItem );
825 pSrcCntntNd->ResetAttr( RES_PAGEDESC );
826 }
827 if( SFX_ITEM_SET == pSrcCntntNd->GetSwAttrSet()
828 .GetItemState( RES_BREAK, sal_False, &pItem ) )
829 {
830 switch( ((SvxFmtBreakItem *)pItem)->GetBreak() )
831 {
832 case SVX_BREAK_PAGE_BEFORE:
833 case SVX_BREAK_PAGE_AFTER:
834 case SVX_BREAK_PAGE_BOTH:
835 if( bFmtBreak )
836 pDestCntntNd->SetAttr( *pItem );
837 pSrcCntntNd->ResetAttr( RES_BREAK );
838 default:
839 ;
840 }
841 }
842 }
843 else if( pSrcNd->IsTableNode() )
844 {
845 SwFrmFmt *pFrmFmt = pSrcNd->GetTableNode()->GetTable().GetFrmFmt();
846
847 const SfxPoolItem* pItem;
848 if( SFX_ITEM_SET == pFrmFmt->GetAttrSet().
849 GetItemState( RES_PAGEDESC, sal_False, &pItem ) )
850 {
851 pDestCntntNd->SetAttr( *pItem );
852 pFrmFmt->ResetFmtAttr( RES_PAGEDESC );
853 }
854 }
855 }
856
857