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