xref: /aoo41x/main/sw/source/filter/html/htmlfly.cxx (revision e1aaeffb)
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 #include <com/sun/star/text/HoriOrientation.hpp>
28 #include <com/sun/star/text/VertOrientation.hpp>
29 #include <com/sun/star/text/RelOrientation.hpp>
30 #include <svx/svxids.hrc>
31 #include "hintids.hxx"
32 #include <tools/string.hxx>
33 #include <svl/urihelper.hxx>
34 #include <vcl/svapp.hxx>
35 #include <vcl/wrkwin.hxx>
36 #include <svtools/htmlkywd.hxx>
37 #include <svtools/htmlout.hxx>
38 #include <svtools/imap.hxx>
39 #include <svtools/imapobj.hxx>
40 #include <svtools/htmlcfg.hxx>
41 #include <svx/xoutbmp.hxx>
42 #include <editeng/boxitem.hxx>
43 #include <editeng/lrspitem.hxx>
44 #include <editeng/ulspitem.hxx>
45 #include <editeng/brshitem.hxx>
46 
47 
48 #include <fmtanchr.hxx>
49 #include <fmtornt.hxx>
50 #include <fmturl.hxx>
51 #include <fmtfsize.hxx>
52 #include <fmtclds.hxx>
53 #include <fmtcntnt.hxx>
54 #include <fmtsrnd.hxx>
55 #include <fmtinfmt.hxx>
56 #include <txtinet.hxx>
57 #include "frmatr.hxx"
58 #include <grfatr.hxx>
59 #include <flypos.hxx>
60 #include <docary.hxx>
61 #include <ndgrf.hxx>
62 
63 #include "doc.hxx"
64 #include "ndtxt.hxx"
65 #include "pam.hxx"
66 #include "swerror.h"
67 #include "frmfmt.hxx"
68 #include "wrthtml.hxx"
69 #include "css1kywd.hxx"
70 #include "htmlfly.hxx"
71 
72 using namespace ::com::sun::star;
73 
74 ////////////////////////////////////////////////////////////
75 
76 const sal_uLong HTML_FRMOPTS_IMG_ALL		=
77 	HTML_FRMOPT_ALT |
78 	HTML_FRMOPT_SIZE |
79 	HTML_FRMOPT_ANYSIZE |
80 	HTML_FRMOPT_BORDER |
81 	HTML_FRMOPT_NAME;
82 const sal_uLong HTML_FRMOPTS_IMG_CNTNR		=
83 	HTML_FRMOPTS_IMG_ALL |
84 	HTML_FRMOPT_ABSSIZE;
85 const sal_uLong HTML_FRMOPTS_IMG			=
86 	HTML_FRMOPTS_IMG_ALL |
87 	HTML_FRMOPT_ALIGN |
88 	HTML_FRMOPT_SPACE |
89 	HTML_FRMOPT_BRCLEAR;
90 const sal_uLong HTML_FRMOPTS_IMG_CSS1		=
91 	HTML_FRMOPT_S_ALIGN |
92 	HTML_FRMOPT_S_SPACE;
93 
94 const sal_uLong HTML_FRMOPTS_DIV 			=
95 	HTML_FRMOPT_ID |
96 	HTML_FRMOPT_S_ALIGN |
97 	HTML_FRMOPT_S_SIZE |
98 	HTML_FRMOPT_ANYSIZE |
99 	HTML_FRMOPT_ABSSIZE |
100 	HTML_FRMOPT_S_SPACE |
101 	HTML_FRMOPT_S_BORDER |
102 	HTML_FRMOPT_S_BACKGROUND |
103 	HTML_FRMOPT_BRCLEAR |
104 	HTML_FRMOPT_DIR;
105 
106 const sal_uLong HTML_FRMOPTS_MULTICOL		=
107 	HTML_FRMOPT_ID |
108 	HTML_FRMOPT_WIDTH |
109 	HTML_FRMOPT_ANYSIZE |
110 	HTML_FRMOPT_ABSSIZE |
111 	HTML_FRMOPT_DIR;
112 const sal_uLong HTML_FRMOPTS_MULTICOL_CNTNR	=
113 	HTML_FRMOPTS_MULTICOL;
114 const sal_uLong HTML_FRMOPTS_MULTICOL_CSS1	=
115 	HTML_FRMOPT_S_ALIGN |
116 	HTML_FRMOPT_S_SIZE |
117 	HTML_FRMOPT_S_SPACE |
118 	HTML_FRMOPT_S_BORDER|
119 	HTML_FRMOPT_S_BACKGROUND;
120 
121 const sal_uLong HTML_FRMOPTS_SPACER			=
122 	HTML_FRMOPT_ALIGN |
123 	HTML_FRMOPT_SIZE |
124 	HTML_FRMOPT_ANYSIZE |
125 	HTML_FRMOPT_BRCLEAR |
126 	HTML_FRMOPT_MARGINSIZE |
127 	HTML_FRMOPT_ABSSIZE;
128 
129 const sal_uLong HTML_FRMOPTS_CNTNR			=
130 	HTML_FRMOPT_S_ALIGN |
131 	HTML_FRMOPT_S_SPACE |
132 	HTML_FRMOPT_S_WIDTH |
133 	HTML_FRMOPT_ANYSIZE |
134 	HTML_FRMOPT_ABSSIZE |
135 	HTML_FRMOPT_S_PIXSIZE;
136 
137 
138 static Writer& OutHTML_FrmFmtTableNode( Writer& rWrt, const SwFrmFmt& rFrmFmt );
139 static Writer& OutHTML_FrmFmtAsMulticol( Writer& rWrt, const SwFrmFmt& rFmt,
140 										 sal_Bool bInCntnr );
141 static Writer& OutHTML_FrmFmtAsSpacer( Writer& rWrt, const SwFrmFmt& rFmt );
142 static Writer& OutHTML_FrmFmtAsDivOrSpan( Writer& rWrt,
143 										  const SwFrmFmt& rFrmFmt, sal_Bool bSpan );
144 static Writer& OutHTML_FrmFmtAsImage( Writer& rWrt, const SwFrmFmt& rFmt,
145 									  sal_Bool bInCntnr	);
146 
147 static Writer& OutHTML_FrmFmtGrfNode( Writer& rWrt, const SwFrmFmt& rFmt,
148 									  sal_Bool bInCntnr	);
149 
150 static Writer& OutHTML_FrmFmtAsMarquee( Writer& rWrt, const SwFrmFmt& rFrmFmt,
151 										const SdrObject& rSdrObj	);
152 //-----------------------------------------------------------------------
153 
154 extern HTMLOutEvent __FAR_DATA aAnchorEventTable[];
155 
156 static HTMLOutEvent __FAR_DATA aImageEventTable[] =
157 {
158 	{ OOO_STRING_SVTOOLS_HTML_O_SDonload,			OOO_STRING_SVTOOLS_HTML_O_onload,		SVX_EVENT_IMAGE_LOAD		},
159 	{ OOO_STRING_SVTOOLS_HTML_O_SDonabort,		OOO_STRING_SVTOOLS_HTML_O_onabort,	SVX_EVENT_IMAGE_ABORT		},
160 	{ OOO_STRING_SVTOOLS_HTML_O_SDonerror,		OOO_STRING_SVTOOLS_HTML_O_onerror,	SVX_EVENT_IMAGE_ERROR		},
161 	{ 0,						0,					0						}
162 };
163 
164 static HTMLOutEvent __FAR_DATA aIMapEventTable[] =
165 {
166 	{ OOO_STRING_SVTOOLS_HTML_O_SDonmouseover,	OOO_STRING_SVTOOLS_HTML_O_onmouseover,	SFX_EVENT_MOUSEOVER_OBJECT	},
167 	{ OOO_STRING_SVTOOLS_HTML_O_SDonmouseout,		OOO_STRING_SVTOOLS_HTML_O_onmouseout,		SFX_EVENT_MOUSEOUT_OBJECT	},
168 	{ 0,						0,					  	0							}
169 };
170 
171 
172 
SV_IMPL_OP_PTRARR_SORT(SwHTMLPosFlyFrms,SwHTMLPosFlyFrmPtr)173 SV_IMPL_OP_PTRARR_SORT( SwHTMLPosFlyFrms, SwHTMLPosFlyFrmPtr )
174 
175 sal_uInt16 SwHTMLWriter::GuessFrmType( const SwFrmFmt& rFrmFmt,
176 								   const SdrObject*& rpSdrObj )
177 {
178 	SwHTMLFrmType eType;
179 
180 	if( RES_DRAWFRMFMT == rFrmFmt.Which() )
181 	{
182 		// Als Default irgendein Zeichen-Objekt
183 		eType = HTML_FRMTYPE_DRAW;
184 
185 		const SdrObject *pObj =
186 			SwHTMLWriter::GetMarqueeTextObj( (const SwDrawFrmFmt &)rFrmFmt );
187 		if( pObj )
188 		{
189 			// Laufschrift
190 			rpSdrObj = pObj;
191 			eType = HTML_FRMTYPE_MARQUEE;
192 		}
193 		else
194 		{
195 			pObj = GetHTMLControl( (const SwDrawFrmFmt &)rFrmFmt );
196 
197 			if( pObj )
198 			{
199 				// Form-Control
200 				rpSdrObj = pObj;
201 				eType = HTML_FRMTYPE_CONTROL;
202 			}
203 		}
204 	}
205 	else
206 	{
207 		// Als Default ein Textrahmen
208 		eType = HTML_FRMTYPE_TEXT;
209 
210 		const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt();
211 		sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex()+1;
212 		const SwNode* pNd = pDoc->GetNodes()[ nStt ];
213 
214 		if( pNd->IsGrfNode() )
215 		{
216 			// Grafik - Node
217 			eType = HTML_FRMTYPE_GRF;
218 		}
219 		else if( pNd->IsOLENode() )
220 		{
221 			// Applet, Plugin, Floating-Frame
222 			eType = (SwHTMLFrmType)GuessOLENodeFrmType( *pNd );
223 		}
224 		else
225 		{
226 			sal_uLong nEnd = pDoc->GetNodes()[nStt-1]->EndOfSectionIndex();
227 
228 			const SfxPoolItem* pItem;
229 			const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet();
230 			if( SFX_ITEM_SET == rItemSet.GetItemState( RES_COL,
231 													   sal_True, &pItem ) &&
232 				((const SwFmtCol *)pItem)->GetNumCols() > 1 )
233 			{
234 				// spaltiger Rahmen
235 				eType = HTML_FRMTYPE_MULTICOL;
236 			}
237 			else if( pNd->IsTableNode() )
238 			{
239 				const SwTableNode *pTblNd = pNd->GetTableNode();
240 				sal_uLong nTblEnd = pTblNd->EndOfSectionIndex();
241 
242 				if( nTblEnd+1 == nEnd )
243 				{
244 					// Tabelle
245 					eType = HTML_FRMTYPE_TABLE;
246 				}
247 				else if( nTblEnd+2 == nEnd )
248 				{
249 					// Tabelle mit Unterschrft
250 					eType = HTML_FRMTYPE_TABLE_CAP;
251 				}
252 			}
253 			else if( pNd->IsTxtNode() )
254 			{
255 				const SwTxtNode *pTxtNd = pNd->GetTxtNode();
256 
257 				sal_Bool bEmpty = sal_False;
258 				if( nStt==nEnd-1 && !pTxtNd->Len() )
259 				{
260 					// leerer Rahmen? Nur wenn kein Rahmen am
261 					// Text- oder Start-Node verankert ist.
262 					bEmpty = sal_True;
263 					if( pHTMLPosFlyFrms )
264 					{
265 						for( sal_uInt16 i=0; i<pHTMLPosFlyFrms->Count(); i++ )
266 						{
267 							sal_uLong nIdx = (*pHTMLPosFlyFrms)[i]
268 												->GetNdIndex().GetIndex();
269 							bEmpty = (nIdx != nStt) && (nIdx != nStt-1);
270 							if( !bEmpty || nIdx > nStt )
271 								break;
272 						}
273 					}
274 				}
275 				if( bEmpty )
276 				{
277 					const SvxBrushItem& rBrush = rFrmFmt.GetBackground();
278                     /// OD 02.09.2002 #99657#
279                     /// background is not empty, if it has a background graphic
280                     /// or its background color is not "no fill"/"auto fill".
281 					if( GPOS_NONE != rBrush.GetGraphicPos() ||
282                         rBrush.GetColor() != COL_TRANSPARENT )
283 						bEmpty = sal_False;
284 				}
285 				if( bEmpty )
286 				{
287 					// leerer Rahmen
288 					eType = HTML_FRMTYPE_EMPTY;
289 				}
290 				else if( pDoc->GetNodes()[nStt+1]->IsTableNode() )
291 				{
292 					const SwTableNode *pTblNd =
293 						pDoc->GetNodes()[nStt+1]->GetTableNode();
294 					if( pTblNd->EndOfSectionIndex()+1 == nEnd )
295 					{
296 						// Tabelle mit Ueberschrift
297 						eType = HTML_FRMTYPE_TABLE_CAP;
298 					}
299 				}
300 			}
301 		}
302 	}
303 
304     return static_cast< sal_uInt16 >(eType);
305 }
306 
CollectFlyFrms()307 void SwHTMLWriter::CollectFlyFrms()
308 {
309 	ASSERT( HTML_CFG_MAX+1 == MAX_BROWSERS,
310 			"number of browser configurations has changed" );
311 
312 	// sal_uInt8 nSz = (sal_uInt8)Min( pDoc->GetSpzFrmFmts()->Count(), sal_uInt16(255) );
313 	SwPosFlyFrms aFlyPos(pDoc->GetAllFlyFmts(bWriteAll ? 0 : pCurPam, sal_True));
314 
315     for(SwPosFlyFrms::const_iterator aIter(aFlyPos.begin()); aIter != aFlyPos.end(); aIter++)
316 	{
317 		const SwFrmFmt& rFrmFmt = (*aIter)->GetFmt();
318 		const SdrObject *pSdrObj = 0;
319 		const SwPosition *pAPos;
320 		const SwCntntNode *pACNd;
321 		SwHTMLFrmType eType = (SwHTMLFrmType)GuessFrmType( rFrmFmt, pSdrObj );
322 
323 		sal_uInt8 nMode;
324 		const SwFmtAnchor& rAnchor = rFrmFmt.GetAnchor();
325         sal_Int16 eHoriRel = rFrmFmt.GetHoriOrient().GetRelationOrient();
326 		switch( rAnchor.GetAnchorId() )
327 		{
328         case FLY_AT_PAGE:
329 		case FLY_AT_FLY:
330 			nMode = aHTMLOutFrmPageFlyTable[eType][nExportMode];
331 			break;
332 
333         case FLY_AT_PARA:
334 			// Absatz-gebundene Rahmen werden nur dann vor den
335 			// Absatz geschrieben, wenn der Absatz einen Abstand
336 			// hat.
337             if( text::RelOrientation::FRAME == eHoriRel &&
338 				(pAPos = rAnchor.GetCntntAnchor()) != 0 &&
339 				(pACNd = pAPos->nNode.GetNode().GetCntntNode()) != 0 )
340 			{
341 				const SvxLRSpaceItem& rLRItem =
342 					(const SvxLRSpaceItem&)pACNd->GetAttr(RES_LR_SPACE);
343 				if( rLRItem.GetTxtLeft() || rLRItem.GetRight() )
344 				{
345 					nMode = aHTMLOutFrmParaFrameTable[eType][nExportMode];
346 					break;
347 				}
348 			}
349 			nMode = aHTMLOutFrmParaPrtAreaTable[eType][nExportMode];
350 			break;
351 
352         case FLY_AT_CHAR:
353             if( text::RelOrientation::FRAME == eHoriRel || text::RelOrientation::PRINT_AREA == eHoriRel )
354 				nMode = aHTMLOutFrmParaPrtAreaTable[eType][nExportMode];
355 			else
356 				nMode = aHTMLOutFrmParaOtherTable[eType][nExportMode];
357 			break;
358 
359 		default:
360 			nMode = aHTMLOutFrmParaPrtAreaTable[eType][nExportMode];
361 			break;
362 		}
363 
364 		if( !pHTMLPosFlyFrms )
365 			pHTMLPosFlyFrms = new SwHTMLPosFlyFrms;
366 
367 		SwHTMLPosFlyFrm *pNew = new SwHTMLPosFlyFrm(**aIter, pSdrObj, nMode);
368 		pHTMLPosFlyFrms->Insert( pNew );
369 	}
370 }
371 
OutFlyFrm(sal_uLong nNdIdx,xub_StrLen nCntntIdx,sal_uInt8 nPos,HTMLOutContext * pContext)372 sal_Bool SwHTMLWriter::OutFlyFrm( sal_uLong nNdIdx, xub_StrLen nCntntIdx, sal_uInt8 nPos,
373 							  HTMLOutContext *pContext )
374 {
375 	sal_Bool bFlysLeft = sal_False;	// Noch Flys an aktueller Node-Position da?
376 
377 	// OutFlyFrm kan rekursiv aufgerufen werden. Deshalb muss man
378 	// manchmal wieder von vorne anfangen, nachdem ein Fly ausgegeben
379 	// wurde.
380 	sal_Bool bRestart = sal_True;
381 	while( pHTMLPosFlyFrms && bRestart )
382 	{
383 		bFlysLeft = bRestart = sal_False;
384 
385 		// suche nach dem Anfang der FlyFrames
386 		sal_uInt16 i;
387 
388 		for( i = 0; i < pHTMLPosFlyFrms->Count() &&
389 			(*pHTMLPosFlyFrms)[i]->GetNdIndex().GetIndex() < nNdIdx; i++ )
390 			;
391 		for( ; !bRestart && i < pHTMLPosFlyFrms->Count() &&
392 			(*pHTMLPosFlyFrms)[i]->GetNdIndex().GetIndex() == nNdIdx; i++ )
393 		{
394 			SwHTMLPosFlyFrm *pPosFly = (*pHTMLPosFlyFrms)[i];
395 			if( ( HTML_POS_ANY == nPos ||
396 				  pPosFly->GetOutPos() == nPos ) &&
397 				pPosFly->GetCntntIndex() == nCntntIdx )
398 			{
399 				// Erst entfernen ist wichtig, weil in tieferen
400 				// Rekursionen evtl. weitere Eintraege oder das
401 				// ganze Array geloscht werden koennte.
402 				pHTMLPosFlyFrms->Remove( i, 1 );
403 				i--;
404 				if( !pHTMLPosFlyFrms->Count() )
405 				{
406 					delete pHTMLPosFlyFrms;
407 					pHTMLPosFlyFrms = 0;
408 					bRestart = sal_True; 	// nicht wirklich, nur raus
409 										// aus der Schleife
410 				}
411 
412 				if( pContext )
413 				{
414 					HTMLOutFuncs::FlushToAscii(Strm(), *pContext );
415 					pContext = 0; // one time only
416 				}
417 
418 				OutFrmFmt( pPosFly->GetOutMode(), pPosFly->GetFmt(),
419 						   pPosFly->GetSdrObject() );
420 				switch( pPosFly->GetOutFn() )
421 				{
422 				case HTML_OUT_DIV:
423 				case HTML_OUT_SPAN:
424 				case HTML_OUT_MULTICOL:
425 				case HTML_OUT_TBLNODE:
426 					bRestart = sal_True; // Hier wird's evtl rekursiv
427 					break;
428 				}
429 				delete pPosFly;
430 			}
431 			else
432 			{
433 				bFlysLeft = sal_True;
434 			}
435 		}
436 	}
437 
438 	return bFlysLeft;
439 }
440 
OutFrmFmt(sal_uInt8 nMode,const SwFrmFmt & rFrmFmt,const SdrObject * pSdrObject)441 void SwHTMLWriter::OutFrmFmt( sal_uInt8 nMode, const SwFrmFmt& rFrmFmt,
442 							  const SdrObject *pSdrObject )
443 {
444 	sal_uInt8 nCntnrMode = SwHTMLPosFlyFrm::GetOutCntnr( nMode );
445 	sal_uInt8 nOutMode = SwHTMLPosFlyFrm::GetOutFn(nMode);
446 	const sal_Char *pCntnrStr = 0;
447 	if( HTML_CNTNR_NONE != nCntnrMode )
448 	{
449 
450 		if( bLFPossible && HTML_CNTNR_DIV == nCntnrMode )
451 			OutNewLine();
452 
453 		ByteString sOut( '<' );
454 		pCntnrStr = (HTML_CNTNR_DIV == nCntnrMode)
455 							? OOO_STRING_SVTOOLS_HTML_division
456 							: OOO_STRING_SVTOOLS_HTML_span;
457 		sOut += pCntnrStr;
458 		((((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_class) += "=\"")
459 			+= sCSS1_class_abs_pos) += '\"';
460 		Strm() << sOut.GetBuffer();
461 
462 		// Fuer Nicht-Zeichenobekte eine Breite ausgeben
463 		sal_uLong nFrmFlags = HTML_FRMOPTS_CNTNR;
464 
465 		// Fuer spaltige Rahmen koennen wir auch noch den Hintergrund ausgeben.
466 		if( HTML_OUT_MULTICOL == nOutMode )
467 			nFrmFlags |= HTML_FRMOPT_S_BACKGROUND|HTML_FRMOPT_S_BORDER;
468 
469 		if( IsHTMLMode( HTMLMODE_BORDER_NONE ) )
470 		   nFrmFlags |= HTML_FRMOPT_S_NOBORDER;
471 		OutCSS1_FrmFmtOptions( rFrmFmt, nFrmFlags, pSdrObject );
472 		Strm() << '>';
473 
474 		if( HTML_CNTNR_DIV == nCntnrMode )
475 		{
476 			IncIndentLevel();
477 			bLFPossible = sal_True;
478 		}
479 	}
480 
481 	switch( nOutMode )
482 	{
483 	case HTML_OUT_TBLNODE:		// OK
484 		ASSERT( !pCntnrStr, "Table: Container ist hier nicht vorgesehen" );
485 		OutHTML_FrmFmtTableNode( *this, rFrmFmt );
486 		break;
487 	case HTML_OUT_GRFNODE:		// OK
488 		OutHTML_FrmFmtGrfNode( *this, rFrmFmt, pCntnrStr != 0 );
489 		break;
490 	case HTML_OUT_OLENODE:		// OK
491 		OutHTML_FrmFmtOLENode( *this, rFrmFmt, pCntnrStr != 0 );
492 		break;
493 	case HTML_OUT_OLEGRF:		// OK
494 		OutHTML_FrmFmtOLENodeGrf( *this, rFrmFmt, pCntnrStr != 0 );
495 		break;
496 	case HTML_OUT_DIV:
497 	case HTML_OUT_SPAN:
498 		ASSERT( !pCntnrStr, "Div: Container ist hier nicht vorgesehen" );
499 		OutHTML_FrmFmtAsDivOrSpan( *this, rFrmFmt, HTML_OUT_SPAN==nOutMode );
500 		break;
501 	case HTML_OUT_MULTICOL:		// OK
502 		OutHTML_FrmFmtAsMulticol( *this, rFrmFmt, pCntnrStr != 0 );
503 		break;
504 	case HTML_OUT_SPACER:		// OK
505 		ASSERT( !pCntnrStr, "Spacer: Container ist hier nicht vorgesehen" );
506 		OutHTML_FrmFmtAsSpacer( *this, rFrmFmt );
507 		break;
508 	case HTML_OUT_CONTROL:		// OK
509 		OutHTML_DrawFrmFmtAsControl( *this,
510 									(const SwDrawFrmFmt &)rFrmFmt, *pSdrObject,
511 									pCntnrStr != 0 );
512 		break;
513 	case HTML_OUT_AMARQUEE:
514 		OutHTML_FrmFmtAsMarquee( *this, rFrmFmt, *pSdrObject );
515 		break;
516 	case HTML_OUT_MARQUEE:
517 		ASSERT( !pCntnrStr, "Marquee: Container ist hier nicht vorgesehen" );
518 		OutHTML_DrawFrmFmtAsMarquee( *this,
519 					(const SwDrawFrmFmt &)rFrmFmt, *pSdrObject );
520 		break;
521 	case HTML_OUT_GRFFRM:
522 		OutHTML_FrmFmtAsImage( *this, rFrmFmt, pCntnrStr != 0 );
523 		break;
524 	}
525 
526 	if( HTML_CNTNR_DIV == nCntnrMode )
527 	{
528 		DecIndentLevel();
529 		if( bLFPossible )
530 			OutNewLine();
531 		HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_division, sal_False );
532 		bLFPossible = sal_True;
533 	}
534 	else if( HTML_CNTNR_SPAN == nCntnrMode )
535 		HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_span, sal_False );
536 }
537 
538 
OutFrmFmtOptions(const SwFrmFmt & rFrmFmt,const String & rAlternateTxt,ByteString & rEndTags,sal_uInt32 nFrmOpts)539 void SwHTMLWriter::OutFrmFmtOptions( const SwFrmFmt &rFrmFmt,
540 									 const String& rAlternateTxt,
541 									 ByteString &rEndTags,
542 									 sal_uInt32 nFrmOpts )
543 {
544 	ByteString sOut;
545 	const SfxPoolItem* pItem;
546 	const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet();
547 
548 	// Name
549 	if( (nFrmOpts & (HTML_FRMOPT_ID|HTML_FRMOPT_NAME)) &&
550 		rFrmFmt.GetName().Len() )
551 	{
552 		const sal_Char *pStr =
553 			(nFrmOpts & HTML_FRMOPT_ID) ? OOO_STRING_SVTOOLS_HTML_O_id : OOO_STRING_SVTOOLS_HTML_O_name;
554 		((sOut += ' ') += pStr) += "=\"";
555 		Strm() << sOut.GetBuffer();
556 		HTMLOutFuncs::Out_String( Strm(), rFrmFmt.GetName(), eDestEnc, &aNonConvertableCharacters );
557 		sOut = '\"';
558 	}
559 
560 	// Name
561 	if( nFrmOpts & HTML_FRMOPT_DIR )
562 	{
563 		sal_uInt16 nDir = GetHTMLDirection( rItemSet );
564 		Strm() << sOut.GetBuffer();
565 		sOut.Erase();
566 		OutDirection( nDir );
567 	}
568 
569 
570 	// ALT
571 	if( (nFrmOpts & HTML_FRMOPT_ALT) && rAlternateTxt.Len() )
572 	{
573 		((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_alt) += "=\"";
574 		Strm() << sOut.GetBuffer();
575 		HTMLOutFuncs::Out_String( Strm(), rAlternateTxt, eDestEnc, &aNonConvertableCharacters );
576 		sOut = '\"';
577 	}
578 
579 	// ALIGN
580 	const sal_Char *pStr = 0;
581 	RndStdIds eAnchorId = rFrmFmt.GetAnchor().GetAnchorId();
582 	if( (nFrmOpts & HTML_FRMOPT_ALIGN) &&
583         ((FLY_AT_PARA == eAnchorId) || (FLY_AT_CHAR == eAnchorId)) )
584     {
585 		// MIB 12.3.98: Ist es nicht schlauer, absatzgebundene
586 		// Rahmen notfalls links auszurichten als sie
587 		// zeichengebunden einzufuegen???
588 		const SwFmtHoriOrient& rHoriOri = rFrmFmt.GetHoriOrient();
589 		if( !(nFrmOpts & HTML_FRMOPT_S_ALIGN) ||
590             text::RelOrientation::FRAME == rHoriOri.GetRelationOrient() ||
591             text::RelOrientation::PRINT_AREA == rHoriOri.GetRelationOrient() )
592 		{
593             pStr = text::HoriOrientation::RIGHT == rHoriOri.GetHoriOrient()
594 						? OOO_STRING_SVTOOLS_HTML_AL_right
595 						: OOO_STRING_SVTOOLS_HTML_AL_left;
596 		}
597 	}
598 	if( (nFrmOpts & HTML_FRMOPT_ALIGN) && !pStr &&
599 		( (nFrmOpts & HTML_FRMOPT_S_ALIGN) == 0 ||
600           (FLY_AS_CHAR == eAnchorId) ) &&
601 		SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_True, &pItem ))
602 	{
603 		switch( ((SwFmtVertOrient*)pItem)->GetVertOrient() )
604 		{
605         case text::VertOrientation::LINE_TOP:     pStr = OOO_STRING_SVTOOLS_HTML_VA_top;        break;
606         case text::VertOrientation::CHAR_TOP:
607         case text::VertOrientation::BOTTOM:       pStr = OOO_STRING_SVTOOLS_HTML_VA_texttop;    break;  // geht nicht
608         case text::VertOrientation::LINE_CENTER:
609         case text::VertOrientation::CHAR_CENTER:  pStr = OOO_STRING_SVTOOLS_HTML_VA_absmiddle;  break;  // geht nicht
610         case text::VertOrientation::CENTER:       pStr = OOO_STRING_SVTOOLS_HTML_VA_middle;     break;
611         case text::VertOrientation::LINE_BOTTOM:
612         case text::VertOrientation::CHAR_BOTTOM:  pStr = OOO_STRING_SVTOOLS_HTML_VA_absbottom;  break;  // geht nicht
613         case text::VertOrientation::TOP:          pStr = OOO_STRING_SVTOOLS_HTML_VA_bottom;     break;
614         case text::VertOrientation::NONE:     break;
615 		}
616 	}
617 	if( pStr )
618 		(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += pStr;
619 
620 
621 	// HSPACE und VSPACE
622 	Size aTwipSpc( 0, 0 );
623 	if( (nFrmOpts & (HTML_FRMOPT_SPACE|HTML_FRMOPT_MARGINSIZE)) &&
624 		SFX_ITEM_SET == rItemSet.GetItemState( RES_LR_SPACE, sal_True, &pItem ))
625 	{
626 		aTwipSpc.Width() =
627 			( ((SvxLRSpaceItem*)pItem)->GetLeft() +
628 				((SvxLRSpaceItem*)pItem)->GetRight() ) / 2;
629 		nDfltLeftMargin = nDfltRightMargin = aTwipSpc.Width();
630 	}
631 	if( (nFrmOpts & (HTML_FRMOPT_SPACE|HTML_FRMOPT_MARGINSIZE)) &&
632 		SFX_ITEM_SET == rItemSet.GetItemState( RES_UL_SPACE, sal_True, &pItem ))
633 	{
634 		aTwipSpc.Height()  =
635 			( ((SvxULSpaceItem*)pItem)->GetUpper() +
636 				((SvxULSpaceItem*)pItem)->GetLower() ) / 2;
637 		nDfltTopMargin = nDfltBottomMargin = (sal_uInt16)aTwipSpc.Height();
638 	}
639 
640 	if( (nFrmOpts & HTML_FRMOPT_SPACE) &&
641 		(aTwipSpc.Width() || aTwipSpc.Height()) &&
642 		Application::GetDefaultDevice() )
643 	{
644 		Size aPixelSpc =
645 			Application::GetDefaultDevice()->LogicToPixel( aTwipSpc,
646 												MapMode(MAP_TWIP) );
647 		if( !aPixelSpc.Width() && aTwipSpc.Width() )
648 			aPixelSpc.Width() = 1;
649 		if( !aPixelSpc.Height() && aTwipSpc.Height() )
650 			aPixelSpc.Height() = 1;
651 
652 		if( aPixelSpc.Width() )
653 		{
654 			(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_hspace) += '=')
655 				+= ByteString::CreateFromInt32( aPixelSpc.Width() );
656 		}
657 
658 		if( aPixelSpc.Height() )
659 		{
660 			(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_vspace) += '=')
661 				+= ByteString::CreateFromInt32( aPixelSpc.Height() );
662 		}
663 	}
664 
665 	// Der Abstand muss bei der Groesse beruecksichtigt, wenn das entsprechende
666 	// Flag gesetzt ist.
667 	if( (nFrmOpts & HTML_FRMOPT_MARGINSIZE) )
668 	{
669 		aTwipSpc.Width() *= -2;
670 		aTwipSpc.Height() *= -2;
671 	}
672 	else
673 	{
674 		aTwipSpc.Width() = 0;
675 		aTwipSpc.Height() = 0;
676 	}
677 
678 	if( !(nFrmOpts & HTML_FRMOPT_ABSSIZE) &&
679 		SFX_ITEM_SET == rItemSet.GetItemState( RES_BOX, sal_True, &pItem ))
680 	{
681 		const SvxBoxItem* pBoxItem = (const SvxBoxItem*)pItem;
682 
683 		aTwipSpc.Width() += pBoxItem->CalcLineSpace( BOX_LINE_LEFT );
684 		aTwipSpc.Width() += pBoxItem->CalcLineSpace( BOX_LINE_RIGHT );
685 		aTwipSpc.Height() += pBoxItem->CalcLineSpace( BOX_LINE_TOP );
686 		aTwipSpc.Height() += pBoxItem->CalcLineSpace( BOX_LINE_BOTTOM );
687 	}
688 
689 	// WIDTH und/oder HEIGHT
690 	// ATT_VAR_SIZE/ATT_MIN_SIZE nur ausgeben, wenn ANYSIZE gesezut ist
691 	if( (nFrmOpts & HTML_FRMOPT_SIZE) &&
692 		SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ) &&
693 		( (nFrmOpts & HTML_FRMOPT_ANYSIZE) ||
694           ATT_FIX_SIZE == ((const SwFmtFrmSize *)pItem)->GetHeightSizeType()) )
695 	{
696 		const SwFmtFrmSize *pFSItem = (const SwFmtFrmSize *)pItem;
697 		sal_uInt8 nPrcWidth = pFSItem->GetWidthPercent();
698 		sal_uInt8 nPrcHeight = pFSItem->GetHeightPercent();
699 
700 		// Groesse des Objekts Twips ohne Raender
701 		Size aTwipSz( (nPrcWidth ? 0
702 								 : pFSItem->GetWidth()-aTwipSpc.Width()),
703 					  (nPrcHeight ? 0
704 								  : pFSItem->GetHeight()-aTwipSpc.Height()) );
705 
706 		ASSERT( aTwipSz.Width() >= 0 && aTwipSz.Height() >= 0,
707 				"Rahmengroesse minus Abstand < 0!!!???" );
708 		if( aTwipSz.Width() < 0 )
709 			aTwipSz.Width() = 0;
710 		if( aTwipSz.Height() < 0 )
711 			aTwipSz.Height() = 0;
712 
713 		Size aPixelSz( 0, 0 );
714 		if( (aTwipSz.Width() || aTwipSz.Height()) &&
715 			Application::GetDefaultDevice() )
716 		{
717 			aPixelSz =
718 				Application::GetDefaultDevice()->LogicToPixel( aTwipSz,
719 													MapMode(MAP_TWIP) );
720 			if( !aPixelSz.Width() && aTwipSz.Width() )
721 				aPixelSz.Width() = 1;
722 			if( !aPixelSz.Height() && aTwipSz.Height() )
723 				aPixelSz.Height() = 1;
724 		}
725 
726 		if( (nFrmOpts & HTML_FRMOPT_WIDTH) &&
727 			((nPrcWidth && nPrcWidth!=255) || aPixelSz.Width()) )
728 		{
729 			((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width) += '=';
730 			if( nPrcWidth )
731 				(sOut += ByteString::CreateFromInt32( nPrcWidth )) += '%';
732 			else
733 				sOut += ByteString::CreateFromInt32( aPixelSz.Width() );
734 		}
735 
736 		if( (nFrmOpts & HTML_FRMOPT_HEIGHT) &&
737 			((nPrcHeight && nPrcHeight!=255) || aPixelSz.Height()) )
738 		{
739 			((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_height) += '=';
740 			if( nPrcHeight )
741 				(sOut += ByteString::CreateFromInt32( nPrcHeight )) += '%';
742 			else
743 				sOut += ByteString::CreateFromInt32( aPixelSz.Height() );
744 		}
745 	}
746 
747 	if( sOut.Len() )
748 		Strm() << sOut.GetBuffer();
749 
750 	// Umlauf fuer absatzgeb. Grafiken als <BR CLEAR=...> in den String
751 	// schreiben
752 	if( (nFrmOpts & HTML_FRMOPT_BRCLEAR) &&
753         ((FLY_AT_PARA == rFrmFmt.GetAnchor().GetAnchorId()) ||
754          (FLY_AT_CHAR == rFrmFmt.GetAnchor().GetAnchorId())) &&
755 		SFX_ITEM_SET == rItemSet.GetItemState( RES_SURROUND, sal_True, &pItem ))
756 	{
757 		const SwFmtSurround* pSurround = (const SwFmtSurround*)pItem;
758         sal_Int16 eHoriOri =    rFrmFmt.GetHoriOrient().GetHoriOrient();
759 		pStr = 0;
760 		SwSurround eSurround = pSurround->GetSurround();
761 		sal_Bool bAnchorOnly = pSurround->IsAnchorOnly();
762 		switch( eHoriOri )
763 		{
764         case text::HoriOrientation::RIGHT:
765 			{
766 				switch( eSurround )
767 				{
768 				case SURROUND_NONE:
769 				case SURROUND_RIGHT:
770 					pStr = OOO_STRING_SVTOOLS_HTML_AL_right;
771 					break;
772 				case SURROUND_LEFT:
773 				case SURROUND_PARALLEL:
774 					if( bAnchorOnly )
775 						bClearRight = sal_True;
776 					break;
777 				default:
778 					;
779 				}
780 			}
781 			break;
782 
783 		default:
784 			// #67508#: If a frame is centered, it gets left aligned. This
785 			// should be taken into account here, too.
786 			{
787 				switch( eSurround )
788 				{
789 				case SURROUND_NONE:
790 				case SURROUND_LEFT:
791 					pStr = OOO_STRING_SVTOOLS_HTML_AL_left;
792 					break;
793 				case SURROUND_RIGHT:
794 				case SURROUND_PARALLEL:
795 					if( bAnchorOnly )
796 						bClearLeft = sal_True;
797 					break;
798 				default:
799 					;
800 				}
801 			}
802 			break;
803 
804 		}
805 
806 		if( pStr )
807 		{
808 			(((((((sOut = '<') += OOO_STRING_SVTOOLS_HTML_linebreak) += ' ')
809 				+= OOO_STRING_SVTOOLS_HTML_O_clear) += '=') += pStr) += '>') += rEndTags;
810 			rEndTags = sOut;
811 		}
812 	}
813 }
814 
815 
OutHTML_Image(Writer & rWrt,const SwFrmFmt & rFrmFmt,const String & rGrfName,const String & rAlternateTxt,const Size & rRealSize,sal_uInt32 nFrmOpts,const sal_Char * pMarkType,const ImageMap * pAltImgMap)816 Writer& OutHTML_Image( Writer& rWrt, const SwFrmFmt &rFrmFmt,
817 					   const String &rGrfName, const String& rAlternateTxt,
818 					   const Size &rRealSize, sal_uInt32 nFrmOpts,
819 					   const sal_Char *pMarkType,
820 					   const ImageMap *pAltImgMap )
821 {
822 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
823 
824 	// ggf. ein noch offenes Attribut voruebergehend beenden
825 	if( rHTMLWrt.aINetFmts.Count() )
826 	{
827 		SwFmtINetFmt *pINetFmt =
828 			rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
829 		OutHTML_INetFmt( rWrt, *pINetFmt, sal_False );
830 	}
831 
832 	String aGrfNm( rGrfName );
833 	if( !HTMLOutFuncs::PrivateURLToInternalImg(aGrfNm) )
834         aGrfNm = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), aGrfNm);
835 
836 	const SfxPoolItem* pItem;
837 	const SfxItemSet& rItemSet = rFrmFmt.GetAttrSet();
838 
839 	const SwFmtURL *pURLItem = 0;
840 
841 	// das URL-Attribut nur beruecksichtigen, wenn keine Image-Map
842 	// uebergeben wurde
843 	if( !pAltImgMap &&
844 		SFX_ITEM_SET == rItemSet.GetItemState( RES_URL, sal_True, &pItem ))
845 	{
846 		pURLItem = (const SwFmtURL *)pItem;
847 	}
848 
849 	// Image-Map rausschreiben
850 	const ImageMap *pIMap = pAltImgMap;
851 	if( !pIMap && pURLItem )
852 	{
853 		pIMap = pURLItem->GetMap();
854 	}
855 
856 	String aIMapName;
857 	if( pIMap )
858 	{
859 		// den Namen eindeutig machen
860 		aIMapName = pIMap->GetName();
861 		String aNameBase;
862 		if( aIMapName.Len() )
863 			aNameBase = aIMapName;
864 		else
865 			aNameBase.AssignAscii( OOO_STRING_SVTOOLS_HTML_map );
866 		if( !aIMapName.Len() )
867 			(aIMapName = aNameBase)
868 				+= String::CreateFromInt32( rHTMLWrt.nImgMapCnt );
869 
870 		sal_Bool bFound;
871 		do
872 		{
873 			bFound = sal_False;
874 			for( sal_uInt16 i=0; i<rHTMLWrt.aImgMapNames.Count(); i++ )
875 			{
876 				// TODO: Unicode: Comparison is case insensitive for ASCII
877 				// characters only now!
878 				if( aIMapName.EqualsIgnoreCaseAscii(*rHTMLWrt.aImgMapNames[i]) )
879 				{
880 					bFound = sal_True;
881 					break;
882 				}
883 			}
884 			if( bFound )
885 			{
886 				rHTMLWrt.nImgMapCnt++;
887 				(aIMapName = aNameBase)
888 					+= String::CreateFromInt32( rHTMLWrt.nImgMapCnt );
889 			}
890 
891 		} while( bFound );
892 
893 		sal_Bool bScale = sal_False;
894 		//Size aGrfSize( rNode.GetTwipSize() );
895 		Fraction aScaleX( 1, 1 );
896 		Fraction aScaleY( 1, 1 );
897 
898 		const SwFmtFrmSize& rFrmSize = rFrmFmt.GetFrmSize();
899 		const SvxBoxItem& rBox = rFrmFmt.GetBox();
900 
901 		if( !rFrmSize.GetWidthPercent() && rRealSize.Width() )
902 		{
903 			SwTwips nWidth = rFrmSize.GetWidth();
904 			nWidth -= ( rBox.CalcLineSpace(BOX_LINE_LEFT) +
905 						rBox.CalcLineSpace(BOX_LINE_RIGHT) );
906 
907 			ASSERT( nWidth>0, "Gibt es 0 twip breite Grafiken!?" );
908 			if( nWidth<=0 )	// sollte nicht passieren
909 				nWidth = 1;
910 
911 			if( rRealSize.Width() != nWidth )
912 			{
913 				aScaleX = Fraction( nWidth, rRealSize.Width() );
914 				bScale = sal_True;
915 			}
916 		}
917 		if( !rFrmSize.GetHeightPercent() && rRealSize.Height() )
918 		{
919 			SwTwips nHeight = rFrmSize.GetHeight();
920 			nHeight -= ( rBox.CalcLineSpace(BOX_LINE_TOP) +
921 						 rBox.CalcLineSpace(BOX_LINE_BOTTOM) );
922 
923 			ASSERT( nHeight>0, "Gibt es 0 twip hohe Grafiken!?" );
924 			if( nHeight<=0 )
925 				nHeight = 1;
926 
927 			if( rRealSize.Height() != nHeight )
928 			{
929 				aScaleY = Fraction( nHeight, rRealSize.Height() );
930 				bScale = sal_True;
931 			}
932 		}
933 
934 		rHTMLWrt.aImgMapNames.Insert( new String(aIMapName),
935 										  rHTMLWrt.aImgMapNames.Count() );
936 
937 		ByteString aIndMap, aIndArea;
938 		const sal_Char *pLF = 0, *pIndArea = 0, *pIndMap = 0;
939 #if defined(UNX)
940 		sal_Char aLF[2] = "\x00";
941 #endif
942 
943 		if( rHTMLWrt.bLFPossible )
944 		{
945 			rHTMLWrt.OutNewLine( sal_True );
946 			rHTMLWrt.GetIndentString( aIndMap );
947 			rHTMLWrt.GetIndentString( aIndArea, 1 );
948 #if defined(UNX)
949 			aLF[0]  = SwHTMLWriter::sNewLine;
950 			pLF = aLF;
951 #else
952 			pLF = SwHTMLWriter::sNewLine;
953 #endif
954 			pIndArea = aIndArea.GetBuffer();
955 			pIndMap = aIndMap.GetBuffer();
956 		}
957 
958 		if( bScale )
959 		{
960 			ImageMap aScaledIMap( *pIMap );
961 			aScaledIMap.Scale( aScaleX, aScaleY );
962             HTMLOutFuncs::Out_ImageMap( rWrt.Strm(), rWrt.GetBaseURL(), aScaledIMap, aIMapName,
963 										aIMapEventTable,
964 										rHTMLWrt.bCfgStarBasic,
965 										pLF, pIndArea, pIndMap,
966 									    rHTMLWrt.eDestEnc,
967 									    &rHTMLWrt.aNonConvertableCharacters );
968 		}
969 		else
970 		{
971             HTMLOutFuncs::Out_ImageMap( rWrt.Strm(), rWrt.GetBaseURL(), *pIMap, aIMapName,
972 										aIMapEventTable,
973 										rHTMLWrt.bCfgStarBasic,
974 										pLF, pIndArea, pIndMap,
975 									 	rHTMLWrt.eDestEnc,
976 									    &rHTMLWrt.aNonConvertableCharacters );
977 		}
978 	}
979 
980 	// wenn meoglich vor der Grafik einen Zeilen-Umbruch ausgeben
981 	if( rHTMLWrt.bLFPossible )
982 		rHTMLWrt.OutNewLine( sal_True );
983 
984 	// Attribute die ausserhelb der Grafik geschreiben werden muessen sammeln
985 	ByteString sOut;
986 	ByteString aEndTags;
987 
988 	// implizite Sprungmarke -> <A NAME=...></A>...<IMG ...>
989 	if( pMarkType && rFrmFmt.GetName().Len() )
990 		rHTMLWrt.OutImplicitMark( rFrmFmt.GetName(), pMarkType );
991 
992 	// URL -> <A>...<IMG ... >...</A>
993 	const SvxMacroItem *pMacItem = 0;
994 	if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRMMACRO, sal_True, &pItem ))
995 		pMacItem = (const SvxMacroItem *)pItem;
996 
997 	if( pURLItem || pMacItem )
998 	{
999 		String aMapURL;
1000 		String aName;
1001 		String aTarget;
1002 		if( pURLItem )
1003 		{
1004 			aMapURL = pURLItem->GetURL();
1005 			aName = pURLItem->GetName();
1006 			aTarget = pURLItem->GetTargetFrameName();
1007 		}
1008 		sal_Bool bEvents = pMacItem && pMacItem->GetMacroTable().Count();
1009 
1010 		if( aMapURL.Len() || aName.Len() || aTarget.Len() || bEvents )
1011 		{
1012 			(sOut = '<') += OOO_STRING_SVTOOLS_HTML_anchor;
1013 
1014 			// Ein HREF nur Ausgaben, wenn es einen Link oder Makros gibt
1015 			if( aMapURL.Len() || bEvents )
1016 			{
1017 				((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_href) += "=\"";
1018 				rWrt.Strm() << sOut.GetBuffer();
1019 				rHTMLWrt.OutHyperlinkHRefValue( aMapURL );
1020 				sOut = '\"';
1021 			}
1022 
1023 			if( aName.Len() )
1024 			{
1025 				((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_name) += "=\"";
1026 				rWrt.Strm() << sOut.GetBuffer();
1027 				HTMLOutFuncs::Out_String( rWrt.Strm(), aName,
1028 										  rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
1029 				sOut = '\"';
1030 			}
1031 
1032 			if( aTarget.Len() )
1033 			{
1034 				((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_target) += "=\"";
1035 				rWrt.Strm() << sOut.GetBuffer();
1036 				HTMLOutFuncs::Out_String( rWrt.Strm(), aTarget,
1037 										  rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
1038 				sOut = '\"';
1039 			}
1040 			if( sOut.Len() )
1041 			{
1042 				rWrt.Strm() << sOut.GetBuffer();
1043 				sOut.Erase();
1044 			}
1045 
1046 			if( pMacItem )
1047 			{
1048 				const SvxMacroTableDtor& rMacTable = pMacItem->GetMacroTable();
1049 				if( rMacTable.Count() )
1050 					HTMLOutFuncs::Out_Events( rWrt.Strm(), rMacTable,
1051 											  aAnchorEventTable,
1052 											  rHTMLWrt.bCfgStarBasic,
1053 										   	  rHTMLWrt.eDestEnc,
1054 									    &rHTMLWrt.aNonConvertableCharacters );
1055 			}
1056 
1057 			rWrt.Strm() << ">";
1058 			(((sOut = "</") += OOO_STRING_SVTOOLS_HTML_anchor) += ">") += aEndTags;
1059 			aEndTags = sOut;
1060 		}
1061 	}
1062 
1063 	// Umrandung -> <FONT COLOR = ...>...<IMG ... >...</FONT>
1064 	sal_uInt16 nBorderWidth = 0;
1065 	if( (nFrmOpts & HTML_FRMOPT_BORDER) &&
1066 		SFX_ITEM_SET == rItemSet.GetItemState( RES_BOX, sal_True, &pItem ))
1067 	{
1068 		Size aTwipBorder( 0, 0 );
1069 		const SvxBoxItem* pBoxItem = (const SvxBoxItem*)pItem;
1070 
1071 		const SvxBorderLine *pColBorderLine = 0;
1072 		const SvxBorderLine *pBorderLine = pBoxItem->GetLeft();
1073 		if( pBorderLine )
1074 		{
1075 			pColBorderLine = pBorderLine;
1076 			aTwipBorder.Width() += pBorderLine->GetOutWidth();
1077 		}
1078 
1079 		pBorderLine = pBoxItem->GetRight();
1080 		if( pBorderLine )
1081 		{
1082 			pColBorderLine = pBorderLine;
1083 			aTwipBorder.Width() += pBorderLine->GetOutWidth();
1084 		}
1085 
1086 		pBorderLine = pBoxItem->GetTop();
1087 		if( pBorderLine )
1088 		{
1089 			pColBorderLine = pBorderLine;
1090 			aTwipBorder.Height() += pBorderLine->GetOutWidth();
1091 		}
1092 
1093 		pBorderLine = pBoxItem->GetBottom();
1094 		if( pBorderLine )
1095 		{
1096 			pColBorderLine = pBorderLine;
1097 			aTwipBorder.Height() += pBorderLine->GetOutWidth();
1098 		}
1099 
1100 		aTwipBorder.Width() /= 2;
1101 		aTwipBorder.Height() /= 2;
1102 
1103 		if( (aTwipBorder.Width() || aTwipBorder.Height()) &&
1104 			Application::GetDefaultDevice() )
1105 		{
1106 			Size aPixelBorder =
1107 				Application::GetDefaultDevice()->LogicToPixel( aTwipBorder,
1108 													MapMode(MAP_TWIP) );
1109 			if( !aPixelBorder.Width() && aTwipBorder.Width() )
1110 				aPixelBorder.Width() = 1;
1111 			if( !aPixelBorder.Height() && aTwipBorder.Height() )
1112 				aPixelBorder.Height() = 1;
1113 
1114 			if( aPixelBorder.Width() )
1115 				aPixelBorder.Height() = 0;
1116 
1117 			nBorderWidth =
1118 				(sal_uInt16)(aPixelBorder.Width() + aPixelBorder.Height());
1119 		}
1120 
1121 		if( pColBorderLine )
1122 		{
1123 			sOut = '<';
1124 			(((sOut += OOO_STRING_SVTOOLS_HTML_font) += ' ') += OOO_STRING_SVTOOLS_HTML_O_color) += '=';
1125 			rWrt.Strm() << sOut.GetBuffer();
1126 			HTMLOutFuncs::Out_Color( rWrt.Strm(),
1127 									 pColBorderLine->GetColor(), rHTMLWrt.eDestEnc ) << '>';
1128 
1129 			(((sOut = "</" ) += OOO_STRING_SVTOOLS_HTML_font) += '>') += aEndTags;
1130 			aEndTags = sOut;
1131 		}
1132 	}
1133 
1134 	sOut = '<';
1135 	(((sOut += OOO_STRING_SVTOOLS_HTML_image) += ' ') += OOO_STRING_SVTOOLS_HTML_O_src) += "=\"";
1136 	rWrt.Strm() << sOut.GetBuffer();
1137 	HTMLOutFuncs::Out_String( rWrt.Strm(), aGrfNm, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ) << '\"';
1138 
1139 	// Events
1140 	sOut.Erase();
1141 	if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRMMACRO, sal_True, &pItem ))
1142 	{
1143 		const SvxMacroTableDtor& rMacTable =
1144 			((const SvxMacroItem *)pItem)->GetMacroTable();
1145 		if( rMacTable.Count() )
1146 			HTMLOutFuncs::Out_Events( rWrt.Strm(), rMacTable, aImageEventTable,
1147 									  rHTMLWrt.bCfgStarBasic, rHTMLWrt.eDestEnc,
1148 									    &rHTMLWrt.aNonConvertableCharacters );
1149 	}
1150 
1151 	// ALT, ALIGN, WIDTH, HEIGHT, HSPACE, VSPACE
1152 	rHTMLWrt.OutFrmFmtOptions( rFrmFmt, rAlternateTxt, aEndTags, nFrmOpts );
1153 	if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) )
1154 		rHTMLWrt.OutCSS1_FrmFmtOptions( rFrmFmt, nFrmOpts );
1155 
1156 
1157 	if( nFrmOpts & HTML_FRMOPT_BORDER )
1158 	{
1159 		(((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_border) += '=')
1160 			+= ByteString::CreateFromInt32( nBorderWidth );
1161 		rWrt.Strm() << sOut.GetBuffer();
1162 	}
1163 
1164 	if( pURLItem && pURLItem->IsServerMap() )
1165 	{
1166 		(sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_ismap;
1167 		rWrt.Strm() << sOut.GetBuffer();
1168 	}
1169 	if( aIMapName.Len() )
1170 	{
1171 		((sOut = ' ') += OOO_STRING_SVTOOLS_HTML_O_usemap) += "=\"#";
1172 		rWrt.Strm() << sOut.GetBuffer();
1173 		HTMLOutFuncs::Out_String( rWrt.Strm(), aIMapName, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters ) << '\"';
1174 	}
1175 
1176 	rHTMLWrt.Strm() << '>';
1177 
1178 	if( aEndTags.Len() )
1179 		rWrt.Strm() << aEndTags.GetBuffer();
1180 
1181 	if( rHTMLWrt.aINetFmts.Count() )
1182 	{
1183 		// es ist noch ein Attribut auf dem Stack, das wieder geoeffnet
1184 		// werden muss
1185 		SwFmtINetFmt *pINetFmt =
1186 			rHTMLWrt.aINetFmts[ rHTMLWrt.aINetFmts.Count()-1 ];
1187 		OutHTML_INetFmt( rWrt, *pINetFmt, sal_True );
1188 	}
1189 
1190 	return rHTMLWrt;
1191 }
1192 
OutHTML_BulletImage(Writer & rWrt,const sal_Char * pTag,const SvxBrushItem * pBrush,String & rGrfName,const Size & rSize,const SwFmtVertOrient * pVertOrient)1193 Writer& OutHTML_BulletImage( Writer& rWrt,
1194 							 const sal_Char *pTag,
1195 							 const SvxBrushItem* pBrush,
1196 							 String &rGrfName,
1197 							 const Size &rSize,
1198 							 const SwFmtVertOrient* pVertOrient )
1199 {
1200 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1201 
1202 	// Wenn es ein BrushItem gibt, muss die Grafiknoch exportiert werden
1203 	const String *pLink = 0;
1204 	if( pBrush )
1205 	{
1206 		pLink = pBrush->GetGraphicLink();
1207 
1208 		// embeddete Grafik -> WriteEmbedded schreiben
1209 		if( !pLink )
1210 		{
1211 			const Graphic* pGrf = pBrush->GetGraphic();
1212 			if( pGrf )
1213 			{
1214 				// Grafik als (JPG-)File speichern
1215 				if( rHTMLWrt.GetOrigFileName() )
1216 					rGrfName = *rHTMLWrt.GetOrigFileName();
1217 				sal_uInt16 nErr = XOutBitmap::WriteGraphic(	*pGrf,  rGrfName,
1218 						String::CreateFromAscii("JPG"),
1219 						(XOUTBMP_USE_GIF_IF_SENSIBLE |
1220 						 XOUTBMP_USE_NATIVE_IF_POSSIBLE));
1221 				if( !nErr )
1222 				{
1223                     rGrfName = URIHelper::SmartRel2Abs(
1224                         INetURLObject( rWrt.GetBaseURL() ), rGrfName,
1225                         URIHelper::GetMaybeFileHdl() );
1226 					pLink = &rGrfName;
1227 				}
1228 				else
1229 				{
1230 					rHTMLWrt.nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE;
1231 				}
1232 			}
1233 		}
1234 		else
1235 		{
1236 			rGrfName = *pLink;
1237 			if( rHTMLWrt.bCfgCpyLinkedGrfs )
1238 			{
1239 				rHTMLWrt.CopyLocalFileToINet( rGrfName );
1240 				pLink = &rGrfName;
1241 			}
1242 		}
1243 	}
1244 	else
1245 	{
1246 		pLink = &rGrfName;
1247 	}
1248 
1249 	ByteString sOut;
1250 	if( pTag )
1251 		(sOut += '<') += pTag;
1252 
1253 	if( pLink )
1254 	{
1255 		sOut += ' ';
1256 		String s( *pLink );
1257 		if( !HTMLOutFuncs::PrivateURLToInternalImg(s) )
1258             s = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), s);
1259 		(sOut += OOO_STRING_SVTOOLS_HTML_O_src) += "=\"";
1260 		rWrt.Strm() << sOut.GetBuffer();
1261 		HTMLOutFuncs::Out_String( rWrt.Strm(), s, rHTMLWrt.eDestEnc, &rHTMLWrt.aNonConvertableCharacters );
1262 		sOut = '\"';
1263 
1264 		// Groesse des Objekts Twips ohne Raender
1265 		Size aPixelSz( 0, 0 );
1266 		if( (rSize.Width() || rSize.Height()) && Application::GetDefaultDevice() )
1267 		{
1268 			aPixelSz =
1269 				Application::GetDefaultDevice()->LogicToPixel( rSize,
1270 													MapMode(MAP_TWIP) );
1271 			if( !aPixelSz.Width() && rSize.Width() )
1272 				aPixelSz.Width() = 1;
1273 			if( !aPixelSz.Height() && rSize.Height() )
1274 				aPixelSz.Height() = 1;
1275 		}
1276 
1277 		if( aPixelSz.Width() )
1278 			(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width) += '=')
1279 				+= ByteString::CreateFromInt32( aPixelSz.Width() );
1280 
1281 		if( aPixelSz.Height() )
1282 			(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_height) += '=')
1283 				+= ByteString::CreateFromInt32( aPixelSz.Height() );
1284 
1285 		if( pVertOrient )
1286 		{
1287 			const sal_Char *pStr = 0;
1288 			switch( pVertOrient->GetVertOrient() )
1289 			{
1290             case text::VertOrientation::LINE_TOP:     pStr = OOO_STRING_SVTOOLS_HTML_VA_top;        break;
1291             case text::VertOrientation::CHAR_TOP:
1292             case text::VertOrientation::BOTTOM:       pStr = OOO_STRING_SVTOOLS_HTML_VA_texttop;    break;  // geht nicht
1293             case text::VertOrientation::LINE_CENTER:
1294             case text::VertOrientation::CHAR_CENTER:  pStr = OOO_STRING_SVTOOLS_HTML_VA_absmiddle;  break;  // geht nicht
1295             case text::VertOrientation::CENTER:       pStr = OOO_STRING_SVTOOLS_HTML_VA_middle;     break;
1296             case text::VertOrientation::LINE_BOTTOM:
1297             case text::VertOrientation::CHAR_BOTTOM:  pStr = OOO_STRING_SVTOOLS_HTML_VA_absbottom;  break;  // geht nicht
1298             case text::VertOrientation::TOP:          pStr = OOO_STRING_SVTOOLS_HTML_VA_bottom;     break;
1299             case text::VertOrientation::NONE:     break;
1300 			}
1301 			if( pStr )
1302 				(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += pStr;
1303 		}
1304 	}
1305 
1306 	if( pTag )
1307 		sOut += '>';
1308 	rWrt.Strm() << sOut.GetBuffer();
1309 
1310 	return rWrt;
1311 }
1312 
1313 
1314 //-----------------------------------------------------------------------
1315 
OutHTML_FrmFmtTableNode(Writer & rWrt,const SwFrmFmt & rFrmFmt)1316 static Writer& OutHTML_FrmFmtTableNode( Writer& rWrt, const SwFrmFmt& rFrmFmt )
1317 {
1318 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1319 
1320 	const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt();
1321 	sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex()+1;
1322 	sal_uLong nEnd = rHTMLWrt.pDoc->GetNodes()[nStt-1]->EndOfSectionIndex();
1323 
1324 	String aCaption;
1325 	sal_Bool bTopCaption = sal_False;
1326 
1327 	// Nicht const, weil GetTable spater mal nicht const ist
1328 	SwNode *pNd = rHTMLWrt.pDoc->GetNodes()[ nStt ];
1329 	SwTableNode *pTblNd = pNd->GetTableNode();
1330 	const SwTxtNode *pTxtNd = pNd->GetTxtNode();
1331 	if( !pTblNd && pTxtNd )
1332 	{
1333 		// Tabelle mit Ueberschrift
1334 		bTopCaption = sal_True;
1335 		pTblNd = rHTMLWrt.pDoc->GetNodes()[nStt+1]->GetTableNode();
1336 	}
1337 	ASSERT( pTblNd, "Rahmen enthaelt keine Tabelle" );
1338 	if( pTblNd )
1339 	{
1340 		sal_uLong nTblEnd = pTblNd->EndOfSectionIndex();
1341 		ASSERT( nTblEnd == nEnd - 1 ||
1342 				(nTblEnd == nEnd - 2 && !bTopCaption),
1343 				"Ungeuelter Rahmen-Inhalt fuer Tabelle" );
1344 
1345 		if( nTblEnd == nEnd - 2 )
1346 			pTxtNd = rHTMLWrt.pDoc->GetNodes()[nTblEnd+1]->GetTxtNode();
1347 	}
1348 	if( pTxtNd )
1349 		aCaption = pTxtNd->GetTxt();
1350 
1351 	{
1352 		HTMLSaveData aSaveData( rHTMLWrt, pTblNd->GetIndex()+1,
1353 								pTblNd->EndOfSectionIndex(),
1354 			   					sal_True, &rFrmFmt );
1355 		rHTMLWrt.bOutFlyFrame = sal_True;
1356 		OutHTML_SwTblNode( rHTMLWrt, *pTblNd, &rFrmFmt, &aCaption,
1357 						   bTopCaption );
1358 	}
1359 
1360 	return rWrt;
1361 }
1362 
OutHTML_FrmFmtAsMulticol(Writer & rWrt,const SwFrmFmt & rFrmFmt,sal_Bool bInCntnr)1363 static Writer & OutHTML_FrmFmtAsMulticol( Writer& rWrt,
1364 										  const SwFrmFmt& rFrmFmt,
1365 										  sal_Bool bInCntnr	)
1366 {
1367 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1368 
1369 	rHTMLWrt.ChangeParaToken( 0 );
1370 
1371 	// Die aktulle <DL> beenden!
1372 	rHTMLWrt.OutAndSetDefList( 0 );
1373 
1374 	// als Multicol ausgeben
1375 	if( rHTMLWrt.bLFPossible )
1376 		rHTMLWrt.OutNewLine();
1377 
1378 	ByteString sOut( '<' );
1379 	sOut += OOO_STRING_SVTOOLS_HTML_multicol;
1380 
1381 	const SwFmtCol& rFmtCol = rFrmFmt.GetCol();
1382 
1383 	// die Anzahl der Spalten als COLS ausgeben
1384 	sal_uInt16 nCols = rFmtCol.GetNumCols();
1385 	if( nCols )
1386 		(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=')
1387 			+= ByteString::CreateFromInt32( nCols );
1388 
1389 	// die Gutter-Breite (Minimalwert) als GUTTER
1390 	sal_uInt16 nGutter = rFmtCol.GetGutterWidth( sal_True );
1391 	if( nGutter!=USHRT_MAX )
1392 	{
1393 		if( nGutter && Application::GetDefaultDevice() )
1394 		{
1395 			nGutter = (sal_uInt16)Application::GetDefaultDevice()
1396 							->LogicToPixel( Size(nGutter,0),
1397 											MapMode(MAP_TWIP) ).Width();
1398 		}
1399 		(((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_gutter) += '=')
1400 			+= ByteString::CreateFromInt32( nGutter );
1401 	}
1402 
1403 	rWrt.Strm() << sOut.GetBuffer();
1404 
1405 	// WIDTH
1406 	sal_uLong nFrmFlags = bInCntnr ? HTML_FRMOPTS_MULTICOL_CNTNR
1407 								: HTML_FRMOPTS_MULTICOL;
1408 	if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr )
1409 		nFrmFlags |= HTML_FRMOPTS_MULTICOL_CSS1;
1410 	ByteString aEndTags;
1411 	rHTMLWrt.OutFrmFmtOptions( rFrmFmt, aEmptyStr, aEndTags, nFrmFlags );
1412 	if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr )
1413 		rHTMLWrt.OutCSS1_FrmFmtOptions( rFrmFmt, nFrmFlags );
1414 
1415 	rWrt.Strm() << '>';
1416 
1417 	rHTMLWrt.bLFPossible = sal_True;
1418 	rHTMLWrt.IncIndentLevel();	// den Inhalt von Multicol einruecken;
1419 
1420 	const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt();
1421 	sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex();
1422 	const SwStartNode* pSttNd = rWrt.pDoc->GetNodes()[nStt]->GetStartNode();
1423 	ASSERT( pSttNd, "Wo ist der Start-Node" );
1424 
1425 	{
1426 		// in einem Block damit rechtzeitig vor dem Ende der alte Zustand
1427 		// wieder hergestellt wird.
1428 		HTMLSaveData aSaveData( rHTMLWrt, nStt+1,
1429 								pSttNd->EndOfSectionIndex(),
1430 			   					sal_True, &rFrmFmt );
1431 		rHTMLWrt.bOutFlyFrame = sal_True;
1432 		rHTMLWrt.Out_SwDoc( rWrt.pCurPam );
1433 	}
1434 
1435 //	rHTMLWrt.ChangeParaToken( 0 );	// MIB 8.7.97: Passiert jetzt in Out_SwDoc
1436 
1437 	rHTMLWrt.DecIndentLevel();	// den Inhalt von Multicol einruecken;
1438 	if( rHTMLWrt.bLFPossible )
1439 		rHTMLWrt.OutNewLine();
1440 	HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_multicol, sal_False );
1441 	rHTMLWrt.bLFPossible = sal_True;
1442 
1443 	return rWrt;
1444 }
1445 
OutHTML_FrmFmtAsSpacer(Writer & rWrt,const SwFrmFmt & rFrmFmt)1446 static Writer& OutHTML_FrmFmtAsSpacer( Writer& rWrt, const SwFrmFmt& rFrmFmt )
1447 {
1448 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1449 
1450 	// wenn meoglich vor der Grafik einen Zeilen-Umbruch ausgeben
1451 	if( rHTMLWrt.bLFPossible )
1452 		rHTMLWrt.OutNewLine( sal_True );
1453 
1454 	ByteString sOut('<');
1455 	((((sOut += OOO_STRING_SVTOOLS_HTML_spacer) += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=')
1456 		+= OOO_STRING_SVTOOLS_HTML_SPTYPE_block;
1457 	rWrt.Strm() << sOut.GetBuffer();
1458 
1459 	// ALIGN, WIDTH, HEIGHT
1460 	ByteString aEndTags;
1461 	rHTMLWrt.OutFrmFmtOptions( rFrmFmt, aEmptyStr, aEndTags,
1462 								HTML_FRMOPTS_SPACER );
1463 
1464 	rWrt.Strm() << '>';
1465 	if( aEndTags.Len() )
1466 		rWrt.Strm() << aEndTags.GetBuffer();
1467 
1468 	return rWrt;
1469 }
1470 
OutHTML_FrmFmtAsDivOrSpan(Writer & rWrt,const SwFrmFmt & rFrmFmt,sal_Bool bSpan)1471 static Writer& OutHTML_FrmFmtAsDivOrSpan( Writer& rWrt,
1472 										  const SwFrmFmt& rFrmFmt, sal_Bool bSpan)
1473 {
1474 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1475 
1476 	const sal_Char *pStr = 0;
1477 	if( !bSpan )
1478 	{
1479 		rHTMLWrt.ChangeParaToken( 0 );
1480 
1481 		// Die aktulle <DL> beenden!
1482 		rHTMLWrt.OutAndSetDefList( 0 );
1483 		pStr = OOO_STRING_SVTOOLS_HTML_division;
1484 	}
1485 	else
1486 		pStr = OOO_STRING_SVTOOLS_HTML_span;
1487 
1488 	// als DIV ausgeben
1489 	if( rHTMLWrt.bLFPossible )
1490 		rHTMLWrt.OutNewLine();
1491 
1492 	ByteString sOut( '<' );
1493 	sOut += pStr;
1494 
1495 	rWrt.Strm() << sOut.GetBuffer();
1496 	ByteString aEndTags;
1497 	sal_uLong nFrmFlags = HTML_FRMOPTS_DIV;
1498 	if( rHTMLWrt.IsHTMLMode( HTMLMODE_BORDER_NONE ) )
1499 	   nFrmFlags |= HTML_FRMOPT_S_NOBORDER;
1500 	rHTMLWrt.OutFrmFmtOptions( rFrmFmt, aEmptyStr, aEndTags, nFrmFlags );
1501 	rHTMLWrt.OutCSS1_FrmFmtOptions( rFrmFmt, nFrmFlags );
1502 	rWrt.Strm() << '>';
1503 
1504 	rHTMLWrt.IncIndentLevel();	// den Inhalt einruecken
1505 	rHTMLWrt.bLFPossible = sal_True;
1506 
1507 	const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt();
1508 	sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex();
1509 
1510 	// Am Start-Node verankerte Rahmen-gebundene Rahmen ausgeben
1511 	rHTMLWrt.OutFlyFrm( nStt, 0, HTML_POS_ANY );
1512 
1513 	const SwStartNode* pSttNd = rWrt.pDoc->GetNodes()[nStt]->GetStartNode();
1514 	ASSERT( pSttNd, "Wo ist der Start-Node" );
1515 
1516 	{
1517 		// in einem Block damit rechtzeitig vor dem Ende der alte Zustand
1518 		// wieder hergestellt wird.
1519 		HTMLSaveData aSaveData( rHTMLWrt, nStt+1,
1520 								pSttNd->EndOfSectionIndex(),
1521 			   					sal_True, &rFrmFmt );
1522 		rHTMLWrt.bOutFlyFrame = sal_True;
1523 		rHTMLWrt.Out_SwDoc( rWrt.pCurPam );
1524 	}
1525 
1526 	rHTMLWrt.DecIndentLevel();	// den Inhalt von Multicol einruecken;
1527 	if( rHTMLWrt.bLFPossible )
1528 		rHTMLWrt.OutNewLine();
1529 	HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), pStr, sal_False );
1530 
1531 	if( aEndTags.Len() )
1532 		rWrt.Strm() << aEndTags.GetBuffer();
1533 
1534 	return rWrt;
1535 }
1536 
OutHTML_FrmFmtAsImage(Writer & rWrt,const SwFrmFmt & rFrmFmt,sal_Bool)1537 static Writer & OutHTML_FrmFmtAsImage( Writer& rWrt, const SwFrmFmt& rFrmFmt,
1538 									   sal_Bool /*bInCntnr*/ )
1539 {
1540 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1541 
1542 	ImageMap aIMap;
1543 	Graphic aGrf( ((SwFrmFmt &)rFrmFmt).MakeGraphic( &aIMap ) );
1544 
1545 	String aGrfNm;
1546 	if( rHTMLWrt.GetOrigFileName() )
1547 		aGrfNm = *rHTMLWrt.GetOrigFileName();
1548 	if( aGrf.GetType() == GRAPHIC_NONE ||
1549 		XOutBitmap::WriteGraphic( aGrf, aGrfNm,
1550 								  String::CreateFromAscii( "JPG" ),
1551 								  (XOUTBMP_USE_GIF_IF_POSSIBLE|
1552 								   XOUTBMP_USE_NATIVE_IF_POSSIBLE) ) != 0 )
1553 	{
1554 		// leer oder fehlerhaft, da ist nichts auszugeben
1555 		rHTMLWrt.nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE;
1556 		return rWrt;
1557 	}
1558 
1559     aGrfNm = URIHelper::SmartRel2Abs(
1560         INetURLObject(rWrt.GetBaseURL()), aGrfNm,
1561         URIHelper::GetMaybeFileHdl() );
1562 	Size aSz( 0, 0 );
1563 	OutHTML_Image( rWrt, rFrmFmt, aGrfNm, rFrmFmt.GetName(), aSz,
1564 					HTML_FRMOPTS_GENIMG, pMarkToFrame,
1565 					aIMap.GetIMapObjectCount() ? &aIMap : 0 );
1566 	return rWrt;
1567 }
1568 
1569 
OutHTML_FrmFmtGrfNode(Writer & rWrt,const SwFrmFmt & rFrmFmt,sal_Bool bInCntnr)1570 static Writer& OutHTML_FrmFmtGrfNode( Writer& rWrt, const SwFrmFmt& rFrmFmt,
1571 									  sal_Bool bInCntnr )
1572 {
1573 	SwHTMLWriter& rHTMLWrt = (SwHTMLWriter&)rWrt;
1574 
1575 	const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt();
1576 	sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex()+1;
1577 	SwGrfNode *pGrfNd = rHTMLWrt.pDoc->GetNodes()[ nStt ]->GetGrfNode();
1578 	ASSERT( pGrfNd, "Grf-Node erwartet" );
1579 	if( !pGrfNd )
1580 		return rWrt;
1581 
1582 	const SwMirrorGrf& rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
1583 
1584 	String aGrfNm;
1585     if( !pGrfNd->IsLinkedFile() || RES_MIRROR_GRAPH_DONT != rMirror.GetValue() )
1586 	{
1587 		// Grafik als File-Referenz speichern (als JPEG-Grafik speichern)
1588 		if( rHTMLWrt.GetOrigFileName() )
1589 			aGrfNm = *rHTMLWrt.GetOrigFileName();
1590 		pGrfNd->SwapIn( sal_True );
1591 
1592 		sal_uLong nFlags = XOUTBMP_USE_GIF_IF_SENSIBLE |
1593 					   XOUTBMP_USE_NATIVE_IF_POSSIBLE;
1594 		switch( rMirror.GetValue() )
1595 		{
1596         case RES_MIRROR_GRAPH_VERT: nFlags = XOUTBMP_MIRROR_HORZ; break;
1597         case RES_MIRROR_GRAPH_HOR:    nFlags = XOUTBMP_MIRROR_VERT; break;
1598         case RES_MIRROR_GRAPH_BOTH:
1599 			nFlags = XOUTBMP_MIRROR_VERT | XOUTBMP_MIRROR_HORZ;
1600 			break;
1601 		}
1602 
1603 		Size aMM100Size;
1604 		const SwFmtFrmSize& rSize = rFrmFmt.GetFrmSize();
1605 		aMM100Size = OutputDevice::LogicToLogic( rSize.GetSize(),
1606 						MapMode( MAP_TWIP ), MapMode( MAP_100TH_MM ));
1607 
1608 		sal_uInt16 nErr = XOutBitmap::WriteGraphic( pGrfNd->GetGrf(), aGrfNm,
1609 				String::CreateFromAscii("JPG"), nFlags, &aMM100Size );
1610 		if( nErr )     			// fehlerhaft, da ist nichts auszugeben
1611 		{
1612 			rHTMLWrt.nWarn = WARN_SWG_POOR_LOAD | WARN_SW_WRITE_BASE;
1613 			return rWrt;
1614 		}
1615         aGrfNm = URIHelper::SmartRel2Abs(
1616             INetURLObject(rWrt.GetBaseURL()), aGrfNm,
1617             URIHelper::GetMaybeFileHdl() );
1618 	}
1619 	else
1620 	{
1621 		pGrfNd->GetFileFilterNms( &aGrfNm, 0 );
1622 		if( rHTMLWrt.bCfgCpyLinkedGrfs )
1623 			rWrt.CopyLocalFileToINet( aGrfNm );
1624 	}
1625 
1626 	sal_uLong nFrmFlags = bInCntnr ? HTML_FRMOPTS_IMG_CNTNR : HTML_FRMOPTS_IMG;
1627 	if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr )
1628 		nFrmFlags |= HTML_FRMOPTS_IMG_CSS1;
1629     OutHTML_Image( rWrt, rFrmFmt, aGrfNm, pGrfNd->GetTitle(),
1630 				   pGrfNd->GetTwipSize(), nFrmFlags, pMarkToGraphic );
1631 
1632 	return rWrt;
1633 }
1634 
1635 
OutHTML_FrmFmtAsMarquee(Writer & rWrt,const SwFrmFmt & rFrmFmt,const SdrObject & rSdrObj)1636 static Writer& OutHTML_FrmFmtAsMarquee( Writer& rWrt, const SwFrmFmt& rFrmFmt,
1637 								  const SdrObject& rSdrObj	)
1638 {
1639 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1640 
1641 	// die Edit-Engine-Attribute des Objekts als SW-Attribute holen
1642 	// und als Hints einsortieren
1643 	const SfxItemSet& rFmtItemSet = rFrmFmt.GetAttrSet();
1644 	SfxItemSet aItemSet( *rFmtItemSet.GetPool(), RES_CHRATR_BEGIN,
1645 												 RES_CHRATR_END );
1646 	SwHTMLWriter::GetEEAttrsFromDrwObj( aItemSet, &rSdrObj, sal_True );
1647 	sal_Bool bCfgOutStylesOld = rHTMLWrt.bCfgOutStyles;
1648 	rHTMLWrt.bCfgOutStyles = sal_False;
1649 	rHTMLWrt.bTxtAttr = sal_True;
1650 	rHTMLWrt.bTagOn = sal_True;
1651 	Out_SfxItemSet( aHTMLAttrFnTab, rWrt, aItemSet, sal_False );
1652 	rHTMLWrt.bTxtAttr = sal_False;
1653 
1654 	OutHTML_DrawFrmFmtAsMarquee( rHTMLWrt,
1655 								 (const SwDrawFrmFmt &)rFrmFmt,
1656 								 rSdrObj );
1657 	rHTMLWrt.bTxtAttr = sal_True;
1658 	rHTMLWrt.bTagOn = sal_False;
1659 	Out_SfxItemSet( aHTMLAttrFnTab, rWrt, aItemSet, sal_False );
1660 	rHTMLWrt.bTxtAttr = sal_False;
1661 	rHTMLWrt.bCfgOutStyles = bCfgOutStylesOld;
1662 
1663 	return rWrt;
1664 }
1665 
1666 //-----------------------------------------------------------------------
1667 
OutHTML_HeaderFooter(Writer & rWrt,const SwFrmFmt & rFrmFmt,sal_Bool bHeader)1668 Writer& OutHTML_HeaderFooter( Writer& rWrt, const SwFrmFmt& rFrmFmt,
1669 							  sal_Bool bHeader )
1670 {
1671 	SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
1672 
1673 	// als Multicol ausgeben
1674 	rHTMLWrt.OutNewLine();
1675 	ByteString sOut( OOO_STRING_SVTOOLS_HTML_division );
1676 	((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_type) += '=';
1677 	sOut += (bHeader ? "HEADER" : "FOOTER" );
1678 	HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), sOut.GetBuffer() );
1679 
1680 	rHTMLWrt.IncIndentLevel();	// den Inhalt von Multicol einruecken;
1681 
1682 	// Einen Spacer fuer den Absatnd zusammenbasteln. Da durch das
1683 	// <DL> bzw. </DL> immer einer Absatz-Abstand entsteht, wird der
1684 	// ggf. abgezogen.
1685 	const SvxULSpaceItem& rULSpace = rFrmFmt.GetULSpace();
1686 	sal_uInt16 nSize = bHeader ? rULSpace.GetLower() : rULSpace.GetUpper();
1687 	rHTMLWrt.nHeaderFooterSpace = nSize;
1688 
1689 	ByteString aSpacer;
1690 	if( rHTMLWrt.IsHTMLMode(HTMLMODE_VERT_SPACER) &&
1691 		nSize > HTML_PARSPACE && Application::GetDefaultDevice() )
1692 	{
1693 		nSize -= HTML_PARSPACE;
1694 		nSize = (sal_Int16)Application::GetDefaultDevice()
1695 			->LogicToPixel( Size(nSize,0), MapMode(MAP_TWIP) ).Width();
1696 
1697 		((((((((aSpacer = OOO_STRING_SVTOOLS_HTML_spacer) += ' ')
1698 			+= OOO_STRING_SVTOOLS_HTML_O_type) += '=') += OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical) += ' ')
1699 			+= OOO_STRING_SVTOOLS_HTML_O_size) += '=') += ByteString::CreateFromInt32(nSize);
1700 	}
1701 
1702 	const SwFmtCntnt& rFlyCntnt = rFrmFmt.GetCntnt();
1703 	sal_uLong nStt = rFlyCntnt.GetCntntIdx()->GetIndex();
1704 	const SwStartNode* pSttNd = rWrt.pDoc->GetNodes()[nStt]->GetStartNode();
1705 	ASSERT( pSttNd, "Wo ist der Start-Node" );
1706 
1707 	if( !bHeader && aSpacer.Len() )
1708 	{
1709 		rHTMLWrt.OutNewLine();
1710 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), aSpacer.GetBuffer() );
1711 	}
1712 
1713 	{
1714 		// in einem Block damit rechtzeitig vor dem Ende der alte Zustand
1715 		// wieder hergestellt wird. pFlyFmt braucht hier nicht gestzt zu
1716 		// werden, denn PageDesc-Attribute koennen hier nicht vorkommen
1717 		HTMLSaveData aSaveData( rHTMLWrt, nStt+1,
1718 								pSttNd->EndOfSectionIndex() );
1719 
1720 		if( bHeader )
1721 			rHTMLWrt.bOutHeader = sal_True;
1722 		else
1723 			rHTMLWrt.bOutFooter = sal_True;
1724 
1725 		rHTMLWrt.Out_SwDoc( rWrt.pCurPam );
1726 	}
1727 
1728 	if( bHeader && aSpacer.Len() )
1729 	{
1730 		rHTMLWrt.OutNewLine();
1731 		HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), aSpacer.GetBuffer() );
1732 	}
1733 
1734 	rHTMLWrt.DecIndentLevel();	// den Inhalt von Multicol einruecken;
1735 	rHTMLWrt.OutNewLine();
1736 	HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_division, sal_False );
1737 
1738 	rHTMLWrt.nHeaderFooterSpace = 0;
1739 
1740 	return rWrt;
1741 }
1742 
1743 
AddLinkTarget(const String & rURL)1744 void SwHTMLWriter::AddLinkTarget( const String& rURL )
1745 {
1746 	if( !rURL.Len() || rURL.GetChar(0) != '#' )
1747 		return;
1748 
1749 	// There might be a '|' as delimiter (if the link has been inserted
1750 	// freshly) or a '%7c' or a '%7C' if the document has been saved and
1751 	// loaded already.
1752 	xub_StrLen nPos = rURL.Len();
1753 	sal_Bool bFound = sal_False, bEncoded = sal_False;
1754 	while( !bFound && nPos > 0 )
1755 	{
1756 		sal_Unicode c = rURL.GetChar( --nPos );
1757 		switch( c )
1758 		{
1759 		case cMarkSeperator:
1760 			bFound = sal_True;
1761 			break;
1762 		case '%':
1763 			bFound = (rURL.Len() - nPos) >=3 &&
1764 					 rURL.GetChar( nPos+1 ) == '7' &&
1765 					 ((c =rURL.GetChar( nPos+2 )) == 'C' || c == 'c');
1766 			if( bFound )
1767 				bEncoded = sal_True;
1768 		}
1769 	}
1770 	if( !bFound || nPos < 2 ) // mindetsens "#a|..."
1771 		return;
1772 
1773 	String aURL( rURL.Copy( 1 ) );
1774 
1775 	String sCmp( aURL.Copy( bEncoded ? nPos+2 : nPos ) ); // nPos-1+1/3 (-1 wg. Erase)
1776 	sCmp.EraseAllChars();
1777 	if( !sCmp.Len() )
1778 		return;
1779 
1780 	sCmp.ToLowerAscii();
1781 
1782 	if( sCmp.EqualsAscii( pMarkToRegion ) ||
1783 		sCmp.EqualsAscii( pMarkToFrame ) ||
1784 		sCmp.EqualsAscii( pMarkToGraphic ) ||
1785 		sCmp.EqualsAscii( pMarkToOLE ) ||
1786 		sCmp.EqualsAscii( pMarkToTable ) )
1787 	{
1788 		// Einfach nur in einem sortierten Array merken
1789 		if( bEncoded )
1790 		{
1791 			aURL.Erase( nPos, 2 );
1792 			aURL.SetChar( nPos-1, cMarkSeperator );
1793 		}
1794 		aImplicitMarks.Insert( new String( aURL ) );
1795 	}
1796 	else if( sCmp.EqualsAscii( pMarkToOutline ) )
1797 	{
1798 		// Hier brauchen wir Position und Name. Deshalb sortieren wir
1799 		// ein sal_uInt16 und ein String-Array selbst
1800 		String aOutline( aURL.Copy( 0, nPos-1 ) );
1801 		SwPosition aPos( *pCurPam->GetPoint() );
1802 		if( pDoc->GotoOutline( aPos, aOutline ) )
1803 		{
1804 			sal_uLong nIdx = aPos.nNode.GetIndex();
1805 
1806 			sal_uInt16 nIns=0;
1807 			while( nIns < aOutlineMarkPoss.Count() &&
1808 				   aOutlineMarkPoss[nIns] < nIdx )
1809 				nIns++;
1810 
1811 			aOutlineMarkPoss.Insert( nIdx, nIns );
1812 			if( bEncoded )
1813 			{
1814 				aURL.Erase( nPos, 2 );
1815 				aURL.SetChar( nPos-1, cMarkSeperator );
1816 			}
1817 			aOutlineMarks.Insert( new String( aURL ), nIns );
1818 		}
1819 	}
1820 	else if( sCmp.EqualsAscii( pMarkToText ) )
1821 	{
1822 		//
1823 	}
1824 }
1825 
CollectLinkTargets()1826 void SwHTMLWriter::CollectLinkTargets()
1827 {
1828 	const SwFmtINetFmt* pINetFmt;
1829 	const SwTxtINetFmt* pTxtAttr;
1830 	const SwTxtNode* pTxtNd;
1831 
1832 	sal_uInt32 n, nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
1833 	for( n = 0; n < nMaxItems; ++n )
1834 	{
1835 		if( 0 != (pINetFmt = (SwFmtINetFmt*)pDoc->GetAttrPool().GetItem2(
1836 			RES_TXTATR_INETFMT, n ) ) &&
1837 			0 != ( pTxtAttr = pINetFmt->GetTxtINetFmt()) &&
1838 			0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
1839 			pTxtNd->GetNodes().IsDocNodes() )
1840 		{
1841 			AddLinkTarget( pINetFmt->GetValue() );
1842 		}
1843 	}
1844 
1845 	const SwFmtURL *pURL;
1846 	nMaxItems = pDoc->GetAttrPool().GetItemCount2( RES_URL );
1847 	for( n = 0; n < nMaxItems; ++n )
1848 	{
1849 		if( 0 != (pURL = (SwFmtURL*)pDoc->GetAttrPool().GetItem2(
1850 			RES_URL, n ) ) )
1851 		{
1852 			AddLinkTarget( pURL->GetURL() );
1853 			const ImageMap *pIMap = pURL->GetMap();
1854 			if( pIMap )
1855 			{
1856 				for( sal_uInt16 i=0; i<pIMap->GetIMapObjectCount(); i++ )
1857 				{
1858 					const IMapObject* pObj = pIMap->GetIMapObject( i );
1859 					if( pObj )
1860 					{
1861 						AddLinkTarget( pObj->GetURL() );
1862 					}
1863 				}
1864 			}
1865 		}
1866 	}
1867 }
1868 
1869 //-----------------------------------------------------------------------
1870 
SwHTMLPosFlyFrm(const SwPosFlyFrm & rPosFly,const SdrObject * pSdrObj,sal_uInt8 nOutMode)1871 SwHTMLPosFlyFrm::SwHTMLPosFlyFrm( const SwPosFlyFrm& rPosFly,
1872 								  const SdrObject *pSdrObj,
1873 								  sal_uInt8 nOutMode ) :
1874 	pFrmFmt( &rPosFly.GetFmt() ),
1875 	pSdrObject( pSdrObj ),
1876 	pNdIdx( new SwNodeIndex( rPosFly.GetNdIndex() ) ),
1877 	nOrdNum( rPosFly.GetOrdNum() ),
1878 	nCntntIdx( 0 ),
1879 	nOutputMode( nOutMode )
1880 {
1881 	const SwFmtAnchor& rAnchor = rPosFly.GetFmt().GetAnchor();
1882     if ((FLY_AT_CHAR == rAnchor.GetAnchorId()) &&
1883 		HTML_POS_INSIDE == GetOutPos() )
1884 	{
1885 		// Auto-gebundene Rahmen werden ein Zeichen weiter hinten
1886 		// ausgegeben, weil dann die Positionierung mit Netscape
1887 		// uebereinstimmt.
1888 		ASSERT( rAnchor.GetCntntAnchor(), "Keine Anker-Position?" );
1889 		if( rAnchor.GetCntntAnchor() )
1890 		{
1891 			nCntntIdx = rAnchor.GetCntntAnchor()->nContent.GetIndex();
1892             sal_Int16 eHoriRel = rPosFly.GetFmt().GetHoriOrient().
1893 												GetRelationOrient();
1894             if( text::RelOrientation::FRAME == eHoriRel || text::RelOrientation::PRINT_AREA == eHoriRel )
1895 			{
1896 				const SwCntntNode *pCNd = pNdIdx->GetNode().GetCntntNode();
1897 				ASSERT( pCNd, "Kein Content-Node an PaM-Position" );
1898 				if( pCNd && nCntntIdx < pCNd->Len() )
1899 					nCntntIdx++;
1900 			}
1901 		}
1902 	}
1903 }
1904 
operator <(const SwHTMLPosFlyFrm & rFrm) const1905 sal_Bool SwHTMLPosFlyFrm::operator<( const SwHTMLPosFlyFrm& rFrm ) const
1906 {
1907 	if( pNdIdx->GetIndex() == rFrm.pNdIdx->GetIndex() )
1908 	{
1909 		if( nCntntIdx == rFrm.nCntntIdx )
1910 		{
1911 			if( GetOutPos() == rFrm.GetOutPos() )
1912 				return nOrdNum < rFrm.nOrdNum;
1913 			else
1914 				return GetOutPos() < rFrm.GetOutPos();
1915 		}
1916 		else
1917 			return nCntntIdx < rFrm.nCntntIdx;
1918 	}
1919 	else
1920 		return pNdIdx->GetIndex() < rFrm.pNdIdx->GetIndex();
1921 }
1922 
1923 
1924