xref: /AOO41X/main/sw/source/filter/html/htmlfly.cxx (revision e1aaeffb7db62c6979c8c469aa0f39b5baa568ab)
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