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