xref: /AOO41X/main/sw/source/filter/html/htmlctxt.cxx (revision efeef26f81c84063fb0a91bde3856d4a51172d90)
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 
28 #include "hintids.hxx"
29 #include <svl/itemiter.hxx>
30 #include <editeng/lrspitem.hxx>
31 #include <editeng/ulspitem.hxx>
32 #include <editeng/brshitem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <svtools/htmltokn.h>
35 
36 #include "doc.hxx"
37 #include "pam.hxx"
38 #include "ndtxt.hxx"
39 #include "shellio.hxx"
40 #include "paratr.hxx"
41 #include "htmlnum.hxx"
42 #include "css1kywd.hxx"
43 #include "swcss1.hxx"
44 #include "swhtml.hxx"
45 
46 using namespace ::com::sun::star;
47 
48 
49 /*  */
50 
51 
52 class _HTMLAttrContext_SaveDoc
53 {
54     SwHTMLNumRuleInfo aNumRuleInfo; // In Umgebung gueltige Numerierung
55     SwPosition  *pPos;              // hierhin beim verlassen den
56                                     // Kontexts zurueckgesprungen
57     _HTMLAttrTable *pAttrTab;       // In Umgebung gueltige Attribute,
58                                     // wenn Attributierung nicht
59                                     // beibehalten werden soll.
60 
61     sal_uInt16 nContextStMin;           // In Umgebung gueltige Stack-
62                                     // Untergrenze, wenn der Stack
63                                     // geschuetzt werden soll.
64     sal_uInt16 nContextStAttrMin;       // In Umgebung gueltige Stack-
65                                     // Untergrenze, wenn die Attribute
66                                     // nicht beibehalten werden sollen.
67 
68     sal_Bool bStripTrailingPara : 1;    // letzen Absatz entfernen?
69     sal_Bool bKeepNumRules : 1;         // Numerierung beibehalten?
70     sal_Bool bPopStack : 1;             // Stack-Elemente oberhalb des
71                                     // zu schliessenden entfernen?
72     sal_Bool bFixHeaderDist : 1;
73     sal_Bool bFixFooterDist : 1;
74 
75 public:
76 
_HTMLAttrContext_SaveDoc()77     _HTMLAttrContext_SaveDoc() :
78         pPos( 0 ), pAttrTab( 0 ),
79         nContextStMin( USHRT_MAX ), nContextStAttrMin( USHRT_MAX ),
80         bStripTrailingPara( sal_False ), bKeepNumRules( sal_False ),
81         bPopStack( sal_False ),
82         bFixHeaderDist( sal_False ), bFixFooterDist( sal_False )
83     {}
84 
~_HTMLAttrContext_SaveDoc()85     ~_HTMLAttrContext_SaveDoc() { delete pPos; delete pAttrTab; }
86 
87     // Die Position gehoert uns, muss also angelegt und zerstoert werden
SetPos(const SwPosition & rPos)88     void SetPos( const SwPosition& rPos ) { pPos = new SwPosition(rPos); }
GetPos() const89     const SwPosition *GetPos() const { return pPos; }
90 
91     // Der Index gehoert uns nicht. Kein Anlgen und Zerstoeren.
SetNumInfo(const SwHTMLNumRuleInfo & rInf)92     void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { aNumRuleInfo.Set(rInf); }
GetNumInfo() const93     const SwHTMLNumRuleInfo& GetNumInfo() const { return aNumRuleInfo; }
94 
95     _HTMLAttrTable *GetAttrTab( sal_Bool bCreate= sal_False );
96 
SetContextStMin(sal_uInt16 nMin)97     void SetContextStMin( sal_uInt16 nMin ) { nContextStMin = nMin; }
GetContextStMin() const98     sal_uInt16 GetContextStMin() const { return nContextStMin; }
99 
SetContextStAttrMin(sal_uInt16 nMin)100     void SetContextStAttrMin( sal_uInt16 nMin ) { nContextStAttrMin = nMin; }
GetContextStAttrMin() const101     sal_uInt16 GetContextStAttrMin() const { return nContextStAttrMin; }
102 
SetStripTrailingPara(sal_Bool bSet)103     void SetStripTrailingPara( sal_Bool bSet ) { bStripTrailingPara = bSet; }
GetStripTrailingPara() const104     sal_Bool GetStripTrailingPara() const { return bStripTrailingPara; }
105 
SetKeepNumRules(sal_Bool bSet)106     void SetKeepNumRules( sal_Bool bSet ) { bKeepNumRules = bSet; }
GetKeepNumRules() const107     sal_Bool GetKeepNumRules() const { return bKeepNumRules; }
108 
SetFixHeaderDist(sal_Bool bSet)109     void SetFixHeaderDist( sal_Bool bSet ) { bFixHeaderDist = bSet; }
GetFixHeaderDist() const110     sal_Bool GetFixHeaderDist() const { return bFixHeaderDist; }
111 
SetFixFooterDist(sal_Bool bSet)112     void SetFixFooterDist( sal_Bool bSet ) { bFixFooterDist = bSet; }
GetFixFooterDist() const113     sal_Bool GetFixFooterDist() const { return bFixFooterDist; }
114 };
115 
GetAttrTab(sal_Bool bCreate)116 _HTMLAttrTable *_HTMLAttrContext_SaveDoc::GetAttrTab( sal_Bool bCreate )
117 {
118     if( !pAttrTab && bCreate )
119     {
120         pAttrTab = new _HTMLAttrTable;
121         memset( pAttrTab, 0, sizeof( _HTMLAttrTable ));
122     }
123     return pAttrTab;
124 }
125 
126 /*  */
127 
GetSaveDocContext(sal_Bool bCreate)128 _HTMLAttrContext_SaveDoc *_HTMLAttrContext::GetSaveDocContext( sal_Bool bCreate )
129 {
130     if( !pSaveDocContext && bCreate )
131         pSaveDocContext = new _HTMLAttrContext_SaveDoc;
132 
133     return pSaveDocContext;
134 }
135 
ClearSaveDocContext()136 void _HTMLAttrContext::ClearSaveDocContext()
137 {
138     delete pSaveDocContext;
139     pSaveDocContext = 0;
140 }
141 
142 /*  */
143 
SplitAttrTab(const SwPosition & rNewPos)144 void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos )
145 {
146     // Hier darf es keine vorlauefigen Absatz-Attribute geben, den die
147     // koennten jetzt gesetzt werden und dann sind die Zeiger ungueltig!!!
148     ASSERT( !aParaAttrs.Count(),
149         "Hoechste Gefahr: Es gibt noch nicht-endgueltige Absatz-Attribute" );
150     if( aParaAttrs.Count() )
151         aParaAttrs.Remove( 0, aParaAttrs.Count() );
152 
153     const SwNodeIndex* pOldEndPara = &pPam->GetPoint()->nNode;
154     xub_StrLen nOldEndCnt = pPam->GetPoint()->nContent.GetIndex();
155 
156     const SwNodeIndex& rNewSttPara = rNewPos.nNode;
157     xub_StrLen nNewSttCnt = rNewPos.nContent.GetIndex();
158 
159     sal_Bool bMoveBack = sal_False;
160 
161     // alle noch offenen Attribute beenden und hinter der Tabelle
162     // neu aufspannen
163     _HTMLAttr** pTbl = (_HTMLAttr**)&aAttrTab;
164     for( sal_uInt16 nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
165             nCnt--; ++pTbl )
166     {
167         _HTMLAttr *pAttr = *pTbl;
168         while( pAttr )
169         {
170             _HTMLAttr *pNext = pAttr->GetNext();
171             _HTMLAttr *pPrev = pAttr->GetPrev();
172 
173             sal_uInt16 nWhich = pAttr->pItem->Which();
174             if( !nOldEndCnt && RES_PARATR_BEGIN <= nWhich &&
175                 pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() )
176             {
177                 // Das Attribut muss eine Content-Position weiter vorne
178                 // beendet werden
179                 if( !bMoveBack )
180                 {
181                     bMoveBack = pPam->Move( fnMoveBackward );
182                     nOldEndCnt = pPam->GetPoint()->nContent.GetIndex();
183                 }
184             }
185             else if( bMoveBack )
186             {
187                 pPam->Move( fnMoveForward );
188                 nOldEndCnt = pPam->GetPoint()->nContent.GetIndex();
189             }
190 
191             if( (RES_PARATR_BEGIN <= nWhich && bMoveBack) ||
192                 pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() ||
193                 (pAttr->GetSttPara() == *pOldEndPara &&
194                  pAttr->GetSttCnt() != nOldEndCnt) )
195             {
196                 // Das Attribut muss gesetzt werden. Da wir
197                 // das Original noch brauchen, weil Zeiger auf das Attribut
198                 // noch in den Kontexten existieren, muessen wir es clonen.
199                 // Die Next-Liste geht dabei verloren, aber die
200                 // Previous-Liste bleibt erhalten
201                 _HTMLAttr *pSetAttr = pAttr->Clone( *pOldEndPara, nOldEndCnt );
202 
203                 if( pNext )
204                     pNext->InsertPrev( pSetAttr );
205                 else
206                 {
207                     sal_uInt16 nTmp =
208                         pSetAttr->bInsAtStart ? 0 : aSetAttrTab.Count();
209                     aSetAttrTab.Insert( pSetAttr, nTmp );
210                 }
211             }
212             else if( pPrev )
213             {
214                 // Wenn das Attribut nicht gesetzt vor der Tabelle
215                 // gesetzt werden muss, muessen der Previous-Attribute
216                 // trotzdem gesetzt werden.
217                 if( pNext )
218                     pNext->InsertPrev( pPrev );
219                 else
220                 {
221                     sal_uInt16 nTmp = pPrev->bInsAtStart ? 0 : aSetAttrTab.Count();
222                     aSetAttrTab.Insert( pPrev, nTmp );
223                 }
224             }
225 
226             // den Start des Attributs neu setzen
227             pAttr->nSttPara = rNewSttPara;
228             pAttr->nEndPara = rNewSttPara;
229             pAttr->nSttCntnt = nNewSttCnt;
230             pAttr->nEndCntnt = nNewSttCnt;
231             pAttr->pPrev = 0;
232 
233             pAttr = pNext;
234         }
235     }
236 
237     if( bMoveBack )
238         pPam->Move( fnMoveForward );
239 
240 }
241 
SaveDocContext(_HTMLAttrContext * pCntxt,sal_uInt16 nFlags,const SwPosition * pNewPos)242 void SwHTMLParser::SaveDocContext( _HTMLAttrContext *pCntxt,
243                                    sal_uInt16 nFlags,
244                                    const SwPosition *pNewPos )
245 {
246     _HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext( sal_True );
247     pSave->SetStripTrailingPara( (HTML_CNTXT_STRIP_PARA & nFlags) != 0 );
248     pSave->SetKeepNumRules( (HTML_CNTXT_KEEP_NUMRULE & nFlags) != 0 );
249     pSave->SetFixHeaderDist( (HTML_CNTXT_HEADER_DIST & nFlags) != 0 );
250     pSave->SetFixFooterDist( (HTML_CNTXT_FOOTER_DIST & nFlags) != 0 );
251 
252     if( pNewPos )
253     {
254         // Wenn der PaM an eine andere Position gesetzt wird, muss
255         // die Numerierung gerettet werden..
256         if( !pSave->GetKeepNumRules() )
257         {
258             // Die Numerierung soll nicht beibehalten werden. Also muss
259             // der aktuelle Zustand gerettet und die Numerierung
260             // anschliessend ausgeschaltet werden.
261             pSave->SetNumInfo( GetNumInfo() );
262             GetNumInfo().Clear();
263         }
264 
265         if( (HTML_CNTXT_KEEP_ATTRS & nFlags) != 0 )
266         {
267             // Attribute an aktueller Position beenden und an neuer neu anfangen
268             SplitAttrTab( *pNewPos );
269         }
270         else
271         {
272             _HTMLAttrTable *pSaveAttrTab = pSave->GetAttrTab( sal_True );
273             SaveAttrTab( *pSaveAttrTab );
274         }
275 
276 
277         pSave->SetPos( *pPam->GetPoint() );
278         *pPam->GetPoint() = *pNewPos;
279     }
280 
281     // Mit dem Setzen von nContextStMin koennen automatisch auch
282     // keine gerade offenen Listen (DL/OL/UL) mehr beendet werden.
283     if( (HTML_CNTXT_PROTECT_STACK & nFlags) != 0  )
284     {
285         pSave->SetContextStMin( nContextStMin );
286         nContextStMin = aContexts.Count();
287 
288         if( (HTML_CNTXT_KEEP_ATTRS & nFlags) == 0 )
289         {
290             pSave->SetContextStAttrMin( nContextStAttrMin );
291             nContextStAttrMin = aContexts.Count();
292         }
293     }
294 }
295 
RestoreDocContext(_HTMLAttrContext * pCntxt)296 void SwHTMLParser::RestoreDocContext( _HTMLAttrContext *pCntxt )
297 {
298     _HTMLAttrContext_SaveDoc *pSave = pCntxt->GetSaveDocContext();
299     if( !pSave )
300         return;
301 
302     if( pSave->GetStripTrailingPara() )
303         StripTrailingPara();
304 
305     if( pSave->GetPos() )
306     {
307         if( pSave->GetFixHeaderDist() || pSave->GetFixFooterDist() )
308             FixHeaderFooterDistance( pSave->GetFixHeaderDist(),
309                                      pSave->GetPos() );
310 
311         _HTMLAttrTable *pSaveAttrTab = pSave->GetAttrTab();
312         if( !pSaveAttrTab )
313         {
314             // Attribute an aktueller Position beenden und an alter neu
315             // anfangen.
316             SplitAttrTab( *pSave->GetPos() );
317         }
318         else
319         {
320             RestoreAttrTab( *pSaveAttrTab );
321         }
322 
323         *pPam->GetPoint() = *pSave->GetPos();
324 
325         // Die bisherigen Attribute koennen wir schonmal setzen.
326         SetAttr();
327     }
328 
329     if( USHRT_MAX != pSave->GetContextStMin() )
330     {
331         nContextStMin = pSave->GetContextStMin();
332         if( USHRT_MAX != pSave->GetContextStAttrMin() )
333             nContextStAttrMin = pSave->GetContextStAttrMin();
334     }
335 
336     if( !pSave->GetKeepNumRules() )
337     {
338         // Die bisherige gemerkte Numerierung wieder setzen
339         GetNumInfo().Set( pSave->GetNumInfo() );
340     }
341 
342     pCntxt->ClearSaveDocContext();
343 }
344 
345 /*  */
346 
EndContext(_HTMLAttrContext * pContext)347 void SwHTMLParser::EndContext( _HTMLAttrContext *pContext )
348 {
349     if( pContext->GetPopStack() )
350     {
351         // Alle noch offenen Kontexte beenden. Der eigene
352         // Kontext muss bereits geloscht sein!
353         while( aContexts.Count() > nContextStMin )
354         {
355             _HTMLAttrContext *pCntxt = PopContext();
356             ASSERT( pCntxt != pContext,
357                     "Kontext noch im Stack" );
358             if( pCntxt == pContext )
359                 break;
360 
361             EndContext( pCntxt );
362             delete pCntxt;
363         }
364     }
365 
366     // Alle noch offenen Attribute beenden
367     if( pContext->HasAttrs() )
368         EndContextAttrs( pContext );
369 
370     // Falls ein Bereich geoeffnet wurde, den verlassen. Da Bereiche
371     // auch innerhalb von absolut positionierten Objekten angelegt werden,
372     // muss das passieren, bever ein alter Dokument-Kontext restauriert wird.
373     if( pContext->GetSpansSection() )
374         EndSection();
375 
376     // Rahmen und sonstige Sonderbereiche verlassen.
377     if( pContext->HasSaveDocContext() )
378         RestoreDocContext( pContext );
379 
380     // Ggf. noch einen Ansatz-Umbruch einfuegen
381     if( AM_NONE != pContext->GetAppendMode() &&
382         pPam->GetPoint()->nContent.GetIndex() )
383         AppendTxtNode( pContext->GetAppendMode() );
384 
385     // PRE-/LISTING- und XMP-Umgebungen wieder starten
386     if( pContext->IsFinishPREListingXMP() )
387         FinishPREListingXMP();
388 
389     if( pContext->IsRestartPRE() )
390         StartPRE();
391 
392     if( pContext->IsRestartXMP() )
393         StartXMP();
394 
395     if( pContext->IsRestartListing() )
396         StartListing();
397 }
398 
ClearContext(_HTMLAttrContext * pContext)399 void SwHTMLParser::ClearContext( _HTMLAttrContext *pContext )
400 {
401     _HTMLAttrs &rAttrs = pContext->GetAttrs();
402     for( sal_uInt16 i=0; i<rAttrs.Count(); i++ )
403     {
404         // einfaches Loeschen reicht hier nicht, weil das
405         // Attribut auch aus seiner Liste ausgetragen werden
406         // muss. Theoretisch koennt man natuerlich auch die Liste
407         // und die Attribute getrennt loeschen, aber wenn man
408         // dann was falsch gemacht hat, sieht es uebel aus.
409         DeleteAttr( rAttrs[i] );
410     }
411 
412     ASSERT( !pContext->GetSpansSection(),
413             "Bereich kann nicht mehr verlassen werden" );
414 
415     ASSERT( !pContext->HasSaveDocContext(),
416             "Rahmen kann nicht mehr verlassen werden" );
417 
418     // PRE-/LISTING- und XMP-Umgebungen wieder starten
419     if( pContext->IsFinishPREListingXMP() )
420         FinishPREListingXMP();
421 
422     if( pContext->IsRestartPRE() )
423         StartPRE();
424 
425     if( pContext->IsRestartXMP() )
426         StartXMP();
427 
428     if( pContext->IsRestartListing() )
429         StartListing();
430 }
431 
432 /*  */
433 
DoPositioning(SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,_HTMLAttrContext * pContext)434 sal_Bool SwHTMLParser::DoPositioning( SfxItemSet &rItemSet,
435                                   SvxCSS1PropertyInfo &rPropInfo,
436                                   _HTMLAttrContext *pContext )
437 {
438     sal_Bool bRet = sal_False;
439 
440     // Unter folgenden Umstaenden wird jetzt ein Rahmen aufgemacht:
441     // - das Tag wird absolut positioniert und left/top sind beide
442     //   gegeben und enthalten auch keine %-Angabe, oder
443     // - das Tag soll fliessen, und
444     // - es wurde eine Breite angegeben (in beiden Faellen noetig)
445     if( SwCSS1Parser::MayBePositioned( rPropInfo ) )
446     {
447         SfxItemSet aFrmItemSet( pDoc->GetAttrPool(),
448                                 RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
449         if( !IsNewDoc() )
450             Reader::ResetFrmFmtAttrs(aFrmItemSet );
451 
452         // Ausrichtung setzen
453         SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE, rItemSet, rPropInfo,
454                                 aFrmItemSet );
455 
456         // Groesse setzen
457         SetVarSize( rItemSet, rPropInfo, aFrmItemSet );
458 
459         // Abstaende setzen
460         SetSpace( Size(0,0), rItemSet, rPropInfo, aFrmItemSet );
461 
462         // Sonstige CSS1-Attribute Setzen
463         SetFrmFmtAttrs( rItemSet, rPropInfo,
464                         HTML_FF_BOX|HTML_FF_PADDING|HTML_FF_BACKGROUND|HTML_FF_DIRECTION,
465                         aFrmItemSet );
466 
467         InsertFlyFrame( aFrmItemSet, pContext, rPropInfo.aId,
468                         CONTEXT_FLAGS_ABSPOS );
469         pContext->SetPopStack( sal_True );
470         rPropInfo.aId.Erase();
471         bRet = sal_True;
472     }
473 
474     return bRet;
475 }
476 
CreateContainer(const String & rClass,SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,_HTMLAttrContext * pContext)477 sal_Bool SwHTMLParser::CreateContainer( const String& rClass,
478                                     SfxItemSet &rItemSet,
479                                     SvxCSS1PropertyInfo &rPropInfo,
480                                     _HTMLAttrContext *pContext )
481 {
482     sal_Bool bRet = sal_False;
483     if( rClass.EqualsIgnoreCaseAscii(sCSS1_class_abs_pos) &&
484         pCSS1Parser->MayBePositioned( rPropInfo ) )
485     {
486         // Container-Klasse
487         SfxItemSet *pFrmItemSet = pContext->GetFrmItemSet( pDoc );
488         if( !IsNewDoc() )
489             Reader::ResetFrmFmtAttrs( *pFrmItemSet );
490 
491         SetAnchorAndAdjustment( text::VertOrientation::NONE, text::HoriOrientation::NONE,
492                                 rItemSet, rPropInfo, *pFrmItemSet );
493         Size aDummy(0,0);
494         SetFixSize( aDummy, aDummy, sal_False, sal_False, rItemSet, rPropInfo,
495                     *pFrmItemSet );
496         SetSpace( aDummy, rItemSet, rPropInfo, *pFrmItemSet );
497         SetFrmFmtAttrs( rItemSet, rPropInfo, HTML_FF_BOX|HTML_FF_BACKGROUND|HTML_FF_DIRECTION,
498                         *pFrmItemSet );
499 
500         bRet = sal_True;
501     }
502 
503     return bRet;
504 }
505 
506 /*  */
507 
InsertAttrs(SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,_HTMLAttrContext * pContext,sal_Bool bCharLvl)508 void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet,
509                                 SvxCSS1PropertyInfo &rPropInfo,
510                                 _HTMLAttrContext *pContext,
511                                 sal_Bool bCharLvl )
512 {
513     // Ein DropCap-Attribut basteln, wenn auf Zeichen-Ebene vor dem
514     // ersten Zeichen ein float: left vorkommt
515     if( bCharLvl && !pPam->GetPoint()->nContent.GetIndex() &&
516         SVX_ADJUST_LEFT == rPropInfo.eFloat )
517     {
518         SwFmtDrop aDrop;
519         aDrop.GetChars() = 1;
520 
521         pCSS1Parser->FillDropCap( aDrop, rItemSet );
522 
523         // Nur wenn das Initial auch ueber mehrere Zeilen geht, wird das
524         // DropCap-Attribut gesetzt. Sonst setzten wir die Attribute hart.
525         if( aDrop.GetLines() > 1 )
526         {
527             NewAttr( &aAttrTab.pDropCap, aDrop );
528 
529             _HTMLAttrs &rAttrs = pContext->GetAttrs();
530             rAttrs.Insert( aAttrTab.pDropCap, rAttrs.Count() );
531 
532             return;
533         }
534     }
535 
536 // Feature: PrintExt
537     if( !bCharLvl )
538         pCSS1Parser->SetFmtBreak( rItemSet, rPropInfo );
539 // /Feature: PrintExt
540 
541     ASSERT( aContexts.Count() <= nContextStAttrMin ||
542             aContexts[aContexts.Count()-1] != pContext,
543             "SwHTMLParser::InsertAttrs: Kontext doch schon auf dem Stack" );
544 
545     SfxItemIter aIter( rItemSet );
546 
547     const SfxPoolItem *pItem = aIter.FirstItem();
548     while( pItem )
549     {
550         _HTMLAttr **ppAttr = 0;
551 
552         switch( pItem->Which() )
553         {
554         case RES_LR_SPACE:
555             {
556                 // Absatz-Einzuege muessen addiert werden und werden immer
557                 // nur absatzweise gesetzt (fuer den ersten Absatz hier,
558                 // fuer alle folgenden in SetTxtCollAttrs)
559 
560                 const SvxLRSpaceItem *pLRItem =
561                     (const SvxLRSpaceItem *)pItem;
562 
563                 // die bisherigen Absatz-Abstaende holen (ohne die vom
564                 // obersten Kontext, denn den veraendern wir ja gerade) ...
565                 sal_uInt16 nOldLeft = 0, nOldRight = 0;
566                 short nOldIndent = 0;
567                 sal_Bool bIgnoreTop = aContexts.Count() > nContextStMin &&
568                                   aContexts[aContexts.Count()-1] == pContext;
569                 GetMarginsFromContext( nOldLeft, nOldRight, nOldIndent,
570                                        bIgnoreTop  );
571 
572 
573                 // und noch die aktuell gueltigen
574                 sal_uInt16 nLeft = nOldLeft, nRight = nOldRight;
575                 short nIndent = nOldIndent;
576                 pContext->GetMargins( nLeft, nRight, nIndent );
577 
578                 // ... und die neuen Abstaende zu den alten addieren
579                 // Hier werden nicht die aus dem Item genommen, sondern die
580                 // extra gemerkten, weil die auch negativ sein koennen. Die
581                 // Abfrage ueber das Item funktioniert aber trotzdem, denn
582                 // fuer negative Werte wird das Item (mit Wert 0) auch
583                 // eingefuegt.
584                 if( rPropInfo.bLeftMargin )
585                 {
586                     ASSERT( rPropInfo.nLeftMargin < 0 ||
587                             rPropInfo.nLeftMargin == pLRItem->GetTxtLeft(),
588                             "linker Abstand stimmt nicht mit Item ueberein" );
589                     if( rPropInfo.nLeftMargin < 0 &&
590                         -rPropInfo.nLeftMargin > nOldLeft )
591                         nLeft = 0;
592                     else
593                         nLeft = nOldLeft + static_cast< sal_uInt16 >(rPropInfo.nLeftMargin);
594                 }
595                 if( rPropInfo.bRightMargin )
596                 {
597                     ASSERT( rPropInfo.nRightMargin < 0 ||
598                             rPropInfo.nRightMargin == pLRItem->GetRight(),
599                             "rechter Abstand stimmt nicht mit Item ueberein" );
600                     if( rPropInfo.nRightMargin < 0 &&
601                         -rPropInfo.nRightMargin > nOldRight )
602                         nRight = 0;
603                     else
604                         nRight = nOldRight + static_cast< sal_uInt16 >(rPropInfo.nRightMargin);
605                 }
606                 if( rPropInfo.bTextIndent )
607                     nIndent = pLRItem->GetTxtFirstLineOfst();
608 
609                 // und die Werte fuer nachfolgende Absaetze merken
610                 pContext->SetMargins( nLeft, nRight, nIndent );
611 
612                 // das Attribut noch am aktuellen Absatz setzen
613                 SvxLRSpaceItem aLRItem( *pLRItem );
614                 aLRItem.SetTxtFirstLineOfst( nIndent );
615                 aLRItem.SetTxtLeft( nLeft );
616                 aLRItem.SetRight( nRight );
617                 NewAttr( &aAttrTab.pLRSpace, aLRItem );
618                 EndAttr( aAttrTab.pLRSpace, 0, sal_False );
619             }
620             break;
621 
622         case RES_UL_SPACE:
623             if( !rPropInfo.bTopMargin || !rPropInfo.bBottomMargin )
624             {
625                 sal_uInt16 nUpper = 0, nLower = 0;
626                 GetULSpaceFromContext( nUpper, nLower );
627                 SvxULSpaceItem aULSpace( *((const SvxULSpaceItem *)pItem) );
628                 if( !rPropInfo.bTopMargin )
629                     aULSpace.SetUpper( nUpper );
630                 if( !rPropInfo.bBottomMargin )
631                     aULSpace.SetLower( nLower );
632 
633                 NewAttr( &aAttrTab.pULSpace, aULSpace );
634 
635                 // ... und noch die Kontext-Information speichern
636                 _HTMLAttrs &rAttrs = pContext->GetAttrs();
637                 rAttrs.Insert( aAttrTab.pULSpace, rAttrs.Count() );
638 
639                 pContext->SetULSpace( aULSpace.GetUpper(), aULSpace.GetLower() );
640             }
641             else
642             {
643                 ppAttr = &aAttrTab.pULSpace;
644             }
645             break;
646         case RES_CHRATR_FONTSIZE:
647             // es werden keine Attribute mit %-Angaben gesetzt
648             if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 )
649                 ppAttr = &aAttrTab.pFontHeight;
650             break;
651         case RES_CHRATR_CJK_FONTSIZE:
652             // es werden keine Attribute mit %-Angaben gesetzt
653             if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 )
654                 ppAttr = &aAttrTab.pFontHeightCJK;
655             break;
656         case RES_CHRATR_CTL_FONTSIZE:
657             // es werden keine Attribute mit %-Angaben gesetzt
658             if( ((const SvxFontHeightItem *)pItem)->GetProp() == 100 )
659                 ppAttr = &aAttrTab.pFontHeightCTL;
660             break;
661 
662         case RES_BACKGROUND:
663             if( bCharLvl )
664             {
665                 // das Frame-Attr ggf. in ein Char-Attr umwandeln
666                 SvxBrushItem aBrushItem( *(const SvxBrushItem *)pItem );
667                 aBrushItem.SetWhich( RES_CHRATR_BACKGROUND );
668 
669                 // Das Attribut setzen ...
670                 NewAttr( &aAttrTab.pCharBrush, aBrushItem );
671 
672                 // ... und noch die Kontext-Information speichern
673                 _HTMLAttrs &rAttrs = pContext->GetAttrs();
674                 rAttrs.Insert( aAttrTab.pCharBrush, rAttrs.Count() );
675             }
676             else if( pContext->GetToken() != HTML_TABLEHEADER_ON &&
677                      pContext->GetToken() != HTML_TABLEDATA_ON )
678             {
679                 ppAttr = &aAttrTab.pBrush;
680             }
681             break;
682 
683         default:
684             // den zu dem Item gehoehrenden Tabellen-Eintrag ermitteln ...
685             ppAttr = GetAttrTabEntry( pItem->Which() );
686             break;
687         }
688 
689         if( ppAttr )
690         {
691             // Das Attribut setzen ...
692             NewAttr( ppAttr, *pItem );
693 
694             // ... und noch die Kontext-Information speichern
695             _HTMLAttrs &rAttrs = pContext->GetAttrs();
696             rAttrs.Insert( *ppAttr, rAttrs.Count() );
697         }
698 
699         // auf zum naechsten Item
700         pItem = aIter.NextItem();
701     }
702 
703     if( rPropInfo.aId.Len() )
704         InsertBookmark( rPropInfo.aId );
705 }
706 
InsertAttr(_HTMLAttr ** ppAttr,const SfxPoolItem & rItem,_HTMLAttrContext * pCntxt)707 void SwHTMLParser::InsertAttr( _HTMLAttr **ppAttr, const SfxPoolItem & rItem,
708                                _HTMLAttrContext *pCntxt )
709 {
710     if( !ppAttr )
711     {
712         ppAttr = GetAttrTabEntry( rItem.Which() );
713         if( !ppAttr )
714             return;
715     }
716 
717     // das Attribut setzen
718     NewAttr( ppAttr, rItem );
719 
720     // und im Kontext merken
721     _HTMLAttrs &rAttrs = pCntxt->GetAttrs();
722     rAttrs.Insert( *ppAttr, rAttrs.Count() );
723 }
724 
SplitPREListingXMP(_HTMLAttrContext * pCntxt)725 void SwHTMLParser::SplitPREListingXMP( _HTMLAttrContext *pCntxt )
726 {
727     // PRE/Listing/XMP soll beim beenden des Kontexts beendet werden.
728     pCntxt->SetFinishPREListingXMP( sal_True );
729 
730     // Und die jetzt gueltigen Flags sollen wieder gesetzt werden.
731     if( IsReadPRE() )
732         pCntxt->SetRestartPRE( sal_True );
733     if( IsReadXMP() )
734         pCntxt->SetRestartXMP( sal_True );
735     if( IsReadListing() )
736         pCntxt->SetRestartListing( sal_True );
737 
738     // PRE/Listing/XMP wird auuserdem sofort beendet
739     FinishPREListingXMP();
740 }
741 
GetFrmItemSet(SwDoc * pCreateDoc)742 SfxItemSet *_HTMLAttrContext::GetFrmItemSet( SwDoc *pCreateDoc )
743 {
744     if( !pFrmItemSet && pCreateDoc )
745         pFrmItemSet = new SfxItemSet( pCreateDoc->GetAttrPool(),
746                         RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
747     return pFrmItemSet;
748 }
749