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