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