1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27
28 #include <hintids.hxx>
29 #include <vcl/svapp.hxx>
30 #include <svtools/htmlout.hxx>
31 #include <svtools/htmltokn.h>
32 #include <svtools/htmlkywd.hxx>
33 #ifndef _WRKWIN_HXX //autogen
34 #include <vcl/wrkwin.hxx>
35 #endif
36 #include <editeng/ulspitem.hxx>
37 #include <editeng/lrspitem.hxx>
38 #include <editeng/brshitem.hxx>
39 #include <editeng/boxitem.hxx>
40 #include <com/sun/star/form/XFormsSupplier.hpp>
41 #include <com/sun/star/form/XForm.hpp>
42 #include <com/sun/star/form/XImageProducerSupplier.hpp>
43 #include <com/sun/star/form/XFormController.hpp>
44 #include <com/sun/star/container/XContainer.hpp>
45 #include <com/sun/star/container/XIndexContainer.hpp>
46 #include <com/sun/star/container/XSet.hpp>
47 #include <fmtornt.hxx>
48 #include <frmfmt.hxx>
49 #include <fmtfsize.hxx>
50 #include <fmtsrnd.hxx>
51 #include <frmatr.hxx>
52 #include <doc.hxx>
53 #include <pam.hxx>
54 #include <ndtxt.hxx>
55 #include <swrect.hxx>
56 #include <cellatr.hxx>
57 #include <poolfmt.hxx>
58 #include <swtable.hxx>
59 #include <htmltbl.hxx>
60 #include <htmlnum.hxx>
61 #include <wrthtml.hxx>
62 #include <wrtswtbl.hxx>
63 #ifdef DBG_UTIL
64 #ifndef _VIEWSH_HXX
65 #include <viewsh.hxx>
66 #endif
67 #include <viewopt.hxx>
68 #endif
69 #include <sal/types.h>
70
71 //#define MAX_DEPTH (USHRT_MAX)
72 #define MAX_DEPTH (3)
73
74 using namespace ::com::sun::star;
75
76
77 class SwHTMLWrtTable : public SwWriteTable
78 {
79 void Pixelize( sal_uInt16& rValue );
80 void PixelizeBorders();
81
82 void OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell,
83 sal_Bool bOutVAlign ) const;
84
85 void OutTableCells( SwHTMLWriter& rWrt,
86 const SwWriteTableCells& rCells,
87 const SvxBrushItem *pBrushItem ) const;
88
89 virtual sal_Bool ShouldExpandSub( const SwTableBox *pBox,
90 sal_Bool bExpandedBefore, sal_uInt16 nDepth ) const;
91
92 static sal_Bool HasTabBackground( const SwTableLine& rLine,
93 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight );
94 static sal_Bool HasTabBackground( const SwTableBox& rBox,
95 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight );
96
97 public:
98 SwHTMLWrtTable( const SwTableLines& rLines, long nWidth, sal_uInt32 nBWidth,
99 sal_Bool bRel, sal_uInt16 nNumOfRowsToRepeat,
100 sal_uInt16 nLeftSub=0, sal_uInt16 nRightSub=0 );
101 SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo );
102
103 void Write( SwHTMLWriter& rWrt, sal_Int16 eAlign=text::HoriOrientation::NONE,
104 sal_Bool bTHead=sal_False, const SwFrmFmt *pFrmFmt=0,
105 const String *pCaption=0, sal_Bool bTopCaption=sal_False,
106 sal_uInt16 nHSpace=0, sal_uInt16 nVSpace=0 ) const;
107 };
108
109
SwHTMLWrtTable(const SwTableLines & rLines,long nWidth,sal_uInt32 nBWidth,sal_Bool bRel,sal_uInt16 nNumOfRowsToRepeat,sal_uInt16 nLSub,sal_uInt16 nRSub)110 SwHTMLWrtTable::SwHTMLWrtTable( const SwTableLines& rLines, long nWidth,
111 sal_uInt32 nBWidth, sal_Bool bRel, sal_uInt16 nNumOfRowsToRepeat,
112 sal_uInt16 nLSub, sal_uInt16 nRSub )
113 : SwWriteTable( rLines, nWidth, nBWidth, bRel, MAX_DEPTH, nLSub, nRSub, nNumOfRowsToRepeat )
114 {
115 PixelizeBorders();
116 }
117
SwHTMLWrtTable(const SwHTMLTableLayout * pLayoutInfo)118 SwHTMLWrtTable::SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo )
119 : SwWriteTable( pLayoutInfo )
120 {
121 // Einige Twip-Werte an Pixel-Grenzen anpassen
122 if( bCollectBorderWidth )
123 PixelizeBorders();
124 }
125
Pixelize(sal_uInt16 & rValue)126 void SwHTMLWrtTable::Pixelize( sal_uInt16& rValue )
127 {
128 if( rValue && Application::GetDefaultDevice() )
129 {
130 Size aSz( rValue, 0 );
131 aSz = Application::GetDefaultDevice()->LogicToPixel( aSz, MapMode(MAP_TWIP) );
132 if( !aSz.Width() )
133 aSz.Width() = 1;
134 aSz = Application::GetDefaultDevice()->PixelToLogic( aSz, MapMode(MAP_TWIP) );
135 rValue = (sal_uInt16)aSz.Width();
136 }
137 }
138
PixelizeBorders()139 void SwHTMLWrtTable::PixelizeBorders()
140 {
141 Pixelize( nBorder );
142 Pixelize( nCellSpacing );
143 Pixelize( nCellPadding );
144 }
145
HasTabBackground(const SwTableBox & rBox,sal_Bool bTop,sal_Bool bBottom,sal_Bool bLeft,sal_Bool bRight)146 sal_Bool SwHTMLWrtTable::HasTabBackground( const SwTableBox& rBox,
147 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight )
148 {
149 ASSERT( bTop || bBottom || bLeft || bRight,
150 "HasTabBackground: darf nicht aufgerufen werden" );
151
152 sal_Bool bRet = sal_False;
153 if( rBox.GetSttNd() )
154 {
155 const SvxBrushItem& rBrushItem =
156 rBox.GetFrmFmt()->GetBackground();
157
158 /// OD 02.09.2002 #99657#
159 /// The table box has a background, if its background color is not "no fill"/
160 /// "auto fill" or it has a background graphic.
161 bRet = rBrushItem.GetColor() != COL_TRANSPARENT ||
162 rBrushItem.GetGraphicLink() || rBrushItem.GetGraphic();
163 }
164 else
165 {
166 const SwTableLines& rLines = rBox.GetTabLines();
167 sal_uInt16 nCount = rLines.Count();
168 sal_Bool bLeftRight = bLeft || bRight;
169 for( sal_uInt16 i=0; !bRet && i<nCount; i++ )
170 {
171 sal_Bool bT = bTop && 0 == i;
172 sal_Bool bB = bBottom && nCount-1 == i;
173 if( bT || bB || bLeftRight )
174 bRet = HasTabBackground( *rLines[i], bT, bB, bLeft, bRight);
175 }
176 }
177
178 return bRet;
179 }
180
HasTabBackground(const SwTableLine & rLine,sal_Bool bTop,sal_Bool bBottom,sal_Bool bLeft,sal_Bool bRight)181 sal_Bool SwHTMLWrtTable::HasTabBackground( const SwTableLine& rLine,
182 sal_Bool bTop, sal_Bool bBottom, sal_Bool bLeft, sal_Bool bRight )
183 {
184 ASSERT( bTop || bBottom || bLeft || bRight,
185 "HasTabBackground: darf nicht aufgerufen werden" );
186
187 sal_Bool bRet = sal_False;
188 const SvxBrushItem& rBrushItem = rLine.GetFrmFmt()->GetBackground();
189 /// OD 02.09.2002 #99657#
190 /// The table line has a background, if its background color is not "no fill"/
191 /// "auto fill" or it has a background graphic.
192 bRet = rBrushItem.GetColor() != COL_TRANSPARENT ||
193 rBrushItem.GetGraphicLink() || rBrushItem.GetGraphic();
194
195 if( !bRet )
196 {
197 const SwTableBoxes& rBoxes = rLine.GetTabBoxes();
198 sal_uInt16 nCount = rBoxes.Count();
199 sal_Bool bTopBottom = bTop || bBottom;
200 for( sal_uInt16 i=0; !bRet && i<nCount; i++ )
201 {
202 sal_Bool bL = bLeft && 0 == i;
203 sal_Bool bR = bRight && nCount-1 == i;
204 if( bTopBottom || bL || bR )
205 bRet = HasTabBackground( *rBoxes[i], bTop, bBottom, bL, bR );
206 }
207 }
208
209 return bRet;
210 }
211
212 sal_Bool lcl_WrtHTMLTbl_HasTabBorders( const SwTableLine*& rpLine, void* pPara );
213
lcl_WrtHTMLTbl_HasTabBorders(const SwTableBox * & rpBox,void * pPara)214 sal_Bool lcl_WrtHTMLTbl_HasTabBorders( const SwTableBox*& rpBox, void* pPara )
215 {
216 sal_Bool *pBorders = (sal_Bool *)pPara;
217 if( *pBorders )
218 return sal_False;
219
220 if( !rpBox->GetSttNd() )
221 {
222 ((SwTableBox *)rpBox)->GetTabLines().ForEach(
223 &lcl_WrtHTMLTbl_HasTabBorders, pPara );
224 }
225 else
226 {
227 const SvxBoxItem& rBoxItem =
228 (const SvxBoxItem&)rpBox->GetFrmFmt()->GetFmtAttr( RES_BOX );
229
230 *pBorders = rBoxItem.GetTop() || rBoxItem.GetBottom() ||
231 rBoxItem.GetLeft() || rBoxItem.GetRight();
232 }
233
234 return !*pBorders;
235 }
236
lcl_WrtHTMLTbl_HasTabBorders(const SwTableLine * & rpLine,void * pPara)237 sal_Bool lcl_WrtHTMLTbl_HasTabBorders( const SwTableLine*& rpLine, void* pPara )
238 {
239 sal_Bool *pBorders = (sal_Bool *)pPara;
240 if( *pBorders )
241 return sal_False;
242
243 ((SwTableLine *)rpLine)->GetTabBoxes().ForEach(
244 &lcl_WrtHTMLTbl_HasTabBorders, pPara );
245 return !*pBorders;
246 }
247
248
ShouldExpandSub(const SwTableBox * pBox,sal_Bool bExpandedBefore,sal_uInt16 nDepth) const249 sal_Bool SwHTMLWrtTable::ShouldExpandSub( const SwTableBox *pBox,
250 sal_Bool bExpandedBefore,
251 sal_uInt16 nDepth ) const
252 {
253 sal_Bool bExpand = !pBox->GetSttNd() && nDepth>0;
254 if( bExpand && bExpandedBefore )
255 {
256 // MIB 30.6.97: Wenn schon eine Box expandiert wurde, wird eine
257 // weitere nur expandiert, wenn sie Umrandungen besitzt.
258 sal_Bool bBorders = sal_False;
259 lcl_WrtHTMLTbl_HasTabBorders( pBox, &bBorders );
260 if( !bBorders )
261 bBorders = HasTabBackground( *pBox, sal_True, sal_True, sal_True, sal_True );
262 bExpand = bBorders;
263 }
264
265 return bExpand;
266 }
267
268
269 // Eine Box als einzelne Zelle schreiben
OutTableCell(SwHTMLWriter & rWrt,const SwWriteTableCell * pCell,sal_Bool bOutVAlign) const270 void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt,
271 const SwWriteTableCell *pCell,
272 sal_Bool bOutVAlign ) const
273 {
274 const SwTableBox *pBox = pCell->GetBox();
275 sal_uInt16 nRow = pCell->GetRow();
276 sal_uInt16 nCol = pCell->GetCol();
277 sal_uInt16 nRowSpan = pCell->GetRowSpan();
278 sal_uInt16 nColSpan = pCell->GetColSpan();
279
280 if ( !nRowSpan )
281 return;
282
283 SwWriteTableCol *pCol = aCols[nCol];
284
285 // sal_Bool bOutWidth = nColSpan>1 || pCol->GetOutWidth();
286 sal_Bool bOutWidth = sal_True; //nColSpan==1 && pCol->GetOutWidth();
287
288 const SwStartNode* pSttNd = pBox->GetSttNd();
289 sal_Bool bHead = sal_False;
290 if( pSttNd )
291 {
292 sal_uLong nNdPos = pSttNd->GetIndex()+1;
293
294 // Art der Zelle (TD/TH) bestimmen
295 SwNode* pNd;
296 while( !( pNd = rWrt.pDoc->GetNodes()[nNdPos])->IsEndNode() )
297 {
298 if( pNd->IsTxtNode() )
299 {
300 // nur Absaetzte betrachten, an denen man was erkennt
301 // Das ist der Fall, wenn die Vorlage eine der Tabellen-Vorlagen
302 // ist oder von einer der beiden abgelitten ist.
303 const SwFmt *pFmt = &((SwTxtNode*)pNd)->GetAnyFmtColl();
304 sal_uInt16 nPoolId = pFmt->GetPoolFmtId();
305 while( !pFmt->IsDefault() &&
306 RES_POOLCOLL_TABLE_HDLN!=nPoolId &&
307 RES_POOLCOLL_TABLE!=nPoolId )
308 {
309 pFmt = pFmt->DerivedFrom();
310 nPoolId = pFmt->GetPoolFmtId();
311 }
312
313 if( !pFmt->IsDefault() )
314 {
315 bHead = (RES_POOLCOLL_TABLE_HDLN==nPoolId);
316 break;
317 }
318 }
319 nNdPos++;
320 }
321 }
322
323 rWrt.OutNewLine(); // <TH>/<TD> in neue Zeile
324 ByteString sOut( '<' );
325 sOut += (bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata );
326
327 // ROW- und COLSPAN ausgeben
328 if( nRowSpan>1 )
329 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_rowspan ) += '=')
330 += ByteString::CreateFromInt32( nRowSpan );
331 if( nColSpan > 1 )
332 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_colspan ) += '=')
333 += ByteString::CreateFromInt32( nColSpan );
334
335 #ifndef PURE_HTML
336 long nWidth = 0;
337 sal_uInt32 nPrcWidth = USHRT_MAX;
338 if( bOutWidth )
339 {
340 if( bLayoutExport )
341 {
342 if( pCell->HasPrcWidthOpt() )
343 {
344 nPrcWidth = pCell->GetWidthOpt();
345 }
346 else
347 {
348 nWidth = pCell->GetWidthOpt();
349 if( !nWidth )
350 bOutWidth = sal_False;
351 }
352 }
353 else
354 {
355 if( HasRelWidths() )
356 nPrcWidth = (sal_uInt16)GetPrcWidth(nCol,nColSpan);
357 else
358 nWidth = GetAbsWidth( nCol, nColSpan );
359 }
360 }
361
362 long nHeight = pCell->GetHeight() > 0
363 ? GetAbsHeight( pCell->GetHeight(), nRow, nRowSpan )
364 : 0;
365 Size aPixelSz( nWidth, nHeight );
366
367 // WIDTH ausgeben (Grrr: nur fuer Netscape)
368 if( (aPixelSz.Width() || aPixelSz.Height()) && Application::GetDefaultDevice() )
369 {
370 Size aOldSz( aPixelSz );
371 aPixelSz = Application::GetDefaultDevice()->LogicToPixel( aPixelSz,
372 MapMode(MAP_TWIP) );
373 if( aOldSz.Width() && !aPixelSz.Width() )
374 aPixelSz.Width() = 1;
375 if( aOldSz.Height() && !aPixelSz.Height() )
376 aPixelSz.Height() = 1;
377 }
378
379 // WIDTH ausgeben: Aus Layout oder berechnet
380 if( bOutWidth )
381 {
382 ((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_width ) += '=';
383 if( nPrcWidth != USHRT_MAX )
384 (sOut += ByteString::CreateFromInt32(nPrcWidth)) += '%';
385 else
386 sOut += ByteString::CreateFromInt32(aPixelSz.Width());
387 if( !bLayoutExport && nColSpan==1 )
388 pCol->SetOutWidth( sal_False );
389 }
390
391 if( nHeight )
392 {
393 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_height) += '=')
394 += ByteString::CreateFromInt32(aPixelSz.Height());
395 }
396 #endif
397
398 const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
399 const SfxPoolItem *pItem;
400
401 // ALIGN wird jetzt nur noch an den Absaetzen ausgegeben
402
403 // VALIGN ausgeben
404 if( bOutVAlign )
405 {
406 sal_Int16 eVertOri = pCell->GetVertOri();
407 if( text::VertOrientation::TOP==eVertOri || text::VertOrientation::BOTTOM==eVertOri )
408 {
409 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_valign) += '=')
410 += (text::VertOrientation::TOP==eVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom);
411 }
412 }
413
414 rWrt.Strm() << sOut.GetBuffer();
415 sOut.Erase();
416
417 rWrt.bTxtAttr = sal_False;
418 rWrt.bOutOpts = sal_True;
419 const SvxBrushItem *pBrushItem = 0;
420 if( SFX_ITEM_SET==rItemSet.GetItemState( RES_BACKGROUND, sal_False, &pItem ) )
421 {
422 pBrushItem = (const SvxBrushItem *)pItem;
423 }
424 if( !pBrushItem )
425 pBrushItem = pCell->GetBackground();
426
427 if( pBrushItem )
428 {
429 // Hintergrund ausgeben
430 String aDummy;
431 rWrt.OutBackground( pBrushItem, aDummy, sal_False );
432
433 if( rWrt.bCfgOutStyles )
434 OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem );
435 }
436
437 sal_uInt32 nNumFmt = 0;
438 double nValue = 0.0;
439 sal_Bool bNumFmt = sal_False, bValue = sal_False;
440 if( SFX_ITEM_SET==rItemSet.GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
441 {
442 nNumFmt = ((const SwTblBoxNumFormat *)pItem)->GetValue();
443 bNumFmt = sal_True;
444 }
445 if( SFX_ITEM_SET==rItemSet.GetItemState( RES_BOXATR_VALUE, sal_False, &pItem ) )
446 {
447 nValue = ((const SwTblBoxValue *)pItem)->GetValue();
448 bValue = sal_True;
449 if( !bNumFmt )
450 nNumFmt = pBox->GetFrmFmt()->GetTblBoxNumFmt().GetValue();
451 }
452
453 if( bNumFmt || bValue )
454 sOut = HTMLOutFuncs::CreateTableDataOptionsValNum( sOut,
455 bValue, nValue, nNumFmt, *rWrt.pDoc->GetNumberFormatter(),
456 rWrt.eDestEnc, &rWrt.aNonConvertableCharacters );
457 sOut += '>';
458 rWrt.Strm() << sOut.GetBuffer();
459 rWrt.bLFPossible = sal_True;
460
461 rWrt.IncIndentLevel(); // den Inhalt von <TD>...</TD> einruecken
462
463 if( pSttNd )
464 {
465 HTMLSaveData aSaveData( rWrt, pSttNd->GetIndex()+1,
466 pSttNd->EndOfSectionIndex() );
467 rWrt.Out_SwDoc( rWrt.pCurPam );
468 }
469 else
470 {
471 sal_uInt16 nTWidth;
472 sal_uInt32 nBWidth;
473 sal_uInt16 nLSub, nRSub;
474 if( HasRelWidths() )
475 {
476 nTWidth = 100;
477 nBWidth = GetRawWidth( nCol, nColSpan );
478 nLSub = 0;
479 nRSub = 0;
480 }
481 else
482 {
483 nTWidth = GetAbsWidth( nCol, nColSpan );
484 nBWidth = nTWidth;
485 nLSub = GetLeftSpace( nCol );
486 nRSub = GetRightSpace( nCol, nColSpan );
487 }
488
489 SwHTMLWrtTable aTableWrt( pBox->GetTabLines(), nTWidth,
490 nBWidth, HasRelWidths(), nLSub, nRSub );
491 aTableWrt.Write( rWrt );
492 }
493
494 rWrt.DecIndentLevel(); // den Inhalt von <TD>...</TD> einruecken
495
496 if( rWrt.bLFPossible )
497 rWrt.OutNewLine();
498 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), bHead ? OOO_STRING_SVTOOLS_HTML_tableheader
499 : OOO_STRING_SVTOOLS_HTML_tabledata,
500 sal_False );
501 rWrt.bLFPossible = sal_True;
502 }
503
504
505 // Eine Line als Zeilen ausgeben
OutTableCells(SwHTMLWriter & rWrt,const SwWriteTableCells & rCells,const SvxBrushItem * pBrushItem) const506 void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt,
507 const SwWriteTableCells& rCells,
508 const SvxBrushItem *pBrushItem ) const
509 {
510 // Wenn die Zeile mehr als eine Zelle nethaelt und alle Zellen
511 // die gleiche Ausrichtung besitzen, das VALIGN an der Zeile statt der
512 // Zelle ausgeben
513 sal_Int16 eRowVertOri = text::VertOrientation::NONE;
514 if( rCells.Count() > 1 )
515 {
516 for( sal_uInt16 nCell = 0; nCell<rCells.Count(); nCell++ )
517 {
518 sal_Int16 eCellVertOri = rCells[nCell]->GetVertOri();
519 if( 0==nCell )
520 {
521 eRowVertOri = eCellVertOri;
522 }
523 else if( eRowVertOri != eCellVertOri )
524 {
525 eRowVertOri = text::VertOrientation::NONE;
526 break;
527 }
528 }
529 }
530
531 rWrt.OutNewLine(); // <TR> in neuer Zeile
532 rWrt.Strm() << '<' << OOO_STRING_SVTOOLS_HTML_tablerow;
533 if( pBrushItem )
534 {
535 String aDummy;
536 rWrt.OutBackground( pBrushItem, aDummy, sal_False );
537
538 rWrt.bTxtAttr = sal_False;
539 rWrt.bOutOpts = sal_True;
540 if( rWrt.bCfgOutStyles )
541 OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem );
542 }
543
544 if( text::VertOrientation::TOP==eRowVertOri || text::VertOrientation::BOTTOM==eRowVertOri )
545 {
546 ByteString sOut( ' ' );
547 ((sOut += OOO_STRING_SVTOOLS_HTML_O_valign) += '=')
548 += (text::VertOrientation::TOP==eRowVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom);
549 rWrt.Strm() << sOut.GetBuffer();
550 }
551
552 rWrt.Strm() << '>';
553
554 rWrt.IncIndentLevel(); // Inhalt von <TR>...</TR> einruecken
555
556 for( sal_uInt16 nCell = 0; nCell<rCells.Count(); nCell++ )
557 OutTableCell( rWrt, rCells[nCell], text::VertOrientation::NONE==eRowVertOri );
558
559 rWrt.DecIndentLevel(); // Inhalt von <TR>...</TR> einruecken
560
561 rWrt.OutNewLine(); // </TR> in neuer Zeile
562 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_tablerow, sal_False );
563 }
564
565
566
Write(SwHTMLWriter & rWrt,sal_Int16 eAlign,sal_Bool bTHead,const SwFrmFmt * pFrmFmt,const String * pCaption,sal_Bool bTopCaption,sal_uInt16 nHSpace,sal_uInt16 nVSpace) const567 void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign,
568 sal_Bool bTHead, const SwFrmFmt *pFrmFmt,
569 const String *pCaption, sal_Bool bTopCaption,
570 sal_uInt16 nHSpace, sal_uInt16 nVSpace ) const
571 {
572 sal_uInt16 nRow;
573
574 // Wert fuer FRAME bestimmen
575 sal_uInt16 nFrameMask = 15;
576 if( !(aRows[0])->bTopBorder )
577 nFrameMask &= ~1;
578 if( !(aRows[aRows.Count()-1])->bBottomBorder )
579 nFrameMask &= ~2;
580 if( !(aCols[0])->bLeftBorder )
581 nFrameMask &= ~4;
582 if( !(aCols[aCols.Count()-1])->bRightBorder )
583 nFrameMask &= ~8;
584
585 // Wert fur RULES bestimmen
586 sal_Bool bRowsHaveBorder = sal_False;
587 sal_Bool bRowsHaveBorderOnly = sal_True;
588 SwWriteTableRow *pRow = aRows[0];
589 for( nRow=1; nRow < aRows.Count(); nRow++ )
590 {
591 SwWriteTableRow *pNextRow = aRows[nRow];
592 sal_Bool bBorder = ( pRow->bBottomBorder || pNextRow->bTopBorder );
593 bRowsHaveBorder |= bBorder;
594 bRowsHaveBorderOnly &= bBorder;
595
596 sal_uInt16 nBorder2 = pRow->bBottomBorder ? pRow->nBottomBorder : USHRT_MAX;
597 if( pNextRow->bTopBorder && pNextRow->nTopBorder < nBorder2 )
598 nBorder2 = pNextRow->nTopBorder;
599
600 pRow->bBottomBorder = bBorder;
601 pRow->nBottomBorder = nBorder2;
602
603 pNextRow->bTopBorder = bBorder;
604 pNextRow->nTopBorder = nBorder2;
605
606 pRow = pNextRow;
607 }
608
609 sal_Bool bColsHaveBorder = sal_False;
610 sal_Bool bColsHaveBorderOnly = sal_True;
611 SwWriteTableCol *pCol = aCols[0];
612 sal_uInt16 nCol;
613 for( nCol=1; nCol<aCols.Count(); nCol++ )
614 {
615 SwWriteTableCol *pNextCol = aCols[nCol];
616 sal_Bool bBorder = ( pCol->bRightBorder || pNextCol->bLeftBorder );
617 bColsHaveBorder |= bBorder;
618 bColsHaveBorderOnly &= bBorder;
619 pCol->bRightBorder = bBorder;
620 pNextCol->bLeftBorder = bBorder;
621 pCol = pNextCol;
622 }
623
624
625 // vorhergende Aufzaehlung etc. beenden
626 rWrt.ChangeParaToken( 0 );
627
628 if( rWrt.bLFPossible )
629 rWrt.OutNewLine(); // <TABLE> in neue Zeile
630 ByteString sOut( '<' );
631 sOut += OOO_STRING_SVTOOLS_HTML_table;
632
633 sal_uInt16 nOldDirection = rWrt.nDirection;
634 if( pFrmFmt )
635 rWrt.nDirection = rWrt.GetHTMLDirection( pFrmFmt->GetAttrSet() );
636 if( rWrt.bOutFlyFrame || nOldDirection != rWrt.nDirection )
637 {
638 rWrt.Strm() << sOut.GetBuffer();
639 sOut.Erase();
640 rWrt.OutDirection( rWrt.nDirection );
641 }
642
643 // COLS ausgeben: Nur bei Export ueber Layout, wenn es beim Import
644 // vorhanden war.
645 if( bColsOption )
646 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_cols) += '=')
647 += ByteString::CreateFromInt32( aCols.Count() );
648
649 // ALIGN= ausgeben
650 if( text::HoriOrientation::RIGHT == eAlign )
651 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align ) += '=') += OOO_STRING_SVTOOLS_HTML_AL_right;
652 else if( text::HoriOrientation::CENTER == eAlign )
653 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align ) += '=') += OOO_STRING_SVTOOLS_HTML_AL_center;
654 else if( text::HoriOrientation::LEFT == eAlign )
655 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align ) += '=') += OOO_STRING_SVTOOLS_HTML_AL_left;
656
657 // WIDTH ausgeben: Stammt aus Layout oder ist berechnet
658 if( nTabWidth )
659 {
660 ((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_width ) += '=';
661 if( HasRelWidths() )
662 (sOut += ByteString::CreateFromInt32( nTabWidth )) += '%';
663 else if( Application::GetDefaultDevice() )
664 {
665 long nPixWidth = Application::GetDefaultDevice()->LogicToPixel(
666 Size(nTabWidth,0), MapMode(MAP_TWIP) ).Width();
667 if( !nPixWidth )
668 nPixWidth = 1;
669
670 sOut += ByteString::CreateFromInt32( nPixWidth );
671 }
672 else
673 {
674 ASSERT( Application::GetDefaultDevice(), "kein Application-Window!?" );
675 sOut += "100%";
676 }
677 }
678
679 if( (nHSpace || nVSpace) && Application::GetDefaultDevice())
680 {
681 Size aPixelSpc =
682 Application::GetDefaultDevice()->LogicToPixel( Size(nHSpace,nVSpace),
683 MapMode(MAP_TWIP) );
684 if( !aPixelSpc.Width() && nHSpace )
685 aPixelSpc.Width() = 1;
686 if( !aPixelSpc.Height() && nVSpace )
687 aPixelSpc.Height() = 1;
688
689 if( aPixelSpc.Width() )
690 {
691 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_hspace) += '=')
692 += ByteString::CreateFromInt32( aPixelSpc.Width() );
693 }
694
695 if( aPixelSpc.Height() )
696 {
697 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_vspace) += '=')
698 += ByteString::CreateFromInt32( aPixelSpc.Height() );
699 }
700 }
701
702 // BORDER ausgeben, aber nur wenn wir die Umrandung selbst berechnet
703 // haben oder die Umrandung 0 ist oder es irgendwelche Umrandungen gibt.
704 // Anderenfalls enthaelt nBorder naemlich nur die Breite der Umrandung,
705 // die genutzt wird, wenn gar kein sheet::Border angegeben ist.
706 sal_Bool bHasAnyBorders = nFrameMask || bColsHaveBorder || bRowsHaveBorder;
707 if( bCollectBorderWidth || nBorder==0 || bHasAnyBorders )
708 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_border ) += '=')
709 += ByteString::CreateFromInt32( rWrt.ToPixel( nBorder ) );
710
711 // BORDERCOLOR ausgeben
712
713 if( (sal_uInt32)-1 != nBorderColor && rWrt.bCfgOutStyles && bHasAnyBorders )
714 {
715 ((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_bordercolor ) += '=';
716 rWrt.Strm() << sOut.GetBuffer();
717 HTMLOutFuncs::Out_Color( rWrt.Strm(), nBorderColor, rWrt.eDestEnc );
718 sOut.Erase();
719 }
720
721 // CELLPADDING ausgeben: Stammt aus Layout oder ist berechnet
722 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_cellpadding ) += '=')
723 += ByteString::CreateFromInt32( rWrt.ToPixel( nCellPadding ) );
724
725 // CELLSPACING ausgeben: Stammt aus Layout oder ist berechnet
726 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_cellspacing ) += '=')
727 += ByteString::CreateFromInt32( rWrt.ToPixel( nCellSpacing ) );
728
729 // FRAME/RULES ausgeben (nur sinnvoll, wenn border!=0)
730 if( nBorder!=0 && (bCollectBorderWidth || bHasAnyBorders) )
731 {
732 const sal_Char *pFrame = 0;
733 switch( nFrameMask )
734 {
735 case 0: pFrame = OOO_STRING_SVTOOLS_HTML_TF_void ;break;
736 case 1: pFrame = OOO_STRING_SVTOOLS_HTML_TF_above ;break;
737 case 2: pFrame = OOO_STRING_SVTOOLS_HTML_TF_below ;break;
738 case 3: pFrame = OOO_STRING_SVTOOLS_HTML_TF_hsides ;break;
739 case 4: pFrame = OOO_STRING_SVTOOLS_HTML_TF_lhs ;break;
740 case 8: pFrame = OOO_STRING_SVTOOLS_HTML_TF_rhs ;break;
741 case 12: pFrame = OOO_STRING_SVTOOLS_HTML_TF_vsides ;break;
742 //FRAME=BOX ist der default wenn BORDER>0
743 //case 15:
744 //default: pFrame = OOO_STRING_SVTOOLS_HTML_TF_box ;break; // geht nicht
745 };
746 if( pFrame )
747 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_frame ) += '=') += pFrame;
748
749 const sal_Char *pRules = 0;
750 if( aCols.Count() > 1 && aRows.Count() > 1 )
751 {
752 if( !bColsHaveBorder )
753 {
754 if( !bRowsHaveBorder )
755 pRules = OOO_STRING_SVTOOLS_HTML_TR_none;
756 else if( bRowsHaveBorderOnly )
757 pRules = OOO_STRING_SVTOOLS_HTML_TR_rows;
758 else
759 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
760 }
761 else if( bColsHaveBorderOnly )
762 {
763 if( !bRowsHaveBorder || !bRowsHaveBorderOnly )
764 pRules = OOO_STRING_SVTOOLS_HTML_TR_cols;
765 }
766 else
767 {
768 if( !bRowsHaveBorder )
769 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
770 else if( bRowsHaveBorderOnly )
771 pRules = OOO_STRING_SVTOOLS_HTML_TR_rows;
772 else
773 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
774 }
775 }
776 else if( aRows.Count() > 1 )
777 {
778 if( !bRowsHaveBorder )
779 pRules = OOO_STRING_SVTOOLS_HTML_TR_none;
780 else if( !bRowsHaveBorderOnly )
781 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
782 }
783 else if( aCols.Count() > 1 )
784 {
785 if( !bColsHaveBorder )
786 pRules = OOO_STRING_SVTOOLS_HTML_TR_none;
787 else if( !bColsHaveBorderOnly )
788 pRules = OOO_STRING_SVTOOLS_HTML_TR_groups;
789 }
790
791 if( pRules )
792 (((sOut += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_rules ) += '=') += pRules;
793 }
794 rWrt.Strm() << sOut.GetBuffer();
795
796 // Hintergrund ausgeben
797 if( pFrmFmt )
798 {
799 String aDummy;
800 rWrt.OutBackground( pFrmFmt->GetAttrSet(), aDummy, sal_False );
801
802 if( rWrt.bCfgOutStyles && pFrmFmt )
803 rWrt.OutCSS1_TableFrmFmtOptions( *pFrmFmt );
804 }
805
806 sOut = '>';
807 rWrt.Strm() << sOut.GetBuffer();
808
809 rWrt.IncIndentLevel(); // Inhalte von Table einruecken
810
811 // Ueberschrift ausgeben
812 if( pCaption && pCaption->Len() )
813 {
814 rWrt.OutNewLine(); // <CAPTION> in neue Zeile
815 ByteString sOutStr( OOO_STRING_SVTOOLS_HTML_caption );
816 (((sOutStr += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=')
817 += (bTopCaption ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom);
818 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), sOutStr.GetBuffer(), sal_True );
819 HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption, rWrt.eDestEnc, &rWrt.aNonConvertableCharacters );
820 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_caption, sal_False );
821 }
822
823 sal_uInt16 nCols = aCols.Count();
824
825 // <COLGRP>/<COL> ausgeben: Bei Export ueber Layout nur wenn beim
826 // Import welche da waren, sonst immer.
827 sal_Bool bColGroups = (bColsHaveBorder && !bColsHaveBorderOnly);
828 if( bColTags )
829 {
830 if( bColGroups )
831 {
832 rWrt.OutNewLine(); // <COLGRP> in neue Zeile
833 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup, sal_True );
834
835 rWrt.IncIndentLevel(); // Inhalt von <COLGRP> einruecken
836 }
837
838 for( nCol=0; nCol<nCols; nCol++ )
839 {
840 rWrt.OutNewLine(); // <COL> in neue Zeile
841
842 const SwWriteTableCol *pColumn = aCols[nCol];
843
844 ByteString sOutStr( '<' );
845 sOutStr += OOO_STRING_SVTOOLS_HTML_col;
846
847 sal_uInt32 nWidth;
848 sal_Bool bRel;
849 if( bLayoutExport )
850 {
851 bRel = pColumn->HasRelWidthOpt();
852 nWidth = pColumn->GetWidthOpt();
853 }
854 else
855 {
856 bRel = HasRelWidths();
857 nWidth = bRel ? GetRelWidth(nCol,1) : GetAbsWidth(nCol,1);
858 }
859
860 ((sOutStr += ' ' ) += OOO_STRING_SVTOOLS_HTML_O_width ) += '=';
861 if( bRel )
862 {
863 (sOutStr += ByteString::CreateFromInt32( nWidth ) ) += '*';
864 }
865 else
866 {
867 sOutStr += ByteString::CreateFromInt32( rWrt.ToPixel( nWidth ) );
868 }
869 sOutStr += '>';
870 rWrt.Strm() << sOutStr.GetBuffer();
871
872 if( bColGroups && pColumn->bRightBorder && nCol<nCols-1 )
873 {
874 rWrt.DecIndentLevel(); // Inhalt von <COLGRP> einruecken
875 rWrt.OutNewLine(); // </COLGRP> in neue Zeile
876 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup,
877 sal_False );
878 rWrt.OutNewLine(); // <COLGRP> in neue Zeile
879 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup,
880 sal_True );
881 rWrt.IncIndentLevel(); // Inhalt von <COLGRP> einruecken
882 }
883 }
884 if( bColGroups )
885 {
886 rWrt.DecIndentLevel(); // Inhalt von <COLGRP> einruecken
887
888 rWrt.OutNewLine(); // </COLGRP> in neue Zeile
889 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_colgroup,
890 sal_False );
891 }
892 }
893
894 // die Lines als Tabellenzeilen rausschreiben
895
896 // <TBODY> ausgeben?
897 sal_Bool bTSections = (bRowsHaveBorder && !bRowsHaveBorderOnly);
898 sal_Bool bTBody = bTSections;
899
900 // Wenn Sections ausgegeben werden muessen darf ein THEAD um die erste
901 // Zeile nur ausgegeben werden, wenn unter der Zeile eine Linie ist
902 if( bTHead &&
903 (bTSections || bColGroups) &&
904 nHeadEndRow<aRows.Count()-1 && !aRows[nHeadEndRow]->bBottomBorder )
905 bTHead = sal_False;
906
907 // <TBODY> aus ausgeben, wenn <THEAD> ausgegeben wird.
908 bTSections |= bTHead;
909
910 if( bTSections )
911 {
912 rWrt.OutNewLine(); // <THEAD>/<TDATA> in neue Zeile
913 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
914 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_True );
915
916 rWrt.IncIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
917 }
918
919 for( nRow = 0; nRow < aRows.Count(); nRow++ )
920 {
921 const SwWriteTableRow *pRow2 = aRows[nRow];
922
923 OutTableCells( rWrt, pRow2->GetCells(), pRow2->GetBackground() );
924 if( !nCellSpacing && nRow < aRows.Count()-1 && pRow2->bBottomBorder &&
925 pRow2->nBottomBorder > DEF_LINE_WIDTH_1 )
926 {
927 sal_uInt16 nCnt = (pRow2->nBottomBorder / DEF_LINE_WIDTH_1) - 1;
928 for( ; nCnt; nCnt-- )
929 {
930 rWrt.OutNewLine();
931 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_tablerow,
932 sal_True );
933 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_tablerow,
934 sal_False );
935 }
936 }
937 if( ( (bTHead && nRow==nHeadEndRow) ||
938 (bTBody && pRow2->bBottomBorder) ) &&
939 nRow < aRows.Count()-1 )
940 {
941 rWrt.DecIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
942 rWrt.OutNewLine(); // </THEAD>/</TDATA> in neue Zeile
943 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
944 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_False );
945 rWrt.OutNewLine(); // <THEAD>/<TDATA> in neue Zeile
946
947 if( bTHead && nRow==nHeadEndRow )
948 bTHead = sal_False;
949
950 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
951 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_True );
952 rWrt.IncIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
953 }
954 }
955
956 if( bTSections )
957 {
958 rWrt.DecIndentLevel(); // Inhalt von <THEAD>/<TDATA> einr.
959
960 rWrt.OutNewLine(); // </THEAD>/</TDATA> in neue Zeile
961 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
962 bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody, sal_False );
963 }
964
965 rWrt.DecIndentLevel(); // Inhalt von <TABLE> einr.
966
967 rWrt.OutNewLine(); // </TABLE> in neue Zeile
968 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_table, sal_False );
969
970 rWrt.nDirection = nOldDirection;
971 }
972
OutHTML_SwTblNode(Writer & rWrt,SwTableNode & rNode,const SwFrmFmt * pFlyFrmFmt,const String * pCaption,sal_Bool bTopCaption)973 Writer& OutHTML_SwTblNode( Writer& rWrt, SwTableNode & rNode,
974 const SwFrmFmt *pFlyFrmFmt,
975 const String *pCaption, sal_Bool bTopCaption )
976 {
977
978 SwTable& rTbl = rNode.GetTable();
979
980 SwHTMLWriter & rHTMLWrt = (SwHTMLWriter&)rWrt;
981 rHTMLWrt.bOutTable = sal_True;
982
983 // die horizontale Ausrichtung des Rahmens hat (falls vorhanden)
984 // Prioritaet. NONE bedeutet, dass keine horizontale
985 // Ausrichtung geschrieben wird.
986 sal_Int16 eFlyHoriOri = text::HoriOrientation::NONE;
987 SwSurround eSurround = SURROUND_NONE;
988 sal_uInt8 nFlyPrcWidth = 0;
989 long nFlyWidth = 0;
990 sal_uInt16 nFlyHSpace = 0;
991 sal_uInt16 nFlyVSpace = 0;
992 if( pFlyFrmFmt )
993 {
994 eSurround = pFlyFrmFmt->GetSurround().GetSurround();
995 const SwFmtFrmSize& rFrmSize = pFlyFrmFmt->GetFrmSize();
996 nFlyPrcWidth = rFrmSize.GetWidthPercent();
997 nFlyWidth = rFrmSize.GetSize().Width();
998
999 eFlyHoriOri = pFlyFrmFmt->GetHoriOrient().GetHoriOrient();
1000 if( text::HoriOrientation::NONE == eFlyHoriOri )
1001 eFlyHoriOri = text::HoriOrientation::LEFT;
1002
1003 const SvxLRSpaceItem& rLRSpace = pFlyFrmFmt->GetLRSpace();
1004 nFlyHSpace = static_cast< sal_uInt16 >((rLRSpace.GetLeft() + rLRSpace.GetRight()) / 2);
1005
1006 const SvxULSpaceItem& rULSpace = pFlyFrmFmt->GetULSpace();
1007 nFlyVSpace = (rULSpace.GetUpper() + rULSpace.GetLower()) / 2;
1008 }
1009
1010 // ggf. eine FORM oeffnen
1011 sal_Bool bPreserveForm = sal_False;
1012 if( !rHTMLWrt.bPreserveForm )
1013 {
1014 rHTMLWrt.OutForm( sal_True, &rNode );
1015 bPreserveForm = (rHTMLWrt.pxFormComps && rHTMLWrt.pxFormComps->is() );
1016 rHTMLWrt.bPreserveForm = bPreserveForm;
1017 }
1018
1019 SwFrmFmt *pFmt = rTbl.GetFrmFmt();
1020
1021 const SwFmtFrmSize& rFrmSize = pFmt->GetFrmSize();
1022 long nWidth = rFrmSize.GetSize().Width();
1023 sal_uInt8 nPrcWidth = rFrmSize.GetWidthPercent();
1024 sal_uInt16 nBaseWidth = (sal_uInt16)nWidth;
1025
1026 sal_Int16 eTabHoriOri = pFmt->GetHoriOrient().GetHoriOrient();
1027
1028 // text::HoriOrientation::NONE und text::HoriOrientation::FULL Tabellen benoetigen relative Breiten
1029 sal_uInt16 nNewDefListLvl = 0;
1030 sal_Bool bRelWidths = sal_False;
1031 sal_Bool bCheckDefList = sal_False;
1032 switch( eTabHoriOri )
1033 {
1034 case text::HoriOrientation::FULL:
1035 // Tabellen mit automatischer Ausrichtung werden zu Tabellen
1036 // mit 100%-Breite
1037 bRelWidths = sal_True;
1038 nWidth = 100;
1039 eTabHoriOri = text::HoriOrientation::LEFT;
1040 break;
1041 case text::HoriOrientation::NONE:
1042 {
1043 const SvxLRSpaceItem& aLRItem = pFmt->GetLRSpace();
1044 if( aLRItem.GetRight() )
1045 {
1046 // Die Tabellenbreite wird anhand des linken und rechten
1047 // Abstandes bestimmt. Deshalb versuchen wir die
1048 // tatsaechliche Breite der Tabelle zu bestimmen. Wenn
1049 // das nicht geht, machen wir eine 100% breite Tabelle
1050 // draus.
1051 nWidth = pFmt->FindLayoutRect(sal_True).Width();
1052 if( !nWidth )
1053 {
1054 bRelWidths = sal_True;
1055 nWidth = 100;
1056 }
1057
1058 }
1059 else if( nPrcWidth )
1060 {
1061 // Ohne rechten Rand bleibt die %-Breite erhalten
1062 nWidth = nPrcWidth;
1063 bRelWidths = sal_True;
1064 }
1065 else
1066 {
1067 // Ohne rechten Rand bleibt auch eine absolute Breite erhalten
1068 // Wir versuchen aber trotzdem ueber das Layout die
1069 // tatsachliche Breite zu ermitteln.
1070 long nRealWidth = pFmt->FindLayoutRect(sal_True).Width();
1071 if( nRealWidth )
1072 nWidth = nRealWidth;
1073 }
1074 bCheckDefList = sal_True;
1075 }
1076 break;
1077 case text::HoriOrientation::LEFT_AND_WIDTH:
1078 eTabHoriOri = text::HoriOrientation::LEFT;
1079 bCheckDefList = sal_True;
1080 // no break
1081 default:
1082 // In allen anderen Faellen kann eine absolute oder relative
1083 // Breite direkt uebernommen werden.
1084 if( nPrcWidth )
1085 {
1086 bRelWidths = sal_True;
1087 nWidth = nPrcWidth;
1088 }
1089 break;
1090 }
1091
1092 if( bCheckDefList )
1093 {
1094 ASSERT( !rHTMLWrt.GetNumInfo().GetNumRule() ||
1095 rHTMLWrt.GetNextNumInfo(),
1096 "NumInfo fuer naechsten Absatz fehlt!" );
1097 const SvxLRSpaceItem& aLRItem = pFmt->GetLRSpace();
1098 if( aLRItem.GetLeft() > 0 && rHTMLWrt.nDefListMargin > 0 &&
1099 ( !rHTMLWrt.GetNumInfo().GetNumRule() ||
1100 ( rHTMLWrt.GetNextNumInfo() &&
1101 (rHTMLWrt.GetNextNumInfo()->IsRestart() ||
1102 rHTMLWrt.GetNumInfo().GetNumRule() !=
1103 rHTMLWrt.GetNextNumInfo()->GetNumRule()) ) ) )
1104 {
1105 // Wenn der Absatz vor der Tabelle nicht numeriert ist oder
1106 // der Absatz nach der Tabelle mit einer anderen oder
1107 // (gar keiner) Regel numeriert ist, koennen wir
1108 // die Einrueckung ueber eine DL regeln. Sonst behalten wir
1109 // die Einrueckung der Numerierung bei.
1110 nNewDefListLvl = static_cast< sal_uInt16 >(
1111 (aLRItem.GetLeft() + (rHTMLWrt.nDefListMargin/2)) /
1112 rHTMLWrt.nDefListMargin );
1113 }
1114 }
1115
1116 if( !pFlyFrmFmt && nNewDefListLvl != rHTMLWrt.nDefListLvl )
1117 rHTMLWrt.OutAndSetDefList( nNewDefListLvl );
1118
1119 if( nNewDefListLvl )
1120 {
1121 if( rHTMLWrt.bLFPossible )
1122 rHTMLWrt.OutNewLine();
1123 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_dd );
1124 }
1125
1126 // eFlyHoriOri und eTabHoriOri besitzen nun nur noch die Werte
1127 // LEFT/CENTER und RIGHT!
1128 if( eFlyHoriOri!=text::HoriOrientation::NONE )
1129 {
1130 eTabHoriOri = eFlyHoriOri;
1131 // MIB 4.7.97: Wenn die Tabelle eine relative Breite besitzt,
1132 // dann richtet sich ihre Breite nach der des Rahmens, also
1133 // exportieren wir dessen Breite. Bei fixer Breite ist die Breite
1134 // der Tabelle massgeblich. Wer Tabellen mit relativer Breite <100%
1135 // in Rahmen steckt, ist selber schuld wenn nix Gutes bei rauskommt.
1136 if( bRelWidths )
1137 {
1138 nWidth = nFlyPrcWidth ? nFlyPrcWidth : nFlyWidth;
1139 bRelWidths = nFlyPrcWidth > 0;
1140 }
1141 }
1142
1143 sal_Int16 eDivHoriOri = text::HoriOrientation::NONE;
1144 switch( eTabHoriOri )
1145 {
1146 case text::HoriOrientation::LEFT:
1147 // Wenn eine linksbuendigeTabelle keinen rechtsseiigen Durchlauf
1148 // hat, brauchen wir auch kein ALIGN=LEFT in der Tabelle.
1149 if( eSurround==SURROUND_NONE || eSurround==SURROUND_LEFT )
1150 eTabHoriOri = text::HoriOrientation::NONE;
1151 break;
1152 case text::HoriOrientation::RIGHT:
1153 // Aehnliches gilt fuer rechtsbuendigeTabelle, hier nehmen wir
1154 // stattdessen ein <DIV ALIGN=RIGHT>.
1155 if( eSurround==SURROUND_NONE || eSurround==SURROUND_RIGHT )
1156 {
1157 eDivHoriOri = text::HoriOrientation::RIGHT;
1158 eTabHoriOri = text::HoriOrientation::NONE;
1159 }
1160 break;
1161 case text::HoriOrientation::CENTER:
1162 // ALIGN=CENTER versteht so gut wie keiner, deshalb verzichten wir
1163 // daruf und nehmen ein <CENTER>.
1164 eDivHoriOri = text::HoriOrientation::CENTER;
1165 eTabHoriOri = text::HoriOrientation::NONE;
1166 break;
1167 default:
1168 ;
1169 }
1170 if( text::HoriOrientation::NONE==eTabHoriOri )
1171 nFlyHSpace = nFlyVSpace = 0;
1172
1173 if( pFmt->GetName().Len() )
1174 rHTMLWrt.OutImplicitMark( pFmt->GetName(), pMarkToTable );
1175
1176 if( text::HoriOrientation::NONE!=eDivHoriOri )
1177 {
1178 if( rHTMLWrt.bLFPossible )
1179 rHTMLWrt.OutNewLine(); // <CENTER> in neuer Zeile
1180 if( text::HoriOrientation::CENTER==eDivHoriOri )
1181 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_center, sal_True );
1182 else
1183 {
1184 ByteString sOut( OOO_STRING_SVTOOLS_HTML_division );
1185 (((sOut += ' ') += OOO_STRING_SVTOOLS_HTML_O_align) += '=') += OOO_STRING_SVTOOLS_HTML_AL_right;
1186 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), sOut.GetBuffer(),
1187 sal_True );
1188 }
1189 rHTMLWrt.IncIndentLevel(); // Inhalt von <CENTER> einruecken
1190 rHTMLWrt.bLFPossible = sal_True;
1191 }
1192
1193 // Wenn die Tabelle in keinem Rahmen ist kann man immer ein LF ausgeben.
1194 if( text::HoriOrientation::NONE==eTabHoriOri )
1195 rHTMLWrt.bLFPossible = sal_True;
1196
1197 const SwHTMLTableLayout *pLayout = rTbl.GetHTMLTableLayout();
1198
1199 #ifdef DBG_UTIL
1200 ViewShell *pSh;
1201 rWrt.pDoc->GetEditShell( &pSh );
1202 if ( pSh && pSh->GetViewOptions()->IsTest1() )
1203 pLayout = 0;
1204 #endif
1205
1206 if( pLayout && pLayout->IsExportable() )
1207 {
1208 SwHTMLWrtTable aTableWrt( pLayout );
1209 aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTbl.GetRowsToRepeat() > 0,
1210 pFmt, pCaption, bTopCaption,
1211 nFlyHSpace, nFlyVSpace );
1212 }
1213 else
1214 {
1215 SwHTMLWrtTable aTableWrt( rTbl.GetTabLines(), nWidth,
1216 nBaseWidth, bRelWidths, rTbl.GetRowsToRepeat() );
1217 aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTbl.GetRowsToRepeat() > 0,
1218 pFmt, pCaption, bTopCaption,
1219 nFlyHSpace, nFlyVSpace );
1220 }
1221
1222 // Wenn die Tabelle in keinem Rahmen war kann man immer ein LF ausgeben.
1223 if( text::HoriOrientation::NONE==eTabHoriOri )
1224 rHTMLWrt.bLFPossible = sal_True;
1225
1226 if( text::HoriOrientation::NONE!=eDivHoriOri )
1227 {
1228 rHTMLWrt.DecIndentLevel(); // Inhalt von <CENTER> einruecken
1229 rHTMLWrt.OutNewLine(); // </CENTER> in neue Teile
1230 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(),
1231 text::HoriOrientation::CENTER==eDivHoriOri ? OOO_STRING_SVTOOLS_HTML_center
1232 : OOO_STRING_SVTOOLS_HTML_division, sal_False );
1233 rHTMLWrt.bLFPossible = sal_True;
1234 }
1235
1236 // Pam hinter die Tabelle verschieben
1237 rHTMLWrt.pCurPam->GetPoint()->nNode = *rNode.EndOfSectionNode();
1238
1239 if( bPreserveForm )
1240 {
1241 rHTMLWrt.bPreserveForm = sal_False;
1242 rHTMLWrt.OutForm( sal_False );
1243 }
1244
1245 rHTMLWrt.bOutTable = sal_False;
1246
1247 if( rHTMLWrt.GetNextNumInfo() &&
1248 !rHTMLWrt.GetNextNumInfo()->IsRestart() &&
1249 rHTMLWrt.GetNextNumInfo()->GetNumRule() ==
1250 rHTMLWrt.GetNumInfo().GetNumRule() )
1251 {
1252 // Wenn der Absatz hinter der Tabelle mit der gleichen Regel
1253 // numeriert ist wie der Absatz vor der Tabelle, dann steht in
1254 // der NumInfo des naechsten Absatzes noch die Ebene des Absatzes
1255 // vor der Tabelle. Es muss deshalb die NumInfo noch einmal geholt
1256 // werden um ggf. die Num-Liste noch zu beenden.
1257 rHTMLWrt.ClearNextNumInfo();
1258 rHTMLWrt.FillNextNumInfo();
1259 OutHTML_NumBulListEnd( rHTMLWrt, *rHTMLWrt.GetNextNumInfo() );
1260 }
1261 return rWrt;
1262 }
1263
1264
1265