merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / html / htmltabw.cxx
blobd0d16334d87825332ce8d648d74af314ac23043c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: htmltabw.cxx,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <hintids.hxx>
36 #include <vcl/svapp.hxx>
37 #include <svtools/htmlout.hxx>
38 #include <svtools/htmltokn.h>
39 #include <svtools/htmlkywd.hxx>
40 #ifndef _WRKWIN_HXX //autogen
41 #include <vcl/wrkwin.hxx>
42 #endif
43 #include <svx/ulspitem.hxx>
44 #include <svx/lrspitem.hxx>
45 #include <svx/brshitem.hxx>
46 #include <svx/boxitem.hxx>
47 #include <com/sun/star/form/XFormsSupplier.hpp>
48 #include <com/sun/star/form/XForm.hpp>
49 #include <com/sun/star/form/XImageProducerSupplier.hpp>
50 #include <com/sun/star/form/XFormController.hpp>
51 #include <com/sun/star/container/XContainer.hpp>
52 #include <com/sun/star/container/XIndexContainer.hpp>
53 #include <com/sun/star/container/XSet.hpp>
54 #include <fmtornt.hxx>
55 #include <frmfmt.hxx>
56 #include <fmtfsize.hxx>
57 #include <fmtsrnd.hxx>
58 #include <frmatr.hxx>
59 #include <doc.hxx>
60 #include <pam.hxx>
61 #include <ndtxt.hxx>
62 #include <swrect.hxx>
63 #include <cellatr.hxx>
64 #include <poolfmt.hxx>
65 #include <swtable.hxx>
66 #include <htmltbl.hxx>
67 #include <htmlnum.hxx>
68 #include <wrthtml.hxx>
69 #include <wrtswtbl.hxx>
70 #ifndef PRODUCT
71 #ifndef _VIEWSH_HXX
72 #include <viewsh.hxx>
73 #endif
74 #include <viewopt.hxx>
75 #endif
77 //#define MAX_DEPTH (USHRT_MAX)
78 #define MAX_DEPTH (3)
80 using namespace ::com::sun::star;
83 class SwHTMLWrtTable : public SwWriteTable
85 void Pixelize( sal_uInt16& rValue );
86 void PixelizeBorders();
88 void OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell,
89 sal_Bool bOutVAlign ) const;
91 void OutTableCells( SwHTMLWriter& rWrt,
92 const SwWriteTableCells& rCells,
93 const SvxBrushItem *pBrushItem ) const;
95 virtual sal_Bool ShouldExpandSub( const SwTableBox *pBox,
96 sal_Bool bExpandedBefore, sal_uInt16 nDepth ) const;
98 static sal_Bool HasTabBackground( const SwTableLine& rLine,
99 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight );
100 static sal_Bool HasTabBackground( const SwTableBox& rBox,
101 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight );
103 public:
104 SwHTMLWrtTable( const SwTableLines& rLines, long nWidth, sal_uInt16 nBWidth,
105 sal_Bool bRel, USHORT nNumOfRowsToRepeat,
106 sal_uInt16 nLeftSub=0, sal_uInt16 nRightSub=0 );
107 SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo );
109 void Write( SwHTMLWriter& rWrt, sal_Int16 eAlign=text::HoriOrientation::NONE,
110 sal_Bool bTHead=sal_False, const SwFrmFmt *pFrmFmt=0,
111 const String *pCaption=0, sal_Bool bTopCaption=sal_False,
112 sal_uInt16 nHSpace=0, sal_uInt16 nVSpace=0 ) const;
116 SwHTMLWrtTable::SwHTMLWrtTable( const SwTableLines& rLines, long nWidth,
117 sal_uInt16 nBWidth, sal_Bool bRel, USHORT nNumOfRowsToRepeat,
118 sal_uInt16 nLSub, sal_uInt16 nRSub )
119 : SwWriteTable( rLines, nWidth, nBWidth, bRel, MAX_DEPTH, nLSub, nRSub, nNumOfRowsToRepeat )
121 PixelizeBorders();
124 SwHTMLWrtTable::SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo )
125 : SwWriteTable( pLayoutInfo )
127 // Einige Twip-Werte an Pixel-Grenzen anpassen
128 if( bCollectBorderWidth )
129 PixelizeBorders();
132 void SwHTMLWrtTable::Pixelize( sal_uInt16& rValue )
134 if( rValue && Application::GetDefaultDevice() )
136 Size aSz( rValue, 0 );
137 aSz = Application::GetDefaultDevice()->LogicToPixel( aSz, MapMode(MAP_TWIP) );
138 if( !aSz.Width() )
139 aSz.Width() = 1;
140 aSz = Application::GetDefaultDevice()->PixelToLogic( aSz, MapMode(MAP_TWIP) );
141 rValue = (sal_uInt16)aSz.Width();
145 void SwHTMLWrtTable::PixelizeBorders()
147 Pixelize( nBorder );
148 Pixelize( nCellSpacing );
149 Pixelize( nCellPadding );
152 sal_Bool SwHTMLWrtTable::HasTabBackground( const SwTableBox& rBox,
153 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight )
155 ASSERT( bTop || bBottom || bLeft || bRight,
156 "HasTabBackground: darf nicht aufgerufen werden" );
158 sal_Bool bRet = sal_False;
159 if( rBox.GetSttNd() )
161 const SvxBrushItem& rBrushItem =
162 rBox.GetFrmFmt()->GetBackground();
164 /// OD 02.09.2002 #99657#
165 /// The table box has a background, if its background color is not "no fill"/
166 /// "auto fill" or it has a background graphic.
167 bRet = rBrushItem.GetColor() != COL_TRANSPARENT ||
168 rBrushItem.GetGraphicLink() || rBrushItem.GetGraphic();
170 else
172 const SwTableLines& rLines = rBox.GetTabLines();
173 sal_uInt16 nCount = rLines.Count();
174 sal_Bool bLeftRight = bLeft || bRight;
175 for( sal_uInt16 i=0; !bRet && i<nCount; i++ )
177 sal_Bool bT = bTop && 0 == i;
178 sal_Bool bB = bBottom && nCount-1 == i;
179 if( bT || bB || bLeftRight )
180 bRet = HasTabBackground( *rLines[i], bT, bB, bLeft, bRight);
184 return bRet;
187 sal_Bool SwHTMLWrtTable::HasTabBackground( const SwTableLine& rLine,
188 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight )
190 ASSERT( bTop || bBottom || bLeft || bRight,
191 "HasTabBackground: darf nicht aufgerufen werden" );
193 sal_Bool bRet = sal_False;
194 const SvxBrushItem& rBrushItem = rLine.GetFrmFmt()->GetBackground();
195 /// OD 02.09.2002 #99657#
196 /// The table line has a background, if its background color is not "no fill"/
197 /// "auto fill" or it has a background graphic.
198 bRet = rBrushItem.GetColor() != COL_TRANSPARENT ||
199 rBrushItem.GetGraphicLink() || rBrushItem.GetGraphic();
201 if( !bRet )
203 const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
204 sal_uInt16 nCount = rBoxes.Count();
205 sal_Bool bTopBottom = bTop || bBottom;
206 for( sal_uInt16 i=0; !bRet && i<nCount; i++ )
208 sal_Bool bL = bLeft && 0 == i;
209 sal_Bool bR = bRight && nCount-1 == i;
210 if( bTopBottom || bL || bR )
211 bRet = HasTabBackground( *rBoxes[i], bTop, bBottom, bL, bR );
215 return bRet;
218 sal_Bool lcl_WrtHTMLTbl_HasTabBorders( const SwTableLine*& rpLine, void* pPara );
220 sal_Bool lcl_WrtHTMLTbl_HasTabBorders( const SwTableBox*& rpBox, void* pPara )
222 sal_Bool *pBorders = (sal_Bool *)pPara;
223 if( *pBorders )
224 return sal_False;
226 if( !rpBox->GetSttNd() )
228 ((SwTableBox *)rpBox)->GetTabLines().ForEach(
229 &lcl_WrtHTMLTbl_HasTabBorders, pPara );
231 else
233 const SvxBoxItem& rBoxItem =
234 (const SvxBoxItem&)rpBox->GetFrmFmt()->GetFmtAttr( RES_BOX );
236 *pBorders = rBoxItem.GetTop() || rBoxItem.GetBottom() ||
237 rBoxItem.GetLeft() || rBoxItem.GetRight();
240 return !*pBorders;
243 sal_Bool lcl_WrtHTMLTbl_HasTabBorders( const SwTableLine*& rpLine, void* pPara )
245 sal_Bool *pBorders = (sal_Bool *)pPara;
246 if( *pBorders )
247 return sal_False;
249 ((SwTableLine *)rpLine)->GetTabBoxes().ForEach(
250 &lcl_WrtHTMLTbl_HasTabBorders, pPara );
251 return !*pBorders;
255 sal_Bool SwHTMLWrtTable::ShouldExpandSub( const SwTableBox *pBox,
256 sal_Bool bExpandedBefore,
257 sal_uInt16 nDepth ) const
259 sal_Bool bExpand = !pBox->GetSttNd() && nDepth>0;
260 if( bExpand && bExpandedBefore )
262 // MIB 30.6.97: Wenn schon eine Box expandiert wurde, wird eine
263 // weitere nur expandiert, wenn sie Umrandungen besitzt.
264 sal_Bool bBorders = sal_False;
265 lcl_WrtHTMLTbl_HasTabBorders( pBox, &bBorders );
266 if( !bBorders )
267 bBorders = HasTabBackground( *pBox, sal_True, sal_True, sal_True, sal_True );
268 bExpand = bBorders;
271 return bExpand;
275 // Eine Box als einzelne Zelle schreiben
276 void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt,
277 const SwWriteTableCell *pCell,
278 sal_Bool bOutVAlign ) const
280 const SwTableBox *pBox = pCell->GetBox();
281 sal_uInt16 nRow = pCell->GetRow();
282 sal_uInt16 nCol = pCell->GetCol();
283 sal_uInt16 nRowSpan = pCell->GetRowSpan();
284 sal_uInt16 nColSpan = pCell->GetColSpan();
286 if ( !nRowSpan )
287 return;
289 SwWriteTableCol *pCol = aCols[nCol];
291 // sal_Bool bOutWidth = nColSpan>1 || pCol->GetOutWidth();
292 sal_Bool bOutWidth = sal_True; //nColSpan==1 && pCol->GetOutWidth();
294 const SwStartNode* pSttNd = pBox->GetSttNd();
295 sal_Bool bHead = sal_False;
296 if( pSttNd )
298 ULONG nNdPos = pSttNd->GetIndex()+1;
300 // Art der Zelle (TD/TH) bestimmen
301 SwNode* pNd;
302 while( !( pNd = rWrt.pDoc->GetNodes()[nNdPos])->IsEndNode() )
304 if( pNd->IsTxtNode() )
306 // nur Absaetzte betrachten, an denen man was erkennt
307 // Das ist der Fall, wenn die Vorlage eine der Tabellen-Vorlagen
308 // ist oder von einer der beiden abgelitten ist.
309 const SwFmt *pFmt = &((SwTxtNode*)pNd)->GetAnyFmtColl();
310 sal_uInt16 nPoolId = pFmt->GetPoolFmtId();
311 while( !pFmt->IsDefault() &&
312 RES_POOLCOLL_TABLE_HDLN!=nPoolId &&
313 RES_POOLCOLL_TABLE!=nPoolId )
315 pFmt = pFmt->DerivedFrom();
316 nPoolId = pFmt->GetPoolFmtId();
319 if( !pFmt->IsDefault() )
321 bHead = (RES_POOLCOLL_TABLE_HDLN==nPoolId);
322 break;
325 nNdPos++;
329 rWrt.OutNewLine(); // <TH>/<TD> in neue Zeile
330 ByteString sOut( '<' );
331 sOut += (bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata );
333 // ROW- und COLSPAN ausgeben
334 if( nRowSpan>1 )
335 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_rowspan ) += '=')
336 += ByteString::CreateFromInt32( nRowSpan );
337 if( nColSpan > 1 )
338 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_colspan ) += '=')
339 += ByteString::CreateFromInt32( nColSpan );
341 #ifndef PURE_HTML
342 long nWidth = 0;
343 sal_uInt16 nPrcWidth = USHRT_MAX;
344 if( bOutWidth )
346 if( bLayoutExport )
348 if( pCell->HasPrcWidthOpt() )
350 nPrcWidth = pCell->GetWidthOpt();
352 else
354 nWidth = pCell->GetWidthOpt();
355 if( !nWidth )
356 bOutWidth = sal_False;
359 else
361 if( HasRelWidths() )
362 nPrcWidth = (sal_uInt16)GetPrcWidth(nCol,nColSpan);
363 else
364 nWidth = GetAbsWidth( nCol, nColSpan );
368 long nHeight = pCell->GetHeight() > 0
369 ? GetAbsHeight( pCell->GetHeight(), nRow, nRowSpan )
370 : 0;
371 Size aPixelSz( nWidth, nHeight );
373 // WIDTH ausgeben (Grrr: nur fuer Netscape)
374 if( (aPixelSz.Width() || aPixelSz.Height()) && Application::GetDefaultDevice() )
376 Size aOldSz( aPixelSz );
377 aPixelSz = Application::GetDefaultDevice()->LogicToPixel( aPixelSz,
378 MapMode(MAP_TWIP) );
379 if( aOldSz.Width() && !aPixelSz.Width() )
380 aPixelSz.Width() = 1;
381 if( aOldSz.Height() && !aPixelSz.Height() )
382 aPixelSz.Height() = 1;
385 // WIDTH ausgeben: Aus Layout oder berechnet
386 if( bOutWidth )
388 ((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_width ) += '=';
389 if( nPrcWidth != USHRT_MAX )
390 (sOut += ByteString::CreateFromInt32(nPrcWidth)) += '%';
391 else
392 sOut += ByteString::CreateFromInt32(aPixelSz.Width());
393 if( !bLayoutExport && nColSpan==1 )
394 pCol->SetOutWidth( sal_False );
397 if( nHeight )
399 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_height) += '=')
400 += ByteString::CreateFromInt32(aPixelSz.Height());
402 #endif
404 const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
405 const SfxPoolItem *pItem;
407 // ALIGN wird jetzt nur noch an den Absaetzen ausgegeben
409 // VALIGN ausgeben
410 if( bOutVAlign )
412 sal_Int16 eVertOri = pCell->GetVertOri();
413 if( text::VertOrientation::TOP==eVertOri || text::VertOrientation::BOTTOM==eVertOri )
415 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_valign) += '=')
416 += (text::VertOrientation::TOP==eVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom);
420 rWrt.Strm() << sOut.GetBuffer();
421 sOut.Erase();
423 rWrt.bTxtAttr = sal_False;
424 rWrt.bOutOpts = sal_True;
425 const SvxBrushItem *pBrushItem = 0;
426 if( SFX_ITEM_SET==rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
428 pBrushItem = (const SvxBrushItem *)pItem;
430 if( !pBrushItem )
431 pBrushItem = pCell->GetBackground();
433 if( pBrushItem )
435 // Hintergrund ausgeben
436 String aDummy;
437 rWrt.OutBackground( pBrushItem, aDummy, sal_False );
439 if( rWrt.bCfgOutStyles )
440 OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem );
443 sal_uInt32 nNumFmt = 0;
444 double nValue = 0.0;
445 sal_Bool bNumFmt = sal_False, bValue = sal_False;
446 if( SFX_ITEM_SET==rItemSet.GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
448 nNumFmt = ((const SwTblBoxNumFormat *)pItem)->GetValue();
449 bNumFmt = sal_True;
451 if( SFX_ITEM_SET==rItemSet.GetItemState( RES_BOXATR_VALUE, sal_False, &pItem ) )
453 nValue = ((const SwTblBoxValue *)pItem)->GetValue();
454 bValue = sal_True;
455 if( !bNumFmt )
456 nNumFmt = pBox->GetFrmFmt()->GetTblBoxNumFmt().GetValue();
459 if( bNumFmt || bValue )
460 sOut = HTMLOutFuncs::CreateTableDataOptionsValNum( sOut,
461 bValue, nValue, nNumFmt, *rWrt.pDoc->GetNumberFormatter(),
462 rWrt.eDestEnc, &rWrt.aNonConvertableCharacters );
463 sOut += '>';
464 rWrt.Strm() << sOut.GetBuffer();
465 rWrt.bLFPossible = sal_True;
467 rWrt.IncIndentLevel(); // den Inhalt von <TD>...</TD> einruecken
469 if( pSttNd )
471 HTMLSaveData aSaveData( rWrt, pSttNd->GetIndex()+1,
472 pSttNd->EndOfSectionIndex() );
473 rWrt.Out_SwDoc( rWrt.pCurPam );
475 else
477 sal_uInt16 nTWidth, nBWidth, nLSub, nRSub;
478 if( HasRelWidths() )
480 nTWidth = 100;
481 nBWidth = GetRawWidth( nCol, nColSpan );
482 nLSub = 0;
483 nRSub = 0;
485 else
487 nTWidth = GetAbsWidth( nCol, nColSpan );
488 nBWidth = nTWidth;
489 nLSub = GetLeftSpace( nCol );
490 nRSub = GetRightSpace( nCol, nColSpan );
493 SwHTMLWrtTable aTableWrt( pBox->GetTabLines(), nTWidth,
494 nBWidth, HasRelWidths(), nLSub, nRSub );
495 aTableWrt.Write( rWrt );
498 rWrt.DecIndentLevel(); // den Inhalt von <TD>...</TD> einruecken
500 if( rWrt.bLFPossible )
501 rWrt.OutNewLine();
502 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), bHead ? OOO_STRING_SVTOOLS_HTML_tableheader
503 : OOO_STRING_SVTOOLS_HTML_tabledata,
504 sal_False );
505 rWrt.bLFPossible = sal_True;
509 // Eine Line als Zeilen ausgeben
510 void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt,
511 const SwWriteTableCells& rCells,
512 const SvxBrushItem *pBrushItem ) const
514 // Wenn die Zeile mehr als eine Zelle nethaelt und alle Zellen
515 // die gleiche Ausrichtung besitzen, das VALIGN an der Zeile statt der
516 // Zelle ausgeben
517 sal_Int16 eRowVertOri = text::VertOrientation::NONE;
518 if( rCells.Count() > 1 )
520 for( sal_uInt16 nCell = 0; nCell<rCells.Count(); nCell++ )
522 sal_Int16 eCellVertOri = rCells[nCell]->GetVertOri();
523 if( 0==nCell )
525 eRowVertOri = eCellVertOri;
527 else if( eRowVertOri != eCellVertOri )
529 eRowVertOri = text::VertOrientation::NONE;
530 break;
535 rWrt.OutNewLine(); // <TR> in neuer Zeile
536 rWrt.Strm() << '<' << OOO_STRING_SVTOOLS_HTML_tablerow;
537 if( pBrushItem )
539 String aDummy;
540 rWrt.OutBackground( pBrushItem, aDummy, sal_False );
542 rWrt.bTxtAttr = sal_False;
543 rWrt.bOutOpts = sal_True;
544 if( rWrt.bCfgOutStyles )
545 OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem );
548 if( text::VertOrientation::TOP==eRowVertOri || text::VertOrientation::BOTTOM==eRowVertOri )
550 ByteString sOut( ' ' );
551 ((sOut += OOO_STRING_SVTOOLS_HTML_O_valign) += '=')
552 += (text::VertOrientation::TOP==eRowVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom);
553 rWrt.Strm() << sOut.GetBuffer();
556 rWrt.Strm() << '>';
558 rWrt.IncIndentLevel(); // Inhalt von <TR>...</TR> einruecken
560 for( sal_uInt16 nCell = 0; nCell<rCells.Count(); nCell++ )
561 OutTableCell( rWrt, rCells[nCell], text::VertOrientation::NONE==eRowVertOri );
563 rWrt.DecIndentLevel(); // Inhalt von <TR>...</TR> einruecken
565 rWrt.OutNewLine(); // </TR> in neuer Zeile
566 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_tablerow, sal_False );
571 void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign,
572 sal_Bool bTHead, const SwFrmFmt *pFrmFmt,
573 const String *pCaption, sal_Bool bTopCaption,
574 sal_uInt16 nHSpace, sal_uInt16 nVSpace ) const
576 sal_uInt16 nRow;
578 // Wert fuer FRAME bestimmen
579 sal_uInt16 nFrameMask = 15;
580 if( !(aRows[0])->bTopBorder )
581 nFrameMask &= ~1;
582 if( !(aRows[aRows.Count()-1])->bBottomBorder )
583 nFrameMask &= ~2;
584 if( !(aCols[0])->bLeftBorder )
585 nFrameMask &= ~4;
586 if( !(aCols[aCols.Count()-1])->bRightBorder )
587 nFrameMask &= ~8;
589 // Wert fur RULES bestimmen
590 sal_Bool bRowsHaveBorder = sal_False;
591 sal_Bool bRowsHaveBorderOnly = sal_True;
592 SwWriteTableRow *pRow = aRows[0];
593 for( nRow=1; nRow < aRows.Count(); nRow++ )
595 SwWriteTableRow *pNextRow = aRows[nRow];
596 sal_Bool bBorder = ( pRow->bBottomBorder || pNextRow->bTopBorder );
597 bRowsHaveBorder |= bBorder;
598 bRowsHaveBorderOnly &= bBorder;
600 sal_uInt16 nBorder2 = pRow->bBottomBorder ? pRow->nBottomBorder : USHRT_MAX;
601 if( pNextRow->bTopBorder && pNextRow->nTopBorder < nBorder2 )
602 nBorder2 = pNextRow->nTopBorder;
604 pRow->bBottomBorder = bBorder;
605 pRow->nBottomBorder = nBorder2;
607 pNextRow->bTopBorder = bBorder;
608 pNextRow->nTopBorder = nBorder2;
610 pRow = pNextRow;
613 sal_Bool bColsHaveBorder = sal_False;
614 sal_Bool bColsHaveBorderOnly = sal_True;
615 SwWriteTableCol *pCol = aCols[0];
616 sal_uInt16 nCol;
617 for( nCol=1; nCol<aCols.Count(); nCol++ )
619 SwWriteTableCol *pNextCol = aCols[nCol];
620 sal_Bool bBorder = ( pCol->bRightBorder || pNextCol->bLeftBorder );
621 bColsHaveBorder |= bBorder;
622 bColsHaveBorderOnly &= bBorder;
623 pCol->bRightBorder = bBorder;
624 pNextCol->bLeftBorder = bBorder;
625 pCol = pNextCol;
629 // vorhergende Aufzaehlung etc. beenden
630 rWrt.ChangeParaToken( 0 );
632 if( rWrt.bLFPossible )
633 rWrt.OutNewLine(); // <TABLE> in neue Zeile
634 ByteString sOut( '<' );
635 sOut += OOO_STRING_SVTOOLS_HTML_table;
637 sal_uInt16 nOldDirection = rWrt.nDirection;
638 if( pFrmFmt )
639 rWrt.nDirection = rWrt.GetHTMLDirection( pFrmFmt->GetAttrSet() );
640 if( rWrt.bOutFlyFrame || nOldDirection != rWrt.nDirection )
642 rWrt.Strm() << sOut.GetBuffer();
643 sOut.Erase();
644 rWrt.OutDirection( rWrt.nDirection );
647 // COLS ausgeben: Nur bei Export ueber Layout, wenn es beim Import
648 // vorhanden war.
649 if( bColsOption )
650 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=')
651 += ByteString::CreateFromInt32( aCols.Count() );
653 // ALIGN= ausgeben
654 if( text::HoriOrientation::RIGHT == eAlign )
655 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align ) += '=') += OOO_STRING_SVTOOLS_HTML_AL_right;
656 else if( text::HoriOrientation::CENTER == eAlign )
657 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align ) += '=') += OOO_STRING_SVTOOLS_HTML_AL_center;
658 else if( text::HoriOrientation::LEFT == eAlign )
659 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align ) += '=') += OOO_STRING_SVTOOLS_HTML_AL_left;
661 // WIDTH ausgeben: Stammt aus Layout oder ist berechnet
662 if( nTabWidth )
664 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width ) += '=';
665 if( HasRelWidths() )
666 (sOut += ByteString::CreateFromInt32( nTabWidth )) += '%';
667 else if( Application::GetDefaultDevice() )
669 long nPixWidth = Application::GetDefaultDevice()->LogicToPixel(
670 Size(nTabWidth,0), MapMode(MAP_TWIP) ).Width();
671 if( !nPixWidth )
672 nPixWidth = 1;
674 sOut += ByteString::CreateFromInt32( nPixWidth );
676 else
678 ASSERT( Application::GetDefaultDevice(), "kein Application-Window!?" );
679 sOut += "100%";
683 if( (nHSpace || nVSpace) && Application::GetDefaultDevice())
685 Size aPixelSpc =
686 Application::GetDefaultDevice()->LogicToPixel( Size(nHSpace,nVSpace),
687 MapMode(MAP_TWIP) );
688 if( !aPixelSpc.Width() && nHSpace )
689 aPixelSpc.Width() = 1;
690 if( !aPixelSpc.Height() && nVSpace )
691 aPixelSpc.Height() = 1;
693 if( aPixelSpc.Width() )
695 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_hspace) += '=')
696 += ByteString::CreateFromInt32( aPixelSpc.Width() );
699 if( aPixelSpc.Height() )
701 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_vspace) += '=')
702 += ByteString::CreateFromInt32( aPixelSpc.Height() );
706 // BORDER ausgeben, aber nur wenn wir die Umrandung selbst berechnet
707 // haben oder die Umrandung 0 ist oder es irgendwelche Umrandungen gibt.
708 // Anderenfalls enthaelt nBorder naemlich nur die Breite der Umrandung,
709 // die genutzt wird, wenn gar kein sheet::Border angegeben ist.
710 sal_Bool bHasAnyBorders = nFrameMask || bColsHaveBorder || bRowsHaveBorder;
711 if( bCollectBorderWidth || nBorder==0 || bHasAnyBorders )
712 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_border ) += '=')
713 += ByteString::CreateFromInt32( rWrt.ToPixel( nBorder ) );
715 // BORDERCOLOR ausgeben
717 if( (sal_uInt32)-1 != nBorderColor && rWrt.bCfgOutStyles && bHasAnyBorders )
719 ((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_bordercolor ) += '=';
720 rWrt.Strm() << sOut.GetBuffer();
721 HTMLOutFuncs::Out_Color( rWrt.Strm(), nBorderColor, rWrt.eDestEnc );
722 sOut.Erase();
725 // CELLPADDING ausgeben: Stammt aus Layout oder ist berechnet
726 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_cellpadding ) += '=')
727 += ByteString::CreateFromInt32( rWrt.ToPixel( nCellPadding ) );
729 // CELLSPACING ausgeben: Stammt aus Layout oder ist berechnet
730 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_cellspacing ) += '=')
731 += ByteString::CreateFromInt32( rWrt.ToPixel( nCellSpacing ) );
733 // FRAME/RULES ausgeben (nur sinnvoll, wenn border!=0)
734 if( nBorder!=0 && (bCollectBorderWidth || bHasAnyBorders) )
736 const sal_Char *pFrame = 0;
737 switch( nFrameMask )
739 case 0: pFrame = OOO_STRING_SVTOOLS_HTML_TF_void ;break;
740 case 1: pFrame = OOO_STRING_SVTOOLS_HTML_TF_above ;break;
741 case 2: pFrame = OOO_STRING_SVTOOLS_HTML_TF_below ;break;
742 case 3: pFrame = OOO_STRING_SVTOOLS_HTML_TF_hsides ;break;
743 case 4: pFrame = OOO_STRING_SVTOOLS_HTML_TF_lhs ;break;
744 case 8: pFrame = OOO_STRING_SVTOOLS_HTML_TF_rhs ;break;
745 case 12: pFrame = OOO_STRING_SVTOOLS_HTML_TF_vsides ;break;
746 //FRAME=BOX ist der default wenn BORDER>0
747 //case 15:
748 //default: pFrame = OOO_STRING_SVTOOLS_HTML_TF_box ;break; // geht nicht
750 if( pFrame )
751 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_frame ) += '=') += pFrame;
753 const sal_Char *pRules = 0;
754 if( aCols.Count() > 1 && aRows.Count() > 1 )
756 if( !bColsHaveBorder )
758 if( !bRowsHaveBorder )
759 pRules = OOO_STRING_SVTOOLS_HTML_TR_none;
760 else if( bRowsHaveBorderOnly )
761 pRules = OOO_STRING_SVTOOLS_HTML_TR_rows;
762 else
763 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
765 else if( bColsHaveBorderOnly )
767 if( !bRowsHaveBorder || !bRowsHaveBorderOnly )
768 pRules = OOO_STRING_SVTOOLS_HTML_TR_cols;
770 else
772 if( !bRowsHaveBorder )
773 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
774 else if( bRowsHaveBorderOnly )
775 pRules = OOO_STRING_SVTOOLS_HTML_TR_rows;
776 else
777 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
780 else if( aRows.Count() > 1 )
782 if( !bRowsHaveBorder )
783 pRules = OOO_STRING_SVTOOLS_HTML_TR_none;
784 else if( !bRowsHaveBorderOnly )
785 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
787 else if( aCols.Count() > 1 )
789 if( !bColsHaveBorder )
790 pRules = OOO_STRING_SVTOOLS_HTML_TR_none;
791 else if( !bColsHaveBorderOnly )
792 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
795 if( pRules )
796 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_rules ) += '=') += pRules;
798 rWrt.Strm() << sOut.GetBuffer();
800 // Hintergrund ausgeben
801 if( pFrmFmt )
803 String aDummy;
804 rWrt.OutBackground( pFrmFmt->GetAttrSet(), aDummy, sal_False );
806 if( rWrt.bCfgOutStyles && pFrmFmt )
807 rWrt.OutCSS1_TableFrmFmtOptions( *pFrmFmt );
810 sOut = '>';
811 rWrt.Strm() << sOut.GetBuffer();
813 rWrt.IncIndentLevel(); // Inhalte von Table einruecken
815 // Ueberschrift ausgeben
816 if( pCaption && pCaption->Len() )
818 rWrt.OutNewLine(); // <CAPTION> in neue Zeile
819 ByteString sOutStr( OOO_STRING_SVTOOLS_HTML_caption );
820 (((sOutStr += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=')
821 += (bTopCaption ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom);
822 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), sOutStr.GetBuffer(), sal_True );
823 HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption, rWrt.eDestEnc, &rWrt.aNonConvertableCharacters );
824 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_caption, sal_False );
827 sal_uInt16 nCols = aCols.Count();
829 // <COLGRP>/<COL> ausgeben: Bei Export ueber Layout nur wenn beim
830 // Import welche da waren, sonst immer.
831 sal_Bool bColGroups = (bColsHaveBorder && !bColsHaveBorderOnly);
832 if( bColTags )
834 if( bColGroups )
836 rWrt.OutNewLine(); // <COLGRP> in neue Zeile
837 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup, sal_True );
839 rWrt.IncIndentLevel(); // Inhalt von <COLGRP> einruecken
842 for( nCol=0; nCol<nCols; nCol++ )
844 rWrt.OutNewLine(); // <COL> in neue Zeile
846 const SwWriteTableCol *pColumn = aCols[nCol];
848 ByteString sOutStr( '<' );
849 sOutStr += OOO_STRING_SVTOOLS_HTML_col;
851 sal_uInt16 nWidth;
852 sal_Bool bRel;
853 if( bLayoutExport )
855 bRel = pColumn->HasRelWidthOpt();
856 nWidth = pColumn->GetWidthOpt();
858 else
860 bRel = HasRelWidths();
861 nWidth = bRel ? GetRelWidth(nCol,1) : GetAbsWidth(nCol,1);
864 ((sOutStr += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_width ) += '=';
865 if( bRel )
867 (sOutStr += ByteString::CreateFromInt32( nWidth ) ) += '*';
869 else
871 sOutStr += ByteString::CreateFromInt32( rWrt.ToPixel( nWidth ) );
873 sOutStr += '>';
874 rWrt.Strm() << sOutStr.GetBuffer();
876 if( bColGroups && pColumn->bRightBorder && nCol<nCols-1 )
878 rWrt.DecIndentLevel(); // Inhalt von <COLGRP> einruecken
879 rWrt.OutNewLine(); // </COLGRP> in neue Zeile
880 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup,
881 sal_False );
882 rWrt.OutNewLine(); // <COLGRP> in neue Zeile
883 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup,
884 sal_True );
885 rWrt.IncIndentLevel(); // Inhalt von <COLGRP> einruecken
888 if( bColGroups )
890 rWrt.DecIndentLevel(); // Inhalt von <COLGRP> einruecken
892 rWrt.OutNewLine(); // </COLGRP> in neue Zeile
893 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup,
894 sal_False );
898 // die Lines als Tabellenzeilen rausschreiben
900 // <TBODY> ausgeben?
901 sal_Bool bTSections = (bRowsHaveBorder && !bRowsHaveBorderOnly);
902 sal_Bool bTBody = bTSections;
904 // Wenn Sections ausgegeben werden muessen darf ein THEAD um die erste
905 // Zeile nur ausgegeben werden, wenn unter der Zeile eine Linie ist
906 if( bTHead &&
907 (bTSections || bColGroups) &&
908 nHeadEndRow<aRows.Count()-1 && !aRows[nHeadEndRow]->bBottomBorder )
909 bTHead = sal_False;
911 // <TBODY> aus ausgeben, wenn <THEAD> ausgegeben wird.
912 bTSections |= bTHead;
914 if( bTSections )
916 rWrt.OutNewLine(); // <THEAD>/<TDATA> in neue Zeile
917 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
918 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_True );
920 rWrt.IncIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
923 for( nRow = 0; nRow < aRows.Count(); nRow++ )
925 const SwWriteTableRow *pRow2 = aRows[nRow];
927 OutTableCells( rWrt, pRow2->GetCells(), pRow2->GetBackground() );
928 if( !nCellSpacing && nRow < aRows.Count()-1 && pRow2->bBottomBorder &&
929 pRow2->nBottomBorder > DEF_LINE_WIDTH_1 )
931 sal_uInt16 nCnt = (pRow2->nBottomBorder / DEF_LINE_WIDTH_1) - 1;
932 for( ; nCnt; nCnt-- )
934 rWrt.OutNewLine();
935 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_tablerow,
936 sal_True );
937 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_tablerow,
938 sal_False );
941 if( ( (bTHead && nRow==nHeadEndRow) ||
942 (bTBody && pRow2->bBottomBorder) ) &&
943 nRow < aRows.Count()-1 )
945 rWrt.DecIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
946 rWrt.OutNewLine(); // </THEAD>/</TDATA> in neue Zeile
947 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
948 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_False );
949 rWrt.OutNewLine(); // <THEAD>/<TDATA> in neue Zeile
951 if( bTHead && nRow==nHeadEndRow )
952 bTHead = sal_False;
954 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
955 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_True );
956 rWrt.IncIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
960 if( bTSections )
962 rWrt.DecIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
964 rWrt.OutNewLine(); // </THEAD>/</TDATA> in neue Zeile
965 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
966 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_False );
969 rWrt.DecIndentLevel(); // Inhalt von <TABLE> einr.
971 rWrt.OutNewLine(); // </TABLE> in neue Zeile
972 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_table, sal_False );
974 rWrt.nDirection = nOldDirection;
977 Writer& OutHTML_SwTblNode( Writer& rWrt, SwTableNode & rNode,
978 const SwFrmFmt *pFlyFrmFmt,
979 const String *pCaption, sal_Bool bTopCaption )
982 SwTable& rTbl = rNode.GetTable();
984 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
985 rHTMLWrt.bOutTable = sal_True;
987 // die horizontale Ausrichtung des Rahmens hat (falls vorhanden)
988 // Prioritaet. NONE bedeutet, dass keine horizontale
989 // Ausrichtung geschrieben wird.
990 sal_Int16 eFlyHoriOri = text::HoriOrientation::NONE;
991 SwSurround eSurround = SURROUND_NONE;
992 sal_uInt8 nFlyPrcWidth = 0;
993 long nFlyWidth = 0;
994 sal_uInt16 nFlyHSpace = 0;
995 sal_uInt16 nFlyVSpace = 0;
996 if( pFlyFrmFmt )
998 eSurround = pFlyFrmFmt->GetSurround().GetSurround();
999 const SwFmtFrmSize& rFrmSize = pFlyFrmFmt->GetFrmSize();
1000 nFlyPrcWidth = rFrmSize.GetWidthPercent();
1001 nFlyWidth = rFrmSize.GetSize().Width();
1003 eFlyHoriOri = pFlyFrmFmt->GetHoriOrient().GetHoriOrient();
1004 if( text::HoriOrientation::NONE == eFlyHoriOri )
1005 eFlyHoriOri = text::HoriOrientation::LEFT;
1007 const SvxLRSpaceItem& rLRSpace = pFlyFrmFmt->GetLRSpace();
1008 nFlyHSpace = static_cast< sal_uInt16 >((rLRSpace.GetLeft() + rLRSpace.GetRight()) / 2);
1010 const SvxULSpaceItem& rULSpace = pFlyFrmFmt->GetULSpace();
1011 nFlyVSpace = (rULSpace.GetUpper() + rULSpace.GetLower()) / 2;
1014 // ggf. eine FORM oeffnen
1015 sal_Bool bPreserveForm = sal_False;
1016 if( !rHTMLWrt.bPreserveForm )
1018 rHTMLWrt.OutForm( sal_True, &rNode );
1019 bPreserveForm = (rHTMLWrt.pxFormComps && rHTMLWrt.pxFormComps->is() );
1020 rHTMLWrt.bPreserveForm = bPreserveForm;
1023 SwFrmFmt *pFmt = rTbl.GetFrmFmt();
1025 const SwFmtFrmSize& rFrmSize = pFmt->GetFrmSize();
1026 long nWidth = rFrmSize.GetSize().Width();
1027 sal_uInt8 nPrcWidth = rFrmSize.GetWidthPercent();
1028 sal_uInt16 nBaseWidth = (sal_uInt16)nWidth;
1030 sal_Int16 eTabHoriOri = pFmt->GetHoriOrient().GetHoriOrient();
1032 // text::HoriOrientation::NONE und text::HoriOrientation::FULL Tabellen benoetigen relative Breiten
1033 sal_uInt16 nNewDefListLvl = 0;
1034 sal_Bool bRelWidths = sal_False;
1035 sal_Bool bCheckDefList = sal_False;
1036 switch( eTabHoriOri )
1038 case text::HoriOrientation::FULL:
1039 // Tabellen mit automatischer Ausrichtung werden zu Tabellen
1040 // mit 100%-Breite
1041 bRelWidths = sal_True;
1042 nWidth = 100;
1043 eTabHoriOri = text::HoriOrientation::LEFT;
1044 break;
1045 case text::HoriOrientation::NONE:
1047 const SvxLRSpaceItem& aLRItem = pFmt->GetLRSpace();
1048 if( aLRItem.GetRight() )
1050 // Die Tabellenbreite wird anhand des linken und rechten
1051 // Abstandes bestimmt. Deshalb versuchen wir die
1052 // tatsaechliche Breite der Tabelle zu bestimmen. Wenn
1053 // das nicht geht, machen wir eine 100% breite Tabelle
1054 // draus.
1055 nWidth = pFmt->FindLayoutRect(sal_True).Width();
1056 if( !nWidth )
1058 bRelWidths = sal_True;
1059 nWidth = 100;
1063 else if( nPrcWidth )
1065 // Ohne rechten Rand bleibt die %-Breite erhalten
1066 nWidth = nPrcWidth;
1067 bRelWidths = sal_True;
1069 else
1071 // Ohne rechten Rand bleibt auch eine absolute Breite erhalten
1072 // Wir versuchen aber trotzdem ueber das Layout die
1073 // tatsachliche Breite zu ermitteln.
1074 long nRealWidth = pFmt->FindLayoutRect(sal_True).Width();
1075 if( nRealWidth )
1076 nWidth = nRealWidth;
1078 bCheckDefList = sal_True;
1080 break;
1081 case text::HoriOrientation::LEFT_AND_WIDTH:
1082 eTabHoriOri = text::HoriOrientation::LEFT;
1083 bCheckDefList = sal_True;
1084 // no break
1085 default:
1086 // In allen anderen Faellen kann eine absolute oder relative
1087 // Breite direkt uebernommen werden.
1088 if( nPrcWidth )
1090 bRelWidths = sal_True;
1091 nWidth = nPrcWidth;
1093 break;
1096 if( bCheckDefList )
1098 ASSERT( !rHTMLWrt.GetNumInfo().GetNumRule() ||
1099 rHTMLWrt.GetNextNumInfo(),
1100 "NumInfo fuer naechsten Absatz fehlt!" );
1101 const SvxLRSpaceItem& aLRItem = pFmt->GetLRSpace();
1102 if( aLRItem.GetLeft() > 0 && rHTMLWrt.nDefListMargin > 0 &&
1103 ( !rHTMLWrt.GetNumInfo().GetNumRule() ||
1104 ( rHTMLWrt.GetNextNumInfo() &&
1105 (rHTMLWrt.GetNextNumInfo()->IsRestart() ||
1106 rHTMLWrt.GetNumInfo().GetNumRule() !=
1107 rHTMLWrt.GetNextNumInfo()->GetNumRule()) ) ) )
1109 // Wenn der Absatz vor der Tabelle nicht numeriert ist oder
1110 // der Absatz nach der Tabelle mit einer anderen oder
1111 // (gar keiner) Regel numeriert ist, koennen wir
1112 // die Einrueckung ueber eine DL regeln. Sonst behalten wir
1113 // die Einrueckung der Numerierung bei.
1114 nNewDefListLvl = static_cast< sal_uInt16 >(
1115 (aLRItem.GetLeft() + (rHTMLWrt.nDefListMargin/2)) /
1116 rHTMLWrt.nDefListMargin );
1120 if( !pFlyFrmFmt && nNewDefListLvl != rHTMLWrt.nDefListLvl )
1121 rHTMLWrt.OutAndSetDefList( nNewDefListLvl );
1123 if( nNewDefListLvl )
1125 if( rHTMLWrt.bLFPossible )
1126 rHTMLWrt.OutNewLine();
1127 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_dd );
1130 // eFlyHoriOri und eTabHoriOri besitzen nun nur noch die Werte
1131 // LEFT/CENTER und RIGHT!
1132 if( eFlyHoriOri!=text::HoriOrientation::NONE )
1134 eTabHoriOri = eFlyHoriOri;
1135 // MIB 4.7.97: Wenn die Tabelle eine relative Breite besitzt,
1136 // dann richtet sich ihre Breite nach der des Rahmens, also
1137 // exportieren wir dessen Breite. Bei fixer Breite ist die Breite
1138 // der Tabelle massgeblich. Wer Tabellen mit relativer Breite <100%
1139 // in Rahmen steckt, ist selber schuld wenn nix Gutes bei rauskommt.
1140 if( bRelWidths )
1142 nWidth = nFlyPrcWidth ? nFlyPrcWidth : nFlyWidth;
1143 bRelWidths = nFlyPrcWidth > 0;
1147 sal_Int16 eDivHoriOri = text::HoriOrientation::NONE;
1148 switch( eTabHoriOri )
1150 case text::HoriOrientation::LEFT:
1151 // Wenn eine linksbuendigeTabelle keinen rechtsseiigen Durchlauf
1152 // hat, brauchen wir auch kein ALIGN=LEFT in der Tabelle.
1153 if( eSurround==SURROUND_NONE || eSurround==SURROUND_LEFT )
1154 eTabHoriOri = text::HoriOrientation::NONE;
1155 break;
1156 case text::HoriOrientation::RIGHT:
1157 // Aehnliches gilt fuer rechtsbuendigeTabelle, hier nehmen wir
1158 // stattdessen ein <DIV ALIGN=RIGHT>.
1159 if( eSurround==SURROUND_NONE || eSurround==SURROUND_RIGHT )
1161 eDivHoriOri = text::HoriOrientation::RIGHT;
1162 eTabHoriOri = text::HoriOrientation::NONE;
1164 break;
1165 case text::HoriOrientation::CENTER:
1166 // ALIGN=CENTER versteht so gut wie keiner, deshalb verzichten wir
1167 // daruf und nehmen ein <CENTER>.
1168 eDivHoriOri = text::HoriOrientation::CENTER;
1169 eTabHoriOri = text::HoriOrientation::NONE;
1170 break;
1171 default:
1174 if( text::HoriOrientation::NONE==eTabHoriOri )
1175 nFlyHSpace = nFlyVSpace = 0;
1177 if( pFmt->GetName().Len() )
1178 rHTMLWrt.OutImplicitMark( pFmt->GetName(), pMarkToTable );
1180 if( text::HoriOrientation::NONE!=eDivHoriOri )
1182 if( rHTMLWrt.bLFPossible )
1183 rHTMLWrt.OutNewLine(); // <CENTER> in neuer Zeile
1184 if( text::HoriOrientation::CENTER==eDivHoriOri )
1185 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_center, sal_True );
1186 else
1188 ByteString sOut( OOO_STRING_SVTOOLS_HTML_division );
1189 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += OOO_STRING_SVTOOLS_HTML_AL_right;
1190 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), sOut.GetBuffer(),
1191 sal_True );
1193 rHTMLWrt.IncIndentLevel(); // Inhalt von <CENTER> einruecken
1194 rHTMLWrt.bLFPossible = sal_True;
1197 // Wenn die Tabelle in keinem Rahmen ist kann man immer ein LF ausgeben.
1198 if( text::HoriOrientation::NONE==eTabHoriOri )
1199 rHTMLWrt.bLFPossible = sal_True;
1201 const SwHTMLTableLayout *pLayout = rTbl.GetHTMLTableLayout();
1203 #ifndef PRODUCT
1204 ViewShell *pSh;
1205 rWrt.pDoc->GetEditShell( &pSh );
1206 if ( pSh && pSh->GetViewOptions()->IsTest1() )
1207 pLayout = 0;
1208 #endif
1210 if( pLayout && pLayout->IsExportable() )
1212 SwHTMLWrtTable aTableWrt( pLayout );
1213 aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTbl.GetRowsToRepeat() > 0,
1214 pFmt, pCaption, bTopCaption,
1215 nFlyHSpace, nFlyVSpace );
1217 else
1219 SwHTMLWrtTable aTableWrt( rTbl.GetTabLines(), nWidth,
1220 nBaseWidth, bRelWidths, rTbl.GetRowsToRepeat() );
1221 aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTbl.GetRowsToRepeat() > 0,
1222 pFmt, pCaption, bTopCaption,
1223 nFlyHSpace, nFlyVSpace );
1226 // Wenn die Tabelle in keinem Rahmen war kann man immer ein LF ausgeben.
1227 if( text::HoriOrientation::NONE==eTabHoriOri )
1228 rHTMLWrt.bLFPossible = sal_True;
1230 if( text::HoriOrientation::NONE!=eDivHoriOri )
1232 rHTMLWrt.DecIndentLevel(); // Inhalt von <CENTER> einruecken
1233 rHTMLWrt.OutNewLine(); // </CENTER> in neue Teile
1234 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
1235 text::HoriOrientation::CENTER==eDivHoriOri ? OOO_STRING_SVTOOLS_HTML_center
1236 : OOO_STRING_SVTOOLS_HTML_division, sal_False );
1237 rHTMLWrt.bLFPossible = sal_True;
1240 // Pam hinter die Tabelle verschieben
1241 rHTMLWrt.pCurPam->GetPoint()->nNode = *rNode.EndOfSectionNode();
1243 if( bPreserveForm )
1245 rHTMLWrt.bPreserveForm = sal_False;
1246 rHTMLWrt.OutForm( sal_False );
1249 rHTMLWrt.bOutTable = sal_False;
1251 if( rHTMLWrt.GetNextNumInfo() &&
1252 !rHTMLWrt.GetNextNumInfo()->IsRestart() &&
1253 rHTMLWrt.GetNextNumInfo()->GetNumRule() ==
1254 rHTMLWrt.GetNumInfo().GetNumRule() )
1256 // Wenn der Absatz hinter der Tabelle mit der gleichen Regel
1257 // numeriert ist wie der Absatz vor der Tabelle, dann steht in
1258 // der NumInfo des naechsten Absatzes noch die Ebene des Absatzes
1259 // vor der Tabelle. Es muss deshalb die NumInfo noch einmal geholt
1260 // werden um ggf. die Num-Liste noch zu beenden.
1261 rHTMLWrt.ClearNextNumInfo();
1262 rHTMLWrt.FillNextNumInfo();
1263 OutHTML_NumBulListEnd( rHTMLWrt, *rHTMLWrt.GetNextNumInfo() );
1265 return rWrt;