xref: /trunk/main/sw/source/filter/html/htmlcss1.cxx (revision 870262e3)
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( sal_False, "Where does the user template come from?" );
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