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