xref: /AOO41X/main/sw/source/filter/html/htmlcss1.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 
29 #include "hintids.hxx"
30 #include <svl/itemiter.hxx>
31 #include <svl/whiter.hxx>
32 #include <svl/urihelper.hxx>
33 #include <i18npool/mslangid.hxx>
34 #include <sfx2/docfile.hxx>
35 #include <vcl/svapp.hxx>
36 #include <editeng/fhgtitem.hxx>
37 #include <editeng/brshitem.hxx>
38 #include <editeng/lrspitem.hxx>
39 #include <editeng/ulspitem.hxx>
40 #include <editeng/boxitem.hxx>
41 #include <editeng/fhgtitem.hxx>
42 #include <editeng/flstitem.hxx>
43 #include <editeng/brkitem.hxx>
44 #include <editeng/keepitem.hxx>
45 #include <editeng/fontitem.hxx>
46 #include <editeng/langitem.hxx>
47 #include <editeng/frmdiritem.hxx>
48 #include <svtools/htmltokn.h>
49 #include <svtools/htmlkywd.hxx>
50 #include <fmtpdsc.hxx>
51 #include <fmtanchr.hxx>
52 #include <fmtornt.hxx>
53 #include <fmtsrnd.hxx>
54 #include <fmtfsize.hxx>
55 #include "frmatr.hxx"
56 #include <charfmt.hxx>
57 #include <docary.hxx>
58 #include <svx/svxids.hrc>
59 
60 #include "doc.hxx"
61 #include "pam.hxx"
62 #include "ndtxt.hxx"
63 #include "poolfmt.hxx"
64 #include "docsh.hxx"
65 #include "paratr.hxx"
66 #include "pagedesc.hxx"
67 #include "css1kywd.hxx"
68 #include "swcss1.hxx"
69 #include "htmlnum.hxx"
70 #include "swhtml.hxx"
71 #include <numrule.hxx>
72 
73 using namespace ::com::sun::star;
74 
75 
76 // Wie viele Zeilen/Zeichen sind fuer DropCaps erlaubt?
77 // (Gibt es vielleicht woanders entsprechende Werte?)
78 #define MAX_DROPCAP_LINES 9
79 #define MAX_DROPCAP_CHARS 9
80 
81 void lcl_swcss1_setEncoding( SwFmt& rFmt, rtl_TextEncoding eEnc );
82 
83 /*  */
84 
85 // Implementierung des SwCSS1Parsers (eigentlich swcss1.cxx)
86 static struct SwCSS1ItemIds
87 {
88     sal_uInt16 nFmtBreak;
89     sal_uInt16 nFmtPageDesc;
90     sal_uInt16 nFmtKeep;
91 
SwCSS1ItemIdsSwCSS1ItemIds92     SwCSS1ItemIds() :
93         nFmtBreak( RES_BREAK ),
94         nFmtPageDesc( RES_PAGEDESC ),
95         nFmtKeep( RES_KEEP )
96     {}
97 
98 } aItemIds;
99 
ChgPageDesc(const SwPageDesc * pPageDesc,const SwPageDesc & rNewPageDesc)100 void SwCSS1Parser::ChgPageDesc( const SwPageDesc *pPageDesc,
101                                 const SwPageDesc& rNewPageDesc )
102 {
103     sal_uInt16 nPageDescs = pDoc->GetPageDescCnt();
104     sal_uInt16 i;
105     for( i=0; i<nPageDescs; i++ )
106         if( pPageDesc == &(const_cast<const SwDoc *>(pDoc)->GetPageDesc(i)) )
107         {
108             pDoc->ChgPageDesc( i, rNewPageDesc );
109             return;
110         }
111 
112     ASSERT( i<nPageDescs, "Seitenvorlage nicht gefunden" );
113 }
114 
SwCSS1Parser(SwDoc * pD,sal_uInt32 aFHeights[7],const String & rBaseURL,sal_Bool bNewDoc)115 SwCSS1Parser::SwCSS1Parser( SwDoc *pD, sal_uInt32 aFHeights[7], const String& rBaseURL, sal_Bool bNewDoc ) :
116     SvxCSS1Parser( pD->GetAttrPool(), rBaseURL, MM50/2,
117                    (sal_uInt16*)&aItemIds, sizeof(aItemIds) / sizeof(sal_uInt16) ),
118     pDoc( pD ),
119     nDropCapCnt( 0 ),
120     bIsNewDoc( bNewDoc ),
121     bBodyBGColorSet( sal_False ),
122     bBodyBackgroundSet( sal_False ),
123     bBodyTextSet( sal_False ),
124     bBodyLinkSet( sal_False ),
125     bBodyVLinkSet( sal_False ),
126     bSetFirstPageDesc( sal_False ),
127     bSetRightPageDesc( sal_False ),
128     bTableHeaderTxtCollSet( sal_False ),
129     bTableTxtCollSet( sal_False ),
130     bLinkCharFmtsSet( sal_False )
131 {
132     aFontHeights[0] = aFHeights[0];
133     aFontHeights[1] = aFHeights[1];
134     aFontHeights[2] = aFHeights[2];
135     aFontHeights[3] = aFHeights[3];
136     aFontHeights[4] = aFHeights[4];
137     aFontHeights[5] = aFHeights[5];
138     aFontHeights[6] = aFHeights[6];
139 }
140 
~SwCSS1Parser()141 SwCSS1Parser::~SwCSS1Parser()
142 {
143 }
144 
145 
146 /*  */
147 
148 // Feature: PrintExt
SetFmtBreak(SfxItemSet & rItemSet,const SvxCSS1PropertyInfo & rPropInfo)149 sal_Bool SwCSS1Parser::SetFmtBreak( SfxItemSet& rItemSet,
150                                 const SvxCSS1PropertyInfo& rPropInfo )
151 {
152     SvxBreak eBreak = SVX_BREAK_NONE;
153     sal_Bool bKeep = sal_False;
154     sal_Bool bSetKeep = sal_False, bSetBreak = sal_False, bSetPageDesc = sal_False;
155     const SwPageDesc *pPageDesc = 0;
156     switch( rPropInfo.ePageBreakBefore )
157     {
158     case SVX_CSS1_PBREAK_ALWAYS:
159         eBreak = SVX_BREAK_PAGE_BEFORE;
160         bSetBreak = sal_True;
161         break;
162     case SVX_CSS1_PBREAK_LEFT:
163         pPageDesc = GetLeftPageDesc( sal_True );
164         bSetPageDesc = sal_True;
165         break;
166     case SVX_CSS1_PBREAK_RIGHT:
167         pPageDesc = GetRightPageDesc( sal_True );
168         bSetPageDesc = sal_True;
169         break;
170     case SVX_CSS1_PBREAK_AUTO:
171         bSetBreak = bSetPageDesc = sal_True;
172         break;
173 //  case SVX_CSS1_PBREAK_AVOID:
174         // Hier koennte man SvxKeepItem am Absatz davor einfuegen
175 //      break;
176     default:
177         ;
178     }
179     switch( rPropInfo.ePageBreakAfter )
180     {
181     case SVX_CSS1_PBREAK_ALWAYS:
182     case SVX_CSS1_PBREAK_LEFT:
183     case SVX_CSS1_PBREAK_RIGHT:
184         // LEFT/RIGHT koennte man auch am Absatz davor setzen
185         eBreak = SVX_BREAK_PAGE_AFTER;
186         bSetBreak = sal_True;
187         break;
188     case SVX_CSS1_PBREAK_AUTO:
189         bSetBreak = bSetKeep = bSetPageDesc = sal_True;
190         break;
191     case SVX_CSS1_PBREAK_AVOID:
192         bKeep = bSetKeep = sal_True;
193         break;
194     default:
195         ;
196     }
197 
198     if( bSetBreak )
199         rItemSet.Put( SvxFmtBreakItem( eBreak, RES_BREAK ) );
200     if( bSetPageDesc )
201         rItemSet.Put( SwFmtPageDesc( pPageDesc ) );
202     if( bSetKeep )
203         rItemSet.Put( SvxFmtKeepItem( bKeep, RES_KEEP ) );
204 
205     return bSetBreak;
206 }
207 // /Feature: PrintExt
208 
SetCharFmtAttrs(SwCharFmt * pCharFmt,SfxItemSet & rItemSet)209 static void SetCharFmtAttrs( SwCharFmt *pCharFmt, SfxItemSet& rItemSet )
210 {
211     const SfxPoolItem *pItem;
212     static sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE,
213                                    RES_CHRATR_CTL_FONTSIZE };
214     for( sal_uInt16 i=0; i<3; i++ )
215     {
216         if( SFX_ITEM_SET == rItemSet.GetItemState( aWhichIds[i], sal_False,
217                                                    &pItem ) &&
218             ((const SvxFontHeightItem *)pItem)->GetProp() != 100)
219         {
220             // %-Angaben beim FontHeight-Item werden nicht unterstuetzt
221             rItemSet.ClearItem( aWhichIds[i] );
222         }
223     }
224 
225     pCharFmt->SetFmtAttr( rItemSet );
226 
227     if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
228     {
229         // Ein Brush-Item mit RES_BACKGROUND muss noch in eines mit
230         // RES_CHRATR_BACKGROUND gewandelt werden
231 
232         SvxBrushItem aBrushItem( *(const SvxBrushItem *)pItem );
233         aBrushItem.SetWhich( RES_CHRATR_BACKGROUND );
234         pCharFmt->SetFmtAttr( aBrushItem );
235     }
236 }
237 
SetLinkCharFmts()238 void SwCSS1Parser::SetLinkCharFmts()
239 {
240     ASSERT( !bLinkCharFmtsSet, "Aufruf von SetLinkCharFmts unnoetig" );
241 
242     SvxCSS1MapEntry *pStyleEntry =
243         GetTag( String::CreateFromAscii(OOO_STRING_SVTOOLS_HTML_anchor) );
244     SwCharFmt *pUnvisited = 0, *pVisited = 0;
245     if( pStyleEntry )
246     {
247         SfxItemSet& rItemSet = pStyleEntry->GetItemSet();
248         sal_Bool bColorSet = (SFX_ITEM_SET==rItemSet.GetItemState(RES_CHRATR_COLOR,
249                                                               sal_False));
250         pUnvisited = GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL );
251         SetCharFmtAttrs( pUnvisited, rItemSet );
252         bBodyLinkSet |= bColorSet;
253 
254         pVisited = GetCharFmtFromPool( RES_POOLCHR_INET_VISIT );
255         SetCharFmtAttrs( pVisited, rItemSet );
256         bBodyVLinkSet |= bColorSet;
257     }
258 
259     String sTmp( String::CreateFromAscii(OOO_STRING_SVTOOLS_HTML_anchor) );
260     sTmp.Append( ':' );
261     sTmp.AppendAscii( sCSS1_link );
262     pStyleEntry = GetTag( sTmp );
263     if( pStyleEntry )
264     {
265         SfxItemSet& rItemSet = pStyleEntry->GetItemSet();
266         sal_Bool bColorSet = (SFX_ITEM_SET==rItemSet.GetItemState(RES_CHRATR_COLOR,
267                                                               sal_False));
268         if( !pUnvisited )
269             pUnvisited = GetCharFmtFromPool( RES_POOLCHR_INET_NORMAL );
270         SetCharFmtAttrs( pUnvisited, rItemSet );
271         bBodyLinkSet |= bColorSet;
272     }
273 
274     sTmp.AssignAscii( OOO_STRING_SVTOOLS_HTML_anchor );
275     sTmp.Assign( ':' );
276     sTmp.AppendAscii( sCSS1_visited );
277     pStyleEntry = GetTag( sTmp );
278     if( pStyleEntry )
279     {
280         SfxItemSet& rItemSet = pStyleEntry->GetItemSet();
281         sal_Bool bColorSet = (SFX_ITEM_SET==rItemSet.GetItemState(RES_CHRATR_COLOR,
282                                                               sal_False));
283         if( !pVisited )
284             pVisited = GetCharFmtFromPool( RES_POOLCHR_INET_VISIT );
285         SetCharFmtAttrs( pVisited, rItemSet );
286         bBodyVLinkSet |= bColorSet;
287     }
288 
289     bLinkCharFmtsSet = sal_True;
290 }
291 
SetTxtCollAttrs(SwTxtFmtColl * pColl,SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,SwCSS1Parser * pCSS1Parser)292 static void SetTxtCollAttrs( SwTxtFmtColl *pColl, SfxItemSet& rItemSet,
293                              SvxCSS1PropertyInfo& rPropInfo,
294                              SwCSS1Parser *pCSS1Parser )
295 {
296     const SfxItemSet& rCollItemSet = pColl->GetAttrSet();
297     const SfxPoolItem *pCollItem, *pItem;
298 
299     // linker, rechter Rand und Erstzeilen-Einzug
300     if( (rPropInfo.bLeftMargin || rPropInfo.bRightMargin ||
301          rPropInfo.bTextIndent) &&
302         (!rPropInfo.bLeftMargin || !rPropInfo.bRightMargin ||
303          !rPropInfo.bTextIndent) &&
304         SFX_ITEM_SET == rCollItemSet.GetItemState(RES_LR_SPACE,sal_True,&pCollItem) &&
305         SFX_ITEM_SET == rItemSet.GetItemState(RES_LR_SPACE,sal_False,&pItem) )
306     {
307         const SvxLRSpaceItem *pLRItem = (const SvxLRSpaceItem *)pItem;
308 
309         SvxLRSpaceItem aLRItem( *((const SvxLRSpaceItem *)pCollItem) );
310         if( rPropInfo.bLeftMargin )
311             aLRItem.SetTxtLeft( pLRItem->GetTxtLeft() );
312         if( rPropInfo.bRightMargin )
313             aLRItem.SetRight( pLRItem->GetRight() );
314         if( rPropInfo.bTextIndent )
315             aLRItem.SetTxtFirstLineOfst( pLRItem->GetTxtFirstLineOfst() );
316 
317         rItemSet.Put( aLRItem );
318     }
319 
320     // oberer und unterer Rand
321     if( (rPropInfo.bTopMargin || rPropInfo.bBottomMargin) &&
322         (!rPropInfo.bTopMargin || !rPropInfo.bBottomMargin) &&
323         SFX_ITEM_SET == rCollItemSet.GetItemState(RES_UL_SPACE,sal_True,
324                                                   &pCollItem) &&
325         SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,sal_False,&pItem) )
326     {
327         const SvxULSpaceItem *pULItem = (const SvxULSpaceItem *)pItem;
328 
329         SvxULSpaceItem aULItem( *((const SvxULSpaceItem *)pCollItem) );
330         if( rPropInfo.bTopMargin )
331             aULItem.SetUpper( pULItem->GetUpper() );
332         if( rPropInfo.bBottomMargin )
333             aULItem.SetLower( pULItem->GetLower() );
334 
335         rItemSet.Put( aULItem );
336     }
337 
338     static sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE,
339                                    RES_CHRATR_CTL_FONTSIZE };
340     for( sal_uInt16 i=0; i<3; i++ )
341     {
342         if( SFX_ITEM_SET == rItemSet.GetItemState( aWhichIds[i], sal_False,
343                                                    &pItem ) &&
344             ((const SvxFontHeightItem *)pItem)->GetProp() != 100)
345         {
346             // %-Angaben beim FontHeight-Item werden nicht unterstuetzt
347             rItemSet.ClearItem( aWhichIds[i] );
348         }
349     }
350 
351 // Feature: PrintExt
352     pCSS1Parser->SetFmtBreak( rItemSet, rPropInfo );
353 // /Feature: PrintExt
354 
355     pColl->SetFmtAttr( rItemSet );
356 }
357 
SetTableTxtColl(sal_Bool bHeader)358 void SwCSS1Parser::SetTableTxtColl( sal_Bool bHeader )
359 {
360     ASSERT( !(bHeader ? bTableHeaderTxtCollSet : bTableTxtCollSet),
361             "Aufruf von SetTableTxtColl unnoetig" );
362 
363     sal_uInt16 nPoolId;
364     String sTag;
365     if( bHeader )
366     {
367         nPoolId = RES_POOLCOLL_TABLE_HDLN;
368         sTag.AssignAscii( OOO_STRING_SVTOOLS_HTML_tableheader );
369     }
370     else
371     {
372         nPoolId = RES_POOLCOLL_TABLE;
373         sTag.AssignAscii( OOO_STRING_SVTOOLS_HTML_tabledata );
374     }
375 
376     SwTxtFmtColl *pColl = 0;
377 
378     // The following entries will never be used again and may be changed.
379     SvxCSS1MapEntry *pStyleEntry = GetTag( sTag );
380     if( pStyleEntry )
381     {
382         pColl = GetTxtFmtColl( nPoolId, aEmptyStr );
383         SetTxtCollAttrs( pColl, pStyleEntry->GetItemSet(),
384                          pStyleEntry->GetPropertyInfo(), this );
385     }
386 
387     String sTmp( sTag );
388     sTmp.Append( ' ' );
389     sTmp.AppendAscii( OOO_STRING_SVTOOLS_HTML_parabreak );
390     pStyleEntry = GetTag( sTmp );
391     if( pStyleEntry )
392     {
393         if( !pColl )
394             pColl = GetTxtFmtColl( nPoolId, aEmptyStr );
395         SetTxtCollAttrs( pColl, pStyleEntry->GetItemSet(),
396                          pStyleEntry->GetPropertyInfo(), this );
397     }
398 
399     if( bHeader )
400         bTableHeaderTxtCollSet = sal_True;
401     else
402         bTableTxtCollSet = sal_True;
403 }
404 
SetPageDescAttrs(const SvxBrushItem * pBrush,SfxItemSet * pItemSet2)405 void SwCSS1Parser::SetPageDescAttrs( const SvxBrushItem *pBrush,
406                                      SfxItemSet *pItemSet2 )
407 {
408     SvxBrushItem aBrushItem( RES_BACKGROUND );
409     SvxBoxItem aBoxItem( RES_BOX );
410     SvxFrameDirectionItem aFrmDirItem(FRMDIR_ENVIRONMENT, RES_FRAMEDIR);
411     sal_Bool bSetBrush = pBrush!=0, bSetBox = sal_False, bSetFrmDir = sal_False;
412     if( pBrush )
413         aBrushItem = *pBrush;
414 
415     if( pItemSet2 )
416     {
417         const SfxPoolItem *pItem = 0;
418         if( SFX_ITEM_SET == pItemSet2->GetItemState( RES_BACKGROUND, sal_False,
419                                                    &pItem ) )
420         {
421             // ein Hintergrund wird gesetzt
422             aBrushItem = *((const SvxBrushItem *)pItem);
423             pItemSet2->ClearItem( RES_BACKGROUND );
424             bSetBrush = sal_True;
425         }
426 
427         if( SFX_ITEM_SET == pItemSet2->GetItemState( RES_BOX, sal_False, &pItem ) )
428         {
429             // eine Umrandung wird gesetzt
430             aBoxItem = *((const SvxBoxItem *)pItem);
431             pItemSet2->ClearItem( RES_BOX );
432             bSetBox = sal_True;
433         }
434 
435         if( SFX_ITEM_SET == pItemSet2->GetItemState( RES_BOX, sal_False, &pItem ) )
436         {
437             // eine Umrandung wird gesetzt
438             aBoxItem = *((const SvxBoxItem *)pItem);
439             pItemSet2->ClearItem( RES_BOX );
440             bSetBox = sal_True;
441         }
442 
443         if( SFX_ITEM_SET == pItemSet2->GetItemState( RES_FRAMEDIR, sal_False, &pItem ) )
444         {
445             // eine Umrandung wird gesetzt
446             aFrmDirItem = *static_cast< const SvxFrameDirectionItem *>( pItem );
447             pItemSet2->ClearItem( RES_FRAMEDIR );
448             bSetFrmDir = sal_True;
449         }
450     }
451 
452     if( bSetBrush || bSetBox || bSetFrmDir )
453     {
454         static sal_uInt16 aPoolIds[] = { RES_POOLPAGE_HTML, RES_POOLPAGE_FIRST,
455                                      RES_POOLPAGE_LEFT, RES_POOLPAGE_RIGHT };
456         for( sal_uInt16 i=0; i<4; i++ )
457         {
458             const SwPageDesc *pPageDesc = GetPageDesc( aPoolIds[i], sal_False );
459             if( pPageDesc )
460             {
461                 SwPageDesc aNewPageDesc( *pPageDesc );
462                 SwFrmFmt &rMaster = aNewPageDesc.GetMaster();
463                 if( bSetBrush )
464                     rMaster.SetFmtAttr( aBrushItem );
465                 if( bSetBox )
466                     rMaster.SetFmtAttr( aBoxItem );
467                 if( bSetFrmDir )
468                     rMaster.SetFmtAttr( aFrmDirItem );
469 
470                 ChgPageDesc( pPageDesc, aNewPageDesc );
471             }
472         }
473     }
474 }
475 
476 // Feature: PrintExt
SetPageDescAttrs(const SwPageDesc * pPageDesc,SfxItemSet & rItemSet,const SvxCSS1PropertyInfo & rPropInfo)477 void SwCSS1Parser::SetPageDescAttrs( const SwPageDesc *pPageDesc,
478                                      SfxItemSet& rItemSet,
479                                      const SvxCSS1PropertyInfo& rPropInfo )
480 {
481     if( !pPageDesc )
482         return;
483 
484     SwPageDesc aNewPageDesc( *pPageDesc );
485     SwFrmFmt &rMaster = aNewPageDesc.GetMaster();
486     const SfxItemSet& rPageItemSet = rMaster.GetAttrSet();
487     const SfxPoolItem *pPageItem, *pItem;
488     sal_Bool bChanged = sal_False;
489 
490     // linker, rechter Rand und Erstzeilen-Einzug
491     if( (rPropInfo.bLeftMargin || rPropInfo.bRightMargin) &&
492         SFX_ITEM_SET == rItemSet.GetItemState(RES_LR_SPACE,sal_False,&pItem) )
493     {
494         if( (!rPropInfo.bLeftMargin || !rPropInfo.bRightMargin) &&
495             SFX_ITEM_SET == rPageItemSet.GetItemState(RES_LR_SPACE,
496                                                       sal_True,&pPageItem) )
497         {
498             const SvxLRSpaceItem *pLRItem = (const SvxLRSpaceItem *)pItem;
499 
500             SvxLRSpaceItem aLRItem( *((const SvxLRSpaceItem *)pPageItem) );
501             if( rPropInfo.bLeftMargin )
502                 aLRItem.SetLeft( pLRItem->GetLeft() );
503             if( rPropInfo.bRightMargin )
504                 aLRItem.SetRight( pLRItem->GetRight() );
505 
506             rMaster.SetFmtAttr( aLRItem );
507         }
508         else
509         {
510             rMaster.SetFmtAttr( *pItem );
511         }
512         bChanged = sal_True;
513     }
514 
515     // oberer und unterer Rand
516     if( (rPropInfo.bTopMargin || rPropInfo.bBottomMargin) &&
517         SFX_ITEM_SET == rItemSet.GetItemState(RES_UL_SPACE,sal_False,&pItem) )
518     {
519         if( (!rPropInfo.bTopMargin || !rPropInfo.bBottomMargin) &&
520             SFX_ITEM_SET == rPageItemSet.GetItemState(RES_UL_SPACE,
521                                                       sal_True,&pPageItem) )
522         {
523             const SvxULSpaceItem *pULItem = (const SvxULSpaceItem *)pItem;
524 
525             SvxULSpaceItem aULItem( *((const SvxULSpaceItem *)pPageItem) );
526             if( rPropInfo.bTopMargin )
527                 aULItem.SetUpper( pULItem->GetUpper() );
528             if( rPropInfo.bBottomMargin )
529                 aULItem.SetLower( pULItem->GetLower() );
530 
531             rMaster.SetFmtAttr( aULItem );
532         }
533         else
534         {
535             rMaster.SetFmtAttr( *pItem );
536         }
537         bChanged = sal_True;
538     }
539 
540     // die Groesse
541     if( rPropInfo.eSizeType != SVX_CSS1_STYPE_NONE )
542     {
543         if( rPropInfo.eSizeType == SVX_CSS1_STYPE_TWIP )
544         {
545             rMaster.SetFmtAttr( SwFmtFrmSize( ATT_FIX_SIZE, rPropInfo.nWidth,
546                                            rPropInfo.nHeight ) );
547             bChanged = sal_True;
548         }
549         else
550         {
551             // Bei "size: auto|portrait|landscape" bleibt die bisherige
552             // Groesse der Vorlage erhalten. Bei "landscape" und "portrait"
553             // wird das Landscape-Flag gesetzt und evtl. die Breite/Hoehe
554             // vertauscht.
555             SwFmtFrmSize aFrmSz( rMaster.GetFrmSize() );
556             sal_Bool bLandscape = aNewPageDesc.GetLandscape();
557             if( ( bLandscape &&
558                   rPropInfo.eSizeType == SVX_CSS1_STYPE_PORTRAIT ) ||
559                 ( !bLandscape &&
560                   rPropInfo.eSizeType == SVX_CSS1_STYPE_LANDSCAPE ) )
561             {
562                 SwTwips nTmp = aFrmSz.GetHeight();
563                 aFrmSz.SetHeight( aFrmSz.GetWidth() );
564                 aFrmSz.SetWidth( nTmp );
565                 rMaster.SetFmtAttr( aFrmSz );
566                 aNewPageDesc.SetLandscape( !bLandscape );
567                 bChanged = sal_True;
568             }
569         }
570     }
571 
572     // Geht das wirklich?
573     if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
574     {
575         // eine Umrandung wird gesetzt
576         rMaster.SetFmtAttr( *pItem );
577         rItemSet.ClearItem( RES_BACKGROUND );
578         bChanged = sal_True;
579     }
580 
581     if( bChanged )
582         ChgPageDesc( pPageDesc, aNewPageDesc );
583 }
584 // /Feature: PrintExt
585 
GetPageDescBackground() const586 const SvxBrushItem& SwCSS1Parser::GetPageDescBackground() const
587 {
588     return pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML, false )
589         ->GetMaster().GetBackground();
590 }
591 
GetScriptFromClass(String & rClass,sal_Bool bSubClassOnly)592 sal_uInt16 SwCSS1Parser::GetScriptFromClass( String& rClass,
593                                       sal_Bool bSubClassOnly )
594 {
595     sal_uInt16 nScriptFlags = CSS1_SCRIPT_ALL;
596     xub_StrLen nLen = rClass.Len();
597     xub_StrLen nPos = nLen > 4 ? rClass.SearchBackward( '-' ) : STRING_NOTFOUND;
598 
599     if( STRING_NOTFOUND == nPos )
600     {
601         if( bSubClassOnly )
602             return nScriptFlags;
603         nPos = 0;
604     }
605     else
606     {
607         nPos++;
608         nLen = nLen - nPos;
609     }
610 
611     switch( nLen )
612     {
613     case 3:
614         if( rClass.EqualsIgnoreCaseAscii( "cjk", nPos, 3 ) )
615         {
616             nScriptFlags = CSS1_SCRIPT_CJK;
617         }
618         else if( rClass.EqualsIgnoreCaseAscii( "ctl", nPos, 3 ) )
619         {
620             nScriptFlags = CSS1_SCRIPT_CTL;
621         }
622         break;
623     case 7:
624         if( rClass.EqualsIgnoreCaseAscii( "western", nPos, 7 ) )
625         {
626             nScriptFlags = CSS1_SCRIPT_WESTERN;
627         }
628         break;
629     }
630     if( CSS1_SCRIPT_ALL != nScriptFlags )
631     {
632         if( nPos )
633         {
634             rClass.Erase( nPos-1 );
635         }
636         else
637         {
638             rClass.Erase();
639         }
640     }
641 
642     return nScriptFlags;
643 }
644 
GetTokenAndClass(const CSS1Selector * pSelector,String & rToken,String & rClass,sal_uInt16 & rScriptFlags)645 static CSS1SelectorType GetTokenAndClass( const CSS1Selector *pSelector,
646                               String& rToken, String& rClass,
647                               sal_uInt16& rScriptFlags )
648 {
649     rToken = pSelector->GetString();
650     rClass.Erase();
651     rScriptFlags = CSS1_SCRIPT_ALL;
652 
653     CSS1SelectorType eType = pSelector->GetType();
654     if( CSS1_SELTYPE_ELEM_CLASS==eType  )
655     {
656         xub_StrLen nPos = rToken.Search( '.' );
657         ASSERT( nPos != STRING_NOTFOUND, "kein Punkt in Class-Selektor???" );
658         if( nPos != STRING_NOTFOUND )
659         {
660             rClass = rToken.Copy( nPos+1 );
661             rToken.Erase( nPos );
662 
663             rScriptFlags = SwCSS1Parser::GetScriptFromClass( rClass, sal_False );
664             if( !rClass.Len() )
665                 eType = CSS1_SELTYPE_ELEMENT;
666         }
667     }
668 
669     rToken.ToUpperAscii();
670     return eType;
671 }
672 
673 extern sal_Bool lcl_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 );
674 
RemoveScriptItems(SfxItemSet & rItemSet,sal_uInt16 nScript,const SfxItemSet * pParentItemSet=0)675 static void RemoveScriptItems( SfxItemSet& rItemSet, sal_uInt16 nScript,
676                                const SfxItemSet *pParentItemSet = 0 )
677 {
678     static sal_uInt16 aWhichIds[3][5] =
679     {
680         { RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, RES_CHRATR_LANGUAGE,
681             RES_CHRATR_POSTURE, RES_CHRATR_WEIGHT },
682         { RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CJK_LANGUAGE,
683             RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT },
684         { RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE, RES_CHRATR_CTL_LANGUAGE,
685             RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT }
686     };
687 
688     sal_uInt16 aClearItems[3] = { sal_False, sal_False, sal_False };
689     switch( nScript )
690     {
691     case CSS1_SCRIPT_WESTERN:
692         aClearItems[1] = aClearItems[2] =  sal_True;
693         break;
694     case CSS1_SCRIPT_CJK:
695         aClearItems[0] = aClearItems[2] =  sal_True;
696         break;
697     case CSS1_SCRIPT_CTL:
698         aClearItems[0] = aClearItems[1] =  sal_True;
699         break;
700     case CSS1_SCRIPT_ALL:
701         break;
702     default:
703         ASSERT( aClearItems[0], "unknown script type" );
704         break;
705     }
706 
707     for( sal_uInt16 j=0; j < 3; j++ )
708     {
709         for( sal_uInt16 i=0; i < 5; i++ )
710         {
711             sal_uInt16 nWhich = aWhichIds[j][i];
712             const SfxPoolItem *pItem;
713             if( aClearItems[j] ||
714                 (pParentItemSet &&
715                  SFX_ITEM_SET == rItemSet.GetItemState( nWhich, sal_False, &pItem ) &&
716                  (0==i ? lcl_css1atr_equalFontItems( *pItem, pParentItemSet->Get(nWhich, sal_True ) )
717                        : *pItem == pParentItemSet->Get(nWhich, sal_True ) ) ) )
718             {
719                 rItemSet.ClearItem( nWhich );
720             }
721         }
722     }
723 }
724 
StyleParsed(const CSS1Selector * pSelector,SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo)725 sal_Bool SwCSS1Parser::StyleParsed( const CSS1Selector *pSelector,
726                                 SfxItemSet& rItemSet,
727                                 SvxCSS1PropertyInfo& rPropInfo )
728 {
729     if( !bIsNewDoc )
730         return sal_True;
731 
732     CSS1SelectorType eSelType = pSelector->GetType();
733     const CSS1Selector *pNext = pSelector->GetNext();
734 
735     if( CSS1_SELTYPE_ID==eSelType && !pNext )
736     {
737         InsertId( pSelector->GetString(), rItemSet, rPropInfo );
738     }
739     else if( CSS1_SELTYPE_CLASS==eSelType && !pNext )
740     {
741         String aClass( pSelector->GetString() );
742         sal_uInt16 nScript = GetScriptFromClass( aClass );
743         if( CSS1_SCRIPT_ALL != nScript )
744         {
745             SfxItemSet aScriptItemSet( rItemSet );
746             RemoveScriptItems( aScriptItemSet, nScript );
747             InsertClass( aClass, aScriptItemSet, rPropInfo );
748         }
749         else
750         {
751             InsertClass( aClass, rItemSet, rPropInfo );
752         }
753     }
754     else if( CSS1_SELTYPE_PAGE==eSelType )
755     {
756         if( !pNext ||
757             (CSS1_SELTYPE_PSEUDO == pNext->GetType() &&
758             (pNext->GetString().EqualsIgnoreCaseAscii(sCSS1_left) ||
759              pNext->GetString().EqualsIgnoreCaseAscii(sCSS1_right) ||
760              pNext->GetString().EqualsIgnoreCaseAscii(sCSS1_first)) ) )
761             // || CSS1_SELTYPE_ELEMENT == pNext->GetType() )
762         {
763             String aName;
764             if( pNext )
765                 aName = pNext->GetString();
766             InsertPage( aName,
767                         pNext != 0 /*CSS1_SELTYPE_PSEUDO == pNext->GetType()*/,
768                         rItemSet, rPropInfo );
769         }
770     }
771 
772     if( CSS1_SELTYPE_ELEMENT != eSelType &&
773         CSS1_SELTYPE_ELEM_CLASS != eSelType)
774         return sal_True;
775 
776     // Token und Class zu dem Selektor holen
777     String aToken2, aClass;
778     sal_uInt16 nScript;
779     eSelType = GetTokenAndClass( pSelector, aToken2, aClass, nScript );
780     int nToken2 = GetHTMLToken( aToken2 );
781 
782     // und noch ein ganz par Infos zum naechsten Element
783     CSS1SelectorType eNextType = pNext ? pNext->GetType()
784                                        : CSS1_SELTYPE_ELEMENT;
785 
786     // Erstmal ein par Spezialfaelle
787     if( CSS1_SELTYPE_ELEMENT==eSelType )
788     {
789         switch( nToken2 )
790         {
791         case HTML_ANCHOR_ON:
792             if( !pNext )
793             {
794                 InsertTag( aToken2, rItemSet, rPropInfo );
795                 return sal_False;
796             }
797             else if( pNext && CSS1_SELTYPE_PSEUDO == eNextType )
798             {
799                 // vielleicht A:visited oder A:link
800 
801                 String aPseudo( pNext->GetString() );
802                 aPseudo.ToLowerAscii();
803 
804                 sal_Bool bInsert = sal_False;
805                 switch( aPseudo.GetChar( 0 ))
806                 {
807                     case 'l':
808                         if( aPseudo.EqualsAscii(sCSS1_link) )
809                         {
810                             bInsert = sal_True;
811                         }
812                         break;
813                     case 'v':
814                         if( aPseudo.EqualsAscii(sCSS1_visited) )
815                         {
816                             bInsert = sal_True;
817                         }
818                         break;
819                 }
820                 if( bInsert )
821                 {
822                     String sTmp( aToken2 );
823                     (sTmp += ':') += aPseudo;
824                     if( CSS1_SCRIPT_ALL != nScript )
825                     {
826                         SfxItemSet aScriptItemSet( rItemSet );
827                         RemoveScriptItems( aScriptItemSet, nScript );
828                         InsertTag( sTmp, aScriptItemSet, rPropInfo );
829                     }
830                     else
831                     {
832                         InsertTag( sTmp, rItemSet, rPropInfo );
833                     }
834                     return sal_False;
835                 }
836             }
837             break;
838         case HTML_BODY_ON:
839             if( !pNext )
840             {
841                 // BODY
842 
843                 // Den Hintergrund muessen wir vor dem Setzen abfragen,
844                 // denn in SetPageDescAttrs wird er geloescht.
845                 const SfxPoolItem *pItem;
846                 if( SFX_ITEM_SET==rItemSet.GetItemState(RES_BACKGROUND,sal_False,&pItem) )
847                 {
848                     const SvxBrushItem *pBrushItem =
849                         (const SvxBrushItem *)pItem;
850 
851                     /// OD 02.09.2002 #99657#
852                     /// Body has a background color, if it is not "no fill"/"auto fill"
853                     if( pBrushItem->GetColor() != COL_TRANSPARENT )
854                         bBodyBGColorSet = sal_True;
855                     if( GPOS_NONE != pBrushItem->GetGraphicPos() )
856                         bBodyBackgroundSet = sal_True;
857                 }
858 
859                 // Border and Padding
860                 rPropInfo.SetBoxItem( rItemSet, MIN_BORDER_DIST );
861 
862                 // Ein par Attribute muessen an der Seitenvorlage gesetzt werden,
863                 // und zwar die, die nicht vererbt werden
864                 SetPageDescAttrs( 0, &rItemSet );
865 
866                 // alle noch uebrigen Optionen koennen an der Standard-Vorlage
867                 // gesetzt werden und gelten dann automatisch als defaults
868                 if( SFX_ITEM_SET==rItemSet.GetItemState(RES_CHRATR_COLOR,sal_False) )
869                     bBodyTextSet = sal_True;
870                 SetTxtCollAttrs(
871                     GetTxtCollFromPool( RES_POOLCOLL_STANDARD ),
872                     rItemSet, rPropInfo, this );
873 
874                 return sal_False;
875             }
876             break;
877         }
878     }
879     else if( CSS1_SELTYPE_ELEM_CLASS==eSelType &&  HTML_ANCHOR_ON==nToken2 &&
880              !pNext && aClass.Len() >= 9 &&
881              ('s' == aClass.GetChar(0) || 'S' == aClass.GetChar(0)) )
882     {
883         sal_uInt16 nPoolFmtId = 0;
884         if( aClass.EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_sdendnote_sym) )
885             nPoolFmtId = RES_POOLCHR_ENDNOTE;
886         else if( aClass.EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_sdfootnote_sym) )
887             nPoolFmtId = RES_POOLCHR_FOOTNOTE;
888         if( nPoolFmtId )
889         {
890             if( CSS1_SCRIPT_ALL == nScript )
891             {
892                 SetCharFmtAttrs( GetCharFmtFromPool(nPoolFmtId), rItemSet );
893             }
894             else
895             {
896                 SfxItemSet aScriptItemSet( rItemSet );
897                 RemoveScriptItems( aScriptItemSet, nScript );
898                 SetCharFmtAttrs( GetCharFmtFromPool(nPoolFmtId),
899                                  aScriptItemSet);
900             }
901             return sal_False;
902         }
903     }
904 
905     // Jetzt werden die Selektoren verarbeitet, die zu einer Absatz-Vorlage
906     // gehoehren
907     sal_uInt16 nPoolCollId = 0;
908     switch( nToken2 )
909     {
910     case HTML_HEAD1_ON:
911         nPoolCollId = RES_POOLCOLL_HEADLINE1;
912         break;
913     case HTML_HEAD2_ON:
914         nPoolCollId = RES_POOLCOLL_HEADLINE2;
915         break;
916     case HTML_HEAD3_ON:
917         nPoolCollId = RES_POOLCOLL_HEADLINE3;
918         break;
919     case HTML_HEAD4_ON:
920         nPoolCollId = RES_POOLCOLL_HEADLINE4;
921         break;
922     case HTML_HEAD5_ON:
923         nPoolCollId = RES_POOLCOLL_HEADLINE5;
924         break;
925     case HTML_HEAD6_ON:
926         nPoolCollId = RES_POOLCOLL_HEADLINE6;
927         break;
928     case HTML_PARABREAK_ON:
929         if( aClass.Len() >= 9 &&
930             ('s' == aClass.GetChar(0) || 'S' == aClass.GetChar(0)) )
931         {
932             if( aClass.EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_sdendnote) )
933                 nPoolCollId = RES_POOLCOLL_ENDNOTE;
934             else if( aClass.EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_sdfootnote) )
935                 nPoolCollId = RES_POOLCOLL_FOOTNOTE;
936 
937             if( nPoolCollId )
938                 aClass = aEmptyStr;
939             else
940                 nPoolCollId = RES_POOLCOLL_TEXT;
941         }
942         else
943         {
944             nPoolCollId = RES_POOLCOLL_TEXT;
945         }
946         break;
947     case HTML_ADDRESS_ON:
948         nPoolCollId = RES_POOLCOLL_SENDADRESS;
949         break;
950     case HTML_BLOCKQUOTE_ON:
951         nPoolCollId = RES_POOLCOLL_HTML_BLOCKQUOTE;
952         break;
953     case HTML_DT_ON:
954         nPoolCollId = RES_POOLCOLL_HTML_DT;
955         break;
956     case HTML_DD_ON:
957         nPoolCollId = RES_POOLCOLL_HTML_DD;
958         break;
959     case HTML_PREFORMTXT_ON:
960         nPoolCollId = RES_POOLCOLL_HTML_PRE;
961         break;
962     case HTML_TABLEHEADER_ON:
963     case HTML_TABLEDATA_ON:
964         if( CSS1_SELTYPE_ELEMENT==eSelType && !pNext )
965         {
966             InsertTag( aToken2, rItemSet, rPropInfo );
967             return sal_False;
968         }
969         else if( CSS1_SELTYPE_ELEMENT==eSelType && pNext &&
970                  (CSS1_SELTYPE_ELEMENT==eNextType ||
971                   CSS1_SELTYPE_ELEM_CLASS==eNextType) )
972         {
973             // nicht TH und TD, aber TH P und TD P
974             String aSubToken, aSubClass;
975             GetTokenAndClass( pNext, aSubToken, aSubClass, nScript );
976             if( HTML_PARABREAK_ON == GetHTMLToken( aSubToken ) )
977             {
978                 aClass = aSubClass;
979                 pNext = pNext->GetNext();
980                 eNextType = pNext ? pNext->GetType() : CSS1_SELTYPE_ELEMENT;
981 
982                 if( aClass.Len() || pNext )
983                 {
984                     nPoolCollId = static_cast< sal_uInt16 >(
985                         HTML_TABLEHEADER_ON == nToken2 ? RES_POOLCOLL_TABLE_HDLN
986                                                       : RES_POOLCOLL_TABLE );
987                 }
988                 else
989                 {
990                     String sTmp( aToken2 );
991                     sTmp += ' ';
992                     sTmp.AppendAscii( OOO_STRING_SVTOOLS_HTML_parabreak );
993 
994                     if( CSS1_SCRIPT_ALL == nScript )
995                     {
996                         InsertTag( sTmp, rItemSet, rPropInfo );
997                     }
998                     else
999                     {
1000                         SfxItemSet aScriptItemSet( rItemSet );
1001                         RemoveScriptItems( aScriptItemSet, nScript );
1002                         InsertTag( sTmp, aScriptItemSet, rPropInfo );
1003                     }
1004 
1005                     return sal_False;
1006                 }
1007             }
1008         }
1009         break;
1010 
1011         default:
1012             ;
1013     }
1014 
1015     if( nPoolCollId )
1016     {
1017         if( !pNext ||
1018             (CSS1_SELTYPE_PSEUDO==eNextType &&
1019 #ifdef FULL_FIRST_LETTER
1020              pNext->GetString().EqualsIgnoreCaseAscii(sCSS1_first_letter)) )
1021 #else
1022              pNext->GetString().EqualsIgnoreCaseAscii(sCSS1_first_letter) &&
1023              SVX_ADJUST_LEFT == rPropInfo.eFloat) )
1024 #endif
1025         {
1026             // Entweder kein zusammengesetzter Selektor oder
1027             // ein X:first-line { float: left; ... }
1028 
1029             // Die Vorlage Suchen bzw. Anlegen
1030             SwTxtFmtColl *pColl = GetTxtFmtColl( nPoolCollId, aEmptyStr );
1031             SwTxtFmtColl* pParentColl = 0;
1032             if( aClass.Len() )
1033             {
1034                 String aName( pColl->GetName() );
1035                 AddClassName( aName, aClass );
1036 
1037                 pParentColl = pColl;
1038                 pColl = pDoc->FindTxtFmtCollByName( aName );
1039                 if( !pColl )
1040                     pColl = pDoc->MakeTxtFmtColl( aName, pParentColl );
1041             }
1042             if( !pNext )
1043             {
1044                 // nur die Attribute an der Vorlage setzen
1045                 const SfxPoolItem *pItem;
1046                 const SvxBoxItem *pBoxItem = 0;
1047                 if( SFX_ITEM_SET ==
1048                         pColl->GetAttrSet().GetItemState(RES_BOX,sal_True,&pItem) )
1049                     pBoxItem = (const SvxBoxItem *)pItem;
1050                 rPropInfo.SetBoxItem( rItemSet, MIN_BORDER_DIST, pBoxItem );
1051                 if( CSS1_SCRIPT_ALL == nScript && !pParentColl )
1052                 {
1053                     SetTxtCollAttrs( pColl, rItemSet, rPropInfo, this );
1054                 }
1055                 else
1056                 {
1057                     SfxItemSet aScriptItemSet( rItemSet );
1058                     RemoveScriptItems( aScriptItemSet, nScript,
1059                                        pParentColl ? &pParentColl->GetAttrSet() : 0 );
1060                     SetTxtCollAttrs( pColl, aScriptItemSet, rPropInfo, this );
1061                 }
1062             }
1063             else
1064             {
1065                 // ein Drop-Cap-Attribut basteln
1066                 SwFmtDrop aDrop( pColl->GetDrop() );
1067                 aDrop.GetChars() = 1;
1068 
1069                 // die Attribute in das DropCap-Attribut einfuegen
1070                 if( CSS1_SCRIPT_ALL == nScript )
1071                 {
1072                     FillDropCap( aDrop, rItemSet, &pColl->GetName() );
1073                 }
1074                 else
1075                 {
1076                     SfxItemSet aScriptItemSet( rItemSet );
1077                     if( CSS1_SCRIPT_WESTERN != nScript )
1078                     {
1079                         aScriptItemSet.ClearItem( RES_CHRATR_FONT );
1080                         aScriptItemSet.ClearItem( RES_CHRATR_LANGUAGE );
1081                         aScriptItemSet.ClearItem( RES_CHRATR_POSTURE );
1082                         aScriptItemSet.ClearItem( RES_CHRATR_WEIGHT );
1083                     }
1084                     if( CSS1_SCRIPT_CJK != nScript )
1085                     {
1086                         aScriptItemSet.ClearItem( RES_CHRATR_CJK_FONT );
1087                         aScriptItemSet.ClearItem( RES_CHRATR_CJK_LANGUAGE );
1088                         aScriptItemSet.ClearItem( RES_CHRATR_CJK_POSTURE );
1089                         aScriptItemSet.ClearItem( RES_CHRATR_CJK_WEIGHT );
1090                     }
1091                     if( CSS1_SCRIPT_CTL != nScript )
1092                     {
1093                         aScriptItemSet.ClearItem( RES_CHRATR_CTL_FONT );
1094                         aScriptItemSet.ClearItem( RES_CHRATR_CTL_LANGUAGE );
1095                         aScriptItemSet.ClearItem( RES_CHRATR_CTL_POSTURE );
1096                         aScriptItemSet.ClearItem( RES_CHRATR_CTL_WEIGHT );
1097                     }
1098                     FillDropCap( aDrop, aScriptItemSet, &pColl->GetName() );
1099                 }
1100 
1101                 // Das Attribut nur setzen, wenn float: left angegeben wurde
1102                 // und das Initial ueber mehrere Zeilen geht. Sonst wird die
1103                 // ggf. angelegte Zeichen-Vorlage spaeter ueber den Namen
1104                 // gesucht und gesetzt.
1105                 if( aDrop.GetLines() > 1 &&
1106                     (SVX_ADJUST_LEFT == rPropInfo.eFloat  ||
1107                      CSS1_SCRIPT_ALL == nScript) )
1108                 {
1109                     pColl->SetFmtAttr( aDrop );
1110                 }
1111             }
1112 
1113             return sal_False;
1114         }
1115 
1116         return sal_True;
1117     }
1118 
1119     // Jetzt werden die Selektoten verarbeitet, die zu einer Zechenvorlage
1120     // gehoehren. Zusammengesetzte gibt es hier allerdings nich nicht.
1121     if( pNext )
1122         return sal_True;
1123 
1124     SwCharFmt *pCFmt = GetChrFmt( static_cast< sal_uInt16 >(nToken2), aEmptyStr );
1125     if( pCFmt )
1126     {
1127         SwCharFmt *pParentCFmt = 0;
1128         if( aClass.Len() )
1129         {
1130             String aName( pCFmt->GetName() );
1131             AddClassName( aName, aClass );
1132             pParentCFmt = pCFmt;
1133 
1134             pCFmt = pDoc->FindCharFmtByName( aName );
1135             if( !pCFmt )
1136             {
1137                 pCFmt = pDoc->MakeCharFmt( aName, pParentCFmt );
1138                 pCFmt->SetAuto( sal_False );
1139             }
1140         }
1141 
1142         if( CSS1_SCRIPT_ALL == nScript && !pParentCFmt )
1143         {
1144             SetCharFmtAttrs( pCFmt, rItemSet );
1145         }
1146         else
1147         {
1148             SfxItemSet aScriptItemSet( rItemSet );
1149             RemoveScriptItems( aScriptItemSet, nScript,
1150                                pParentCFmt ? &pParentCFmt->GetAttrSet() : 0 );
1151             SetCharFmtAttrs( pCFmt, aScriptItemSet );
1152         }
1153         return sal_False;
1154     }
1155 
1156     return sal_True;
1157 }
1158 
GetFontHeight(sal_uInt16 nSize) const1159 sal_uInt32 SwCSS1Parser::GetFontHeight( sal_uInt16 nSize ) const
1160 {
1161     return aFontHeights[ nSize>6 ? 6 : nSize ];
1162 }
1163 
GetFontList() const1164 const FontList *SwCSS1Parser::GetFontList() const
1165 {
1166     const FontList *pFList = 0;
1167     SwDocShell *pDocSh = pDoc->GetDocShell();
1168     if( pDocSh )
1169     {
1170         const SvxFontListItem *pFListItem =
1171             (const SvxFontListItem *)pDocSh->GetItem(SID_ATTR_CHAR_FONTLIST);
1172         if( pFListItem )
1173             pFList = pFListItem->GetFontList();
1174     }
1175 
1176     return pFList;
1177 }
1178 
1179 /*  */
1180 
GetChrFmt(sal_uInt16 nToken2,const String & rClass) const1181 SwCharFmt* SwCSS1Parser::GetChrFmt( sal_uInt16 nToken2, const String& rClass ) const
1182 {
1183     // die entsprechende Vorlage suchen
1184     sal_uInt16 nPoolId = 0;
1185     const sal_Char* sName = 0;
1186     switch( nToken2 )
1187     {
1188     case HTML_EMPHASIS_ON:      nPoolId = RES_POOLCHR_HTML_EMPHASIS;    break;
1189     case HTML_CITIATION_ON:     nPoolId = RES_POOLCHR_HTML_CITIATION;   break;
1190     case HTML_STRONG_ON:        nPoolId = RES_POOLCHR_HTML_STRONG;      break;
1191     case HTML_CODE_ON:          nPoolId = RES_POOLCHR_HTML_CODE;        break;
1192     case HTML_SAMPLE_ON:        nPoolId = RES_POOLCHR_HTML_SAMPLE;      break;
1193     case HTML_KEYBOARD_ON:      nPoolId = RES_POOLCHR_HTML_KEYBOARD;    break;
1194     case HTML_VARIABLE_ON:      nPoolId = RES_POOLCHR_HTML_VARIABLE;    break;
1195     case HTML_DEFINSTANCE_ON:   nPoolId = RES_POOLCHR_HTML_DEFINSTANCE; break;
1196     case HTML_TELETYPE_ON:      nPoolId = RES_POOLCHR_HTML_TELETYPE;    break;
1197 
1198     case HTML_SHORTQUOTE_ON:    sName = OOO_STRING_SVTOOLS_HTML_shortquote;     break;
1199     case HTML_LANGUAGE_ON:      sName = OOO_STRING_SVTOOLS_HTML_language;   break;
1200     case HTML_AUTHOR_ON:        sName = OOO_STRING_SVTOOLS_HTML_author;         break;
1201     case HTML_PERSON_ON:        sName = OOO_STRING_SVTOOLS_HTML_person;         break;
1202     case HTML_ACRONYM_ON:       sName = OOO_STRING_SVTOOLS_HTML_acronym;        break;
1203     case HTML_ABBREVIATION_ON:  sName = OOO_STRING_SVTOOLS_HTML_abbreviation;   break;
1204     case HTML_INSERTEDTEXT_ON:  sName = OOO_STRING_SVTOOLS_HTML_insertedtext;   break;
1205     case HTML_DELETEDTEXT_ON:   sName = OOO_STRING_SVTOOLS_HTML_deletedtext;    break;
1206     }
1207 
1208     // die Vorlage suchen oder anlegen (geht nur mit Namen)
1209     if( !nPoolId && !sName )
1210         return 0;
1211 
1212     // Die Vorlage (ohne Class) suchen oder anlegen
1213     SwCharFmt *pCFmt = 0;
1214     if( nPoolId )
1215     {
1216         pCFmt = GetCharFmtFromPool( nPoolId );
1217     }
1218     else
1219     {
1220         String sCName( String::CreateFromAscii(sName) );
1221         pCFmt = pDoc->FindCharFmtByName( sCName );
1222         if( !pCFmt )
1223         {
1224             pCFmt = pDoc->MakeCharFmt( sCName, pDoc->GetDfltCharFmt() );
1225             pCFmt->SetAuto( sal_False );
1226         }
1227     }
1228 
1229     ASSERT( pCFmt, "Keine Zeichen-Vorlage???" );
1230 
1231     // Wenn es eine Klasse gibt, die Klassen-Vorlage suchen aber nicht
1232     // neu anlegen.
1233     String aClass( rClass );
1234     GetScriptFromClass( aClass, sal_False );
1235     if( aClass.Len() )
1236     {
1237         String aTmp( pCFmt->GetName() );
1238         AddClassName( aTmp, aClass );
1239         SwCharFmt *pClassCFmt = pDoc->FindCharFmtByName( aTmp );
1240         if( pClassCFmt )
1241         {
1242             pCFmt = pClassCFmt;
1243         }
1244         else
1245         {
1246             SvxCSS1MapEntry *pClass = GetClass( aClass );
1247             if( pClass )
1248             {
1249                 pCFmt = pDoc->MakeCharFmt( aTmp, pCFmt );
1250                 pCFmt->SetAuto( sal_False );
1251                 SfxItemSet aItemSet( pClass->GetItemSet() );
1252                 SetCharFmtAttrs( pCFmt, aItemSet );
1253             }
1254         }
1255     }
1256 
1257     return pCFmt;
1258 }
1259 
1260 
1261 /*  */
1262 
GetTxtCollFromPool(sal_uInt16 nPoolId) const1263 SwTxtFmtColl *SwCSS1Parser::GetTxtCollFromPool( sal_uInt16 nPoolId ) const
1264 {
1265     sal_uInt16 nOldArrLen = pDoc->GetTxtFmtColls()->Count();
1266 
1267     SwTxtFmtColl *pColl = pDoc->GetTxtCollFromPool( nPoolId, false );
1268 
1269     if( bIsNewDoc )
1270     {
1271         sal_uInt16 nArrLen = pDoc->GetTxtFmtColls()->Count();
1272         for( sal_uInt16 i=nOldArrLen; i<nArrLen; i++ )
1273             lcl_swcss1_setEncoding( *(*pDoc->GetTxtFmtColls())[i],
1274                                     GetDfltEncoding() );
1275     }
1276 
1277     return pColl;
1278 }
1279 
GetCharFmtFromPool(sal_uInt16 nPoolId) const1280 SwCharFmt *SwCSS1Parser::GetCharFmtFromPool( sal_uInt16 nPoolId ) const
1281 {
1282     sal_uInt16 nOldArrLen = pDoc->GetCharFmts()->Count();
1283 
1284     SwCharFmt *pCharFmt = pDoc->GetCharFmtFromPool( nPoolId );
1285 
1286     if( bIsNewDoc )
1287     {
1288         sal_uInt16 nArrLen = pDoc->GetCharFmts()->Count();
1289 
1290         for( sal_uInt16 i=nOldArrLen; i<nArrLen; i++ )
1291             lcl_swcss1_setEncoding( *(*pDoc->GetCharFmts())[i],
1292                                     GetDfltEncoding() );
1293     }
1294 
1295     return pCharFmt;
1296 }
1297 
GetTxtFmtColl(sal_uInt16 nTxtColl,const String & rClass)1298 SwTxtFmtColl *SwCSS1Parser::GetTxtFmtColl( sal_uInt16 nTxtColl,
1299                                            const String& rClass )
1300 {
1301     SwTxtFmtColl* pColl = 0;
1302 
1303     String aClass( rClass );
1304     GetScriptFromClass( aClass, sal_False );
1305     if( RES_POOLCOLL_TEXT == nTxtColl && aClass.Len() >= 9 &&
1306         ('s' == aClass.GetChar(0) || 'S' == aClass.GetChar(0) ) )
1307     {
1308         if( aClass.EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_sdendnote) )
1309         {
1310             nTxtColl = RES_POOLCOLL_ENDNOTE;
1311             aClass = aEmptyStr;
1312         }
1313         else if( aClass.EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_sdfootnote) )
1314         {
1315             nTxtColl = RES_POOLCOLL_FOOTNOTE;
1316             aClass = aEmptyStr;
1317         }
1318     }
1319 
1320     String sName;
1321     if( USER_FMT & nTxtColl )       // eine vom Reader angelegte
1322     {
1323         ASSERT( !this, "Wo kommt die Benutzer-Vorlage her?" );
1324         pColl = GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
1325     }
1326     else
1327     {
1328         pColl = GetTxtCollFromPool( nTxtColl );
1329     }
1330 
1331     ASSERT( pColl, "Keine Absatz-Vorlage???" );
1332     if( aClass.Len() )
1333     {
1334         String aTmp( pColl->GetName() );
1335         AddClassName( aTmp, aClass );
1336         SwTxtFmtColl* pClassColl = pDoc->FindTxtFmtCollByName( aTmp );
1337 
1338         if( !pClassColl &&
1339             (nTxtColl==RES_POOLCOLL_TABLE ||
1340              nTxtColl==RES_POOLCOLL_TABLE_HDLN) )
1341         {
1342             // Wenn dieser Fall eintritt, dann wurde ein <TD><P CLASS=foo>
1343             // gelesen, aber die TD.foo Vorlage nicht gefunden. Dann muessen
1344             // wir P.foo nehmen, wenn es sie gibt.
1345             SwTxtFmtColl* pCollText =
1346                 GetTxtCollFromPool( RES_POOLCOLL_TEXT );
1347             aTmp = pCollText->GetName();
1348             AddClassName( aTmp, aClass );
1349             pClassColl = pDoc->FindTxtFmtCollByName( aTmp );
1350         }
1351 
1352         if( pClassColl )
1353         {
1354             pColl = pClassColl;
1355         }
1356         else
1357         {
1358             const SvxCSS1MapEntry *pClass = GetClass( aClass );
1359             if( pClass )
1360             {
1361                 pColl = pDoc->MakeTxtFmtColl( aTmp, pColl );
1362                 SfxItemSet aItemSet( pClass->GetItemSet() );
1363                 SvxCSS1PropertyInfo aPropInfo( pClass->GetPropertyInfo() );
1364                 aPropInfo.SetBoxItem( aItemSet, MIN_BORDER_DIST );
1365                 sal_Bool bPositioned = MayBePositioned( pClass->GetPropertyInfo() );
1366                 if( bPositioned )
1367                     aItemSet.ClearItem( RES_BACKGROUND );
1368                 SetTxtCollAttrs( pColl, aItemSet, aPropInfo,
1369                                  this );
1370             }
1371         }
1372 
1373     }
1374 
1375     if( pColl )
1376         lcl_swcss1_setEncoding( *pColl, GetDfltEncoding() );
1377 
1378     return pColl;
1379 }
1380 
GetMasterPageDesc()1381 SwPageDesc *SwCSS1Parser::GetMasterPageDesc()
1382 {
1383     return pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1384 }
1385 
FindPageDesc(SwDoc * pDoc,sal_uInt16 nPoolId,sal_uInt16 & rPage)1386 static SwPageDesc *FindPageDesc( SwDoc *pDoc, sal_uInt16 nPoolId, sal_uInt16& rPage )
1387 {
1388     sal_uInt16 nPageDescs = pDoc->GetPageDescCnt();
1389     for( rPage=0; rPage < nPageDescs &&
1390          const_cast<const SwDoc *>(pDoc)->
1391              GetPageDesc(rPage).GetPoolFmtId() != nPoolId; rPage++ )
1392          ;
1393 
1394     return rPage < nPageDescs ? &pDoc->_GetPageDesc( rPage ) : 0;
1395 }
1396 
GetPageDesc(sal_uInt16 nPoolId,sal_Bool bCreate)1397 const SwPageDesc *SwCSS1Parser::GetPageDesc( sal_uInt16 nPoolId, sal_Bool bCreate )
1398 {
1399     if( RES_POOLPAGE_HTML == nPoolId )
1400         return pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1401 
1402     sal_uInt16 nPage;
1403     const SwPageDesc *pPageDesc = FindPageDesc( pDoc, nPoolId, nPage );
1404     if( !pPageDesc && bCreate )
1405     {
1406         // Die erste Seite wird aus der rechten Seite erzeugt, wenn es die
1407         // gibt.
1408         SwPageDesc *pMasterPageDesc = 0;
1409         if( RES_POOLPAGE_FIRST == nPoolId )
1410             pMasterPageDesc = FindPageDesc( pDoc, RES_POOLPAGE_RIGHT, nPage );
1411         if( !pMasterPageDesc )
1412             pMasterPageDesc = pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1413 
1414         // Die neue Seitenvorlage entsteht aus dem Master durch kopieren.
1415         SwPageDesc *pNewPageDesc = pDoc->
1416             GetPageDescFromPool( nPoolId, false );
1417 
1418         // dazu brauchen wir auch die Nummer der neuen Vorlage
1419         pPageDesc = FindPageDesc( pDoc, nPoolId, nPage );
1420         ASSERT( pPageDesc==pNewPageDesc, "Seitenvorlage nicht gefunden" );
1421 
1422         pDoc->CopyPageDesc( *pMasterPageDesc, *pNewPageDesc, sal_False );
1423 
1424         // Die Vorlagen an ihren neuen Zweck anpassen.
1425         const SwPageDesc *pFollow = 0;
1426         sal_Bool bSetFollowFollow = sal_False;
1427         switch( nPoolId )
1428         {
1429         case RES_POOLPAGE_FIRST:
1430             // Wenn es schon eine linke Seite gibt, dann ist das die
1431             // Folge-Vorlage, sonst ist es die HTML-Vorlage.
1432             pFollow = GetLeftPageDesc();
1433             if( !pFollow )
1434                 pFollow = pMasterPageDesc;
1435             break;
1436 
1437         case RES_POOLPAGE_RIGHT:
1438             // Wenn die linke Vorlage schon angelegt ist, passiert hier gar
1439             // nichts. Sonst wird die linke Vorlage angelegt und sorgt auch
1440             // fuer die richtige Verkettung mit der rechten Voralge.
1441             GetLeftPageDesc( sal_True );
1442             break;
1443 
1444         case RES_POOLPAGE_LEFT:
1445             // Die rechte Vorlage wird angelegt, wenn sie noch nicht existiert.
1446             // Es findet aber keine Verkettung statt.
1447             // Wenn schon eine erste Seitenvorlage existiert, wird die linke
1448             // Vorlage die Folge-Vorlage der ersten Seite.
1449             pFollow = GetRightPageDesc( sal_True );
1450             bSetFollowFollow = sal_True;
1451             {
1452                 const SwPageDesc *pFirstPageDesc = GetFirstPageDesc();
1453                 if( pFirstPageDesc )
1454                 {
1455                     SwPageDesc aNewFirstPageDesc( *pFirstPageDesc );
1456                     aNewFirstPageDesc.SetFollow( pNewPageDesc );
1457                     ChgPageDesc( pFirstPageDesc, aNewFirstPageDesc );
1458                 }
1459             }
1460             break;
1461         }
1462 
1463         if( pFollow )
1464         {
1465             SwPageDesc aNewPageDesc( *pNewPageDesc );
1466             aNewPageDesc.SetFollow( pFollow );
1467             ChgPageDesc( pNewPageDesc, aNewPageDesc );
1468 
1469             if( bSetFollowFollow )
1470             {
1471                 SwPageDesc aNewFollowPageDesc( *pFollow );
1472                 aNewFollowPageDesc.SetFollow( pNewPageDesc );
1473                 ChgPageDesc( pFollow, aNewFollowPageDesc );
1474             }
1475         }
1476         pPageDesc = pNewPageDesc;
1477     }
1478 
1479     return pPageDesc;
1480 }
1481 
1482 
MayBePositioned(const SvxCSS1PropertyInfo & rPropInfo,sal_Bool bAutoWidth)1483 sal_Bool SwCSS1Parser::MayBePositioned( const SvxCSS1PropertyInfo& rPropInfo,
1484                                     sal_Bool bAutoWidth )
1485 {
1486     // abs-pos
1487     // left/top none    auto    twip    perc
1488     //
1489     // none     Z       Z       -       -
1490     // auto     Z       Z       -       -
1491     // twip     Z       Z       S/R     -
1492     // perc     -       -       -       -
1493     //
1494     // - das Tag wird absolut positioniert und left/top sind beide
1495     //   gegeben und enthalten auch keine %-Angabe, oder
1496     // - das Tag soll fliessen, und
1497     // - es wurde eine Breite angegeben (in beiden Faellen noetig)
1498     return ( ( SVX_CSS1_POS_ABSOLUTE     == rPropInfo.ePosition &&
1499                SVX_CSS1_LTYPE_PERCENTAGE != rPropInfo.eLeftType &&
1500                SVX_CSS1_LTYPE_PERCENTAGE != rPropInfo.eTopType &&
1501               (SVX_CSS1_LTYPE_TWIP       == rPropInfo.eLeftType ||
1502                SVX_CSS1_LTYPE_TWIP       != rPropInfo.eTopType) ) ||
1503              ( SVX_ADJUST_END            != rPropInfo.eFloat  ) ) &&
1504            ( bAutoWidth ||
1505              SVX_CSS1_LTYPE_TWIP         == rPropInfo.eWidthType ||
1506              SVX_CSS1_LTYPE_PERCENTAGE   == rPropInfo.eWidthType );
1507 }
1508 
1509 
1510 /*  */
1511 
AddClassName(String & rFmtName,const String & rClass)1512 void SwCSS1Parser::AddClassName( String& rFmtName, const String& rClass )
1513 {
1514     ASSERT( rClass.Len(), "Style-Klasse ohne Laenge?" );
1515 
1516 // ??????????
1517 //  String aTmp( rClass );
1518 //  GetpApp()->GetAppInternational().ToLower( aTmp );
1519 
1520     (rFmtName += '.') += rClass;
1521 }
1522 
1523 /*  */
1524 
FillDropCap(SwFmtDrop & rDrop,SfxItemSet & rItemSet,const String * pName)1525 void SwCSS1Parser::FillDropCap( SwFmtDrop& rDrop,
1526                                 SfxItemSet& rItemSet,
1527                                 const String *pName )
1528 {
1529     // die Anzahl der Zeilen entspricht in etwa einer %-Angabe
1530     // fuer die Hoehe (was passiert mit absoluten Hoehen???)
1531     sal_uInt8 nLines = rDrop.GetLines();
1532     const SfxPoolItem *pItem;
1533     if( SFX_ITEM_SET == rItemSet.GetItemState( RES_CHRATR_FONTSIZE, sal_False, &pItem ) )
1534     {
1535         sal_uInt16 nProp = ((const SvxFontHeightItem *)pItem)->GetProp();
1536         nLines = (sal_uInt8)((nProp + 50) / 100);
1537         if( nLines < 1 )
1538             nLines = 1;
1539         else if( nLines > MAX_DROPCAP_LINES )
1540             nLines = MAX_DROPCAP_LINES;
1541 
1542         // Nur wenn nLines>1 ist, wird das Attribut auch gesetzt. Dann
1543         // brauchen wir die Font-Hoehe aber auch nicht in der Zeichen-Vorlage.
1544         if( nLines > 1 )
1545         {
1546             rItemSet.ClearItem( RES_CHRATR_FONTSIZE );
1547             rItemSet.ClearItem( RES_CHRATR_CJK_FONTSIZE );
1548             rItemSet.ClearItem( RES_CHRATR_CTL_FONTSIZE );
1549         }
1550     }
1551 
1552     // Bei harter Attributierung (pName==0) koennen wir aufhoehren, wenn
1553     // das Initial nur ueber eine Zeile geht.
1554 #ifdef FULL_FIRST_LETTER
1555     if( nLines<=1 && !pName )
1556 #else
1557     if( nLines<=1 )
1558 #endif
1559         return;
1560 
1561     rDrop.GetLines() = nLines;
1562 
1563     // ein rechter Rand wird der Abstand zum Text!
1564     if( SFX_ITEM_SET == rItemSet.GetItemState( RES_LR_SPACE, sal_False, &pItem ) )
1565     {
1566         rDrop.GetDistance() = static_cast< sal_uInt16 >(
1567             ((const SvxLRSpaceItem *)pItem)->GetRight() );
1568         rItemSet.ClearItem( RES_LR_SPACE );
1569     }
1570 
1571     // Fuer alle anderen Attribute eine Zeichen-Vorlage anlegen
1572     if( rItemSet.Count() )
1573     {
1574         SwCharFmt *pCFmt = 0;
1575         String aName;
1576         if( pName )
1577         {
1578             aName = *pName;
1579             AddFirstLetterExt( aName );
1580             pCFmt = pDoc->FindCharFmtByName( aName );
1581         }
1582         else
1583         {
1584             do
1585             {
1586                 aName.AssignAscii( sCSS1_first_letter );
1587                 aName.Append( ' ' );
1588                 aName.Append(
1589                     String::CreateFromInt32( (sal_Int32)(++nDropCapCnt) ) );
1590             }
1591             while( pDoc->FindCharFmtByName(aName) );
1592         }
1593 
1594         if( !pCFmt )
1595         {
1596             pCFmt = pDoc->MakeCharFmt( aName, pDoc->GetDfltCharFmt() );
1597             pCFmt->SetAuto( sal_False );
1598         }
1599         SetCharFmtAttrs( pCFmt, rItemSet );
1600 
1601         // Die Zeichenvorlage braucht nur im Attribut gesetzt werden, wenn
1602         // auch das Attribut gesetzt wird.
1603         if( nLines > 1 )
1604             rDrop.SetCharFmt( pCFmt );
1605     }
1606 }
1607 
1608 /*  */
1609 
1610 // CSS1-sezifisches des SwHTMLParsers
1611 
GetAttrTabEntry(sal_uInt16 nWhich)1612 _HTMLAttr **SwHTMLParser::GetAttrTabEntry( sal_uInt16 nWhich )
1613 {
1614     // den zu dem Item gehoehrenden Tabellen-Eintrag ermitteln ...
1615     _HTMLAttr **ppAttr = 0;
1616     switch( nWhich )
1617     {
1618     case RES_CHRATR_BLINK:
1619         ppAttr = &aAttrTab.pBlink;
1620         break;
1621     case RES_CHRATR_CASEMAP:
1622         ppAttr = &aAttrTab.pCaseMap;
1623         break;
1624     case RES_CHRATR_COLOR:
1625         ppAttr = &aAttrTab.pFontColor;
1626         break;
1627     case RES_CHRATR_CROSSEDOUT:
1628         ppAttr = &aAttrTab.pStrike;
1629         break;
1630     case RES_CHRATR_ESCAPEMENT:
1631         ppAttr = &aAttrTab.pEscapement;
1632         break;
1633     case RES_CHRATR_FONT:
1634         ppAttr = &aAttrTab.pFont;
1635         break;
1636     case RES_CHRATR_CJK_FONT:
1637         ppAttr = &aAttrTab.pFontCJK;
1638         break;
1639     case RES_CHRATR_CTL_FONT:
1640         ppAttr = &aAttrTab.pFontCTL;
1641         break;
1642     case RES_CHRATR_FONTSIZE:
1643         ppAttr = &aAttrTab.pFontHeight;
1644         break;
1645     case RES_CHRATR_CJK_FONTSIZE:
1646         ppAttr = &aAttrTab.pFontHeightCJK;
1647         break;
1648     case RES_CHRATR_CTL_FONTSIZE:
1649         ppAttr = &aAttrTab.pFontHeightCTL;
1650         break;
1651     case RES_CHRATR_KERNING:
1652         ppAttr = &aAttrTab.pKerning;
1653         break;
1654     case RES_CHRATR_POSTURE:
1655         ppAttr = &aAttrTab.pItalic;
1656         break;
1657     case RES_CHRATR_CJK_POSTURE:
1658         ppAttr = &aAttrTab.pItalicCJK;
1659         break;
1660     case RES_CHRATR_CTL_POSTURE:
1661         ppAttr = &aAttrTab.pItalicCTL;
1662         break;
1663     case RES_CHRATR_UNDERLINE:
1664         ppAttr = &aAttrTab.pUnderline;
1665         break;
1666     case RES_CHRATR_WEIGHT:
1667         ppAttr = &aAttrTab.pBold;
1668         break;
1669     case RES_CHRATR_CJK_WEIGHT:
1670         ppAttr = &aAttrTab.pBoldCJK;
1671         break;
1672     case RES_CHRATR_CTL_WEIGHT:
1673         ppAttr = &aAttrTab.pBoldCTL;
1674         break;
1675     case RES_CHRATR_BACKGROUND:
1676         ppAttr = &aAttrTab.pCharBrush;
1677         break;
1678 
1679     case RES_PARATR_LINESPACING:
1680         ppAttr = &aAttrTab.pLineSpacing;
1681         break;
1682     case RES_PARATR_ADJUST:
1683         ppAttr = &aAttrTab.pAdjust;
1684         break;
1685 
1686     case RES_LR_SPACE:
1687         ppAttr = &aAttrTab.pLRSpace;
1688         break;
1689     case RES_UL_SPACE:
1690         ppAttr = &aAttrTab.pULSpace;
1691         break;
1692     case RES_BOX:
1693         ppAttr = &aAttrTab.pBox;
1694         break;
1695     case RES_BACKGROUND:
1696         ppAttr = &aAttrTab.pBrush;
1697         break;
1698     case RES_BREAK:
1699         ppAttr = &aAttrTab.pBreak;
1700         break;
1701     case RES_PAGEDESC:
1702         ppAttr = &aAttrTab.pPageDesc;
1703         break;
1704     case RES_PARATR_SPLIT:
1705         ppAttr = &aAttrTab.pSplit;
1706         break;
1707     case RES_PARATR_WIDOWS:
1708         ppAttr = &aAttrTab.pWidows;
1709         break;
1710     case RES_PARATR_ORPHANS:
1711         ppAttr = &aAttrTab.pOrphans;
1712         break;
1713     case RES_KEEP:
1714         ppAttr = &aAttrTab.pKeep;
1715         break;
1716 
1717     case RES_CHRATR_LANGUAGE:
1718         ppAttr = &aAttrTab.pLanguage;
1719         break;
1720     case RES_CHRATR_CJK_LANGUAGE:
1721         ppAttr = &aAttrTab.pLanguageCJK;
1722         break;
1723     case RES_CHRATR_CTL_LANGUAGE:
1724         ppAttr = &aAttrTab.pLanguageCTL;
1725         break;
1726 
1727     case RES_FRAMEDIR:
1728         ppAttr = &aAttrTab.pDirection;
1729         break;
1730     }
1731 
1732     return ppAttr;
1733 }
1734 
NewStyle()1735 void SwHTMLParser::NewStyle()
1736 {
1737     String sType;
1738 
1739     const HTMLOptions *pOptions2 = GetOptions();
1740     for( sal_uInt16 i = pOptions2->Count(); i; )
1741     {
1742         const HTMLOption *pOption = (*pOptions2)[--i];
1743         if( HTML_O_TYPE==pOption->GetToken() )
1744             sType = pOption->GetString();
1745     }
1746 
1747     bIgnoreRawData = sType.Len() &&
1748                      !sType.GetToken(0,';').EqualsAscii(sCSS_mimetype);
1749 }
1750 
EndStyle()1751 void SwHTMLParser::EndStyle()
1752 {
1753     bIgnoreRawData = sal_False;
1754 
1755     if( aStyleSource.Len() )
1756     {
1757         pCSS1Parser->ParseStyleSheet( aStyleSource );
1758         aStyleSource.Erase();
1759     }
1760 }
1761 
FileDownload(const String & rURL,String & rStr)1762 sal_Bool SwHTMLParser::FileDownload( const String& rURL,
1763                                  String& rStr )
1764 {
1765     // View wegschmeissen (wegen Reschedule)
1766     ViewShell *pOldVSh = CallEndAction();
1767 
1768     // Ein Medium anlegen
1769     SfxMedium aDLMedium( rURL, STREAM_READ | STREAM_SHARE_DENYWRITE, sal_False );
1770 
1771     // Medium registrieren, damit abgebrochen werden kann
1772     if( pDoc->GetDocShell() )
1773         pDoc->GetDocShell()->RegisterTransfer( aDLMedium );
1774 
1775     SvStream* pStream = aDLMedium.GetInStream();
1776     if( pStream )
1777     {
1778         SvMemoryStream aStream;
1779         aStream << *pStream;
1780 
1781         aStream.Seek( STREAM_SEEK_TO_END );
1782         DBG_ASSERT( aStream.Tell() < STRING_MAXLEN,
1783                     "File zu lang fuer einen String, Ende abgeschnitten" );
1784         xub_StrLen nLen = aStream.Tell() < STRING_MAXLEN
1785                         ? (xub_StrLen)aStream.Tell()
1786                         : STRING_MAXLEN;
1787 
1788         rStr = String( (const sal_Char *)aStream.GetData(), nLen,
1789                        GetSrcEncoding() );
1790     }
1791 
1792 
1793     // wurde abgebrochen?
1794     if( ( pDoc->GetDocShell() && pDoc->GetDocShell()->IsAbortingImport() )
1795         || 1 == pDoc->getReferenceCount() )
1796     {
1797         // wurde der Import vom SFX abgebrochen?
1798         eState = SVPAR_ERROR;
1799         pStream = 0;
1800     }
1801 
1802     // View wieder anlgen
1803 #if OSL_DEBUG_LEVEL > 1
1804     ViewShell *pVSh =
1805 #endif
1806         CallStartAction( pOldVSh );
1807 #if OSL_DEBUG_LEVEL > 1
1808     ASSERT( pOldVSh == pVSh, "FileDownload: ViewShell wurde ausgetauscht" );
1809     (void) pVSh;
1810 #endif
1811 
1812     return pStream!=0;
1813 }
1814 
InsertLink()1815 void SwHTMLParser::InsertLink()
1816 {
1817     sal_Bool bFinishDownload = sal_False;
1818     if( pPendStack )
1819     {
1820         ASSERT( ShouldFinishFileDownload(),
1821                 "Pending-Stack ohne File-Download?" );
1822 
1823         SwPendingStack* pTmp = pPendStack->pNext;
1824         delete pPendStack;
1825         pPendStack = pTmp;
1826         ASSERT( !pPendStack, "Wo kommt der Pending-Stack her?" );
1827 
1828         bFinishDownload = sal_True;
1829     }
1830     else
1831     {
1832         String sRel, sHRef, sType;
1833 
1834         const HTMLOptions *pOptions2 = GetOptions();
1835         for( sal_uInt16 i = pOptions2->Count(); i; )
1836         {
1837             const HTMLOption *pOption = (*pOptions2)[--i];
1838             switch( pOption->GetToken() )
1839             {
1840                 case HTML_O_REL:
1841                     sRel = pOption->GetString();
1842                     break;
1843                 case HTML_O_HREF:
1844                     sHRef = URIHelper::SmartRel2Abs( INetURLObject( sBaseURL ), pOption->GetString(), Link(), false );
1845                     break;
1846                 case HTML_O_TYPE:
1847                     sType = pOption->GetString();
1848                     break;
1849             }
1850         }
1851 
1852         if( sHRef.Len() && sRel.EqualsIgnoreCaseAscii( "STYLESHEET" ) &&
1853             ( !sType.Len() ||
1854               sType.GetToken(0,';').EqualsAscii(sCSS_mimetype) ) )
1855         {
1856             if( GetMedium() )
1857             {
1858                 // Download des Style-Source starten
1859                 StartFileDownload( sHRef, 0, pDoc->GetDocShell() );
1860                 if( IsParserWorking() )
1861                 {
1862                     // Der Style wurde synchron geladen und wir koennen
1863                     // es direkt aufrufen.
1864                     bFinishDownload = sal_True;
1865                 }
1866                 else
1867                 {
1868                     // Der Style wird asynchron geladen und ist erst beim
1869                     // naechsten Continue-Aufruf da. Wir muessen deshalb einen
1870                     // Pending-Stack anlegen, damit wir hierher zurueckkehren
1871                     pPendStack = new SwPendingStack( HTML_LINK, pPendStack );
1872                 }
1873             }
1874             else
1875             {
1876                 // File synchron holen
1877                 String sSource;
1878                 if( FileDownload( sHRef, sSource ) )
1879                     pCSS1Parser->ParseStyleSheet( sSource );
1880             }
1881         }
1882     }
1883 
1884     if( bFinishDownload )
1885     {
1886         String sSource;
1887         if( FinishFileDownload(sSource) && sSource.Len() )
1888             pCSS1Parser->ParseStyleSheet( sSource );
1889     }
1890 }
1891 
ParseStyleSheet(const String & rIn)1892 sal_Bool SwCSS1Parser::ParseStyleSheet( const String& rIn )
1893 {
1894     if( !SvxCSS1Parser::ParseStyleSheet( rIn ) )
1895         return sal_False;
1896 
1897     SwPageDesc *pMasterPageDesc =
1898         pDoc->GetPageDescFromPool( RES_POOLPAGE_HTML, false );
1899 
1900     SvxCSS1MapEntry *pPageEntry = GetPage( aEmptyStr, sal_False );
1901     if( pPageEntry )
1902     {
1903         // @page (wirkt auf alle Seiten, die es schon gibt
1904 
1905         SetPageDescAttrs( pMasterPageDesc, pPageEntry->GetItemSet(),
1906                           pPageEntry->GetPropertyInfo() );
1907 
1908         // Fuer alle anderen Seiten-Vorlagen, die es schon gibt,
1909         // muessen die Attribute auch noch gesetzt werden
1910 
1911         SetPageDescAttrs( GetFirstPageDesc(), pPageEntry->GetItemSet(),
1912                           pPageEntry->GetPropertyInfo() );
1913         SetPageDescAttrs( GetLeftPageDesc(), pPageEntry->GetItemSet(),
1914                           pPageEntry->GetPropertyInfo() );
1915         SetPageDescAttrs( GetRightPageDesc(), pPageEntry->GetItemSet(),
1916                           pPageEntry->GetPropertyInfo() );
1917 //      if( pNamedPageDescs )
1918 //      {
1919 //          for( sal_uInt16 i=0; i<pNamedPageDescs->Count(); i++ )
1920 //              SetPageDescAttrs( (*pNamedPageDescs)[i],
1921 //                                pPageEntry->GetItemSet(),
1922 //                                pPageEntry->GetPropertyInfo() );
1923 //      }
1924 
1925     }
1926 
1927     pPageEntry = GetPage( String::CreateFromAscii(sCSS1_first), sal_True );
1928     if( pPageEntry )
1929     {
1930         SetPageDescAttrs( GetFirstPageDesc(sal_True), pPageEntry->GetItemSet(),
1931                           pPageEntry->GetPropertyInfo() );
1932         bSetFirstPageDesc = sal_True;
1933     }
1934 
1935     pPageEntry = GetPage( String::CreateFromAscii(sCSS1_right), sal_True );
1936     if( pPageEntry )
1937     {
1938         SetPageDescAttrs( GetRightPageDesc(sal_True), pPageEntry->GetItemSet(),
1939                           pPageEntry->GetPropertyInfo() );
1940         bSetRightPageDesc = sal_True;
1941     }
1942 
1943     pPageEntry = GetPage( String::CreateFromAscii(sCSS1_left), sal_True );
1944     if( pPageEntry )
1945         SetPageDescAttrs( GetLeftPageDesc(sal_True), pPageEntry->GetItemSet(),
1946                           pPageEntry->GetPropertyInfo() );
1947 
1948     // und jetzt noch die benannten Vorlagen
1949 //  for( sal_uInt16 i=0; i < GetPageCount(); i++ )
1950 //  {
1951 //      pPageEntry = GetPage( i );
1952 //      const String& rKey = pPageEntry->GetKey();
1953 //      if( !rKey.Len() || rKey.GetChar(0) == ':' )
1954 //          continue;
1955 //
1956 //      String aName( rKey );
1957 //      GetpApp()->GetAppInternational().ToLower( aName );
1958 //      sal_uInt16 nPage = pDoc->MakePageDesc( aName );
1959 //      SwPageDesc *pPageDesc = &pDoc->_GetPageDesc( nPage );
1960 //
1961 //      // Die neue Seitenvorlage entsteht aus dem Master durch kopieren.
1962 //      pDoc->CopyPageDesc( *pMasterPageDesc, *pPageDesc );
1963 //      SetPageDescAttrs( pPageDesc, pPageEntry->GetItemSet(),
1964 //                        pPageEntry->GetPropertyInfo() );
1965 //
1966 //      if( !pNamedPageDescs )
1967 //          pNamedPageDescs = new SwHTMLPageDescs;
1968 //      pNamedPageDescs->Insert( pPageDesc, pNamedPageDescs->Count() );
1969 //  }
1970 
1971     return sal_True;
1972 }
1973 
ParseStyleOptions(const String & rStyle,const String & rId,const String & rClass,SfxItemSet & rItemSet,SvxCSS1PropertyInfo & rPropInfo,const String * pLang,const String * pDir)1974 sal_Bool SwHTMLParser::ParseStyleOptions( const String &rStyle,
1975                                       const String &rId,
1976                                       const String &rClass,
1977                                       SfxItemSet &rItemSet,
1978                                       SvxCSS1PropertyInfo &rPropInfo,
1979                                       const String *pLang,
1980                                       const String *pDir )
1981 {
1982     sal_Bool bRet = sal_False;
1983 
1984     if( rClass.Len() )
1985     {
1986         String aClass( rClass );
1987         SwCSS1Parser::GetScriptFromClass( aClass );
1988         SvxCSS1MapEntry *pClass = pCSS1Parser->GetClass( aClass );
1989         if( pClass )
1990         {
1991             pCSS1Parser->MergeStyles( pClass->GetItemSet(),
1992                                       pClass->GetPropertyInfo(),
1993                                       rItemSet, rPropInfo, sal_False );
1994             bRet = sal_True;
1995         }
1996     }
1997 
1998     if( rId.Len() )
1999     {
2000         SvxCSS1MapEntry *pId = pCSS1Parser->GetId( rId );
2001         if( pId )
2002             pCSS1Parser->MergeStyles( pId->GetItemSet(),
2003                                       pId->GetPropertyInfo(),
2004                                       rItemSet, rPropInfo, rClass.Len()!=0 );
2005         rPropInfo.aId = rId;
2006         bRet = sal_True;
2007     }
2008 
2009     if( rStyle.Len() )
2010     {
2011         pCSS1Parser->ParseStyleOption( rStyle, rItemSet, rPropInfo );
2012         bRet = sal_True;
2013     }
2014 
2015     if( bRet )
2016         rPropInfo.SetBoxItem( rItemSet, MIN_BORDER_DIST );
2017 
2018     if( pLang && pLang->Len() )
2019     {
2020         LanguageType eLang = MsLangId::convertIsoStringToLanguage( *pLang );
2021         if( LANGUAGE_DONTKNOW != eLang )
2022         {
2023             SvxLanguageItem aLang( eLang, RES_CHRATR_LANGUAGE );
2024             rItemSet.Put( aLang );
2025             aLang.SetWhich( RES_CHRATR_CJK_LANGUAGE );
2026             rItemSet.Put( aLang );
2027             aLang.SetWhich( RES_CHRATR_CTL_LANGUAGE );
2028             rItemSet.Put( aLang );
2029 
2030             bRet = sal_True;
2031         }
2032     }
2033     if( pDir && pDir->Len() )
2034     {
2035         String aValue( *pDir );
2036         aValue.ToUpperAscii();
2037         SvxFrameDirection eDir = FRMDIR_ENVIRONMENT;
2038         if( aValue.EqualsAscii( "LTR" ) )
2039             eDir = FRMDIR_HORI_LEFT_TOP;
2040         else if( aValue.EqualsAscii( "RTL" ) )
2041             eDir = FRMDIR_HORI_RIGHT_TOP;
2042 
2043         if( FRMDIR_ENVIRONMENT != eDir )
2044         {
2045             SvxFrameDirectionItem aDir( eDir, RES_FRAMEDIR );
2046             rItemSet.Put( aDir );
2047 
2048             bRet = sal_True;
2049         }
2050     }
2051 
2052     return bRet;
2053 }
2054 
SetAnchorAndAdjustment(const SfxItemSet &,const SvxCSS1PropertyInfo & rPropInfo,SfxItemSet & rFrmItemSet)2055 void SwHTMLParser::SetAnchorAndAdjustment( const SfxItemSet & /*rItemSet*/,
2056                                            const SvxCSS1PropertyInfo &rPropInfo,
2057                                            SfxItemSet &rFrmItemSet )
2058 {
2059     SwFmtAnchor aAnchor;
2060 
2061     sal_Int16 eHoriOri = text::HoriOrientation::NONE;
2062     sal_Int16 eVertOri = text::VertOrientation::NONE;
2063     sal_Int16 eHoriRel = text::RelOrientation::FRAME;
2064     sal_Int16 eVertRel = text::RelOrientation::FRAME;
2065     SwTwips nHoriPos = 0, nVertPos = 0;
2066     SwSurround eSurround = SURROUND_THROUGHT;
2067     if( SVX_CSS1_POS_ABSOLUTE == rPropInfo.ePosition )
2068     {
2069         if( SVX_CSS1_LTYPE_TWIP == rPropInfo.eLeftType &&
2070             SVX_CSS1_LTYPE_TWIP == rPropInfo.eTopType )
2071         {
2072             // Absolut positionierte Objekte sind seitengebunden, wenn
2073             // sie nicht schon in einem Rahmen stehen und sonst
2074             // Rahmengebunden.
2075             const SwStartNode *pFlySttNd =
2076                 pPam->GetPoint()->nNode.GetNode().FindFlyStartNode();
2077             if( pFlySttNd )
2078             {
2079                 aAnchor.SetType( FLY_AT_FLY );
2080                 SwPosition aPos( *pFlySttNd );
2081                 aAnchor.SetAnchor( &aPos );
2082             }
2083             else
2084             {
2085                 aAnchor.SetType( FLY_AT_PAGE );
2086                 aAnchor.SetPageNum( 1 );
2087             }
2088             nHoriPos = rPropInfo.nLeft;
2089             nVertPos = rPropInfo.nTop;
2090         }
2091         else
2092         {
2093             aAnchor.SetType( FLY_AT_PARA );
2094             aAnchor.SetAnchor( pPam->GetPoint() );
2095             eVertOri = text::VertOrientation::TOP;
2096             eVertRel = text::RelOrientation::CHAR;
2097             if( SVX_CSS1_LTYPE_TWIP == rPropInfo.eLeftType )
2098             {
2099                 eHoriOri = text::HoriOrientation::NONE;
2100                 eHoriRel = text::RelOrientation::PAGE_FRAME;
2101                 nHoriPos = rPropInfo.nLeft;
2102             }
2103             else
2104             {
2105                 eHoriOri = text::HoriOrientation::LEFT;
2106                 eHoriRel = text::RelOrientation::FRAME;   // wird noch umgeschossen
2107             }
2108         }
2109     }
2110     else
2111     {
2112         // fliessende Objekte werden Absatzgebunden eingefuegt, wenn
2113         // der Absatz noch leer ist und sonst auto-gebunden.
2114         // Auto-gebundene Rahmen werden zunaechst an der Position davor
2115         // eingefuegt und erst spaeter verschoben.
2116         xub_StrLen nCntnt = pPam->GetPoint()->nContent.GetIndex();
2117         if( nCntnt )
2118         {
2119             aAnchor.SetType( FLY_AT_CHAR );
2120             pPam->Move( fnMoveBackward );
2121             eVertOri = text::VertOrientation::CHAR_BOTTOM;
2122             eVertRel = text::RelOrientation::CHAR;
2123         }
2124         else
2125         {
2126             aAnchor.SetType( FLY_AT_PARA );
2127             eVertOri = text::VertOrientation::TOP;
2128             eVertRel = text::RelOrientation::PRINT_AREA;
2129         }
2130 
2131         aAnchor.SetAnchor( pPam->GetPoint() );
2132 
2133         if( nCntnt )
2134             pPam->Move( fnMoveForward );
2135 
2136         sal_uInt16 nLeftSpace = 0, nRightSpace = 0;
2137         short nIndent = 0;
2138         GetMarginsFromContextWithNumBul( nLeftSpace, nRightSpace, nIndent );
2139 
2140         if( SVX_ADJUST_RIGHT==rPropInfo.eFloat )
2141         {
2142             eHoriOri = text::HoriOrientation::RIGHT;
2143             eHoriRel = nRightSpace ? text::RelOrientation::PRINT_AREA : text::RelOrientation::FRAME;
2144             eSurround = SURROUND_LEFT;
2145         }
2146         else
2147         {
2148             eHoriOri = text::HoriOrientation::LEFT;
2149             eHoriRel = nLeftSpace ? text::RelOrientation::PRINT_AREA : text::RelOrientation::FRAME;
2150             eSurround = SURROUND_RIGHT;
2151         }
2152     }
2153     rFrmItemSet.Put( aAnchor );
2154 
2155     // Absolut Positioniert mit Durchlauf
2156     rFrmItemSet.Put( SwFmtHoriOrient( nHoriPos, eHoriOri, eHoriRel ) );
2157     rFrmItemSet.Put( SwFmtVertOrient( nVertPos, eVertOri, eVertRel ) );
2158     rFrmItemSet.Put( SwFmtSurround( eSurround ) );
2159 }
2160 
SetVarSize(SfxItemSet &,SvxCSS1PropertyInfo & rPropInfo,SfxItemSet & rFrmItemSet,SwTwips nDfltWidth,sal_uInt8 nDfltPrcWidth)2161 void SwHTMLParser::SetVarSize( SfxItemSet & /*rItemSet*/,
2162                                SvxCSS1PropertyInfo &rPropInfo,
2163                                SfxItemSet &rFrmItemSet,
2164                                SwTwips nDfltWidth, sal_uInt8 nDfltPrcWidth )
2165 {
2166     SwFrmSize eSize = ATT_MIN_SIZE;
2167     SwTwips nWidth = nDfltWidth, nHeight = MINFLY;
2168     sal_uInt8 nPrcWidth = nDfltPrcWidth, nPrcHeight = 0;
2169     switch( rPropInfo.eWidthType )
2170     {
2171     case SVX_CSS1_LTYPE_PERCENTAGE:
2172         nPrcWidth = rPropInfo.nWidth > 0 ? (sal_uInt8)rPropInfo.nWidth : 1;
2173         nWidth = MINFLY;
2174         break;
2175     case SVX_CSS1_LTYPE_TWIP:
2176         nWidth = rPropInfo.nWidth > MINFLY ? rPropInfo.nWidth : MINFLY;
2177         nPrcWidth = 0;
2178         break;
2179     default:
2180         ;
2181     }
2182     switch( rPropInfo.eHeightType )
2183     {
2184     case SVX_CSS1_LTYPE_PERCENTAGE:
2185         nPrcHeight = rPropInfo.nHeight > 0 ? (sal_uInt8)rPropInfo.nHeight : 1;
2186         break;
2187     case SVX_CSS1_LTYPE_TWIP:
2188         // Netscape und MS-IE interpretieren die Hoehe regelwiedrig
2189         // als Mindest-Hoehe, also machwn wir das auch so.
2190         nHeight = rPropInfo.nHeight > MINFLY ? rPropInfo.nHeight : MINFLY;
2191         break;
2192     default:
2193         ;
2194     }
2195 
2196     SwFmtFrmSize aFrmSize( eSize, nWidth, nHeight );
2197     aFrmSize.SetWidthPercent( nPrcWidth );
2198     aFrmSize.SetHeightPercent( nPrcHeight );
2199     rFrmItemSet.Put( aFrmSize );
2200 }
2201 
SetFrmFmtAttrs(SfxItemSet & rItemSet,SvxCSS1PropertyInfo &,sal_uInt16 nFlags,SfxItemSet & rFrmItemSet)2202 void SwHTMLParser::SetFrmFmtAttrs( SfxItemSet &rItemSet,
2203                                    SvxCSS1PropertyInfo & /*rPropInfo*/,
2204                                    sal_uInt16 nFlags,
2205                                    SfxItemSet &rFrmItemSet )
2206 {
2207     const SfxPoolItem *pItem;
2208     if( (nFlags & HTML_FF_BOX) != 0 &&
2209         SFX_ITEM_SET==rItemSet.GetItemState( RES_BOX, sal_True, &pItem ) )
2210     {
2211         if( (nFlags & HTML_FF_PADDING) == 0 )
2212         {
2213             SvxBoxItem aBoxItem( *(const SvxBoxItem *)pItem );
2214             // Alle 4 Seiten gleichzeitig auf 0 setzen
2215             aBoxItem.SetDistance( 0 );
2216             rFrmItemSet.Put( aBoxItem );
2217         }
2218         else
2219         {
2220             rFrmItemSet.Put( *pItem );
2221         }
2222         rItemSet.ClearItem( RES_BOX );
2223     }
2224 
2225     if( (nFlags & HTML_FF_BACKGROUND) != 0 &&
2226         SFX_ITEM_SET==rItemSet.GetItemState( RES_BACKGROUND, sal_True, &pItem ) )
2227     {
2228         rFrmItemSet.Put( *pItem );
2229         rItemSet.ClearItem( RES_BACKGROUND );
2230     }
2231 
2232     if( (nFlags & HTML_FF_DIRECTION) != 0 &&
2233         SFX_ITEM_SET==rItemSet.GetItemState( RES_FRAMEDIR, sal_True, &pItem ) )
2234     {
2235         rFrmItemSet.Put( *pItem );
2236         rItemSet.ClearItem( RES_FRAMEDIR );
2237     }
2238 }
2239 
2240 
2241 /*  */
2242 
PopContext(sal_uInt16 nToken,sal_uInt16 nLimit,sal_Bool bRemove)2243 _HTMLAttrContext *SwHTMLParser::PopContext( sal_uInt16 nToken, sal_uInt16 nLimit,
2244                                             sal_Bool bRemove )
2245 {
2246     sal_uInt16 nPos = aContexts.Count();
2247     if( nPos <= nContextStMin )
2248         return 0;
2249 
2250     sal_Bool bFound = 0==nToken;
2251     if( nToken )
2252     {
2253         // Stack-Eintrag zu dem Token suchen
2254         while( nPos > nContextStMin )
2255         {
2256             sal_uInt16 nCntxtToken = aContexts[--nPos]->GetToken();
2257             if( nCntxtToken == nToken )
2258             {
2259                 bFound = sal_True;
2260                 break;
2261             }
2262             else if( nCntxtToken == nLimit ) // 0 als Token kommt nicht vor
2263             {
2264                 break;
2265             }
2266         }
2267     }
2268     else
2269     {
2270         nPos--;
2271     }
2272 
2273     _HTMLAttrContext *pCntxt = 0;
2274     if( bFound )
2275     {
2276         pCntxt = aContexts[nPos];
2277         if( bRemove )
2278             aContexts.Remove( nPos, 1 );
2279     }
2280 
2281     return pCntxt;
2282 }
2283 
GetMarginsFromContext(sal_uInt16 & nLeft,sal_uInt16 & nRight,short & nIndent,sal_Bool bIgnoreTopContext) const2284 sal_Bool SwHTMLParser::GetMarginsFromContext( sal_uInt16& nLeft,
2285                                           sal_uInt16& nRight,
2286                                           short& nIndent,
2287                                           sal_Bool bIgnoreTopContext ) const
2288 {
2289     sal_uInt16 nPos = aContexts.Count();
2290     if( bIgnoreTopContext )
2291     {
2292         if( !nPos )
2293             return sal_False;
2294         else
2295             nPos--;
2296     }
2297 
2298     while( nPos > nContextStAttrMin )
2299     {
2300         const _HTMLAttrContext *pCntxt = aContexts[--nPos];
2301         if( pCntxt->IsLRSpaceChanged() )
2302         {
2303             pCntxt->GetMargins( nLeft, nRight, nIndent );
2304             return sal_True;
2305         }
2306     }
2307 
2308     return sal_False;
2309 }
2310 
GetMarginsFromContextWithNumBul(sal_uInt16 & nLeft,sal_uInt16 & nRight,short & nIndent) const2311 sal_Bool SwHTMLParser::GetMarginsFromContextWithNumBul( sal_uInt16& nLeft,
2312                                                     sal_uInt16& nRight,
2313                                                     short& nIndent ) const
2314 {
2315     sal_Bool bRet = GetMarginsFromContext( nLeft, nRight, nIndent );
2316     const SwHTMLNumRuleInfo& rInfo = ((SwHTMLParser*)this)->GetNumInfo();
2317     if( rInfo.GetDepth() )
2318     {
2319         sal_uInt8 nLevel = (sal_uInt8)( (rInfo.GetDepth() <= MAXLEVEL ? rInfo.GetDepth()
2320                                                             : MAXLEVEL) - 1 );
2321         const SwNumFmt& rNumFmt = rInfo.GetNumRule()->Get(nLevel);
2322         nLeft = nLeft + rNumFmt.GetAbsLSpace();
2323         nIndent = rNumFmt.GetFirstLineOffset();
2324     }
2325 
2326     return bRet;
2327 }
2328 
GetULSpaceFromContext(sal_uInt16 & nUpper,sal_uInt16 & nLower) const2329 void SwHTMLParser::GetULSpaceFromContext( sal_uInt16& nUpper,
2330                                           sal_uInt16& nLower ) const
2331 {
2332     sal_uInt16 nDfltColl = 0;
2333     String aDfltClass;
2334 
2335     sal_uInt16 nPos = aContexts.Count();
2336     while( nPos > nContextStAttrMin )
2337     {
2338         const _HTMLAttrContext *pCntxt = aContexts[--nPos];
2339         if( pCntxt->IsULSpaceChanged() )
2340         {
2341             pCntxt->GetULSpace( nUpper, nLower );
2342             return;
2343         }
2344         else if( !nDfltColl )
2345         {
2346             nDfltColl = pCntxt->GetDfltTxtFmtColl();
2347             if( nDfltColl )
2348                 aDfltClass = pCntxt->GetClass();
2349         }
2350     }
2351 
2352     if( !nDfltColl )
2353         nDfltColl = RES_POOLCOLL_TEXT;
2354 
2355     const SwTxtFmtColl *pColl =
2356         pCSS1Parser->GetTxtFmtColl( nDfltColl, aDfltClass );
2357     const SvxULSpaceItem& rULSpace = pColl->GetULSpace();
2358     nUpper = rULSpace.GetUpper();
2359     nLower = rULSpace.GetLower();
2360 }
2361 
EndContextAttrs(_HTMLAttrContext * pContext,sal_Bool bRemove)2362 void SwHTMLParser::EndContextAttrs( _HTMLAttrContext *pContext, sal_Bool bRemove )
2363 {
2364     _HTMLAttrs &rAttrs = pContext->GetAttrs();
2365     for( sal_uInt16 i=0; i<rAttrs.Count(); i++ )
2366     {
2367         _HTMLAttr *pAttr = rAttrs[i];
2368 
2369         if( RES_PARATR_DROP==pAttr->GetItem().Which() )
2370         {
2371             // Fuer DropCaps noch die Anzahl der Zeichen anpassen. Wenn
2372             // es am Ende 0 sind, wird das Attribut invalidiert und dann
2373             // von _SetAttr gar nicht erst gesetzt.
2374             xub_StrLen nChars = pPam->GetPoint()->nContent.GetIndex();
2375             if( nChars < 1 )
2376                 pAttr->Invalidate();
2377             else if( nChars > MAX_DROPCAP_CHARS )
2378                 nChars = MAX_DROPCAP_CHARS;
2379             ((SwFmtDrop&)pAttr->GetItem()).GetChars() = (sal_uInt8)nChars;
2380         }
2381 
2382         EndAttr( pAttr );
2383     }
2384 
2385     if( bRemove && rAttrs.Count() )
2386         rAttrs.Remove( 0, rAttrs.Count() );
2387 }
2388 
InsertParaAttrs(const SfxItemSet & rItemSet)2389 void SwHTMLParser::InsertParaAttrs( const SfxItemSet& rItemSet )
2390 {
2391     SfxItemIter aIter( rItemSet );
2392 
2393     const SfxPoolItem *pItem = aIter.FirstItem();
2394     while( pItem )
2395     {
2396         // den zu dem Item gehoehrenden Tabellen-Eintrag ermitteln ...
2397         sal_uInt16 nWhich = pItem->Which();
2398         _HTMLAttr **ppAttr = GetAttrTabEntry( nWhich );
2399 
2400         if( ppAttr )
2401         {
2402             NewAttr( ppAttr, *pItem );
2403             if( RES_PARATR_BEGIN > nWhich )
2404                 (*ppAttr)->SetLikePara();
2405             aParaAttrs.Insert( *ppAttr, aParaAttrs.Count() );
2406             EndAttr( *ppAttr, 0, sal_False );
2407         }
2408 
2409         pItem = aIter.NextItem();
2410     }
2411 }
2412 
lcl_swcss1_setEncoding(SwFmt & rFmt,rtl_TextEncoding eEnc)2413 void lcl_swcss1_setEncoding( SwFmt& rFmt, rtl_TextEncoding eEnc )
2414 {
2415     if( RTL_TEXTENCODING_DONTKNOW == eEnc )
2416         return;
2417 
2418     const SfxItemSet& rItemSet = rFmt.GetAttrSet();
2419     static sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT,
2420                                    RES_CHRATR_CTL_FONT };
2421     const SfxPoolItem *pItem;
2422     for( sal_uInt16 i=0; i<3; i++ )
2423     {
2424         if( SFX_ITEM_SET == rItemSet.GetItemState( aWhichIds[i], sal_False,&pItem ) )
2425         {
2426             const SvxFontItem& rFont = *(const SvxFontItem *)pItem;
2427             if( RTL_TEXTENCODING_SYMBOL != rFont.GetCharSet() )
2428             {
2429                 SvxFontItem aFont( rFont.GetFamily(), rFont.GetFamilyName(),
2430                                    rFont.GetStyleName(), rFont.GetPitch(),
2431                                    eEnc, aWhichIds[i]);
2432                 rFmt.SetFmtAttr( aFont );
2433             }
2434         }
2435     }
2436 }
2437 
SetDfltEncoding(rtl_TextEncoding eEnc)2438 void SwCSS1Parser::SetDfltEncoding( rtl_TextEncoding eEnc )
2439 {
2440     if( eEnc != GetDfltEncoding() )
2441     {
2442         if( bIsNewDoc )
2443         {
2444             // Set new encoding as pool default
2445             static sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT,
2446                                            RES_CHRATR_CTL_FONT };
2447             sal_uInt16 i;
2448             for( i=0; i<3; i++ )
2449             {
2450                 const SvxFontItem& rDfltFont =
2451                     (const SvxFontItem&)pDoc->GetDefault( aWhichIds[i]);
2452                 SvxFontItem aFont( rDfltFont.GetFamily(),
2453                                    rDfltFont.GetFamilyName(),
2454                                    rDfltFont.GetStyleName(),
2455                                    rDfltFont.GetPitch(),
2456                                    eEnc, aWhichIds[i] );
2457                 pDoc->SetDefault( aFont );
2458             }
2459 
2460             // Change all paragraph styles that do specify a font.
2461             sal_uInt16 nArrLen = pDoc->GetTxtFmtColls()->Count();
2462             for( i=1; i<nArrLen; i++ )
2463                 lcl_swcss1_setEncoding( *(*pDoc->GetTxtFmtColls())[i], eEnc );
2464 
2465             // Change all character styles that do specify a font.
2466             nArrLen = pDoc->GetCharFmts()->Count();
2467             for( i=1; i<nArrLen; i++ )
2468                 lcl_swcss1_setEncoding( *(*pDoc->GetCharFmts())[i], eEnc );
2469         }
2470 
2471         SvxCSS1Parser::SetDfltEncoding( eEnc );
2472     }
2473 }
2474