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