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 <vcl/wrkwin.hxx>
23 : #include <editeng/boxitem.hxx>
24 : #include <editeng/brushitem.hxx>
25 : #include <editeng/adjustitem.hxx>
26 : #include <editeng/fhgtitem.hxx>
27 : #include <editeng/ulspitem.hxx>
28 : #include <editeng/lrspitem.hxx>
29 : #include <editeng/formatbreakitem.hxx>
30 : #include <editeng/spltitem.hxx>
31 : #include <svtools/htmltokn.h>
32 : #include <svtools/htmlkywd.hxx>
33 : #include <svl/urihelper.hxx>
34 :
35 : #include <fmtornt.hxx>
36 : #include <frmfmt.hxx>
37 : #include <fmtfsize.hxx>
38 : #include <fmtsrnd.hxx>
39 : #include <fmtpdsc.hxx>
40 : #include <fmtcntnt.hxx>
41 : #include <fmtanchr.hxx>
42 : #include <fmtlsplt.hxx>
43 : #include "frmatr.hxx"
44 : #include "pam.hxx"
45 : #include "doc.hxx"
46 : #include <IDocumentLayoutAccess.hxx>
47 : #include "ndtxt.hxx"
48 : #include "shellio.hxx"
49 : #include "poolfmt.hxx"
50 : #include "swtable.hxx"
51 : #include "cellatr.hxx"
52 : #include "htmltbl.hxx"
53 : #include "swtblfmt.hxx"
54 : #include "htmlnum.hxx"
55 : #include "swhtml.hxx"
56 : #include "swcss1.hxx"
57 : #include <numrule.hxx>
58 :
59 : #define NETSCAPE_DFLT_BORDER 1
60 : #define NETSCAPE_DFLT_CELLSPACING 2
61 :
62 : using ::editeng::SvxBorderLine;
63 : using namespace ::com::sun::star;
64 :
65 : static HTMLOptionEnum aHTMLTableVAlignTable[] =
66 : {
67 : { OOO_STRING_SVTOOLS_HTML_VA_top, text::VertOrientation::NONE },
68 : { OOO_STRING_SVTOOLS_HTML_VA_middle, text::VertOrientation::CENTER },
69 : { OOO_STRING_SVTOOLS_HTML_VA_bottom, text::VertOrientation::BOTTOM },
70 : { 0, 0 }
71 : };
72 :
73 : // table tags options
74 :
75 6 : struct HTMLTableOptions
76 : {
77 : sal_uInt16 nCols;
78 : sal_uInt16 nWidth;
79 : sal_uInt16 nHeight;
80 : sal_uInt16 nCellPadding;
81 : sal_uInt16 nCellSpacing;
82 : sal_uInt16 nBorder;
83 : sal_uInt16 nHSpace;
84 : sal_uInt16 nVSpace;
85 :
86 : SvxAdjust eAdjust;
87 : sal_Int16 eVertOri;
88 : HTMLTableFrame eFrame;
89 : HTMLTableRules eRules;
90 :
91 : bool bPrcWidth : 1;
92 : bool bTableAdjust : 1;
93 : bool bBGColor : 1;
94 :
95 : Color aBorderColor;
96 : Color aBGColor;
97 :
98 : OUString aBGImage, aStyle, aId, aClass, aDir;
99 :
100 : HTMLTableOptions( const HTMLOptions& rOptions, SvxAdjust eParentAdjust );
101 : };
102 :
103 : class _HTMLTableContext
104 : {
105 : SwHTMLNumRuleInfo aNumRuleInfo; // Numbering valid before the table
106 :
107 : SwTableNode *pTableNd; // table node
108 : SwFrameFormat *pFrameFormat; // der Fly frame::Frame, containing the table
109 : SwPosition *pPos; // position behind the table
110 :
111 : size_t nContextStAttrMin;
112 : size_t nContextStMin;
113 :
114 : bool bRestartPRE : 1;
115 : bool bRestartXMP : 1;
116 : bool bRestartListing : 1;
117 :
118 : public:
119 :
120 : _HTMLAttrTable aAttrTab; // attributes
121 :
122 6 : _HTMLTableContext( SwPosition *pPs, size_t nCntxtStMin,
123 : size_t nCntxtStAttrMin ) :
124 : pTableNd( 0 ),
125 : pFrameFormat( 0 ),
126 : pPos( pPs ),
127 : nContextStAttrMin( nCntxtStAttrMin ),
128 : nContextStMin( nCntxtStMin ),
129 : bRestartPRE( false ),
130 : bRestartXMP( false ),
131 6 : bRestartListing( false )
132 : {
133 6 : memset( &aAttrTab, 0, sizeof( _HTMLAttrTable ));
134 6 : }
135 :
136 : ~_HTMLTableContext();
137 :
138 6 : void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { aNumRuleInfo.Set(rInf); }
139 6 : const SwHTMLNumRuleInfo& GetNumInfo() const { return aNumRuleInfo; };
140 :
141 : void SavePREListingXMP( SwHTMLParser& rParser );
142 : void RestorePREListingXMP( SwHTMLParser& rParser );
143 :
144 6 : SwPosition *GetPos() const { return pPos; }
145 :
146 6 : void SetTableNode( SwTableNode *pNd ) { pTableNd = pNd; }
147 18 : SwTableNode *GetTableNode() const { return pTableNd; }
148 :
149 0 : void SetFrameFormat( SwFrameFormat *pFormat ) { pFrameFormat = pFormat; }
150 6 : SwFrameFormat *GetFrameFormat() const { return pFrameFormat; }
151 :
152 6 : size_t GetContextStMin() const { return nContextStMin; }
153 6 : size_t GetContextStAttrMin() const { return nContextStAttrMin; }
154 : };
155 :
156 : // Cell content is a linked list with SwStartNodes and
157 : // HTMLTables.
158 :
159 : class HTMLTableCnts
160 : {
161 : HTMLTableCnts *m_pNext; // next content
162 :
163 : // Only one of the next two pointers must be set!
164 : const SwStartNode *m_pStartNode; // a paragraph
165 : HTMLTable *m_pTable; // a table
166 :
167 : SwHTMLTableLayoutCnts* m_pLayoutInfo;
168 :
169 : bool m_bNoBreak;
170 :
171 : void InitCtor();
172 :
173 : public:
174 :
175 : explicit HTMLTableCnts( const SwStartNode* pStNd );
176 : explicit HTMLTableCnts( HTMLTable* pTab );
177 :
178 : ~HTMLTableCnts(); // only allowed in ~HTMLTableCell
179 :
180 : // Determine SwStartNode and HTMLTable respectively
181 572 : const SwStartNode *GetStartNode() const { return m_pStartNode; }
182 0 : const HTMLTable *GetTable() const { return m_pTable; }
183 286 : HTMLTable *GetTable() { return m_pTable; }
184 :
185 : // Add a new node at the end of the list
186 : void Add( HTMLTableCnts* pNewCnts );
187 :
188 : // Determine next node
189 0 : const HTMLTableCnts *Next() const { return m_pNext; }
190 572 : HTMLTableCnts *Next() { return m_pNext; }
191 :
192 : inline void SetTableBox( SwTableBox *pBox );
193 :
194 0 : void SetNoBreak() { m_bNoBreak = true; }
195 :
196 : SwHTMLTableLayoutCnts *CreateLayoutInfo();
197 : };
198 :
199 : // Cell of a HTML table
200 : class HTMLTableCell
201 : {
202 : // !!!ATTENTION!!!!! For each new pointer the SetProtected
203 : // method (and the dtor) has to be executed.
204 : HTMLTableCnts *pContents; // cell content
205 : SvxBrushItem *pBGBrush; // cell background
206 : // !!!ATTENTION!!!!!
207 : ::boost::shared_ptr<SvxBoxItem> m_pBoxItem;
208 :
209 : sal_uInt32 nNumFormat;
210 : sal_uInt16 nRowSpan; // cell ROWSPAN
211 : sal_uInt16 nColSpan; // cell COLSPAN
212 : sal_uInt16 nWidth; // cell WIDTH
213 : double nValue;
214 : sal_Int16 eVertOri; // vertical alignment of the cell
215 : bool bProtected : 1; // cell must not filled
216 : bool bRelWidth : 1; // nWidth is given in %
217 : bool bHasNumFormat : 1;
218 : bool bHasValue : 1;
219 : bool bNoWrap : 1;
220 : bool mbCovered : 1;
221 :
222 : public:
223 :
224 : HTMLTableCell(); // new cells always empty
225 :
226 : ~HTMLTableCell(); // only allowed in ~HTMLTableRow
227 :
228 : // Fill a not empty cell
229 : void Set( HTMLTableCnts *pCnts, sal_uInt16 nRSpan, sal_uInt16 nCSpan,
230 : sal_Int16 eVertOri, SvxBrushItem *pBGBrush,
231 : ::boost::shared_ptr<SvxBoxItem> const& rBoxItem,
232 : bool bHasNumFormat, sal_uInt32 nNumFormat,
233 : bool bHasValue, double nValue, bool bNoWrap, bool bCovered );
234 :
235 : // Protect an empty 1x1 cell
236 : void SetProtected();
237 :
238 : // Set/Get cell content
239 0 : void SetContents( HTMLTableCnts *pCnts ) { pContents = pCnts; }
240 1481 : HTMLTableCnts *GetContents() { return pContents; }
241 :
242 : // Set/Get cell ROWSPAN/COLSPAN
243 0 : void SetRowSpan( sal_uInt16 nRSpan ) { nRowSpan = nRSpan; }
244 286 : sal_uInt16 GetRowSpan() const { return nRowSpan; }
245 :
246 0 : void SetColSpan( sal_uInt16 nCSpan ) { nColSpan = nCSpan; }
247 572 : sal_uInt16 GetColSpan() const { return nColSpan; }
248 :
249 : inline void SetWidth( sal_uInt16 nWidth, bool bRelWidth );
250 :
251 286 : const SvxBrushItem *GetBGBrush() const { return pBGBrush; }
252 286 : ::boost::shared_ptr<SvxBoxItem> GetBoxItem() const { return m_pBoxItem; }
253 :
254 : inline bool GetNumFormat( sal_uInt32& rNumFormat ) const;
255 : inline bool GetValue( double& rValue ) const;
256 :
257 286 : sal_Int16 GetVertOri() const { return eVertOri; }
258 :
259 : // Is the cell filled or protected ?
260 281 : bool IsUsed() const { return pContents!=0 || bProtected; }
261 :
262 : SwHTMLTableLayoutCell *CreateLayoutInfo();
263 :
264 286 : bool IsCovered() const { return mbCovered; }
265 : };
266 :
267 : // Row of a HTML table
268 : typedef boost::ptr_vector<HTMLTableCell> HTMLTableCells;
269 :
270 : class HTMLTableRow
271 : {
272 : HTMLTableCells *pCells; // cells of the row
273 :
274 : bool bIsEndOfGroup : 1;
275 :
276 : sal_uInt16 nHeight; // options of <TR>/<TD>
277 : sal_uInt16 nEmptyRows; // number of empty rows are following
278 :
279 : SvxAdjust eAdjust;
280 : sal_Int16 eVertOri;
281 : SvxBrushItem *pBGBrush; // background of cell from STYLE
282 :
283 : public:
284 :
285 : bool bBottomBorder; // Is there a line after the row?
286 :
287 : explicit HTMLTableRow( sal_uInt16 nCells=0 ); // cells of the row are empty
288 :
289 : ~HTMLTableRow();
290 :
291 : inline void SetHeight( sal_uInt16 nHeight );
292 64 : sal_uInt16 GetHeight() const { return nHeight; }
293 :
294 : inline HTMLTableCell *GetCell( sal_uInt16 nCell ) const;
295 :
296 64 : inline void SetAdjust( SvxAdjust eAdj ) { eAdjust = eAdj; }
297 286 : inline SvxAdjust GetAdjust() const { return eAdjust; }
298 :
299 64 : inline void SetVertOri( sal_Int16 eV) { eVertOri = eV; }
300 286 : inline sal_Int16 GetVertOri() const { return eVertOri; }
301 :
302 0 : void SetBGBrush( SvxBrushItem *pBrush ) { pBGBrush = pBrush; }
303 64 : const SvxBrushItem *GetBGBrush() const { return pBGBrush; }
304 :
305 6 : inline void SetEndOfGroup() { bIsEndOfGroup = true; }
306 0 : inline bool IsEndOfGroup() const { return bIsEndOfGroup; }
307 :
308 0 : void IncEmptyRows() { nEmptyRows++; }
309 0 : sal_uInt16 GetEmptyRows() const { return nEmptyRows; }
310 :
311 : // Expand row by adding empty cells
312 : void Expand( sal_uInt16 nCells, bool bOneCell=false );
313 :
314 : // Shrink row by deleting empty cells
315 : void Shrink( sal_uInt16 nCells );
316 : };
317 :
318 : // Column of a HTML table
319 : class HTMLTableColumn
320 : {
321 : bool bIsEndOfGroup;
322 :
323 : sal_uInt16 nWidth; // options of <COL>
324 : bool bRelWidth;
325 :
326 : SvxAdjust eAdjust;
327 : sal_Int16 eVertOri;
328 :
329 : SwFrameFormat *aFrameFormats[6];
330 :
331 : static inline sal_uInt16 GetFrameFormatIdx( bool bBorderLine,
332 : sal_Int16 eVertOri );
333 :
334 : public:
335 :
336 : bool bLeftBorder; // is there a line before the column
337 :
338 : HTMLTableColumn();
339 :
340 : inline void SetWidth( sal_uInt16 nWidth, bool bRelWidth);
341 :
342 8 : inline void SetAdjust( SvxAdjust eAdj ) { eAdjust = eAdj; }
343 281 : inline SvxAdjust GetAdjust() const { return eAdjust; }
344 :
345 8 : inline void SetVertOri( sal_Int16 eV) { eVertOri = eV; }
346 21 : inline sal_Int16 GetVertOri() const { return eVertOri; }
347 :
348 4 : inline void SetEndOfGroup() { bIsEndOfGroup = true; }
349 0 : inline bool IsEndOfGroup() const { return bIsEndOfGroup; }
350 :
351 : inline void SetFrameFormat( SwFrameFormat *pFormat, bool bBorderLine,
352 : sal_Int16 eVertOri );
353 : inline SwFrameFormat *GetFrameFormat( bool bBorderLine,
354 : sal_Int16 eVertOri ) const;
355 :
356 : SwHTMLTableLayoutColumn *CreateLayoutInfo();
357 : };
358 :
359 : // HTML table
360 : typedef boost::ptr_vector<HTMLTableRow> HTMLTableRows;
361 :
362 : typedef boost::ptr_vector<HTMLTableColumn> HTMLTableColumns;
363 :
364 : typedef std::vector<SdrObject *> SdrObjects;
365 :
366 : class HTMLTable
367 : {
368 : OUString aId;
369 : OUString aStyle;
370 : OUString aClass;
371 : OUString aDir;
372 :
373 : SdrObjects *pResizeDrawObjs;// SDR objects
374 : std::vector<sal_uInt16> *pDrawObjPrcWidths; // column of draw object and its rel. width
375 :
376 : HTMLTableRows *pRows; // table rows
377 : HTMLTableColumns *pColumns; // table columns
378 :
379 : sal_uInt16 nRows; // number of rows
380 : sal_uInt16 nCols; // number of columns
381 : sal_uInt16 nFilledCols; // number of filled columns
382 :
383 : sal_uInt16 nCurRow; // current Row
384 : sal_uInt16 nCurCol; // current Column
385 :
386 : sal_uInt16 nLeftMargin; // Space to the left margin (from paragraph edge)
387 : sal_uInt16 nRightMargin; // Space to the right margin (from paragraph edge)
388 :
389 : sal_uInt16 nCellPadding; // Space from border to Text
390 : sal_uInt16 nCellSpacing; // Space between two cells
391 : sal_uInt16 nHSpace;
392 : sal_uInt16 nVSpace;
393 :
394 : sal_uInt16 nBoxes; // number of boxes in the table
395 :
396 : const SwStartNode *pPrevStNd; // the Table-Node or the Start-Node of the section before
397 : const SwTable *pSwTable; // SW-Table (only on Top-Level)
398 : SwTableBox *pBox1; // TableBox, generated when the Top-Level-Table was build
399 : SwTableBoxFormat *pBoxFormat; // frame::Frame-Format from SwTableBox
400 : SwTableLineFormat *pLineFormat; // frame::Frame-Format from SwTableLine
401 : SwTableLineFormat *pLineFrameFormatNoHeight;
402 : SvxBrushItem *pBGBrush; // background of the table
403 : SvxBrushItem *pInhBGBrush; // "inherited" background of the table
404 : const SwStartNode *pCaptionStartNode; // Start-Node of the table-caption
405 : //lines for the border
406 : SvxBorderLine aTopBorderLine;
407 : SvxBorderLine aBottomBorderLine;
408 : SvxBorderLine aLeftBorderLine;
409 : SvxBorderLine aRightBorderLine;
410 : SvxBorderLine aBorderLine;
411 : SvxBorderLine aInhLeftBorderLine;
412 : SvxBorderLine aInhRightBorderLine;
413 : bool bTopBorder; // is there a line on the top of the table
414 : bool bRightBorder; // is there a line on the top right of the table
415 : bool bTopAlwd; // is it allowed to set the border?
416 : bool bRightAlwd;
417 : bool bFillerTopBorder; // gets the left/right filler-cell a border on the
418 : bool bFillerBottomBorder; // top or in the bottom
419 : bool bInhLeftBorder;
420 : bool bInhRightBorder;
421 : bool bBordersSet; // the border is setted already
422 : bool bForceFrame;
423 : bool bTableAdjustOfTag; // comes nTableAdjust from <TABLE>?
424 : sal_uInt32 nHeadlineRepeat; // repeating rows
425 : bool bIsParentHead;
426 : bool bHasParentSection;
427 : bool bHasToFly;
428 : bool bFixedCols;
429 : bool bColSpec; // where there COL(GROUP)-elements?
430 : bool bPrcWidth; // width is declarated in %
431 :
432 : SwHTMLParser *pParser; // the current parser
433 : HTMLTable *pTopTable; // the table on the Top-Level
434 : HTMLTableCnts *pParentContents;
435 :
436 : _HTMLTableContext *pContext; // the context of the table
437 :
438 : SwHTMLTableLayout *pLayoutInfo;
439 :
440 : // the following parameters are from the <TABLE>-Tag
441 : sal_uInt16 nWidth; // width of the table
442 : sal_uInt16 nHeight; // absolute height of the table
443 : SvxAdjust eTableAdjust; // drawing::Alignment of the table
444 : sal_Int16 eVertOri; // Default vertical direction of the cells
445 : sal_uInt16 nBorder; // width of the external border
446 : HTMLTableFrame eFrame; // frame around the table
447 : HTMLTableRules eRules; // frame in the table
448 : bool bTopCaption; // Caption of the table
449 :
450 : void InitCtor( const HTMLTableOptions *pOptions );
451 :
452 : // Correction of the Row-Spans for all cells above the chosen cell and the cell itself for the indicated content. The chosen cell gets the Row-Span 1
453 : void FixRowSpan( sal_uInt16 nRow, sal_uInt16 nCol, const HTMLTableCnts *pCnts );
454 :
455 : // Protects the chosen cell and the cells among
456 : void ProtectRowSpan( sal_uInt16 nRow, sal_uInt16 nCol, sal_uInt16 nRowSpan );
457 :
458 : // Looking for the SwStartNodes of the box ahead
459 : // If nRow==nCell==USHRT_MAX, return the last Start-Node of the table.
460 : const SwStartNode* GetPrevBoxStartNode( sal_uInt16 nRow, sal_uInt16 nCell ) const;
461 :
462 : sal_uInt16 GetTopCellSpace( sal_uInt16 nRow, sal_uInt16 nRowSpan,
463 : bool bSwBorders=true ) const;
464 : sal_uInt16 GetBottomCellSpace( sal_uInt16 nRow, sal_uInt16 nRowSpan,
465 : bool bSwBorders=true ) const;
466 :
467 : // Conforming of the frame::Frame-Format of the box
468 : void FixFrameFormat( SwTableBox *pBox, sal_uInt16 nRow, sal_uInt16 nCol,
469 : sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
470 : bool bFirstPara=true, bool bLastPara=true ) const;
471 : void FixFillerFrameFormat( SwTableBox *pBox, bool bRight ) const;
472 :
473 : // Create a table with the content (lines/boxes)
474 : void _MakeTable( SwTableBox *pUpper=0 );
475 :
476 : // Gernerate a new SwTableBox, which contains a SwStartNode
477 : SwTableBox *NewTableBox( const SwStartNode *pStNd,
478 : SwTableLine *pUpper ) const;
479 :
480 : // Generate a SwTableLine from the cells of the rectangle
481 : // (nTopRow/nLeftCol) inclusive to (nBottomRow/nRightRow) exclusive
482 : SwTableLine *MakeTableLine( SwTableBox *pUpper,
483 : sal_uInt16 nTopRow, sal_uInt16 nLeftCol,
484 : sal_uInt16 nBottomRow, sal_uInt16 nRightCol );
485 :
486 : // Generate a SwTableBox from the content of the cell
487 : SwTableBox *MakeTableBox( SwTableLine *pUpper,
488 : HTMLTableCnts *pCnts,
489 : sal_uInt16 nTopRow, sal_uInt16 nLeftCol,
490 : sal_uInt16 nBootomRow, sal_uInt16 nRightCol );
491 :
492 : // Autolayout-Algorithm
493 :
494 : // Setting the border with the help of guidelines of the Parent-Table
495 : void InheritBorders( const HTMLTable *pParent,
496 : sal_uInt16 nRow, sal_uInt16 nCol,
497 : sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
498 : bool bFirstPara, bool bLastPara );
499 :
500 : // Inherit the left and the right border of the surrounding table
501 : void InheritVertBorders( const HTMLTable *pParent,
502 : sal_uInt16 nCol, sal_uInt16 nColSpan );
503 :
504 : // Set the border with the help of the information from the user
505 : void SetBorders();
506 :
507 : // is the border already setted?
508 0 : bool BordersSet() const { return bBordersSet; }
509 :
510 7 : const SvxBrushItem *GetBGBrush() const { return pBGBrush; }
511 0 : const SvxBrushItem *GetInhBGBrush() const { return pInhBGBrush; }
512 :
513 : sal_uInt16 GetBorderWidth( const SvxBorderLine& rBLine,
514 : bool bWithDistance=false ) const;
515 :
516 : public:
517 :
518 : bool bFirstCell; // wurde schon eine Zelle angelegt?
519 :
520 : HTMLTable( SwHTMLParser* pPars, HTMLTable *pTopTab,
521 : bool bParHead, bool bHasParentSec,
522 : bool bHasToFly,
523 : const HTMLTableOptions *pOptions );
524 :
525 : ~HTMLTable();
526 :
527 : // Identifying of a cell
528 : inline HTMLTableCell *GetCell( sal_uInt16 nRow, sal_uInt16 nCell ) const;
529 :
530 : // set/determine caption
531 : inline void SetCaption( const SwStartNode *pStNd, bool bTop );
532 6 : const SwStartNode *GetCaptionStartNode() const { return pCaptionStartNode; }
533 0 : bool IsTopCaption() const { return bTopCaption; }
534 :
535 6 : SvxAdjust GetTableAdjust( bool bAny ) const
536 : {
537 6 : return (bTableAdjustOfTag || bAny) ? eTableAdjust : SVX_ADJUST_END;
538 : }
539 :
540 0 : sal_uInt16 GetHSpace() const { return nHSpace; }
541 0 : sal_uInt16 GetVSpace() const { return nVSpace; }
542 :
543 : // get inherited drawing::Alignment of rows and column
544 : SvxAdjust GetInheritedAdjust() const;
545 : sal_Int16 GetInheritedVertOri() const;
546 :
547 : // Insert a cell on the current position
548 : void InsertCell( HTMLTableCnts *pCnts, sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
549 : sal_uInt16 nWidth, bool bRelWidth, sal_uInt16 nHeight,
550 : sal_Int16 eVertOri, SvxBrushItem *pBGBrush,
551 : boost::shared_ptr<SvxBoxItem> const& rBoxItem,
552 : bool bHasNumFormat, sal_uInt32 nNumFormat,
553 : bool bHasValue, double nValue, bool bNoWrap );
554 :
555 : // announce the start/end of a new row
556 : void OpenRow( SvxAdjust eAdjust, sal_Int16 eVertOri,
557 : SvxBrushItem *pBGBrush );
558 : void CloseRow( bool bEmpty );
559 :
560 : // announce the end of a new section
561 : inline void CloseSection( bool bHead );
562 :
563 : // announce the end of a column-group
564 : inline void CloseColGroup( sal_uInt16 nSpan, sal_uInt16 nWidth, bool bRelWidth,
565 : SvxAdjust eAdjust, sal_Int16 eVertOri );
566 :
567 : // insert a new column
568 : void InsertCol( sal_uInt16 nSpan, sal_uInt16 nWidth, bool bRelWidth,
569 : SvxAdjust eAdjust, sal_Int16 eVertOri );
570 :
571 : // Beenden einer Tab-Definition (MUSS fuer ALLE Tabs aufgerufen werden)
572 : void CloseTable();
573 :
574 : // SwTable konstruieren (inkl. der Child-Tabellen)
575 : void MakeTable( SwTableBox *pUpper, sal_uInt16 nAbsAvail,
576 : sal_uInt16 nRelAvail=0, sal_uInt16 nAbsLeftSpace=0,
577 : sal_uInt16 nAbsRightSpace=0, sal_uInt16 nInhAbsSpace=0 );
578 :
579 0 : inline bool IsNewDoc() const { return pParser->IsNewDoc(); }
580 :
581 0 : void SetHasParentSection( bool bSet ) { bHasParentSection = bSet; }
582 38 : bool HasParentSection() const { return bHasParentSection; }
583 :
584 0 : void SetParentContents( HTMLTableCnts *pCnts ) { pParentContents = pCnts; }
585 0 : HTMLTableCnts *GetParentContents() const { return pParentContents; }
586 :
587 : void MakeParentContents();
588 :
589 0 : bool GetIsParentHeader() const { return bIsParentHead; }
590 :
591 6 : bool HasToFly() const { return bHasToFly; }
592 :
593 : void SetTable( const SwStartNode *pStNd, _HTMLTableContext *pCntxt,
594 : sal_uInt16 nLeft, sal_uInt16 nRight,
595 : const SwTable *pSwTab=0, bool bFrcFrame=false );
596 :
597 729 : _HTMLTableContext *GetContext() const { return pContext; }
598 :
599 : SwHTMLTableLayout *CreateLayoutInfo();
600 :
601 0 : bool HasColTags() const { return bColSpec; }
602 :
603 0 : sal_uInt16 IncGrfsThatResize() { return pSwTable ? const_cast<SwTable *>(pSwTable)->IncGrfsThatResize() : 0; }
604 :
605 : void RegisterDrawObject( SdrObject *pObj, sal_uInt8 nPrcWidth );
606 :
607 0 : const SwTable *GetSwTable() const { return pSwTable; }
608 :
609 0 : void SetBGBrush( const SvxBrushItem& rBrush ) { delete pBGBrush; pBGBrush = new SvxBrushItem( rBrush ); }
610 :
611 6 : const OUString& GetId() const { return aId; }
612 6 : const OUString& GetClass() const { return aClass; }
613 6 : const OUString& GetStyle() const { return aStyle; }
614 6 : const OUString& GetDirection() const { return aDir; }
615 :
616 280 : void IncBoxCount() { nBoxes++; }
617 642 : bool IsOverflowing() const { return nBoxes > 64000; }
618 : };
619 :
620 286 : void HTMLTableCnts::InitCtor()
621 : {
622 286 : m_pNext = 0;
623 286 : m_pLayoutInfo = 0;
624 :
625 286 : m_bNoBreak = false;
626 286 : }
627 :
628 286 : HTMLTableCnts::HTMLTableCnts( const SwStartNode* pStNd ):
629 286 : m_pStartNode(pStNd), m_pTable(0)
630 : {
631 286 : InitCtor();
632 286 : }
633 :
634 0 : HTMLTableCnts::HTMLTableCnts( HTMLTable* pTab ):
635 0 : m_pStartNode(0), m_pTable(pTab)
636 : {
637 0 : InitCtor();
638 0 : }
639 :
640 286 : HTMLTableCnts::~HTMLTableCnts()
641 : {
642 286 : delete m_pTable; // die Tabellen brauchen wir nicht mehr
643 286 : delete m_pNext;
644 286 : }
645 :
646 0 : void HTMLTableCnts::Add( HTMLTableCnts* pNewCnts )
647 : {
648 0 : HTMLTableCnts *pCnts = this;
649 :
650 0 : while( pCnts->m_pNext )
651 0 : pCnts = pCnts->m_pNext;
652 :
653 0 : pCnts->m_pNext = pNewCnts;
654 0 : }
655 :
656 286 : inline void HTMLTableCnts::SetTableBox( SwTableBox *pBox )
657 : {
658 : OSL_ENSURE( m_pLayoutInfo, "Da sit noch keine Layout-Info" );
659 286 : if( m_pLayoutInfo )
660 286 : m_pLayoutInfo->SetTableBox( pBox );
661 286 : }
662 :
663 286 : SwHTMLTableLayoutCnts *HTMLTableCnts::CreateLayoutInfo()
664 : {
665 286 : if( !m_pLayoutInfo )
666 : {
667 286 : SwHTMLTableLayoutCnts *pNextInfo = m_pNext ? m_pNext->CreateLayoutInfo() : 0;
668 286 : SwHTMLTableLayout *pTableInfo = m_pTable ? m_pTable->CreateLayoutInfo() : 0;
669 :
670 : m_pLayoutInfo = new SwHTMLTableLayoutCnts( m_pStartNode, pTableInfo,
671 286 : m_bNoBreak, pNextInfo );
672 : }
673 :
674 286 : return m_pLayoutInfo;
675 : }
676 :
677 286 : HTMLTableCell::HTMLTableCell():
678 : pContents(0),
679 : pBGBrush(0),
680 : nNumFormat(0),
681 : nRowSpan(1),
682 : nColSpan(1),
683 : nWidth( 0 ),
684 : nValue(0),
685 : eVertOri( text::VertOrientation::NONE ),
686 : bProtected(false),
687 : bRelWidth( false ),
688 : bHasNumFormat(false),
689 : bHasValue(false),
690 : bNoWrap(false),
691 286 : mbCovered(false)
692 286 : {}
693 :
694 572 : HTMLTableCell::~HTMLTableCell()
695 : {
696 : // der Inhalt ist in mehrere Zellen eingetragen, darf aber nur einmal
697 : // geloescht werden
698 286 : if( 1==nRowSpan && 1==nColSpan )
699 : {
700 286 : delete pContents;
701 286 : delete pBGBrush;
702 : }
703 286 : }
704 :
705 286 : void HTMLTableCell::Set( HTMLTableCnts *pCnts, sal_uInt16 nRSpan, sal_uInt16 nCSpan,
706 : sal_Int16 eVert, SvxBrushItem *pBrush,
707 : ::boost::shared_ptr<SvxBoxItem> const& rBoxItem,
708 : bool bHasNF, sal_uInt32 nNF, bool bHasV, double nVal,
709 : bool bNWrap, bool bCovered )
710 : {
711 286 : pContents = pCnts;
712 286 : nRowSpan = nRSpan;
713 286 : nColSpan = nCSpan;
714 286 : bProtected = false;
715 286 : eVertOri = eVert;
716 286 : pBGBrush = pBrush;
717 286 : m_pBoxItem = rBoxItem;
718 :
719 286 : bHasNumFormat = bHasNF;
720 286 : bHasValue = bHasV;
721 286 : nNumFormat = nNF;
722 286 : nValue = nVal;
723 :
724 286 : bNoWrap = bNWrap;
725 286 : mbCovered = bCovered;
726 286 : }
727 :
728 280 : inline void HTMLTableCell::SetWidth( sal_uInt16 nWdth, bool bRelWdth )
729 : {
730 280 : nWidth = nWdth;
731 280 : bRelWidth = bRelWdth;
732 280 : }
733 :
734 0 : void HTMLTableCell::SetProtected()
735 : {
736 : // Die Inhalte dieser Zelle mussen nich irgenwo anders verankert
737 : // sein, weil sie nicht geloescht werden!!!
738 :
739 : // Inhalt loeschen
740 0 : pContents = 0;
741 :
742 : // Hintergrundfarbe kopieren.
743 0 : if( pBGBrush )
744 0 : pBGBrush = new SvxBrushItem( *pBGBrush );
745 :
746 0 : nRowSpan = 1;
747 0 : nColSpan = 1;
748 0 : bProtected = true;
749 0 : }
750 :
751 286 : inline bool HTMLTableCell::GetNumFormat( sal_uInt32& rNumFormat ) const
752 : {
753 286 : rNumFormat = nNumFormat;
754 286 : return bHasNumFormat;
755 : }
756 :
757 0 : inline bool HTMLTableCell::GetValue( double& rValue ) const
758 : {
759 0 : rValue = nValue;
760 0 : return bHasValue;
761 : }
762 :
763 286 : SwHTMLTableLayoutCell *HTMLTableCell::CreateLayoutInfo()
764 : {
765 286 : SwHTMLTableLayoutCnts *pCntInfo = pContents ? pContents->CreateLayoutInfo() : 0;
766 :
767 : return new SwHTMLTableLayoutCell( pCntInfo, nRowSpan, nColSpan, nWidth,
768 286 : bRelWidth, bNoWrap );
769 : }
770 :
771 64 : HTMLTableRow::HTMLTableRow( sal_uInt16 nCells ):
772 64 : pCells(new HTMLTableCells),
773 : bIsEndOfGroup(false),
774 : nHeight(0),
775 : nEmptyRows(0),
776 : eAdjust(SVX_ADJUST_END),
777 : eVertOri(text::VertOrientation::TOP),
778 : pBGBrush(0),
779 128 : bBottomBorder(false)
780 : {
781 345 : for( sal_uInt16 i=0; i<nCells; i++ )
782 : {
783 281 : pCells->push_back( new HTMLTableCell );
784 : }
785 :
786 : OSL_ENSURE(nCells == pCells->size(),
787 : "wrong Cell count in new HTML table row");
788 64 : }
789 :
790 64 : HTMLTableRow::~HTMLTableRow()
791 : {
792 64 : delete pCells;
793 64 : delete pBGBrush;
794 64 : }
795 :
796 0 : inline void HTMLTableRow::SetHeight( sal_uInt16 nHght )
797 : {
798 0 : if( nHght > nHeight )
799 0 : nHeight = nHght;
800 0 : }
801 :
802 2614 : inline HTMLTableCell *HTMLTableRow::GetCell( sal_uInt16 nCell ) const
803 : {
804 : OSL_ENSURE( nCell<pCells->size(),
805 : "ungueltiger Zellen-Index in HTML-Tabellenzeile" );
806 2614 : return &(*pCells)[nCell];
807 : }
808 :
809 5 : void HTMLTableRow::Expand( sal_uInt16 nCells, bool bOneCell )
810 : {
811 : // die Zeile wird mit einer einzigen Zelle aufgefuellt, wenn
812 : // bOneCell gesetzt ist. Das geht, nur fuer Zeilen, in die keine
813 : // Zellen mehr eingefuegt werden!
814 :
815 5 : sal_uInt16 nColSpan = nCells-pCells->size();
816 10 : for( sal_uInt16 i=pCells->size(); i<nCells; i++ )
817 : {
818 5 : HTMLTableCell *pCell = new HTMLTableCell;
819 5 : if( bOneCell )
820 0 : pCell->SetColSpan( nColSpan );
821 :
822 5 : pCells->push_back( pCell );
823 5 : nColSpan--;
824 : }
825 :
826 : OSL_ENSURE(nCells == pCells->size(),
827 : "wrong Cell count in expanded HTML table row");
828 5 : }
829 :
830 0 : void HTMLTableRow::Shrink( sal_uInt16 nCells )
831 : {
832 : OSL_ENSURE(nCells < pCells->size(), "number of cells too large");
833 :
834 : #if OSL_DEBUG_LEVEL > 0
835 : sal_uInt16 nEnd = pCells->size();
836 : #endif
837 : // The colspan of empty cells at the end has to be fixed to the new
838 : // number of cells.
839 0 : sal_uInt16 i=nCells;
840 0 : while( i )
841 : {
842 0 : HTMLTableCell *pCell = &(*pCells)[--i];
843 0 : if( !pCell->GetContents() )
844 : {
845 : #if OSL_DEBUG_LEVEL > 0
846 : OSL_ENSURE( pCell->GetColSpan() == nEnd - i,
847 : "invalid col span for empty cell at row end" );
848 : #endif
849 0 : pCell->SetColSpan( nCells-i);
850 : }
851 : else
852 0 : break;
853 : }
854 : #if OSL_DEBUG_LEVEL > 0
855 : for( i=nCells; i<nEnd; i++ )
856 : {
857 : HTMLTableCell *pCell = &(*pCells)[i];
858 : OSL_ENSURE( pCell->GetRowSpan() == 1,
859 : "RowSpan von zu loesender Zelle ist falsch" );
860 : OSL_ENSURE( pCell->GetColSpan() == nEnd - i,
861 : "ColSpan von zu loesender Zelle ist falsch" );
862 : OSL_ENSURE( !pCell->GetContents(), "Zu loeschende Zelle hat Inhalt" );
863 : }
864 : #endif
865 :
866 0 : pCells->erase( pCells->begin() + nCells, pCells->end() );
867 0 : }
868 :
869 13 : HTMLTableColumn::HTMLTableColumn():
870 : bIsEndOfGroup(false),
871 : nWidth(0), bRelWidth(false),
872 : eAdjust(SVX_ADJUST_END), eVertOri(text::VertOrientation::TOP),
873 13 : bLeftBorder(false)
874 : {
875 91 : for( sal_uInt16 i=0; i<6; i++ )
876 78 : aFrameFormats[i] = 0;
877 13 : }
878 :
879 8 : inline void HTMLTableColumn::SetWidth( sal_uInt16 nWdth, bool bRelWdth )
880 : {
881 8 : if( bRelWidth==bRelWdth )
882 : {
883 0 : if( nWdth > nWidth )
884 0 : nWidth = nWdth;
885 : }
886 : else
887 8 : nWidth = nWdth;
888 8 : bRelWidth = bRelWdth;
889 8 : }
890 :
891 13 : inline SwHTMLTableLayoutColumn *HTMLTableColumn::CreateLayoutInfo()
892 : {
893 13 : return new SwHTMLTableLayoutColumn( nWidth, bRelWidth, bLeftBorder );
894 : }
895 :
896 10 : inline sal_uInt16 HTMLTableColumn::GetFrameFormatIdx( bool bBorderLine,
897 : sal_Int16 eVertOrient )
898 : {
899 : OSL_ENSURE( text::VertOrientation::TOP != eVertOrient, "Top ist nicht erlaubt" );
900 10 : sal_uInt16 n = bBorderLine ? 3 : 0;
901 10 : switch( eVertOrient )
902 : {
903 10 : case text::VertOrientation::CENTER: n+=1; break;
904 0 : case text::VertOrientation::BOTTOM: n+=2; break;
905 : default:
906 : ;
907 : }
908 10 : return n;
909 : }
910 :
911 2 : inline void HTMLTableColumn::SetFrameFormat( SwFrameFormat *pFormat, bool bBorderLine,
912 : sal_Int16 eVertOrient )
913 : {
914 2 : aFrameFormats[GetFrameFormatIdx(bBorderLine,eVertOrient)] = pFormat;
915 2 : }
916 :
917 8 : inline SwFrameFormat *HTMLTableColumn::GetFrameFormat( bool bBorderLine,
918 : sal_Int16 eVertOrient ) const
919 : {
920 8 : return aFrameFormats[GetFrameFormatIdx(bBorderLine,eVertOrient)];
921 : }
922 :
923 6 : void HTMLTable::InitCtor( const HTMLTableOptions *pOptions )
924 : {
925 6 : pResizeDrawObjs = 0;
926 6 : pDrawObjPrcWidths = 0;
927 :
928 6 : pRows = new HTMLTableRows;
929 6 : pColumns = new HTMLTableColumns;
930 6 : nRows = 0;
931 6 : nCurRow = 0; nCurCol = 0;
932 :
933 6 : pBox1 = 0;
934 6 : pBoxFormat = 0; pLineFormat = 0;
935 6 : pLineFrameFormatNoHeight = 0;
936 6 : pInhBGBrush = 0;
937 :
938 6 : pPrevStNd = 0;
939 6 : pSwTable = 0;
940 :
941 6 : bTopBorder = false; bRightBorder = false;
942 6 : bTopAlwd = true; bRightAlwd = true;
943 6 : bFillerTopBorder = false; bFillerBottomBorder = false;
944 6 : bInhLeftBorder = false; bInhRightBorder = false;
945 6 : bBordersSet = false;
946 6 : bForceFrame = false;
947 6 : nHeadlineRepeat = 0;
948 :
949 6 : nLeftMargin = 0;
950 6 : nRightMargin = 0;
951 :
952 6 : const Color& rBorderColor = pOptions->aBorderColor;
953 :
954 6 : long nBorderOpt = (long)pOptions->nBorder;
955 : long nPWidth = nBorderOpt==USHRT_MAX ? NETSCAPE_DFLT_BORDER
956 6 : : nBorderOpt;
957 6 : long nPHeight = nBorderOpt==USHRT_MAX ? 0 : nBorderOpt;
958 6 : SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
959 :
960 : // nBorder gibt die Breite der Umrandung an, wie sie in die
961 : // Breitenberechnung in Netscape einfliesst. Wenn pOption->nBorder
962 : // == USHRT_MAX, wurde keine BORDER-Option angegeben. Trotzdem fliesst
963 : // eine 1 Pixel breite Umrandung in die Breitenberechnung mit ein.
964 6 : nBorder = (sal_uInt16)nPWidth;
965 6 : if( nBorderOpt==USHRT_MAX )
966 6 : nPWidth = 0;
967 :
968 : // HACK: ein Pixel-breite Linien sollen zur Haarlinie werden, wenn
969 : // wir mit doppelter Umrandung arbeiten
970 6 : if( pOptions->nCellSpacing!=0 && nBorderOpt==1 )
971 : {
972 0 : nPWidth = 1;
973 0 : nPHeight = 1;
974 : }
975 :
976 6 : if ( pOptions->nCellSpacing != 0 )
977 : {
978 2 : aTopBorderLine.SetBorderLineStyle(table::BorderLineStyle::DOUBLE);
979 : }
980 6 : aTopBorderLine.SetWidth( nPHeight );
981 6 : aTopBorderLine.SetColor( rBorderColor );
982 6 : aBottomBorderLine = aTopBorderLine;
983 :
984 6 : if( nPWidth == nPHeight )
985 : {
986 6 : aLeftBorderLine = aTopBorderLine;
987 : }
988 : else
989 : {
990 0 : if ( pOptions->nCellSpacing != 0 )
991 : {
992 0 : aLeftBorderLine.SetBorderLineStyle(table::BorderLineStyle::DOUBLE);
993 : }
994 0 : aLeftBorderLine.SetWidth( nPWidth );
995 0 : aLeftBorderLine.SetColor( rBorderColor );
996 : }
997 6 : aRightBorderLine = aLeftBorderLine;
998 :
999 6 : if( pOptions->nCellSpacing != 0 )
1000 : {
1001 2 : aBorderLine.SetBorderLineStyle(table::BorderLineStyle::DOUBLE);
1002 2 : aBorderLine.SetWidth( DEF_LINE_WIDTH_0 );
1003 : }
1004 : else
1005 : {
1006 4 : aBorderLine.SetWidth( DEF_LINE_WIDTH_0 );
1007 : }
1008 6 : aBorderLine.SetColor( rBorderColor );
1009 :
1010 6 : if( nCellPadding )
1011 : {
1012 6 : if( nCellPadding==USHRT_MAX )
1013 0 : nCellPadding = MIN_BORDER_DIST; // default
1014 : else
1015 : {
1016 6 : nCellPadding = SwHTMLParser::ToTwips( nCellPadding );
1017 6 : if( nCellPadding<MIN_BORDER_DIST )
1018 0 : nCellPadding = MIN_BORDER_DIST;
1019 : }
1020 : }
1021 6 : if( nCellSpacing )
1022 : {
1023 2 : if( nCellSpacing==USHRT_MAX )
1024 2 : nCellSpacing = NETSCAPE_DFLT_CELLSPACING;
1025 2 : nCellSpacing = SwHTMLParser::ToTwips( nCellSpacing );
1026 : }
1027 :
1028 6 : nPWidth = pOptions->nHSpace;
1029 6 : nPHeight = pOptions->nVSpace;
1030 6 : SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
1031 6 : nHSpace = (sal_uInt16)nPWidth;
1032 6 : nVSpace = (sal_uInt16)nPHeight;
1033 :
1034 6 : bColSpec = false;
1035 :
1036 : pBGBrush = pParser->CreateBrushItem(
1037 : pOptions->bBGColor ? &(pOptions->aBGColor) : 0,
1038 6 : pOptions->aBGImage, aEmptyOUStr, aEmptyOUStr, aEmptyOUStr );
1039 :
1040 6 : pContext = 0;
1041 6 : pParentContents = 0;
1042 :
1043 6 : aId = pOptions->aId;
1044 6 : aClass = pOptions->aClass;
1045 6 : aStyle = pOptions->aStyle;
1046 6 : aDir = pOptions->aDir;
1047 6 : }
1048 :
1049 6 : HTMLTable::HTMLTable( SwHTMLParser* pPars, HTMLTable *pTopTab,
1050 : bool bParHead,
1051 : bool bHasParentSec, bool bHasToFlw,
1052 : const HTMLTableOptions *pOptions ) :
1053 : nCols( pOptions->nCols ),
1054 : nFilledCols( 0 ),
1055 : nCellPadding( pOptions->nCellPadding ),
1056 : nCellSpacing( pOptions->nCellSpacing ),
1057 : nBoxes( 1 ),
1058 : pCaptionStartNode( 0 ),
1059 6 : bTableAdjustOfTag( !pTopTab && pOptions->bTableAdjust ),
1060 : bIsParentHead( bParHead ),
1061 : bHasParentSection( bHasParentSec ),
1062 : bHasToFly( bHasToFlw ),
1063 6 : bFixedCols( pOptions->nCols>0 ),
1064 : bPrcWidth( pOptions->bPrcWidth ),
1065 : pParser( pPars ),
1066 : pTopTable( pTopTab ? pTopTab : this ),
1067 : pLayoutInfo( 0 ),
1068 : nWidth( pOptions->nWidth ),
1069 : nHeight( pTopTab ? 0 : pOptions->nHeight ),
1070 : eTableAdjust( pOptions->eAdjust ),
1071 : eVertOri( pOptions->eVertOri ),
1072 : eFrame( pOptions->eFrame ),
1073 : eRules( pOptions->eRules ),
1074 : bTopCaption( false ),
1075 18 : bFirstCell( !pTopTab )
1076 : {
1077 6 : InitCtor( pOptions );
1078 :
1079 6 : for( sal_uInt16 i=0; i<nCols; i++ )
1080 0 : pColumns->push_back( new HTMLTableColumn );
1081 6 : }
1082 :
1083 12 : HTMLTable::~HTMLTable()
1084 : {
1085 6 : delete pResizeDrawObjs;
1086 6 : delete pDrawObjPrcWidths;
1087 :
1088 6 : delete pRows;
1089 6 : delete pColumns;
1090 6 : delete pBGBrush;
1091 6 : delete pInhBGBrush;
1092 :
1093 6 : delete pContext;
1094 :
1095 : // pLayoutInfo wurde entweder bereits geloescht oder muss aber es
1096 : // in den Besitz der SwTable uebergegangen.
1097 6 : }
1098 :
1099 6 : SwHTMLTableLayout *HTMLTable::CreateLayoutInfo()
1100 : {
1101 6 : sal_uInt16 nW = bPrcWidth ? nWidth : SwHTMLParser::ToTwips( nWidth );
1102 :
1103 6 : sal_uInt16 nBorderWidth = GetBorderWidth( aBorderLine, true );
1104 : sal_uInt16 nLeftBorderWidth =
1105 6 : ((*pColumns)[0]).bLeftBorder ? GetBorderWidth( aLeftBorderLine, true ) : 0;
1106 : sal_uInt16 nRightBorderWidth =
1107 6 : bRightBorder ? GetBorderWidth( aRightBorderLine, true ) : 0;
1108 6 : sal_uInt16 nInhLeftBorderWidth = 0;
1109 6 : sal_uInt16 nInhRightBorderWidth = 0;
1110 :
1111 : pLayoutInfo = new SwHTMLTableLayout(
1112 : pSwTable,
1113 : nRows, nCols, bFixedCols, bColSpec,
1114 : nW, bPrcWidth, nBorder, nCellPadding,
1115 : nCellSpacing, eTableAdjust,
1116 : nLeftMargin, nRightMargin,
1117 : nBorderWidth, nLeftBorderWidth, nRightBorderWidth,
1118 6 : nInhLeftBorderWidth, nInhRightBorderWidth );
1119 :
1120 6 : bool bExportable = true;
1121 : sal_uInt16 i;
1122 70 : for( i=0; i<nRows; i++ )
1123 : {
1124 64 : HTMLTableRow *pRow = &(*pRows)[i];
1125 350 : for( sal_uInt16 j=0; j<nCols; j++ )
1126 : {
1127 : SwHTMLTableLayoutCell *pLayoutCell =
1128 286 : pRow->GetCell(j)->CreateLayoutInfo();
1129 :
1130 286 : pLayoutInfo->SetCell( pLayoutCell, i, j );
1131 :
1132 286 : if( bExportable )
1133 : {
1134 : SwHTMLTableLayoutCnts *pLayoutCnts =
1135 286 : pLayoutCell->GetContents();
1136 858 : bExportable = !pLayoutCnts ||
1137 572 : ( pLayoutCnts->GetStartNode() &&
1138 572 : !pLayoutCnts->GetNext() );
1139 : }
1140 : }
1141 : }
1142 :
1143 6 : pLayoutInfo->SetExportable( bExportable );
1144 :
1145 19 : for( i=0; i<nCols; i++ )
1146 13 : pLayoutInfo->SetColumn( ((*pColumns)[i]).CreateLayoutInfo(), i );
1147 :
1148 6 : return pLayoutInfo;
1149 : }
1150 :
1151 0 : inline void HTMLTable::SetCaption( const SwStartNode *pStNd, bool bTop )
1152 : {
1153 0 : pCaptionStartNode = pStNd;
1154 0 : bTopCaption = bTop;
1155 0 : }
1156 :
1157 0 : void HTMLTable::FixRowSpan( sal_uInt16 nRow, sal_uInt16 nCol,
1158 : const HTMLTableCnts *pCnts )
1159 : {
1160 0 : sal_uInt16 nRowSpan=1;
1161 : HTMLTableCell *pCell;
1162 0 : while( ( pCell=GetCell(nRow,nCol), pCell->GetContents()==pCnts ) )
1163 : {
1164 0 : pCell->SetRowSpan( nRowSpan );
1165 0 : if( pLayoutInfo )
1166 0 : pLayoutInfo->GetCell(nRow,nCol)->SetRowSpan( nRowSpan );
1167 :
1168 0 : if( !nRow ) break;
1169 0 : nRowSpan++; nRow--;
1170 : }
1171 0 : }
1172 :
1173 0 : void HTMLTable::ProtectRowSpan( sal_uInt16 nRow, sal_uInt16 nCol, sal_uInt16 nRowSpan )
1174 : {
1175 0 : for( sal_uInt16 i=0; i<nRowSpan; i++ )
1176 : {
1177 0 : GetCell(nRow+i,nCol)->SetProtected();
1178 0 : if( pLayoutInfo )
1179 0 : pLayoutInfo->GetCell(nRow+i,nCol)->SetProtected();
1180 : }
1181 0 : }
1182 :
1183 : // Suchen des SwStartNodes der letzten belegten Vorgaengerbox
1184 0 : const SwStartNode* HTMLTable::GetPrevBoxStartNode( sal_uInt16 nRow, sal_uInt16 nCol ) const
1185 : {
1186 0 : const HTMLTableCnts *pPrevCnts = 0;
1187 :
1188 0 : if( 0==nRow )
1189 : {
1190 : // immer die Vorgaenger-Zelle
1191 0 : if( nCol>0 )
1192 0 : pPrevCnts = GetCell( 0, nCol-1 )->GetContents();
1193 : else
1194 0 : return pPrevStNd;
1195 : }
1196 0 : else if( USHRT_MAX==nRow && USHRT_MAX==nCol )
1197 : // der Contents der letzten Zelle
1198 0 : pPrevCnts = GetCell( nRows-1, nCols-1 )->GetContents();
1199 : else
1200 : {
1201 : sal_uInt16 i;
1202 0 : HTMLTableRow *pPrevRow = &(*pRows)[nRow-1];
1203 :
1204 : // evtl. eine Zelle in der aktuellen Zeile
1205 0 : i = nCol;
1206 0 : while( i )
1207 : {
1208 0 : i--;
1209 0 : if( 1 == pPrevRow->GetCell(i)->GetRowSpan() )
1210 : {
1211 0 : pPrevCnts = GetCell(nRow,i)->GetContents();
1212 0 : break;
1213 : }
1214 : }
1215 :
1216 : // sonst die letzte gefuellte Zelle der Zeile davor suchen
1217 0 : if( !pPrevCnts )
1218 : {
1219 0 : i = nCols;
1220 0 : while( !pPrevCnts && i )
1221 : {
1222 0 : i--;
1223 0 : pPrevCnts = pPrevRow->GetCell(i)->GetContents();
1224 : }
1225 : }
1226 : }
1227 : OSL_ENSURE( pPrevCnts, "keine gefuellte Vorgaenger-Zelle gefunden" );
1228 0 : if( !pPrevCnts )
1229 : {
1230 0 : pPrevCnts = GetCell(0,0)->GetContents();
1231 0 : if( !pPrevCnts )
1232 0 : return pPrevStNd;
1233 : }
1234 :
1235 0 : while( pPrevCnts->Next() )
1236 0 : pPrevCnts = pPrevCnts->Next();
1237 :
1238 0 : return ( pPrevCnts->GetStartNode() ? pPrevCnts->GetStartNode()
1239 0 : : pPrevCnts->GetTable()->GetPrevBoxStartNode( USHRT_MAX, USHRT_MAX ) );
1240 : }
1241 :
1242 0 : static bool IsBoxEmpty( const SwTableBox *pBox )
1243 : {
1244 0 : const SwStartNode *pSttNd = pBox->GetSttNd();
1245 0 : if( pSttNd &&
1246 0 : pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex() )
1247 : {
1248 : const SwContentNode *pCNd =
1249 0 : pSttNd->GetNodes()[pSttNd->GetIndex()+1]->GetContentNode();
1250 0 : if( pCNd && !pCNd->Len() )
1251 0 : return true;
1252 : }
1253 :
1254 0 : return false;
1255 : }
1256 :
1257 0 : sal_uInt16 HTMLTable::GetTopCellSpace( sal_uInt16 nRow, sal_uInt16 nRowSpan,
1258 : bool bSwBorders ) const
1259 : {
1260 0 : sal_uInt16 nSpace = nCellPadding;
1261 :
1262 0 : if( nRow == 0 )
1263 : {
1264 0 : nSpace += nBorder + nCellSpacing;
1265 0 : if( bSwBorders )
1266 : {
1267 : sal_uInt16 nTopBorderWidth =
1268 0 : GetBorderWidth( aTopBorderLine, true );
1269 0 : if( nSpace < nTopBorderWidth )
1270 0 : nSpace = nTopBorderWidth;
1271 : }
1272 : }
1273 0 : else if( bSwBorders && (*pRows)[nRow+nRowSpan-1].bBottomBorder &&
1274 : nSpace < MIN_BORDER_DIST )
1275 : {
1276 : OSL_ENSURE( !nCellPadding, "GetTopCellSpace: CELLPADDING!=0" );
1277 : // Wenn die Gegenueberliegende Seite umrandet ist muessen
1278 : // wir zumindest den minimalen Abstand zum Inhalt
1279 : // beruecksichtigen. (Koennte man zusaetzlich auch an
1280 : // nCellPadding festmachen.)
1281 0 : nSpace = MIN_BORDER_DIST;
1282 : }
1283 :
1284 0 : return nSpace;
1285 : }
1286 :
1287 0 : sal_uInt16 HTMLTable::GetBottomCellSpace( sal_uInt16 nRow, sal_uInt16 nRowSpan,
1288 : bool bSwBorders ) const
1289 : {
1290 0 : sal_uInt16 nSpace = nCellSpacing + nCellPadding;
1291 :
1292 0 : if( nRow+nRowSpan == nRows )
1293 : {
1294 0 : nSpace = nSpace + nBorder;
1295 :
1296 0 : if( bSwBorders )
1297 : {
1298 : sal_uInt16 nBottomBorderWidth =
1299 0 : GetBorderWidth( aBottomBorderLine, true );
1300 0 : if( nSpace < nBottomBorderWidth )
1301 0 : nSpace = nBottomBorderWidth;
1302 : }
1303 : }
1304 0 : else if( bSwBorders )
1305 : {
1306 0 : if( (*pRows)[nRow+nRowSpan+1].bBottomBorder )
1307 : {
1308 0 : sal_uInt16 nBorderWidth = GetBorderWidth( aBorderLine, true );
1309 0 : if( nSpace < nBorderWidth )
1310 0 : nSpace = nBorderWidth;
1311 : }
1312 0 : else if( nRow==0 && bTopBorder && nSpace < MIN_BORDER_DIST )
1313 : {
1314 : OSL_ENSURE( GetBorderWidth( aTopBorderLine, true ) > 0,
1315 : "GetBottomCellSpace: |aTopLine| == 0" );
1316 : OSL_ENSURE( !nCellPadding, "GetBottomCellSpace: CELLPADDING!=0" );
1317 : // Wenn die Gegenueberliegende Seite umrandet ist muessen
1318 : // wir zumindest den minimalen Abstand zum Inhalt
1319 : // beruecksichtigen. (Koennte man zusaetzlich auch an
1320 : // nCellPadding festmachen.)
1321 0 : nSpace = MIN_BORDER_DIST;
1322 : }
1323 : }
1324 :
1325 0 : return nSpace;
1326 : }
1327 :
1328 286 : void HTMLTable::FixFrameFormat( SwTableBox *pBox,
1329 : sal_uInt16 nRow, sal_uInt16 nCol,
1330 : sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
1331 : bool bFirstPara, bool bLastPara ) const
1332 : {
1333 286 : SwFrameFormat *pFrameFormat = 0; // frame::Frame-Format
1334 286 : sal_Int16 eVOri = text::VertOrientation::NONE;
1335 286 : const SvxBrushItem *pBGBrushItem = 0; // Hintergrund
1336 286 : boost::shared_ptr<SvxBoxItem> pBoxItem;
1337 286 : bool bTopLine = false, bBottomLine = false, bLastBottomLine = false;
1338 286 : bool bReUsable = false; // Format nochmals verwendbar?
1339 286 : sal_uInt16 nEmptyRows = 0;
1340 286 : bool bHasNumFormat = false;
1341 286 : bool bHasValue = false;
1342 286 : sal_uInt32 nNumFormat = 0;
1343 286 : double nValue = 0.0;
1344 :
1345 286 : HTMLTableColumn *pColumn = &(*pColumns)[nCol];
1346 :
1347 286 : if( pBox->GetSttNd() )
1348 : {
1349 : // die Hintergrundfarbe/-grafik bestimmen
1350 286 : const HTMLTableCell *pCell = GetCell( nRow, nCol );
1351 286 : pBoxItem = pCell->GetBoxItem();
1352 286 : pBGBrushItem = pCell->GetBGBrush();
1353 286 : if( !pBGBrushItem )
1354 : {
1355 : // Wenn die Zelle ueber mehrere Zeilen geht muss ein evtl.
1356 : // an der Zeile gesetzter Hintergrund an die Zelle uebernommen
1357 : // werden.
1358 : // Wenn es sich um eine Tabelle in der Tabelle handelt und
1359 : // die Zelle ueber die gesamte Heoehe der Tabelle geht muss
1360 : // ebenfalls der Hintergrund der Zeile uebernommen werden, weil
1361 : // die Line von der GC (zu Recht) wegoptimiert wird.
1362 23 : if( nRowSpan > 1 || (this != pTopTable && nRowSpan==nRows) )
1363 : {
1364 0 : pBGBrushItem = (*pRows)[nRow].GetBGBrush();
1365 0 : if( !pBGBrushItem && this != pTopTable )
1366 : {
1367 0 : pBGBrushItem = GetBGBrush();
1368 0 : if( !pBGBrushItem )
1369 0 : pBGBrushItem = GetInhBGBrush();
1370 : }
1371 : }
1372 : }
1373 :
1374 286 : bTopLine = 0==nRow && bTopBorder && bFirstPara;
1375 286 : if( (*pRows)[nRow+nRowSpan-1].bBottomBorder && bLastPara )
1376 : {
1377 0 : nEmptyRows = (*pRows)[nRow+nRowSpan-1].GetEmptyRows();
1378 0 : if( nRow+nRowSpan == nRows )
1379 0 : bLastBottomLine = true;
1380 : else
1381 0 : bBottomLine = true;
1382 : }
1383 :
1384 286 : eVOri = pCell->GetVertOri();
1385 286 : bHasNumFormat = pCell->GetNumFormat( nNumFormat );
1386 286 : if( bHasNumFormat )
1387 0 : bHasValue = pCell->GetValue( nValue );
1388 :
1389 572 : if( nColSpan==1 && !bTopLine && !bLastBottomLine && !nEmptyRows &&
1390 309 : !pBGBrushItem && !bHasNumFormat && !pBoxItem)
1391 : {
1392 8 : pFrameFormat = pColumn->GetFrameFormat( bBottomLine, eVOri );
1393 8 : bReUsable = !pFrameFormat;
1394 : }
1395 : }
1396 :
1397 286 : if( !pFrameFormat )
1398 : {
1399 280 : pFrameFormat = pBox->ClaimFrameFormat();
1400 :
1401 : // die Breite der Box berechnen
1402 : SwTwips nFrmWidth = (SwTwips)pLayoutInfo->GetColumn(nCol)
1403 280 : ->GetRelColWidth();
1404 280 : for( sal_uInt16 i=1; i<nColSpan; i++ )
1405 : nFrmWidth += (SwTwips)pLayoutInfo->GetColumn(nCol+i)
1406 0 : ->GetRelColWidth();
1407 :
1408 : // die Umrandung nur an Edit-Boxen setzen (bei der oberen und unteren
1409 : // Umrandung muss beruecks. werden, ob es sich um den ersten oder
1410 : // letzen Absatz der Zelle handelt)
1411 280 : if( pBox->GetSttNd() )
1412 : {
1413 280 : bool bSet = (nCellPadding > 0);
1414 :
1415 280 : SvxBoxItem aBoxItem( RES_BOX );
1416 280 : long nInnerFrmWidth = nFrmWidth;
1417 :
1418 280 : if( bTopLine )
1419 : {
1420 0 : aBoxItem.SetLine( &aTopBorderLine, SvxBoxItemLine::TOP );
1421 0 : bSet = true;
1422 : }
1423 280 : if( bLastBottomLine )
1424 : {
1425 0 : aBoxItem.SetLine( &aBottomBorderLine, SvxBoxItemLine::BOTTOM );
1426 0 : bSet = true;
1427 : }
1428 280 : else if( bBottomLine )
1429 : {
1430 0 : if( nEmptyRows && !aBorderLine.GetInWidth() )
1431 : {
1432 : // Leere Zeilen koennen zur Zeit nur dann ueber
1433 : // dicke Linien simuliert werden, wenn die Linie
1434 : // einfach ist.
1435 0 : SvxBorderLine aThickBorderLine( aBorderLine );
1436 :
1437 0 : sal_uInt16 nBorderWidth = aBorderLine.GetOutWidth();
1438 0 : nBorderWidth *= (nEmptyRows + 1);
1439 : aThickBorderLine.SetBorderLineStyle(
1440 0 : table::BorderLineStyle::SOLID);
1441 0 : aThickBorderLine.SetWidth( nBorderWidth );
1442 0 : aBoxItem.SetLine( &aThickBorderLine, SvxBoxItemLine::BOTTOM );
1443 : }
1444 : else
1445 : {
1446 0 : aBoxItem.SetLine( &aBorderLine, SvxBoxItemLine::BOTTOM );
1447 : }
1448 0 : bSet = true;
1449 : }
1450 280 : if( ((*pColumns)[nCol]).bLeftBorder )
1451 : {
1452 : const SvxBorderLine& rBorderLine =
1453 0 : 0==nCol ? aLeftBorderLine : aBorderLine;
1454 0 : aBoxItem.SetLine( &rBorderLine, SvxBoxItemLine::LEFT );
1455 0 : nInnerFrmWidth -= GetBorderWidth( rBorderLine );
1456 0 : bSet = true;
1457 : }
1458 280 : if( nCol+nColSpan == nCols && bRightBorder )
1459 : {
1460 0 : aBoxItem.SetLine( &aRightBorderLine, SvxBoxItemLine::RIGHT );
1461 0 : nInnerFrmWidth -= GetBorderWidth( aRightBorderLine );
1462 0 : bSet = true;
1463 : }
1464 :
1465 280 : if (pBoxItem)
1466 : {
1467 278 : pFrameFormat->SetFormatAttr( *pBoxItem );
1468 : }
1469 2 : else if (bSet)
1470 : {
1471 : // BorderDist nicht mehr Bestandteil einer Zelle mit fixer Breite
1472 : sal_uInt16 nBDist = static_cast< sal_uInt16 >(
1473 2 : (2*nCellPadding <= nInnerFrmWidth) ? nCellPadding
1474 2 : : (nInnerFrmWidth / 2) );
1475 : // wir setzen das Item nur, wenn es eine Umrandung gibt
1476 : // oder eine sheet::Border-Distanz vorgegeben ist. Fehlt letztere,
1477 : // dann gibt es eine Umrandung, und wir muessen die Distanz
1478 : // setzen
1479 2 : aBoxItem.SetDistance( nBDist ? nBDist : MIN_BORDER_DIST );
1480 2 : pFrameFormat->SetFormatAttr( aBoxItem );
1481 : }
1482 : else
1483 0 : pFrameFormat->ResetFormatAttr( RES_BOX );
1484 :
1485 280 : if( pBGBrushItem )
1486 : {
1487 263 : pFrameFormat->SetFormatAttr( *pBGBrushItem );
1488 : }
1489 : else
1490 17 : pFrameFormat->ResetFormatAttr( RES_BACKGROUND );
1491 :
1492 : // Format nur setzten, wenn es auch einen Value gibt oder die Box leer ist.
1493 280 : if( bHasNumFormat && (bHasValue || IsBoxEmpty(pBox)) )
1494 : {
1495 : bool bLock = pFrameFormat->GetDoc()->GetNumberFormatter()
1496 0 : ->IsTextFormat( nNumFormat );
1497 0 : SfxItemSet aItemSet( *pFrameFormat->GetAttrSet().GetPool(),
1498 0 : RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
1499 0 : SvxAdjust eAdjust = SVX_ADJUST_END;
1500 0 : SwContentNode *pCNd = 0;
1501 0 : if( !bLock )
1502 : {
1503 0 : const SwStartNode *pSttNd = pBox->GetSttNd();
1504 0 : pCNd = pSttNd->GetNodes()[pSttNd->GetIndex()+1]
1505 0 : ->GetContentNode();
1506 : const SfxPoolItem *pItem;
1507 0 : if( pCNd && pCNd->HasSwAttrSet() &&
1508 0 : SfxItemState::SET==pCNd->GetpSwAttrSet()->GetItemState(
1509 0 : RES_PARATR_ADJUST, false, &pItem ) )
1510 : {
1511 : eAdjust = static_cast<const SvxAdjustItem *>(pItem)
1512 0 : ->GetAdjust();
1513 : }
1514 : }
1515 0 : aItemSet.Put( SwTableBoxNumFormat(nNumFormat) );
1516 0 : if( bHasValue )
1517 0 : aItemSet.Put( SwTableBoxValue(nValue) );
1518 :
1519 0 : if( bLock )
1520 0 : pFrameFormat->LockModify();
1521 0 : pFrameFormat->SetFormatAttr( aItemSet );
1522 0 : if( bLock )
1523 0 : pFrameFormat->UnlockModify();
1524 0 : else if( pCNd && SVX_ADJUST_END != eAdjust )
1525 : {
1526 0 : SvxAdjustItem aAdjItem( eAdjust, RES_PARATR_ADJUST );
1527 0 : pCNd->SetAttr( aAdjItem );
1528 0 : }
1529 : }
1530 : else
1531 280 : pFrameFormat->ResetFormatAttr( RES_BOXATR_FORMAT );
1532 :
1533 : OSL_ENSURE( eVOri != text::VertOrientation::TOP, "text::VertOrientation::TOP ist nicht erlaubt!" );
1534 280 : if( text::VertOrientation::NONE != eVOri )
1535 : {
1536 17 : pFrameFormat->SetFormatAttr( SwFormatVertOrient( 0, eVOri ) );
1537 : }
1538 : else
1539 263 : pFrameFormat->ResetFormatAttr( RES_VERT_ORIENT );
1540 :
1541 280 : if( bReUsable )
1542 2 : pColumn->SetFrameFormat( pFrameFormat, bBottomLine, eVOri );
1543 : }
1544 : else
1545 : {
1546 0 : pFrameFormat->ResetFormatAttr( RES_BOX );
1547 0 : pFrameFormat->ResetFormatAttr( RES_BACKGROUND );
1548 0 : pFrameFormat->ResetFormatAttr( RES_VERT_ORIENT );
1549 0 : pFrameFormat->ResetFormatAttr( RES_BOXATR_FORMAT );
1550 : }
1551 : }
1552 : else
1553 : {
1554 : OSL_ENSURE( pBox->GetSttNd() ||
1555 : SfxItemState::SET!=pFrameFormat->GetAttrSet().GetItemState(
1556 : RES_VERT_ORIENT, false ),
1557 : "Box ohne Inhalt hat vertikale Ausrichtung" );
1558 6 : pBox->ChgFrameFormat( static_cast<SwTableBoxFormat*>(pFrameFormat) );
1559 286 : }
1560 :
1561 286 : }
1562 :
1563 0 : void HTMLTable::FixFillerFrameFormat( SwTableBox *pBox, bool bRight ) const
1564 : {
1565 0 : SwFrameFormat *pFrameFormat = pBox->ClaimFrameFormat();
1566 :
1567 0 : if( bFillerTopBorder || bFillerBottomBorder ||
1568 0 : (!bRight && bInhLeftBorder) || (bRight && bInhRightBorder) )
1569 : {
1570 0 : SvxBoxItem aBoxItem( RES_BOX );
1571 0 : if( bFillerTopBorder )
1572 0 : aBoxItem.SetLine( &aTopBorderLine, SvxBoxItemLine::TOP );
1573 0 : if( bFillerBottomBorder )
1574 0 : aBoxItem.SetLine( &aBottomBorderLine, SvxBoxItemLine::BOTTOM );
1575 0 : if( !bRight && bInhLeftBorder )
1576 0 : aBoxItem.SetLine( &aInhLeftBorderLine, SvxBoxItemLine::LEFT );
1577 0 : if( bRight && bInhRightBorder )
1578 0 : aBoxItem.SetLine( &aInhRightBorderLine, SvxBoxItemLine::RIGHT );
1579 0 : aBoxItem.SetDistance( MIN_BORDER_DIST );
1580 0 : pFrameFormat->SetFormatAttr( aBoxItem );
1581 : }
1582 : else
1583 : {
1584 0 : pFrameFormat->ResetFormatAttr( RES_BOX );
1585 : }
1586 :
1587 0 : if( GetInhBGBrush() )
1588 0 : pFrameFormat->SetFormatAttr( *GetInhBGBrush() );
1589 : else
1590 0 : pFrameFormat->ResetFormatAttr( RES_BACKGROUND );
1591 :
1592 0 : pFrameFormat->ResetFormatAttr( RES_VERT_ORIENT );
1593 0 : pFrameFormat->ResetFormatAttr( RES_BOXATR_FORMAT );
1594 0 : }
1595 :
1596 286 : SwTableBox *HTMLTable::NewTableBox( const SwStartNode *pStNd,
1597 : SwTableLine *pUpper ) const
1598 : {
1599 : SwTableBox *pBox;
1600 :
1601 292 : if( pTopTable->pBox1 &&
1602 6 : pTopTable->pBox1->GetSttNd() == pStNd )
1603 : {
1604 : // wenn der StartNode dem StartNode der initial angelegten Box
1605 : // entspricht nehmen wir diese Box
1606 6 : pBox = pTopTable->pBox1;
1607 6 : pBox->SetUpper( pUpper );
1608 6 : pTopTable->pBox1 = 0;
1609 : }
1610 : else
1611 280 : pBox = new SwTableBox( pBoxFormat, *pStNd, pUpper );
1612 :
1613 286 : return pBox;
1614 : }
1615 :
1616 6 : static void ResetLineFrameFormatAttrs( SwFrameFormat *pFrameFormat )
1617 : {
1618 6 : pFrameFormat->ResetFormatAttr( RES_FRM_SIZE );
1619 6 : pFrameFormat->ResetFormatAttr( RES_BACKGROUND );
1620 : OSL_ENSURE( SfxItemState::SET!=pFrameFormat->GetAttrSet().GetItemState(
1621 : RES_VERT_ORIENT, false ),
1622 : "Zeile hat vertikale Ausrichtung" );
1623 6 : }
1624 :
1625 : // !!! kann noch vereinfacht werden
1626 64 : SwTableLine *HTMLTable::MakeTableLine( SwTableBox *pUpper,
1627 : sal_uInt16 nTopRow, sal_uInt16 nLeftCol,
1628 : sal_uInt16 nBottomRow, sal_uInt16 nRightCol )
1629 : {
1630 : SwTableLine *pLine;
1631 64 : if( this==pTopTable && !pUpper && 0==nTopRow )
1632 6 : pLine = (pSwTable->GetTabLines())[0];
1633 : else
1634 : pLine = new SwTableLine( pLineFrameFormatNoHeight ? pLineFrameFormatNoHeight
1635 : : pLineFormat,
1636 58 : 0, pUpper );
1637 :
1638 64 : HTMLTableRow *pTopRow = &(*pRows)[nTopRow];
1639 64 : sal_uInt16 nRowHeight = pTopRow->GetHeight();
1640 64 : const SvxBrushItem *pBGBrushItem = 0;
1641 64 : if( this == pTopTable || nTopRow>0 || nBottomRow<nRows )
1642 : {
1643 : // An der Line eine Frabe zu setzen macht keinen Sinn, wenn sie
1644 : // die auesserste und gleichzeitig einzige Zeile einer Tabelle in
1645 : // der Tabelle ist.
1646 64 : pBGBrushItem = pTopRow->GetBGBrush();
1647 :
1648 64 : if( !pBGBrushItem && this != pTopTable )
1649 : {
1650 : // Ein an einer Tabellen in der Tabelle gesetzter Hintergrund
1651 : // wird an den Rows gesetzt. Das gilt auch fuer den Hintergrund
1652 : // der Zelle, in dem die Tabelle vorkommt.
1653 0 : pBGBrushItem = GetBGBrush();
1654 0 : if( !pBGBrushItem )
1655 0 : pBGBrushItem = GetInhBGBrush();
1656 : }
1657 : }
1658 64 : if( nTopRow==nBottomRow-1 && (nRowHeight || pBGBrushItem) )
1659 : {
1660 0 : SwTableLineFormat *pFrameFormat = static_cast<SwTableLineFormat*>(pLine->ClaimFrameFormat());
1661 0 : ResetLineFrameFormatAttrs( pFrameFormat );
1662 :
1663 0 : if( nRowHeight )
1664 : {
1665 : // Tabellenhoehe einstellen. Da es sich um eine
1666 : // Mindesthoehe handelt, kann sie genauso wie in
1667 : // Netscape berechnet werden, also ohne Beruecksichtigung
1668 : // der tatsaechlichen Umrandungsbreite.
1669 0 : nRowHeight += GetTopCellSpace( nTopRow, 1, false ) +
1670 0 : GetBottomCellSpace( nTopRow, 1, false );
1671 :
1672 0 : pFrameFormat->SetFormatAttr( SwFormatFrmSize( ATT_MIN_SIZE, 0, nRowHeight ) );
1673 : }
1674 :
1675 0 : if( pBGBrushItem )
1676 : {
1677 0 : pFrameFormat->SetFormatAttr( *pBGBrushItem );
1678 0 : }
1679 :
1680 : }
1681 64 : else if( !pLineFrameFormatNoHeight )
1682 : {
1683 : // sonst muessen wir die Hoehe aus dem Attribut entfernen
1684 : // und koennen uns das Format merken
1685 6 : pLineFrameFormatNoHeight = static_cast<SwTableLineFormat*>(pLine->ClaimFrameFormat());
1686 :
1687 6 : ResetLineFrameFormatAttrs( pLineFrameFormatNoHeight );
1688 : }
1689 :
1690 64 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
1691 :
1692 64 : sal_uInt16 nStartCol = nLeftCol;
1693 414 : while( nStartCol<nRightCol )
1694 : {
1695 286 : sal_uInt16 nCol = nStartCol;
1696 286 : sal_uInt16 nSplitCol = nRightCol;
1697 286 : bool bSplitted = false;
1698 858 : while( !bSplitted )
1699 : {
1700 : OSL_ENSURE( nCol < nRightCol, "Zu weit gelaufen" );
1701 :
1702 286 : HTMLTableCell *pCell = GetCell(nTopRow,nCol);
1703 286 : const bool bSplit = 1 == pCell->GetColSpan();
1704 :
1705 : OSL_ENSURE((nCol != nRightCol-1) || bSplit, "Split-Flag wrong");
1706 286 : if( bSplit )
1707 : {
1708 286 : SwTableBox* pBox = 0;
1709 286 : HTMLTableCell *pCell2 = GetCell( nTopRow, nStartCol );
1710 286 : if( pCell2->GetColSpan() == (nCol+1-nStartCol) )
1711 : {
1712 : // Die HTML-Tabellen-Zellen bilden genau eine Box.
1713 : // Dann muss hinter der Box gesplittet werden
1714 286 : nSplitCol = nCol + 1;
1715 :
1716 286 : long nBoxRowSpan = pCell2->GetRowSpan();
1717 286 : if ( !pCell2->GetContents() || pCell2->IsCovered() )
1718 : {
1719 0 : if ( pCell2->IsCovered() )
1720 0 : nBoxRowSpan = -1 * nBoxRowSpan;
1721 :
1722 : const SwStartNode* pPrevStartNd =
1723 0 : GetPrevBoxStartNode( nTopRow, nStartCol );
1724 : HTMLTableCnts *pCnts = new HTMLTableCnts(
1725 0 : pParser->InsertTableSection(pPrevStartNd) );
1726 : SwHTMLTableLayoutCnts *pCntsLayoutInfo =
1727 0 : pCnts->CreateLayoutInfo();
1728 :
1729 0 : pCell2->SetContents( pCnts );
1730 0 : SwHTMLTableLayoutCell *pCurrCell = pLayoutInfo->GetCell( nTopRow, nStartCol );
1731 0 : pCurrCell->SetContents( pCntsLayoutInfo );
1732 0 : if( nBoxRowSpan < 0 )
1733 0 : pCurrCell->SetRowSpan( 0 );
1734 :
1735 : // ggf. COLSPAN beachten
1736 0 : for( sal_uInt16 j=nStartCol+1; j<nSplitCol; j++ )
1737 : {
1738 0 : GetCell(nTopRow,j)->SetContents( pCnts );
1739 : pLayoutInfo->GetCell( nTopRow, j )
1740 0 : ->SetContents( pCntsLayoutInfo );
1741 : }
1742 : }
1743 :
1744 : pBox = MakeTableBox( pLine, pCell2->GetContents(),
1745 : nTopRow, nStartCol,
1746 286 : nBottomRow, nSplitCol );
1747 :
1748 286 : if ( 1 != nBoxRowSpan )
1749 0 : pBox->setRowSpan( nBoxRowSpan );
1750 :
1751 286 : bSplitted = true;
1752 : }
1753 :
1754 : OSL_ENSURE( pBox, "Colspan trouble" );
1755 :
1756 286 : if( pBox )
1757 286 : rBoxes.push_back( pBox );
1758 : }
1759 286 : nCol++;
1760 : }
1761 286 : nStartCol = nSplitCol;
1762 : }
1763 :
1764 64 : return pLine;
1765 : }
1766 :
1767 286 : SwTableBox *HTMLTable::MakeTableBox( SwTableLine *pUpper,
1768 : HTMLTableCnts *pCnts,
1769 : sal_uInt16 nTopRow, sal_uInt16 nLeftCol,
1770 : sal_uInt16 nBottomRow, sal_uInt16 nRightCol )
1771 : {
1772 : SwTableBox *pBox;
1773 286 : sal_uInt16 nColSpan = nRightCol - nLeftCol;
1774 286 : sal_uInt16 nRowSpan = nBottomRow - nTopRow;
1775 :
1776 286 : if( !pCnts->Next() )
1777 : {
1778 : // nur eine Inhalts-Section
1779 286 : if( pCnts->GetStartNode() )
1780 : {
1781 : // und die ist keine Tabelle
1782 286 : pBox = NewTableBox( pCnts->GetStartNode(), pUpper );
1783 286 : pCnts->SetTableBox( pBox );
1784 : }
1785 : else
1786 : {
1787 : pCnts->GetTable()->InheritVertBorders( this, nLeftCol,
1788 0 : nRightCol-nLeftCol );
1789 : // und die ist eine Tabelle: dann bauen wir eine neue
1790 : // Box und fuegen die Zeilen der Tabelle in die Zeilen
1791 : // der Box ein
1792 0 : pBox = new SwTableBox( pBoxFormat, 0, pUpper );
1793 : sal_uInt16 nAbs, nRel;
1794 0 : pLayoutInfo->GetAvail( nLeftCol, nColSpan, nAbs, nRel );
1795 0 : sal_uInt16 nLSpace = pLayoutInfo->GetLeftCellSpace( nLeftCol, nColSpan );
1796 0 : sal_uInt16 nRSpace = pLayoutInfo->GetRightCellSpace( nLeftCol, nColSpan );
1797 0 : sal_uInt16 nInhSpace = pLayoutInfo->GetInhCellSpace( nLeftCol, nColSpan );
1798 : pCnts->GetTable()->MakeTable( pBox, nAbs, nRel, nLSpace, nRSpace,
1799 0 : nInhSpace );
1800 : }
1801 : }
1802 : else
1803 : {
1804 : // mehrere Inhalts Sections: dann brauchen wir eine Box mit Zeilen
1805 0 : pBox = new SwTableBox( pBoxFormat, 0, pUpper );
1806 0 : SwTableLines& rLines = pBox->GetTabLines();
1807 0 : bool bFirstPara = true;
1808 :
1809 0 : while( pCnts )
1810 : {
1811 0 : if( pCnts->GetStartNode() )
1812 : {
1813 : // normale Absaetze werden zu einer Box in einer Zeile
1814 : SwTableLine *pLine =
1815 : new SwTableLine( pLineFrameFormatNoHeight ? pLineFrameFormatNoHeight
1816 0 : : pLineFormat, 0, pBox );
1817 0 : if( !pLineFrameFormatNoHeight )
1818 : {
1819 : // Wenn es noch kein Line-Format ohne Hoehe gibt, koennen
1820 : // wir uns dieses her als soleches merken
1821 0 : pLineFrameFormatNoHeight = static_cast<SwTableLineFormat*>(pLine->ClaimFrameFormat());
1822 :
1823 0 : ResetLineFrameFormatAttrs( pLineFrameFormatNoHeight );
1824 : }
1825 :
1826 : SwTableBox* pCntBox = NewTableBox( pCnts->GetStartNode(),
1827 0 : pLine );
1828 0 : pCnts->SetTableBox( pCntBox );
1829 : FixFrameFormat( pCntBox, nTopRow, nLeftCol, nRowSpan, nColSpan,
1830 0 : bFirstPara, 0==pCnts->Next() );
1831 0 : pLine->GetTabBoxes().push_back( pCntBox );
1832 :
1833 0 : rLines.push_back( pLine );
1834 : }
1835 : else
1836 : {
1837 : pCnts->GetTable()->InheritVertBorders( this, nLeftCol,
1838 0 : nRightCol-nLeftCol );
1839 : // Tabellen werden direkt eingetragen
1840 : sal_uInt16 nAbs, nRel;
1841 0 : pLayoutInfo->GetAvail( nLeftCol, nColSpan, nAbs, nRel );
1842 : sal_uInt16 nLSpace = pLayoutInfo->GetLeftCellSpace( nLeftCol,
1843 0 : nColSpan );
1844 : sal_uInt16 nRSpace = pLayoutInfo->GetRightCellSpace( nLeftCol,
1845 0 : nColSpan );
1846 0 : sal_uInt16 nInhSpace = pLayoutInfo->GetInhCellSpace( nLeftCol, nColSpan );
1847 : pCnts->GetTable()->MakeTable( pBox, nAbs, nRel, nLSpace,
1848 0 : nRSpace, nInhSpace );
1849 : }
1850 :
1851 0 : pCnts = pCnts->Next();
1852 0 : bFirstPara = false;
1853 : }
1854 : }
1855 :
1856 286 : FixFrameFormat( pBox, nTopRow, nLeftCol, nRowSpan, nColSpan );
1857 :
1858 286 : return pBox;
1859 : }
1860 :
1861 0 : void HTMLTable::InheritBorders( const HTMLTable *pParent,
1862 : sal_uInt16 nRow, sal_uInt16 nCol,
1863 : sal_uInt16 nRowSpan, sal_uInt16 /*nColSpan*/,
1864 : bool bFirstPara, bool bLastPara )
1865 : {
1866 : OSL_ENSURE( nRows>0 && nCols>0 && nCurRow==nRows,
1867 : "Wurde CloseTable nicht aufgerufen?" );
1868 :
1869 : // Die Child-Tabelle muss einen Rahmen bekommen, wenn die umgebende
1870 : // Zelle einen Rand an der betreffenden Seite besitzt.
1871 : // Der obere bzw. untere Rand wird nur gesetzt, wenn die Tabelle
1872 : // ale erster bzw. letzter Absatz in der Zelle vorkommt. Ansonsten
1873 : // Fuer den linken/rechten Rand kann noch nicht entschieden werden,
1874 : // ob eine Umrandung der Tabelle noetig/moeglich ist, weil das davon
1875 : // abhaengt, ob "Filler"-Zellen eingefuegt werden. Hier werden deshalb
1876 : // erstmal nur Informationen gesammelt
1877 :
1878 0 : if( 0==nRow && pParent->bTopBorder && bFirstPara )
1879 : {
1880 0 : bTopBorder = true;
1881 0 : bFillerTopBorder = true; // auch Filler bekommt eine Umrandung
1882 0 : aTopBorderLine = pParent->aTopBorderLine;
1883 : }
1884 0 : if( (*pParent->pRows)[nRow+nRowSpan-1].bBottomBorder && bLastPara )
1885 : {
1886 0 : (*pRows)[nRows-1].bBottomBorder = true;
1887 0 : bFillerBottomBorder = true; // auch Filler bekommt eine Umrandung
1888 0 : aBottomBorderLine =
1889 0 : nRow+nRowSpan==pParent->nRows ? pParent->aBottomBorderLine
1890 0 : : pParent->aBorderLine;
1891 : }
1892 :
1893 : // Die Child Tabelle darf keinen oberen oder linken Rahmen bekommen,
1894 : // wenn der bereits durch die umgebende Tabelle gesetzt ist.
1895 : // Sie darf jedoch immer einen oberen Rand bekommen, wenn die Tabelle
1896 : // nicht der erste Absatz in der Zelle ist.
1897 0 : bTopAlwd = ( !bFirstPara || (pParent->bTopAlwd &&
1898 0 : (0==nRow || !((*pParent->pRows)[nRow-1]).bBottomBorder)) );
1899 :
1900 : // die Child-Tabelle muss die Farbe der Zelle erben, in der sie
1901 : // vorkommt, wenn sie keine eigene besitzt
1902 0 : const SvxBrushItem *pInhBG = pParent->GetCell(nRow,nCol)->GetBGBrush();
1903 0 : if( !pInhBG && pParent != pTopTable &&
1904 0 : pParent->GetCell(nRow,nCol)->GetRowSpan() == pParent->nRows )
1905 : {
1906 : // die ganze umgebende Tabelle ist eine Tabelle in der Tabelle
1907 : // und besteht nur aus einer Line, die bei der GC (zu Recht)
1908 : // wegoptimiert wird. Deshalb muss der Hintergrund der Line in
1909 : // diese Tabelle uebernommen werden.
1910 0 : pInhBG = (*pParent->pRows)[nRow].GetBGBrush();
1911 0 : if( !pInhBG )
1912 0 : pInhBG = pParent->GetBGBrush();
1913 0 : if( !pInhBG )
1914 0 : pInhBG = pParent->GetInhBGBrush();
1915 : }
1916 0 : if( pInhBG )
1917 0 : pInhBGBrush = new SvxBrushItem( *pInhBG );
1918 0 : }
1919 :
1920 0 : void HTMLTable::InheritVertBorders( const HTMLTable *pParent,
1921 : sal_uInt16 nCol, sal_uInt16 nColSpan )
1922 : {
1923 0 : sal_uInt16 nInhLeftBorderWidth = 0;
1924 0 : sal_uInt16 nInhRightBorderWidth = 0;
1925 :
1926 0 : if( nCol+nColSpan==pParent->nCols && pParent->bRightBorder )
1927 : {
1928 0 : bInhRightBorder = true; // erstmal nur merken
1929 0 : aInhRightBorderLine = pParent->aRightBorderLine;
1930 : nInhRightBorderWidth =
1931 0 : GetBorderWidth( aInhRightBorderLine, true ) + MIN_BORDER_DIST;
1932 : }
1933 :
1934 0 : if( ((*pParent->pColumns)[nCol]).bLeftBorder )
1935 : {
1936 0 : bInhLeftBorder = true; // erstmal nur merken
1937 0 : aInhLeftBorderLine = 0==nCol ? pParent->aLeftBorderLine
1938 0 : : pParent->aBorderLine;
1939 : nInhLeftBorderWidth =
1940 0 : GetBorderWidth( aInhLeftBorderLine, true ) + MIN_BORDER_DIST;
1941 : }
1942 :
1943 0 : if( !bInhLeftBorder && (bFillerTopBorder || bFillerBottomBorder) )
1944 0 : nInhLeftBorderWidth = 2 * MIN_BORDER_DIST;
1945 0 : if( !bInhRightBorder && (bFillerTopBorder || bFillerBottomBorder) )
1946 0 : nInhRightBorderWidth = 2 * MIN_BORDER_DIST;
1947 : pLayoutInfo->SetInhBorderWidths( nInhLeftBorderWidth,
1948 0 : nInhRightBorderWidth );
1949 :
1950 0 : bRightAlwd = ( pParent->bRightAlwd &&
1951 0 : (nCol+nColSpan==pParent->nCols ||
1952 0 : !((*pParent->pColumns)[nCol+nColSpan]).bLeftBorder) );
1953 0 : }
1954 :
1955 6 : void HTMLTable::SetBorders()
1956 : {
1957 : sal_uInt16 i;
1958 13 : for( i=1; i<nCols; i++ )
1959 14 : if( HTML_TR_ALL==eRules || HTML_TR_COLS==eRules ||
1960 14 : ((HTML_TR_ROWS==eRules || HTML_TR_GROUPS==eRules) &&
1961 0 : ((*pColumns)[i-1]).IsEndOfGroup()) )
1962 0 : ((*pColumns)[i]).bLeftBorder = true;
1963 :
1964 64 : for( i=0; i<nRows-1; i++ )
1965 116 : if( HTML_TR_ALL==eRules || HTML_TR_ROWS==eRules ||
1966 116 : ((HTML_TR_COLS==eRules || HTML_TR_GROUPS==eRules) &&
1967 0 : (*pRows)[i].IsEndOfGroup()) )
1968 0 : (*pRows)[i].bBottomBorder = true;
1969 :
1970 12 : if( bTopAlwd && (HTML_TF_ABOVE==eFrame || HTML_TF_HSIDES==eFrame ||
1971 6 : HTML_TF_BOX==eFrame) )
1972 0 : bTopBorder = true;
1973 12 : if( HTML_TF_BELOW==eFrame || HTML_TF_HSIDES==eFrame ||
1974 6 : HTML_TF_BOX==eFrame )
1975 0 : (*pRows)[nRows-1].bBottomBorder = true;
1976 12 : if( (HTML_TF_RHS==eFrame || HTML_TF_VSIDES==eFrame ||
1977 6 : HTML_TF_BOX==eFrame) )
1978 0 : bRightBorder = true;
1979 6 : if( HTML_TF_LHS==eFrame || HTML_TF_VSIDES==eFrame || HTML_TF_BOX==eFrame )
1980 0 : ((*pColumns)[0]).bLeftBorder = true;
1981 :
1982 70 : for( i=0; i<nRows; i++ )
1983 : {
1984 64 : HTMLTableRow *pRow = &(*pRows)[i];
1985 350 : for( sal_uInt16 j=0; j<nCols; j++ )
1986 : {
1987 286 : HTMLTableCell *pCell = pRow->GetCell(j);
1988 286 : if( pCell->GetContents() )
1989 : {
1990 286 : HTMLTableCnts *pCnts = pCell->GetContents();
1991 286 : bool bFirstPara = true;
1992 858 : while( pCnts )
1993 : {
1994 286 : HTMLTable *pTable = pCnts->GetTable();
1995 286 : if( pTable && !pTable->BordersSet() )
1996 : {
1997 : pTable->InheritBorders( this, i, j,
1998 0 : pCell->GetRowSpan(),
1999 0 : pCell->GetColSpan(),
2000 : bFirstPara,
2001 0 : 0==pCnts->Next() );
2002 0 : pTable->SetBorders();
2003 : }
2004 286 : bFirstPara = false;
2005 286 : pCnts = pCnts->Next();
2006 : }
2007 : }
2008 : }
2009 : }
2010 :
2011 6 : bBordersSet = true;
2012 6 : }
2013 :
2014 6 : sal_uInt16 HTMLTable::GetBorderWidth( const SvxBorderLine& rBLine,
2015 : bool bWithDistance ) const
2016 : {
2017 6 : sal_uInt16 nBorderWidth = rBLine.GetWidth();
2018 6 : if( bWithDistance )
2019 : {
2020 6 : if( nCellPadding )
2021 6 : nBorderWidth = nBorderWidth + nCellPadding;
2022 0 : else if( nBorderWidth )
2023 0 : nBorderWidth = nBorderWidth + MIN_BORDER_DIST;
2024 : }
2025 :
2026 6 : return nBorderWidth;
2027 : }
2028 :
2029 1705 : inline HTMLTableCell *HTMLTable::GetCell( sal_uInt16 nRow,
2030 : sal_uInt16 nCell ) const
2031 : {
2032 : OSL_ENSURE(nRow < pRows->size(), "invalid row index in HTML table");
2033 1705 : return (*pRows)[nRow].GetCell( nCell );
2034 : }
2035 :
2036 286 : SvxAdjust HTMLTable::GetInheritedAdjust() const
2037 : {
2038 567 : SvxAdjust eAdjust = (nCurCol<nCols ? ((*pColumns)[nCurCol]).GetAdjust()
2039 567 : : SVX_ADJUST_END );
2040 286 : if( SVX_ADJUST_END==eAdjust )
2041 286 : eAdjust = (*pRows)[nCurRow].GetAdjust();
2042 :
2043 286 : return eAdjust;
2044 : }
2045 :
2046 286 : sal_Int16 HTMLTable::GetInheritedVertOri() const
2047 : {
2048 : // text::VertOrientation::TOP ist der default!
2049 286 : sal_Int16 eVOri = (*pRows)[nCurRow].GetVertOri();
2050 286 : if( text::VertOrientation::TOP==eVOri && nCurCol<nCols )
2051 21 : eVOri = ((*pColumns)[nCurCol]).GetVertOri();
2052 286 : if( text::VertOrientation::TOP==eVOri )
2053 26 : eVOri = eVertOri;
2054 :
2055 : OSL_ENSURE( eVertOri != text::VertOrientation::TOP, "text::VertOrientation::TOP ist nicht erlaubt!" );
2056 286 : return eVOri;
2057 : }
2058 :
2059 286 : void HTMLTable::InsertCell( HTMLTableCnts *pCnts,
2060 : sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
2061 : sal_uInt16 nCellWidth, bool bRelWidth, sal_uInt16 nCellHeight,
2062 : sal_Int16 eVertOrient, SvxBrushItem *pBGBrushItem,
2063 : boost::shared_ptr<SvxBoxItem> const& rBoxItem,
2064 : bool bHasNumFormat, sal_uInt32 nNumFormat,
2065 : bool bHasValue, double nValue, bool bNoWrap )
2066 : {
2067 286 : if( !nRowSpan || (sal_uInt32)nCurRow + nRowSpan > USHRT_MAX )
2068 0 : nRowSpan = 1;
2069 :
2070 286 : if( !nColSpan || (sal_uInt32)nCurCol + nColSpan > USHRT_MAX )
2071 0 : nColSpan = 1;
2072 :
2073 286 : sal_uInt16 nColsReq = nCurCol + nColSpan; // benoetigte Spalten
2074 286 : sal_uInt16 nRowsReq = nCurRow + nRowSpan; // benoetigte Zeilen
2075 : sal_uInt16 i, j;
2076 :
2077 : // falls wir mehr Spalten benoetigen als wir zur Zeit haben,
2078 : // muessen wir in allen Zeilen noch Zellen hinzufuegen
2079 286 : if( nCols < nColsReq )
2080 : {
2081 10 : for( i=nCols; i<nColsReq; i++ )
2082 5 : pColumns->push_back( new HTMLTableColumn );
2083 10 : for( i=0; i<nRows; i++ )
2084 5 : (*pRows)[i].Expand( nColsReq, i<nCurRow );
2085 5 : nCols = nColsReq;
2086 : OSL_ENSURE(pColumns->size() == nCols,
2087 : "wrong number of columns after expanding");
2088 : }
2089 286 : if( nColsReq > nFilledCols )
2090 13 : nFilledCols = nColsReq;
2091 :
2092 : // falls wir mehr Zeilen benoetigen als wir zur Zeit haben,
2093 : // muessen wir noch neue Zeilen hinzufuegen
2094 286 : if( nRows < nRowsReq )
2095 : {
2096 0 : for( i=nRows; i<nRowsReq; i++ )
2097 0 : pRows->push_back( new HTMLTableRow(nCols) );
2098 0 : nRows = nRowsReq;
2099 : OSL_ENSURE(nRows == pRows->size(), "wrong number of rows in Insert");
2100 : }
2101 :
2102 : // Testen, ob eine Ueberschneidung vorliegt und diese
2103 : // gegebenfalls beseitigen
2104 286 : sal_uInt16 nSpanedCols = 0;
2105 286 : if( nCurRow>0 )
2106 : {
2107 273 : HTMLTableRow *pCurRow = &(*pRows)[nCurRow];
2108 546 : for( i=nCurCol; i<nColsReq; i++ )
2109 : {
2110 273 : HTMLTableCell *pCell = pCurRow->GetCell(i);
2111 273 : if( pCell->GetContents() )
2112 : {
2113 : // Der Inhalt reicht von einer weiter oben stehenden Zelle
2114 : // hier herein. Inhalt und Farbe der Zelle sind deshalb in
2115 : // jedem Fall noch dort verankert und koennen deshalb
2116 : // ueberschrieben werden bzw. von ProtectRowSpan geloescht
2117 : // (Inhalt) oder kopiert (Farbe) werden.
2118 0 : nSpanedCols = i + pCell->GetColSpan();
2119 0 : FixRowSpan( nCurRow-1, i, pCell->GetContents() );
2120 0 : if( pCell->GetRowSpan() > nRowSpan )
2121 : ProtectRowSpan( nRowsReq, i,
2122 0 : pCell->GetRowSpan()-nRowSpan );
2123 : }
2124 : }
2125 273 : for( i=nColsReq; i<nSpanedCols; i++ )
2126 : {
2127 : // Auch diese Inhalte sind in jedem Fall nich in der Zeile
2128 : // darueber verankert.
2129 0 : HTMLTableCell *pCell = pCurRow->GetCell(i);
2130 0 : FixRowSpan( nCurRow-1, i, pCell->GetContents() );
2131 0 : ProtectRowSpan( nCurRow, i, pCell->GetRowSpan() );
2132 : }
2133 : }
2134 :
2135 : // Fill the cells
2136 572 : for( i=nColSpan; i>0; i-- )
2137 : {
2138 572 : for( j=nRowSpan; j>0; j-- )
2139 : {
2140 286 : const bool bCovered = i != nColSpan || j != nRowSpan;
2141 : GetCell( nRowsReq-j, nColsReq-i )
2142 : ->Set( pCnts, j, i, eVertOrient, pBGBrushItem, rBoxItem,
2143 286 : bHasNumFormat, nNumFormat, bHasValue, nValue, bNoWrap, bCovered );
2144 : }
2145 : }
2146 :
2147 286 : Size aTwipSz( bRelWidth ? 0 : nCellWidth, nCellHeight );
2148 286 : if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() )
2149 : {
2150 : aTwipSz = Application::GetDefaultDevice()
2151 17 : ->PixelToLogic( aTwipSz, MapMode( MAP_TWIP ) );
2152 : }
2153 :
2154 : // die Breite nur in die erste Zelle setzen!
2155 286 : if( nCellWidth )
2156 : {
2157 280 : sal_uInt16 nTmp = bRelWidth ? nCellWidth : (sal_uInt16)aTwipSz.Width();
2158 280 : GetCell( nCurRow, nCurCol )->SetWidth( nTmp, bRelWidth );
2159 : }
2160 :
2161 : // Ausserdem noch die Hoehe merken
2162 286 : if( nCellHeight && 1==nRowSpan )
2163 : {
2164 0 : if( nCellHeight < MINLAY )
2165 0 : nCellHeight = MINLAY;
2166 0 : (*pRows)[nCurRow].SetHeight( (sal_uInt16)aTwipSz.Height() );
2167 : }
2168 :
2169 : // den Spaltenzaehler hinter die neuen Zellen setzen
2170 286 : nCurCol = nColsReq;
2171 286 : if( nSpanedCols > nCurCol )
2172 0 : nCurCol = nSpanedCols;
2173 :
2174 : // und die naechste freie Zelle suchen
2175 572 : while( nCurCol<nCols && GetCell(nCurRow,nCurCol)->IsUsed() )
2176 0 : nCurCol++;
2177 286 : }
2178 :
2179 6 : inline void HTMLTable::CloseSection( bool bHead )
2180 : {
2181 : // die vorhergende Section beenden, falls es schon eine Zeile gibt
2182 : OSL_ENSURE( nCurRow<=nRows, "ungeultige aktuelle Zeile" );
2183 6 : if( nCurRow>0 && nCurRow<=nRows )
2184 6 : (*pRows)[nCurRow-1].SetEndOfGroup();
2185 6 : if( bHead )
2186 0 : nHeadlineRepeat = nCurRow;
2187 6 : }
2188 :
2189 64 : void HTMLTable::OpenRow( SvxAdjust eAdjust, sal_Int16 eVertOrient,
2190 : SvxBrushItem *pBGBrushItem )
2191 : {
2192 64 : sal_uInt16 nRowsReq = nCurRow+1; // Anzahl benoetigter Zeilen;
2193 :
2194 : // die naechste Zeile anlegen, falls sie nicht schon da ist
2195 64 : if( nRows<nRowsReq )
2196 : {
2197 128 : for( sal_uInt16 i=nRows; i<nRowsReq; i++ )
2198 64 : pRows->push_back( new HTMLTableRow(nCols) );
2199 64 : nRows = nRowsReq;
2200 : OSL_ENSURE( nRows==pRows->size(),
2201 : "Zeilenzahl in OpenRow stimmt nicht" );
2202 : }
2203 :
2204 64 : HTMLTableRow *pCurRow = &((*pRows)[nCurRow]);
2205 64 : pCurRow->SetAdjust( eAdjust );
2206 64 : pCurRow->SetVertOri( eVertOrient );
2207 64 : if( pBGBrushItem )
2208 0 : (*pRows)[nCurRow].SetBGBrush( pBGBrushItem );
2209 :
2210 : // den Spaltenzaehler wieder an den Anfang setzen
2211 64 : nCurCol=0;
2212 :
2213 : // und die naechste freie Zelle suchen
2214 128 : while( nCurCol<nCols && GetCell(nCurRow,nCurCol)->IsUsed() )
2215 0 : nCurCol++;
2216 64 : }
2217 :
2218 64 : void HTMLTable::CloseRow( bool bEmpty )
2219 : {
2220 : OSL_ENSURE( nCurRow<nRows, "aktulle Zeile hinter dem Tabellenende" );
2221 :
2222 : // leere Zellen bekommen einfach einen etwas dickeren unteren Rand!
2223 64 : if( bEmpty )
2224 : {
2225 0 : if( nCurRow > 0 )
2226 0 : (*pRows)[nCurRow-1].IncEmptyRows();
2227 64 : return;
2228 : }
2229 :
2230 64 : HTMLTableRow *pRow = &(*pRows)[nCurRow];
2231 :
2232 : // den COLSPAN aller leeren Zellen am Zeilenende so anpassen, dass
2233 : // eine Zelle daraus wird. Das kann man hier machen (und auf keinen
2234 : // Fall frueher), weill jetzt keine Zellen mehr in die Zeile eingefuegt
2235 : // werden.
2236 64 : sal_uInt16 i=nCols;
2237 128 : while( i )
2238 : {
2239 64 : HTMLTableCell *pCell = pRow->GetCell(--i);
2240 64 : if( !pCell->GetContents() )
2241 : {
2242 0 : sal_uInt16 nColSpan = nCols-i;
2243 0 : if( nColSpan > 1 )
2244 0 : pCell->SetColSpan( nColSpan );
2245 : }
2246 : else
2247 64 : break;
2248 : }
2249 :
2250 64 : nCurRow++;
2251 : }
2252 :
2253 4 : inline void HTMLTable::CloseColGroup( sal_uInt16 nSpan, sal_uInt16 _nWidth,
2254 : bool bRelWidth, SvxAdjust eAdjust,
2255 : sal_Int16 eVertOrient )
2256 : {
2257 4 : if( nSpan )
2258 0 : InsertCol( nSpan, _nWidth, bRelWidth, eAdjust, eVertOrient );
2259 :
2260 : OSL_ENSURE( nCurCol<=nCols, "ungueltige Spalte" );
2261 4 : if( nCurCol>0 && nCurCol<=nCols )
2262 4 : ((*pColumns)[nCurCol-1]).SetEndOfGroup();
2263 4 : }
2264 :
2265 8 : void HTMLTable::InsertCol( sal_uInt16 nSpan, sal_uInt16 nColWidth, bool bRelWidth,
2266 : SvxAdjust eAdjust, sal_Int16 eVertOrient )
2267 : {
2268 : // #i35143# - no columns, if rows already exist.
2269 8 : if ( nRows > 0 )
2270 8 : return;
2271 :
2272 : sal_uInt16 i;
2273 :
2274 8 : if( !nSpan )
2275 0 : nSpan = 1;
2276 :
2277 8 : sal_uInt16 nColsReq = nCurCol + nSpan; // benoetigte Spalten
2278 :
2279 8 : if( nCols < nColsReq )
2280 : {
2281 16 : for( i=nCols; i<nColsReq; i++ )
2282 8 : pColumns->push_back( new HTMLTableColumn );
2283 8 : nCols = nColsReq;
2284 : }
2285 :
2286 8 : Size aTwipSz( bRelWidth ? 0 : nColWidth, 0 );
2287 8 : if( aTwipSz.Width() && Application::GetDefaultDevice() )
2288 : {
2289 : aTwipSz = Application::GetDefaultDevice()
2290 0 : ->PixelToLogic( aTwipSz, MapMode( MAP_TWIP ) );
2291 : }
2292 :
2293 16 : for( i=nCurCol; i<nColsReq; i++ )
2294 : {
2295 8 : HTMLTableColumn *pCol = &(*pColumns)[i];
2296 8 : sal_uInt16 nTmp = bRelWidth ? nColWidth : (sal_uInt16)aTwipSz.Width();
2297 8 : pCol->SetWidth( nTmp, bRelWidth );
2298 8 : pCol->SetAdjust( eAdjust );
2299 8 : pCol->SetVertOri( eVertOrient );
2300 : }
2301 :
2302 8 : bColSpec = true;
2303 :
2304 8 : nCurCol = nColsReq;
2305 : }
2306 :
2307 6 : void HTMLTable::CloseTable()
2308 : {
2309 : sal_uInt16 i;
2310 :
2311 : // Die Anzahl der Tabellenzeilen richtet sich nur nach den
2312 : // <TR>-Elementen (d.h. nach nCurRow). Durch ROWSPAN aufgespannte
2313 : // Zeilen hinter Zeile nCurRow muessen wir deshalb loeschen
2314 : // und vor allem aber den ROWSPAN in den darueberliegenden Zeilen
2315 : // anpassen.
2316 6 : if( nRows>nCurRow )
2317 : {
2318 0 : HTMLTableRow *pPrevRow = &(*pRows)[nCurRow-1];
2319 : HTMLTableCell *pCell;
2320 0 : for( i=0; i<nCols; i++ )
2321 0 : if( ( (pCell=(pPrevRow->GetCell(i))), (pCell->GetRowSpan()) > 1 ) )
2322 : {
2323 0 : FixRowSpan( nCurRow-1, i, pCell->GetContents() );
2324 0 : ProtectRowSpan( nCurRow, i, (*pRows)[nCurRow].GetCell(i)->GetRowSpan() );
2325 : }
2326 0 : for( i=nRows-1; i>=nCurRow; i-- )
2327 0 : pRows->erase(pRows->begin() + i);
2328 0 : nRows = nCurRow;
2329 : }
2330 :
2331 : // falls die Tabelle keine Spalte hat, muessen wir eine hinzufuegen
2332 6 : if( 0==nCols )
2333 : {
2334 0 : pColumns->push_back( new HTMLTableColumn );
2335 0 : for( i=0; i<nRows; i++ )
2336 0 : (*pRows)[i].Expand(1);
2337 0 : nCols = 1;
2338 0 : nFilledCols = 1;
2339 : }
2340 :
2341 : // falls die Tabelle keine Zeile hat, muessen wir eine hinzufuegen
2342 6 : if( 0==nRows )
2343 : {
2344 0 : pRows->push_back( new HTMLTableRow(nCols) );
2345 0 : nRows = 1;
2346 0 : nCurRow = 1;
2347 : }
2348 :
2349 6 : if( nFilledCols < nCols )
2350 : {
2351 0 : pColumns->erase( pColumns->begin() + nFilledCols, pColumns->begin() + nCols );
2352 0 : for( i=0; i<nRows; i++ )
2353 0 : (*pRows)[i].Shrink( nFilledCols );
2354 0 : nCols = nFilledCols;
2355 : }
2356 6 : }
2357 :
2358 6 : void HTMLTable::_MakeTable( SwTableBox *pBox )
2359 : {
2360 : SwTableLines& rLines = (pBox ? pBox->GetTabLines()
2361 6 : : const_cast<SwTable *>(pSwTable)->GetTabLines() );
2362 :
2363 : // jetzt geht's richtig los ...
2364 :
2365 70 : for( sal_uInt16 i=0; i<nRows; i++ )
2366 : {
2367 64 : SwTableLine *pLine = MakeTableLine( pBox, i, 0, i+1, nCols );
2368 64 : if( pBox || i > 0 )
2369 58 : rLines.push_back( pLine );
2370 : }
2371 6 : }
2372 :
2373 : /* Wie werden Tabellen ausgerichtet?
2374 :
2375 : erste Zeile: ohne Absatz-Einzuege
2376 : zweite Zeile: mit Absatz-Einzuegen
2377 :
2378 : ALIGN= LEFT RIGHT CENTER -
2379 : -------------------------------------------------------------------------
2380 : xxx bei Tabellen mit WIDTH=nn% ist die Prozent-Angabe von Bedeutung:
2381 : xxx nn = 100 text::HoriOrientation::FULL text::HoriOrientation::FULL text::HoriOrientation::FULL text::HoriOrientation::FULL %
2382 : xxx text::HoriOrientation::NONE text::HoriOrientation::NONE text::HoriOrientation::NONE % text::HoriOrientation::NONE %
2383 : xxx nn < 100 Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::LEFT %
2384 : xxx Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::NONE %
2385 :
2386 : bei Tabellen mit WIDTH=nn% ist die Prozent-Angabe von Bedeutung:
2387 : nn = 100 text::HoriOrientation::LEFT text::HoriOrientation::RIGHT text::HoriOrientation::CENTER % text::HoriOrientation::LEFT %
2388 : text::HoriOrientation::LEFT_AND text::HoriOrientation::RIGHT text::HoriOrientation::CENTER % text::HoriOrientation::LEFT_AND %
2389 : nn < 100 Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::LEFT %
2390 : Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::NONE %
2391 :
2392 : sonst die berechnete Breite w
2393 : w = avail* text::HoriOrientation::LEFT text::HoriOrientation::RIGHT text::HoriOrientation::CENTER text::HoriOrientation::LEFT
2394 : HORI_LEDT_AND text::HoriOrientation::RIGHT text::HoriOrientation::CENTER text::HoriOrientation::LEFT_AND
2395 : w < avail Rahmen L Rahmen L text::HoriOrientation::CENTER text::HoriOrientation::LEFT
2396 : Rahmen L Rahmen L text::HoriOrientation::CENTER text::HoriOrientation::NONE
2397 :
2398 : xxx *) wenn fuer die Tabelle keine Groesse angegeben wurde, wird immer
2399 : xxx text::HoriOrientation::FULL genommen
2400 :
2401 : */
2402 :
2403 6 : void HTMLTable::MakeTable( SwTableBox *pBox, sal_uInt16 nAbsAvail,
2404 : sal_uInt16 nRelAvail, sal_uInt16 nAbsLeftSpace,
2405 : sal_uInt16 nAbsRightSpace, sal_uInt16 nInhAbsSpace )
2406 : {
2407 : OSL_ENSURE( nRows>0 && nCols>0 && nCurRow==nRows,
2408 : "Wurde CloseTable nicht aufgerufen?" );
2409 :
2410 : OSL_ENSURE( (pLayoutInfo==0) == (this==pTopTable),
2411 : "Top-Tabelle hat keine Layout-Info oder umgekehrt" );
2412 :
2413 6 : if( this==pTopTable )
2414 : {
2415 : // Umrandung der Tabelle und aller in ihr enthaltenen berechnen
2416 6 : SetBorders();
2417 :
2418 : // Schritt 1: Die benoetigten Layout-Strukturen werden angelegt
2419 : // (inklusive Tabellen in Tabellen).
2420 6 : CreateLayoutInfo();
2421 :
2422 : // Schritt 2: Die minimalen und maximalen Spaltenbreiten werden
2423 : // berechnet (inklusive Tabellen in Tabellen). Da wir noch keine
2424 : // Boxen haben, arabeiten wir noch auf den Start-Nodes.
2425 6 : pLayoutInfo->AutoLayoutPass1();
2426 : }
2427 :
2428 : // Schritt 3: Die tatsaechlichen Spaltenbreiten dieser Tabelle werden
2429 : // berechnet (nicht von Tabellen in Tabellen). Dies muss jetzt schon
2430 : // sein, damit wir entscheiden koennen ob Filler-Zellen benoetigt werden
2431 : // oder nicht (deshalb war auch Pass1 schon noetig).
2432 : pLayoutInfo->AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace,
2433 6 : nAbsRightSpace, nInhAbsSpace );
2434 :
2435 6 : if( this!=pTopTable )
2436 : {
2437 : // die linke und rechte Umrandung der Tabelle kann jetzt entgueltig
2438 : // festgelegt werden
2439 0 : if( pLayoutInfo->GetRelRightFill() == 0 )
2440 : {
2441 0 : if( !bRightBorder )
2442 : {
2443 : // linke Umrandung von auesserer Tabelle uebernehmen
2444 0 : if( bInhRightBorder )
2445 : {
2446 0 : bRightBorder = true;
2447 0 : aRightBorderLine = aInhRightBorderLine;
2448 : }
2449 : }
2450 : else
2451 : {
2452 : // Umrandung nur setzen, wenn es erlaubt ist
2453 0 : bRightBorder = bRightAlwd;
2454 : }
2455 : }
2456 :
2457 0 : if( pLayoutInfo->GetRelLeftFill() == 0 &&
2458 0 : !((*pColumns)[0]).bLeftBorder &&
2459 : bInhLeftBorder )
2460 : {
2461 : // ggf. rechte Umrandung von auesserer Tabelle uebernehmen
2462 0 : ((*pColumns)[0]).bLeftBorder = true;
2463 0 : aLeftBorderLine = aInhLeftBorderLine;
2464 : }
2465 : }
2466 :
2467 : // Fuer die Top-Table muss die Ausrichtung gesetzt werden
2468 6 : if( this==pTopTable )
2469 : {
2470 : sal_Int16 eHoriOri;
2471 6 : if( bForceFrame )
2472 : {
2473 : // Die Tabelle soll in einen Rahmen und ist auch schmaler
2474 : // als der verfuegbare Platz und nicht 100% breit.
2475 : // Dann kommt sie in einen Rahmen
2476 0 : eHoriOri = bPrcWidth ? text::HoriOrientation::FULL : text::HoriOrientation::LEFT;
2477 : }
2478 6 : else switch( eTableAdjust )
2479 : {
2480 : // Die Tabelle passt entweder auf die Seite, soll aber in keinen
2481 : // Rahmen oder sie ist Breiter als die Seite und soll deshalb
2482 : // in keinen Rahmen
2483 :
2484 : case SVX_ADJUST_RIGHT:
2485 : // in rechtsbuendigen Tabellen kann nicht auf den rechten
2486 : // Rand Ruecksicht genommen werden
2487 0 : eHoriOri = text::HoriOrientation::RIGHT;
2488 0 : break;
2489 : case SVX_ADJUST_CENTER:
2490 : // zentrierte Tabellen nehmen keine Ruecksicht auf Raender!
2491 0 : eHoriOri = text::HoriOrientation::CENTER;
2492 0 : break;
2493 : case SVX_ADJUST_LEFT:
2494 : default:
2495 : // linksbuendige Tabellen nehmen nur auf den linken Rand
2496 : // Ruecksicht
2497 6 : eHoriOri = nLeftMargin ? text::HoriOrientation::LEFT_AND_WIDTH : text::HoriOrientation::LEFT;
2498 6 : break;
2499 : }
2500 :
2501 : // das Tabellenform holen und anpassen
2502 6 : SwFrameFormat *pFrameFormat = pSwTable->GetFrameFormat();
2503 6 : pFrameFormat->SetFormatAttr( SwFormatHoriOrient(0,eHoriOri) );
2504 6 : if( text::HoriOrientation::LEFT_AND_WIDTH==eHoriOri )
2505 : {
2506 : OSL_ENSURE( nLeftMargin || nRightMargin,
2507 : "Da gibt's wohl noch Reste von relativen Breiten" );
2508 :
2509 : // The right margin will be ignored anyway.
2510 0 : SvxLRSpaceItem aLRItem( pSwTable->GetFrameFormat()->GetLRSpace() );
2511 0 : aLRItem.SetLeft( nLeftMargin );
2512 0 : aLRItem.SetRight( nRightMargin );
2513 0 : pFrameFormat->SetFormatAttr( aLRItem );
2514 : }
2515 :
2516 6 : if( bPrcWidth && text::HoriOrientation::FULL!=eHoriOri )
2517 : {
2518 4 : pFrameFormat->LockModify();
2519 4 : SwFormatFrmSize aFrmSize( pFrameFormat->GetFrmSize() );
2520 4 : aFrmSize.SetWidthPercent( (sal_uInt8)nWidth );
2521 4 : pFrameFormat->SetFormatAttr( aFrmSize );
2522 4 : pFrameFormat->UnlockModify();
2523 : }
2524 : }
2525 :
2526 : // die Default Line- und Box-Formate holen
2527 6 : if( this==pTopTable )
2528 : {
2529 : // die erste Box merken und aus der ersten Zeile ausketten
2530 6 : SwTableLine *pLine1 = (pSwTable->GetTabLines())[0];
2531 6 : pBox1 = (pLine1->GetTabBoxes())[0];
2532 6 : pLine1->GetTabBoxes().erase(pLine1->GetTabBoxes().begin());
2533 :
2534 6 : pLineFormat = static_cast<SwTableLineFormat*>(pLine1->GetFrameFormat());
2535 6 : pBoxFormat = static_cast<SwTableBoxFormat*>(pBox1->GetFrameFormat());
2536 : }
2537 : else
2538 : {
2539 0 : pLineFormat = pTopTable->pLineFormat;
2540 0 : pBoxFormat = pTopTable->pBoxFormat;
2541 : }
2542 :
2543 : // ggf. muessen fuer Tabellen in Tabellen "Filler"-Zellen eingefuegt
2544 : // werden
2545 6 : if( this != pTopTable &&
2546 0 : ( pLayoutInfo->GetRelLeftFill() > 0 ||
2547 0 : pLayoutInfo->GetRelRightFill() > 0 ) )
2548 : {
2549 : OSL_ENSURE( pBox, "kein TableBox fuer Tabelle in Tabelle" );
2550 :
2551 0 : SwTableLines& rLines = pBox->GetTabLines();
2552 :
2553 : // dazu brauchen wir erstmal ein eine neue Table-Line in der Box
2554 : SwTableLine *pLine =
2555 : new SwTableLine( pLineFrameFormatNoHeight ? pLineFrameFormatNoHeight
2556 0 : : pLineFormat, 0, pBox );
2557 0 : rLines.push_back( pLine );
2558 :
2559 : // Sicherstellen, dass wie ein Format ohne Hoehe erwischt haben
2560 0 : if( !pLineFrameFormatNoHeight )
2561 : {
2562 : // sonst muessen wir die Hoehe aus dem Attribut entfernen
2563 : // und koennen uns das Format merken
2564 0 : pLineFrameFormatNoHeight = static_cast<SwTableLineFormat*>(pLine->ClaimFrameFormat());
2565 :
2566 0 : ResetLineFrameFormatAttrs( pLineFrameFormatNoHeight );
2567 : }
2568 :
2569 0 : SwTableBoxes& rBoxes = pLine->GetTabBoxes();
2570 : SwTableBox *pNewBox;
2571 :
2572 : // ggf. links eine Zelle einfuegen
2573 0 : if( pLayoutInfo->GetRelLeftFill() > 0 )
2574 : {
2575 : // pPrevStNd ist der Vorgaenger-Start-Node der Tabelle. Den
2576 : // "Filler"-Node fuegen wir einfach dahinter ein ...
2577 0 : pPrevStNd = pParser->InsertTableSection( pPrevStNd );
2578 :
2579 0 : pNewBox = NewTableBox( pPrevStNd, pLine );
2580 0 : rBoxes.push_back( pNewBox );
2581 0 : FixFillerFrameFormat( pNewBox, false );
2582 0 : pLayoutInfo->SetLeftFillerBox( pNewBox );
2583 : }
2584 :
2585 : // jetzt die Tabelle bearbeiten
2586 0 : pNewBox = new SwTableBox( pBoxFormat, 0, pLine );
2587 0 : rBoxes.push_back( pNewBox );
2588 :
2589 0 : SwFrameFormat *pFrameFormat = pNewBox->ClaimFrameFormat();
2590 0 : pFrameFormat->ResetFormatAttr( RES_BOX );
2591 0 : pFrameFormat->ResetFormatAttr( RES_BACKGROUND );
2592 0 : pFrameFormat->ResetFormatAttr( RES_VERT_ORIENT );
2593 0 : pFrameFormat->ResetFormatAttr( RES_BOXATR_FORMAT );
2594 :
2595 0 : _MakeTable( pNewBox );
2596 :
2597 : // und noch ggf. rechts eine Zelle einfuegen
2598 0 : if( pLayoutInfo->GetRelRightFill() > 0 )
2599 : {
2600 : const SwStartNode *pStNd =
2601 0 : GetPrevBoxStartNode( USHRT_MAX, USHRT_MAX );
2602 0 : pStNd = pParser->InsertTableSection( pStNd );
2603 :
2604 0 : pNewBox = NewTableBox( pStNd, pLine );
2605 0 : rBoxes.push_back( pNewBox );
2606 :
2607 0 : FixFillerFrameFormat( pNewBox, true );
2608 0 : pLayoutInfo->SetRightFillerBox( pNewBox );
2609 : }
2610 : }
2611 : else
2612 : {
2613 6 : _MakeTable( pBox );
2614 : }
2615 :
2616 : // zum Schluss fuehren wir noch eine Garbage-Collection fuer die
2617 : // Top-Level-Tabelle durch
2618 6 : if( this==pTopTable )
2619 : {
2620 6 : if( 1==nRows && nHeight && 1==pSwTable->GetTabLines().size() )
2621 : {
2622 : // Hoehe einer einzeiligen Tabelle als Mindesthoehe der
2623 : // Zeile setzen. (War mal fixe Hoehe, aber das gibt manchmal
2624 : // Probleme (fix #34972#) und ist auch nicht Netscape 4.0
2625 : // konform
2626 0 : nHeight = SwHTMLParser::ToTwips( nHeight );
2627 0 : if( nHeight < MINLAY )
2628 0 : nHeight = MINLAY;
2629 :
2630 0 : (pSwTable->GetTabLines())[0]->ClaimFrameFormat();
2631 0 : (pSwTable->GetTabLines())[0]->GetFrameFormat()
2632 0 : ->SetFormatAttr( SwFormatFrmSize( ATT_MIN_SIZE, 0, nHeight ) );
2633 : }
2634 :
2635 6 : if( GetBGBrush() )
2636 1 : pSwTable->GetFrameFormat()->SetFormatAttr( *GetBGBrush() );
2637 :
2638 6 : const_cast<SwTable *>(pSwTable)->SetRowsToRepeat( static_cast< sal_uInt16 >(nHeadlineRepeat) );
2639 6 : const_cast<SwTable *>(pSwTable)->GCLines();
2640 :
2641 6 : bool bIsInFlyFrame = pContext && pContext->GetFrameFormat();
2642 6 : if( bIsInFlyFrame && !nWidth )
2643 : {
2644 0 : SvxAdjust eAdjust = GetTableAdjust(false);
2645 0 : if (eAdjust != SVX_ADJUST_LEFT &&
2646 : eAdjust != SVX_ADJUST_RIGHT)
2647 : {
2648 : // Wenn eine Tabelle ohne Breitenangabe nicht links oder
2649 : // rechts umflossen werden soll, dann stacken wir sie
2650 : // in einem Rahmen mit 100%-Breite, damit ihre Groesse
2651 : // angepasst wird. Der Rahmen darf nicht angepasst werden.
2652 : OSL_ENSURE( HasToFly(), "Warum ist die Tabelle in einem Rahmen?" );
2653 0 : sal_uInt32 nMin = pLayoutInfo->GetMin();
2654 0 : if( nMin > USHRT_MAX )
2655 0 : nMin = USHRT_MAX;
2656 0 : SwFormatFrmSize aFlyFrmSize( ATT_VAR_SIZE, (SwTwips)nMin, MINLAY );
2657 0 : aFlyFrmSize.SetWidthPercent( 100 );
2658 0 : pContext->GetFrameFormat()->SetFormatAttr( aFlyFrmSize );
2659 0 : bIsInFlyFrame = false;
2660 : }
2661 : else
2662 : {
2663 : // Links und rechts ausgerichtete Tabellen ohne Breite
2664 : // duerfen leider nicht in der Breite angepasst werden, denn
2665 : // sie wuerden nur schrumpfen aber nie wachsen.
2666 0 : pLayoutInfo->SetMustNotRecalc( true );
2667 0 : if( pContext->GetFrameFormat()->GetAnchor().GetContentAnchor()
2668 0 : ->nNode.GetNode().FindTableNode() )
2669 : {
2670 0 : sal_uInt32 nMax = pLayoutInfo->GetMax();
2671 0 : if( nMax > USHRT_MAX )
2672 0 : nMax = USHRT_MAX;
2673 0 : SwFormatFrmSize aFlyFrmSize( ATT_VAR_SIZE, (SwTwips)nMax, MINLAY );
2674 0 : pContext->GetFrameFormat()->SetFormatAttr( aFlyFrmSize );
2675 0 : bIsInFlyFrame = false;
2676 : }
2677 : else
2678 : {
2679 0 : pLayoutInfo->SetMustNotResize( true );
2680 : }
2681 : }
2682 : }
2683 6 : pLayoutInfo->SetMayBeInFlyFrame( bIsInFlyFrame );
2684 :
2685 : // Nur Tabellen mit relativer Breite oder ohne Breite muessen
2686 : // angepasst werden.
2687 6 : pLayoutInfo->SetMustResize( bPrcWidth || !nWidth );
2688 :
2689 6 : pLayoutInfo->SetWidths();
2690 :
2691 6 : const_cast<SwTable *>(pSwTable)->SetHTMLTableLayout( pLayoutInfo );
2692 :
2693 6 : if( pResizeDrawObjs )
2694 : {
2695 0 : sal_uInt16 nCount = pResizeDrawObjs->size();
2696 0 : for( sal_uInt16 i=0; i<nCount; i++ )
2697 : {
2698 0 : SdrObject *pObj = (*pResizeDrawObjs)[i];
2699 0 : sal_uInt16 nRow = (*pDrawObjPrcWidths)[3*i];
2700 0 : sal_uInt16 nCol = (*pDrawObjPrcWidths)[3*i+1];
2701 0 : sal_uInt8 nPrcWidth = (sal_uInt8)(*pDrawObjPrcWidths)[3*i+2];
2702 :
2703 : SwHTMLTableLayoutCell *pLayoutCell =
2704 0 : pLayoutInfo->GetCell( nRow, nCol );
2705 0 : sal_uInt16 nColSpan = pLayoutCell->GetColSpan();
2706 :
2707 : sal_uInt16 nWidth2, nDummy;
2708 0 : pLayoutInfo->GetAvail( nCol, nColSpan, nWidth2, nDummy );
2709 0 : nWidth2 = nWidth2 - pLayoutInfo->GetLeftCellSpace( nCol, nColSpan );
2710 0 : nWidth2 = nWidth2 - pLayoutInfo->GetRightCellSpace( nCol, nColSpan );
2711 0 : nWidth2 = static_cast< sal_uInt16 >(((long)nWidth * nPrcWidth) / 100);
2712 :
2713 0 : SwHTMLParser::ResizeDrawObject( pObj, nWidth2 );
2714 : }
2715 : }
2716 : }
2717 6 : }
2718 :
2719 6 : void HTMLTable::SetTable( const SwStartNode *pStNd, _HTMLTableContext *pCntxt,
2720 : sal_uInt16 nLeft, sal_uInt16 nRight,
2721 : const SwTable *pSwTab, bool bFrcFrame )
2722 : {
2723 6 : pPrevStNd = pStNd;
2724 6 : pSwTable = pSwTab;
2725 6 : pContext = pCntxt;
2726 :
2727 6 : nLeftMargin = nLeft;
2728 6 : nRightMargin = nRight;
2729 :
2730 6 : bForceFrame = bFrcFrame;
2731 6 : }
2732 :
2733 0 : void HTMLTable::RegisterDrawObject( SdrObject *pObj, sal_uInt8 nPrcWidth )
2734 : {
2735 0 : if( !pResizeDrawObjs )
2736 0 : pResizeDrawObjs = new SdrObjects;
2737 0 : pResizeDrawObjs->push_back( pObj );
2738 :
2739 0 : if( !pDrawObjPrcWidths )
2740 0 : pDrawObjPrcWidths = new std::vector<sal_uInt16>;
2741 0 : pDrawObjPrcWidths->push_back( nCurRow );
2742 0 : pDrawObjPrcWidths->push_back( nCurCol );
2743 0 : pDrawObjPrcWidths->push_back( (sal_uInt16)nPrcWidth );
2744 0 : }
2745 :
2746 19 : void HTMLTable::MakeParentContents()
2747 : {
2748 19 : if( !GetContext() && !HasParentSection() )
2749 : {
2750 : SetParentContents(
2751 0 : pParser->InsertTableContents( GetIsParentHeader() ) );
2752 :
2753 0 : SetHasParentSection( true );
2754 : }
2755 19 : }
2756 :
2757 6 : _HTMLTableContext::~_HTMLTableContext()
2758 : {
2759 6 : delete pPos;
2760 6 : }
2761 :
2762 6 : void _HTMLTableContext::SavePREListingXMP( SwHTMLParser& rParser )
2763 : {
2764 6 : bRestartPRE = rParser.IsReadPRE();
2765 6 : bRestartXMP = rParser.IsReadXMP();
2766 6 : bRestartListing = rParser.IsReadListing();
2767 6 : rParser.FinishPREListingXMP();
2768 6 : }
2769 :
2770 6 : void _HTMLTableContext::RestorePREListingXMP( SwHTMLParser& rParser )
2771 : {
2772 6 : rParser.FinishPREListingXMP();
2773 :
2774 6 : if( bRestartPRE )
2775 0 : rParser.StartPRE();
2776 :
2777 6 : if( bRestartXMP )
2778 0 : rParser.StartXMP();
2779 :
2780 6 : if( bRestartListing )
2781 0 : rParser.StartListing();
2782 6 : }
2783 :
2784 0 : const SwStartNode *SwHTMLParser::InsertTableSection
2785 : ( const SwStartNode *pPrevStNd )
2786 : {
2787 : OSL_ENSURE( pPrevStNd, "Start-Node ist NULL" );
2788 :
2789 0 : pCSS1Parser->SetTDTagStyles();
2790 0 : SwTextFormatColl *pColl = pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_TABLE );
2791 :
2792 : const SwStartNode *pStNd;
2793 0 : if (pTable->bFirstCell )
2794 : {
2795 0 : SwNode *const pNd = & pPam->GetPoint()->nNode.GetNode();
2796 0 : pNd->GetTextNode()->ChgFormatColl( pColl );
2797 0 : pStNd = pNd->FindTableBoxStartNode();
2798 0 : pTable->bFirstCell = false;
2799 : }
2800 : else
2801 : {
2802 : const SwNode* pNd;
2803 0 : if( pPrevStNd->IsTableNode() )
2804 0 : pNd = pPrevStNd;
2805 : else
2806 0 : pNd = pPrevStNd->EndOfSectionNode();
2807 0 : SwNodeIndex nIdx( *pNd, 1 );
2808 0 : pStNd = pDoc->GetNodes().MakeTextSection( nIdx, SwTableBoxStartNode,
2809 0 : pColl );
2810 0 : pTable->IncBoxCount();
2811 : }
2812 :
2813 : //Added defaults to CJK and CTL
2814 0 : SwContentNode *pCNd = pDoc->GetNodes()[pStNd->GetIndex()+1] ->GetContentNode();
2815 0 : SvxFontHeightItem aFontHeight( 40, 100, RES_CHRATR_FONTSIZE );
2816 0 : pCNd->SetAttr( aFontHeight );
2817 0 : SvxFontHeightItem aFontHeightCJK( 40, 100, RES_CHRATR_CJK_FONTSIZE );
2818 0 : pCNd->SetAttr( aFontHeightCJK );
2819 0 : SvxFontHeightItem aFontHeightCTL( 40, 100, RES_CHRATR_CTL_FONTSIZE );
2820 0 : pCNd->SetAttr( aFontHeightCTL );
2821 :
2822 0 : return pStNd;
2823 : }
2824 :
2825 286 : const SwStartNode *SwHTMLParser::InsertTableSection( sal_uInt16 nPoolId )
2826 : {
2827 286 : switch( nPoolId )
2828 : {
2829 : case RES_POOLCOLL_TABLE_HDLN:
2830 0 : pCSS1Parser->SetTHTagStyles();
2831 0 : break;
2832 : case RES_POOLCOLL_TABLE:
2833 286 : pCSS1Parser->SetTDTagStyles();
2834 286 : break;
2835 : }
2836 :
2837 286 : SwTextFormatColl *pColl = pCSS1Parser->GetTextCollFromPool( nPoolId );
2838 :
2839 286 : SwNode *const pNd = & pPam->GetPoint()->nNode.GetNode();
2840 : const SwStartNode *pStNd;
2841 286 : if (pTable->bFirstCell)
2842 : {
2843 6 : pNd->GetTextNode()->ChgFormatColl( pColl );
2844 6 : pTable->bFirstCell = false;
2845 6 : pStNd = pNd->FindTableBoxStartNode();
2846 : }
2847 : else
2848 : {
2849 280 : SwTableNode *pTableNd = pNd->FindTableNode();
2850 280 : if( pTableNd->GetTable().GetHTMLTableLayout() )
2851 : { // if there is already a HTMTableLayout, this table is already finished
2852 : // and we have to look for the right table in the environment
2853 0 : SwTableNode *pOutTable = pTableNd;
2854 0 : do {
2855 0 : pTableNd = pOutTable;
2856 0 : pOutTable = pOutTable->StartOfSectionNode()->FindTableNode();
2857 0 : } while( pOutTable && pTableNd->GetTable().GetHTMLTableLayout() );
2858 : }
2859 280 : SwNodeIndex aIdx( *pTableNd->EndOfSectionNode() );
2860 280 : pStNd = pDoc->GetNodes().MakeTextSection( aIdx, SwTableBoxStartNode,
2861 280 : pColl );
2862 :
2863 280 : pPam->GetPoint()->nNode = pStNd->GetIndex() + 1;
2864 280 : SwTextNode *pTextNd = pPam->GetPoint()->nNode.GetNode().GetTextNode();
2865 280 : pPam->GetPoint()->nContent.Assign( pTextNd, 0 );
2866 280 : pTable->IncBoxCount();
2867 : }
2868 :
2869 286 : return pStNd;
2870 : }
2871 :
2872 0 : SwStartNode *SwHTMLParser::InsertTempTableCaptionSection()
2873 : {
2874 0 : SwTextFormatColl *pColl = pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_TEXT );
2875 0 : SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
2876 0 : rIdx = pDoc->GetNodes().GetEndOfExtras();
2877 0 : SwStartNode *pStNd = pDoc->GetNodes().MakeTextSection( rIdx,
2878 0 : SwNormalStartNode, pColl );
2879 :
2880 0 : rIdx = pStNd->GetIndex() + 1;
2881 0 : pPam->GetPoint()->nContent.Assign( rIdx.GetNode().GetTextNode(), 0 );
2882 :
2883 0 : return pStNd;
2884 : }
2885 :
2886 589 : sal_Int32 SwHTMLParser::StripTrailingLF()
2887 : {
2888 589 : sal_Int32 nStripped = 0;
2889 :
2890 589 : const sal_Int32 nLen = pPam->GetPoint()->nContent.GetIndex();
2891 589 : if( nLen )
2892 : {
2893 309 : SwTextNode* pTextNd = pPam->GetPoint()->nNode.GetNode().GetTextNode();
2894 : // vorsicht, wenn Kommentare nicht uebrlesen werden!!!
2895 309 : if( pTextNd )
2896 : {
2897 309 : sal_Int32 nPos = nLen;
2898 309 : sal_Int32 nLFCount = 0;
2899 891 : while (nPos && ('\x0a' == pTextNd->GetText()[--nPos]))
2900 273 : nLFCount++;
2901 :
2902 309 : if( nLFCount )
2903 : {
2904 269 : if( nLFCount > 2 )
2905 : {
2906 : // Bei Netscape entspricht ein Absatz-Ende zwei LFs
2907 : // (mit einem kommt man in die naechste Zeile, das
2908 : // zweite erzeugt eine Leerzeile) Diesen Abstand
2909 : // erreichen wie aber schon mit dem unteren
2910 : // Absatz-Abstand. Wenn nach den <BR> ein neuer
2911 : // Absatz aufgemacht wird, wird das Maximum des Abstands,
2912 : // der sich aus den BR und dem P ergibt genommen.
2913 : // Deshalb muessen wir 2 bzw. alle bei weniger
2914 : // als zweien loeschen
2915 0 : nLFCount = 2;
2916 : }
2917 :
2918 269 : nPos = nLen - nLFCount;
2919 269 : SwIndex nIdx( pTextNd, nPos );
2920 269 : pTextNd->EraseText( nIdx, nLFCount );
2921 269 : nStripped = nLFCount;
2922 : }
2923 : }
2924 : }
2925 :
2926 589 : return nStripped;
2927 : }
2928 :
2929 356 : SvxBrushItem* SwHTMLParser::CreateBrushItem( const Color *pColor,
2930 : const OUString& rImageURL,
2931 : const OUString& rStyle,
2932 : const OUString& rId,
2933 : const OUString& rClass )
2934 : {
2935 356 : SvxBrushItem *pBrushItem = 0;
2936 :
2937 356 : if( !rStyle.isEmpty() || !rId.isEmpty() || !rClass.isEmpty() )
2938 : {
2939 286 : SfxItemSet aItemSet( pDoc->GetAttrPool(), RES_BACKGROUND,
2940 286 : RES_BACKGROUND );
2941 572 : SvxCSS1PropertyInfo aPropInfo;
2942 :
2943 286 : if( !rClass.isEmpty() )
2944 : {
2945 0 : OUString aClass( rClass );
2946 0 : SwCSS1Parser::GetScriptFromClass( aClass );
2947 0 : const SvxCSS1MapEntry *pClass = pCSS1Parser->GetClass( aClass );
2948 0 : if( pClass )
2949 0 : aItemSet.Put( pClass->GetItemSet() );
2950 : }
2951 :
2952 286 : if( !rId.isEmpty() )
2953 : {
2954 0 : const SvxCSS1MapEntry *pId = pCSS1Parser->GetId( rId );
2955 0 : if( pId )
2956 0 : aItemSet.Put( pId->GetItemSet() );
2957 : }
2958 :
2959 286 : pCSS1Parser->ParseStyleOption( rStyle, aItemSet, aPropInfo );
2960 286 : const SfxPoolItem *pItem = 0;
2961 286 : if( SfxItemState::SET == aItemSet.GetItemState( RES_BACKGROUND, false,
2962 286 : &pItem ) )
2963 : {
2964 0 : pBrushItem = new SvxBrushItem( *static_cast<const SvxBrushItem *>(pItem) );
2965 286 : }
2966 : }
2967 :
2968 356 : if( !pBrushItem && (pColor || !rImageURL.isEmpty()) )
2969 : {
2970 264 : pBrushItem = new SvxBrushItem(RES_BACKGROUND);
2971 :
2972 264 : if( pColor )
2973 264 : pBrushItem->SetColor(*pColor);
2974 :
2975 264 : if( !rImageURL.isEmpty() )
2976 : {
2977 0 : pBrushItem->SetGraphicLink( URIHelper::SmartRel2Abs( INetURLObject(sBaseURL), rImageURL, Link<OUString *, bool>(), false) );
2978 0 : pBrushItem->SetGraphicPos( GPOS_TILED );
2979 : }
2980 : }
2981 :
2982 356 : return pBrushItem;
2983 : }
2984 :
2985 : class _SectionSaveStruct : public SwPendingStackData
2986 : {
2987 : sal_uInt16 m_nBaseFontStMinSave, m_nFontStMinSave, m_nFontStHeadStartSave;
2988 : sal_uInt16 m_nDefListDeepSave;
2989 : size_t m_nContextStMinSave;
2990 : size_t m_nContextStAttrMinSave;
2991 :
2992 : public:
2993 :
2994 : HTMLTable *m_pTable;
2995 :
2996 : explicit _SectionSaveStruct( SwHTMLParser& rParser );
2997 : virtual ~_SectionSaveStruct();
2998 :
2999 : #if OSL_DEBUG_LEVEL > 0
3000 : size_t GetContextStAttrMin() const { return m_nContextStAttrMinSave; }
3001 : #endif
3002 : void Restore( SwHTMLParser& rParser );
3003 : };
3004 :
3005 286 : _SectionSaveStruct::_SectionSaveStruct( SwHTMLParser& rParser ) :
3006 : m_nBaseFontStMinSave(0), m_nFontStMinSave(0), m_nFontStHeadStartSave(0),
3007 : m_nDefListDeepSave(0), m_nContextStMinSave(0), m_nContextStAttrMinSave(0),
3008 286 : m_pTable( 0 )
3009 : {
3010 : // Font-Stacks einfrieren
3011 286 : m_nBaseFontStMinSave = rParser.nBaseFontStMin;
3012 286 : rParser.nBaseFontStMin = rParser.aBaseFontStack.size();
3013 :
3014 286 : m_nFontStMinSave = rParser.nFontStMin;
3015 286 : m_nFontStHeadStartSave = rParser.nFontStHeadStart;
3016 286 : rParser.nFontStMin = rParser.aFontStack.size();
3017 :
3018 : // Kontext-Stack einfrieren
3019 286 : m_nContextStMinSave = rParser.nContextStMin;
3020 286 : m_nContextStAttrMinSave = rParser.nContextStAttrMin;
3021 286 : rParser.nContextStMin = rParser.aContexts.size();
3022 286 : rParser.nContextStAttrMin = rParser.nContextStMin;
3023 :
3024 : // und noch ein par Zaehler retten
3025 286 : m_nDefListDeepSave = rParser.nDefListDeep;
3026 286 : rParser.nDefListDeep = 0;
3027 286 : }
3028 :
3029 286 : _SectionSaveStruct::~_SectionSaveStruct()
3030 286 : {}
3031 :
3032 286 : void _SectionSaveStruct::Restore( SwHTMLParser& rParser )
3033 : {
3034 : // Font-Stacks wieder auftauen
3035 286 : sal_uInt16 nMin = rParser.nBaseFontStMin;
3036 286 : if( rParser.aBaseFontStack.size() > nMin )
3037 0 : rParser.aBaseFontStack.erase( rParser.aBaseFontStack.begin() + nMin,
3038 0 : rParser.aBaseFontStack.end() );
3039 286 : rParser.nBaseFontStMin = m_nBaseFontStMinSave;
3040 :
3041 286 : nMin = rParser.nFontStMin;
3042 286 : if( rParser.aFontStack.size() > nMin )
3043 0 : rParser.aFontStack.erase( rParser.aFontStack.begin() + nMin,
3044 0 : rParser.aFontStack.end() );
3045 286 : rParser.nFontStMin = m_nFontStMinSave;
3046 286 : rParser.nFontStHeadStart = m_nFontStHeadStartSave;
3047 :
3048 : OSL_ENSURE( rParser.aContexts.size() == rParser.nContextStMin &&
3049 : rParser.aContexts.size() == rParser.nContextStAttrMin,
3050 : "The Context Stack was not cleaned up" );
3051 286 : rParser.nContextStMin = m_nContextStMinSave;
3052 286 : rParser.nContextStAttrMin = m_nContextStAttrMinSave;
3053 :
3054 : // und noch ein par Zaehler rekonstruieren
3055 286 : rParser.nDefListDeep = m_nDefListDeepSave;
3056 :
3057 : // und ein par Flags zuruecksetzen
3058 286 : rParser.bNoParSpace = false;
3059 286 : rParser.nOpenParaToken = 0;
3060 :
3061 286 : if( !rParser.aParaAttrs.empty() )
3062 0 : rParser.aParaAttrs.clear();
3063 286 : }
3064 :
3065 : class _CellSaveStruct : public _SectionSaveStruct
3066 : {
3067 : OUString aStyle, aId, aClass, aLang, aDir;
3068 : OUString aBGImage;
3069 : Color aBGColor;
3070 : boost::shared_ptr<SvxBoxItem> m_pBoxItem;
3071 :
3072 : HTMLTableCnts* pCnts; // Liste aller Inhalte
3073 : HTMLTableCnts* pCurrCnts; // der aktuelle Inhalt oder 0
3074 : SwNodeIndex *pNoBreakEndParaIdx;// Absatz-Index eines </NOBR>
3075 :
3076 : double nValue;
3077 :
3078 : sal_uInt32 nNumFormat;
3079 :
3080 : sal_uInt16 nRowSpan, nColSpan, nWidth, nHeight;
3081 : sal_Int32 nNoBreakEndContentPos; // Zeichen-Index eines </NOBR>
3082 :
3083 : SvxAdjust eAdjust;
3084 : sal_Int16 eVertOri;
3085 :
3086 : bool bHead : 1;
3087 : bool bPrcWidth : 1;
3088 : bool bHasNumFormat : 1;
3089 : bool bHasValue : 1;
3090 : bool bBGColor : 1;
3091 : bool bNoWrap : 1; // NOWRAP-Option
3092 : bool bNoBreak : 1; // NOBREAK-Tag
3093 :
3094 : public:
3095 :
3096 : _CellSaveStruct( SwHTMLParser& rParser, HTMLTable *pCurTable, bool bHd,
3097 : bool bReadOpt );
3098 :
3099 : virtual ~_CellSaveStruct();
3100 :
3101 : void AddContents( HTMLTableCnts *pNewCnts );
3102 286 : HTMLTableCnts *GetFirstContents() { return pCnts; }
3103 :
3104 3 : void ClearIsInSection() { pCurrCnts = 0; }
3105 2757 : bool IsInSection() const { return pCurrCnts!=0; }
3106 :
3107 : void InsertCell( SwHTMLParser& rParser, HTMLTable *pCurTable );
3108 :
3109 3 : bool IsHeaderCell() const { return bHead; }
3110 :
3111 : void StartNoBreak( const SwPosition& rPos );
3112 : void EndNoBreak( const SwPosition& rPos );
3113 : void CheckNoBreak( const SwPosition& rPos, SwDoc *pDoc );
3114 : };
3115 :
3116 286 : _CellSaveStruct::_CellSaveStruct( SwHTMLParser& rParser, HTMLTable *pCurTable,
3117 : bool bHd, bool bReadOpt ) :
3118 : _SectionSaveStruct( rParser ),
3119 : pCnts( 0 ),
3120 : pCurrCnts( 0 ),
3121 : pNoBreakEndParaIdx( 0 ),
3122 : nValue( 0.0 ),
3123 : nNumFormat( 0 ),
3124 : nRowSpan( 1 ),
3125 : nColSpan( 1 ),
3126 : nWidth( 0 ),
3127 : nHeight( 0 ),
3128 : nNoBreakEndContentPos( 0 ),
3129 286 : eAdjust( pCurTable->GetInheritedAdjust() ),
3130 286 : eVertOri( pCurTable->GetInheritedVertOri() ),
3131 : bHead( bHd ),
3132 : bPrcWidth( false ),
3133 : bHasNumFormat( false ),
3134 : bHasValue( false ),
3135 : bBGColor( false ),
3136 : bNoWrap( false ),
3137 858 : bNoBreak( false )
3138 : {
3139 572 : OUString aNumFormat, aValue;
3140 :
3141 286 : if( bReadOpt )
3142 : {
3143 286 : const HTMLOptions& rOptions = rParser.GetOptions();
3144 1405 : for (size_t i = rOptions.size(); i; )
3145 : {
3146 833 : const HTMLOption& rOption = rOptions[--i];
3147 833 : switch( rOption.GetToken() )
3148 : {
3149 : case HTML_O_ID:
3150 0 : aId = rOption.GetString();
3151 0 : break;
3152 : case HTML_O_COLSPAN:
3153 0 : nColSpan = (sal_uInt16)rOption.GetNumber();
3154 0 : break;
3155 : case HTML_O_ROWSPAN:
3156 0 : nRowSpan = (sal_uInt16)rOption.GetNumber();
3157 0 : break;
3158 : case HTML_O_ALIGN:
3159 : eAdjust = (SvxAdjust)rOption.GetEnum(
3160 0 : aHTMLPAlignTable, static_cast< sal_uInt16 >(eAdjust) );
3161 0 : break;
3162 : case HTML_O_VALIGN:
3163 : eVertOri = rOption.GetEnum(
3164 3 : aHTMLTableVAlignTable, eVertOri );
3165 3 : break;
3166 : case HTML_O_WIDTH:
3167 280 : nWidth = (sal_uInt16)rOption.GetNumber(); // nur fuer Netscape
3168 280 : bPrcWidth = (rOption.GetString().indexOf('%') != -1);
3169 280 : if( bPrcWidth && nWidth>100 )
3170 0 : nWidth = 100;
3171 280 : break;
3172 : case HTML_O_HEIGHT:
3173 0 : nHeight = (sal_uInt16)rOption.GetNumber(); // nur fuer Netscape
3174 0 : if( rOption.GetString().indexOf('%') != -1)
3175 0 : nHeight = 0; // keine %-Angaben beruecksichtigen
3176 0 : break;
3177 : case HTML_O_BGCOLOR:
3178 : // Leere BGCOLOR bei <TABLE>, <TR> und <TD>/<TH> wie Netscape
3179 : // ignorieren, bei allen anderen Tags *wirklich* nicht.
3180 263 : if( !rOption.GetString().isEmpty() )
3181 : {
3182 263 : rOption.GetColor( aBGColor );
3183 263 : bBGColor = true;
3184 : }
3185 263 : break;
3186 : case HTML_O_BACKGROUND:
3187 0 : aBGImage = rOption.GetString();
3188 0 : break;
3189 : case HTML_O_STYLE:
3190 286 : aStyle = rOption.GetString();
3191 286 : break;
3192 : case HTML_O_CLASS:
3193 0 : aClass = rOption.GetString();
3194 0 : break;
3195 : case HTML_O_LANG:
3196 0 : aLang = rOption.GetString();
3197 0 : break;
3198 : case HTML_O_DIR:
3199 0 : aDir = rOption.GetString();
3200 0 : break;
3201 : case HTML_O_SDNUM:
3202 0 : aNumFormat = rOption.GetString();
3203 0 : bHasNumFormat = true;
3204 0 : break;
3205 : case HTML_O_SDVAL:
3206 0 : bHasValue = true;
3207 0 : aValue = rOption.GetString();
3208 0 : break;
3209 : case HTML_O_NOWRAP:
3210 0 : bNoWrap = true;
3211 0 : break;
3212 : }
3213 : }
3214 :
3215 286 : if( !aId.isEmpty() )
3216 0 : rParser.InsertBookmark( aId );
3217 : }
3218 :
3219 286 : if( bHasNumFormat )
3220 : {
3221 : LanguageType eLang;
3222 : nValue = SfxHTMLParser::GetTableDataOptionsValNum(
3223 : nNumFormat, eLang, aValue, aNumFormat,
3224 0 : *rParser.pDoc->GetNumberFormatter() );
3225 : }
3226 :
3227 : // einen neuen Kontext anlegen, aber das drawing::Alignment-Attribut
3228 : // nicht dort verankern, weil es noch ger keine Section gibt, in der
3229 : // es gibt.
3230 : sal_uInt16 nToken, nColl;
3231 286 : if( bHead )
3232 : {
3233 0 : nToken = HTML_TABLEHEADER_ON;
3234 0 : nColl = RES_POOLCOLL_TABLE_HDLN;
3235 : }
3236 : else
3237 : {
3238 286 : nToken = HTML_TABLEDATA_ON;
3239 286 : nColl = RES_POOLCOLL_TABLE;
3240 : }
3241 286 : _HTMLAttrContext *pCntxt = new _HTMLAttrContext( nToken, nColl, aEmptyOUStr, true );
3242 286 : if( SVX_ADJUST_END != eAdjust )
3243 : rParser.InsertAttr( &rParser.aAttrTab.pAdjust, SvxAdjustItem(eAdjust, RES_PARATR_ADJUST),
3244 0 : pCntxt );
3245 :
3246 286 : if( SwHTMLParser::HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) )
3247 : {
3248 286 : SfxItemSet aItemSet( rParser.pDoc->GetAttrPool(),
3249 572 : rParser.pCSS1Parser->GetWhichMap() );
3250 572 : SvxCSS1PropertyInfo aPropInfo;
3251 :
3252 286 : if( rParser.ParseStyleOptions( aStyle, aId, aClass, aItemSet,
3253 286 : aPropInfo, &aLang, &aDir ) )
3254 : {
3255 : SfxPoolItem const* pItem;
3256 286 : if (SfxItemState::SET == aItemSet.GetItemState(RES_BOX, false, &pItem))
3257 : { // fdo#41796: steal box item to set it in FixFrameFormat later!
3258 278 : m_pBoxItem.reset(dynamic_cast<SvxBoxItem *>(pItem->Clone()));
3259 278 : aItemSet.ClearItem(RES_BOX);
3260 : }
3261 286 : rParser.InsertAttrs( aItemSet, aPropInfo, pCntxt );
3262 286 : }
3263 : }
3264 :
3265 286 : rParser.SplitPREListingXMP( pCntxt );
3266 :
3267 572 : rParser.PushContext( pCntxt );
3268 286 : }
3269 :
3270 858 : _CellSaveStruct::~_CellSaveStruct()
3271 : {
3272 286 : delete pNoBreakEndParaIdx;
3273 572 : }
3274 :
3275 286 : void _CellSaveStruct::AddContents( HTMLTableCnts *pNewCnts )
3276 : {
3277 286 : if( pCnts )
3278 0 : pCnts->Add( pNewCnts );
3279 : else
3280 286 : pCnts = pNewCnts;
3281 :
3282 286 : pCurrCnts = pNewCnts;
3283 286 : }
3284 :
3285 286 : void _CellSaveStruct::InsertCell( SwHTMLParser& rParser,
3286 : HTMLTable *pCurTable )
3287 : {
3288 : #if OSL_DEBUG_LEVEL > 0
3289 : // Die Attribute muessen schon beim Auefrauemen des Kontext-Stacks
3290 : // entfernt worden sein, sonst ist etwas schiefgelaufen. Das
3291 : // Checken wir mal eben ...
3292 : // MIB 8.1.98: Wenn ausserhalb einer Zelle Attribute geoeffnet
3293 : // wurden stehen diese noch in der Attribut-Tabelle und werden erst
3294 : // ganz zum Schluss durch die CleanContext-Aufrufe in BuildTable
3295 : // geloescht. Damit es in diesem Fall keine Asserts gibt findet dann
3296 : // keine Ueberpruefung statt. Erkennen tut man diesen Fall an
3297 : // nContextStAttrMin: Der gemerkte Wert nContextStAttrMinSave ist der
3298 : // Wert, den nContextStAttrMin beim Start der Tabelle hatte. Und
3299 : // der aktuelle Wert von nContextStAttrMin entspricht der Anzahl der
3300 : // Kontexte, die beim Start der Zelle vorgefunden wurden. Sind beide
3301 : // Werte unterschiedlich, wurden ausserhalb der Zelle Kontexte
3302 : // angelegt und wir ueberpruefen nichts.
3303 :
3304 : if( rParser.nContextStAttrMin == GetContextStAttrMin() )
3305 : {
3306 : _HTMLAttr** pTable = reinterpret_cast<_HTMLAttr**>(&rParser.aAttrTab);
3307 :
3308 : for( auto nCnt = sizeof( _HTMLAttrTable ) / sizeof( _HTMLAttr* );
3309 : nCnt--; ++pTable )
3310 : {
3311 : OSL_ENSURE( !*pTable, "Die Attribut-Tabelle ist nicht leer" );
3312 : }
3313 : }
3314 : #endif
3315 :
3316 : // jetzt muessen wir noch die Zelle an der aktuellen Position einfuegen
3317 : SvxBrushItem *pBrushItem =
3318 : rParser.CreateBrushItem( bBGColor ? &aBGColor : 0, aBGImage,
3319 286 : aStyle, aId, aClass );
3320 : pCurTable->InsertCell( pCnts, nRowSpan, nColSpan, nWidth,
3321 : bPrcWidth, nHeight, eVertOri, pBrushItem, m_pBoxItem,
3322 : bHasNumFormat, nNumFormat, bHasValue, nValue,
3323 286 : bNoWrap );
3324 286 : Restore( rParser );
3325 286 : }
3326 :
3327 0 : void _CellSaveStruct::StartNoBreak( const SwPosition& rPos )
3328 : {
3329 0 : if( !pCnts ||
3330 0 : (!rPos.nContent.GetIndex() && pCurrCnts==pCnts &&
3331 0 : pCnts->GetStartNode() &&
3332 0 : pCnts->GetStartNode()->GetIndex() + 1 ==
3333 0 : rPos.nNode.GetIndex()) )
3334 : {
3335 0 : bNoBreak = true;
3336 : }
3337 0 : }
3338 :
3339 0 : void _CellSaveStruct::EndNoBreak( const SwPosition& rPos )
3340 : {
3341 0 : if( bNoBreak )
3342 : {
3343 0 : delete pNoBreakEndParaIdx;
3344 0 : pNoBreakEndParaIdx = new SwNodeIndex( rPos.nNode );
3345 0 : nNoBreakEndContentPos = rPos.nContent.GetIndex();
3346 0 : bNoBreak = false;
3347 : }
3348 0 : }
3349 :
3350 283 : void _CellSaveStruct::CheckNoBreak( const SwPosition& rPos, SwDoc * /*pDoc*/ )
3351 : {
3352 283 : if( pCnts && pCurrCnts==pCnts )
3353 : {
3354 283 : if( bNoBreak )
3355 : {
3356 : // <NOBR> wurde nicht beendet
3357 0 : pCnts->SetNoBreak();
3358 : }
3359 283 : else if( pNoBreakEndParaIdx &&
3360 0 : pNoBreakEndParaIdx->GetIndex() == rPos.nNode.GetIndex() )
3361 : {
3362 0 : if( nNoBreakEndContentPos == rPos.nContent.GetIndex() )
3363 : {
3364 : // <NOBR> wurde unmittelbar vor dem Zellen-Ende beendet
3365 0 : pCnts->SetNoBreak();
3366 : }
3367 0 : else if( nNoBreakEndContentPos + 1 == rPos.nContent.GetIndex() )
3368 : {
3369 0 : SwTextNode const*const pTextNd(rPos.nNode.GetNode().GetTextNode());
3370 0 : if( pTextNd )
3371 : {
3372 : sal_Unicode const cLast =
3373 0 : pTextNd->GetText()[nNoBreakEndContentPos];
3374 0 : if( ' '==cLast || '\x0a'==cLast )
3375 : {
3376 : // Zwischem dem </NOBR> und dem Zellen-Ende gibt es nur
3377 : // ein Blank oder einen Zeilenumbruch.
3378 0 : pCnts->SetNoBreak();
3379 : }
3380 : }
3381 : }
3382 : }
3383 : }
3384 283 : }
3385 :
3386 283 : HTMLTableCnts *SwHTMLParser::InsertTableContents(
3387 : bool bHead )
3388 : {
3389 : // eine neue Section anlegen, der PaM steht dann darin
3390 : const SwStartNode *pStNd =
3391 : InsertTableSection( static_cast< sal_uInt16 >(bHead ? RES_POOLCOLL_TABLE_HDLN
3392 283 : : RES_POOLCOLL_TABLE) );
3393 :
3394 283 : if( GetNumInfo().GetNumRule() )
3395 : {
3396 : // 1. Absatz auf nicht numeriert setzen
3397 0 : sal_uInt8 nLvl = GetNumInfo().GetLevel();
3398 :
3399 0 : SetNodeNum( nLvl, false );
3400 : }
3401 :
3402 : // Attributierungs-Anfang neu setzen
3403 283 : const SwNodeIndex& rSttPara = pPam->GetPoint()->nNode;
3404 283 : sal_Int32 nSttCnt = pPam->GetPoint()->nContent.GetIndex();
3405 :
3406 283 : _HTMLAttr** pHTMLAttributes = reinterpret_cast<_HTMLAttr**>(&aAttrTab);
3407 11603 : for (sal_uInt16 nCnt = sizeof(_HTMLAttrTable) / sizeof(_HTMLAttr*); nCnt--; ++pHTMLAttributes)
3408 : {
3409 11320 : _HTMLAttr *pAttr = *pHTMLAttributes;
3410 22679 : while( pAttr )
3411 : {
3412 : OSL_ENSURE( !pAttr->GetPrev(), "Attribut hat Previous-Liste" );
3413 39 : pAttr->nSttPara = rSttPara;
3414 39 : pAttr->nEndPara = rSttPara;
3415 39 : pAttr->nSttContent = nSttCnt;
3416 39 : pAttr->nEndContent = nSttCnt;
3417 :
3418 39 : pAttr = pAttr->GetNext();
3419 : }
3420 : }
3421 :
3422 283 : return new HTMLTableCnts( pStNd );
3423 : }
3424 :
3425 0 : sal_uInt16 SwHTMLParser::IncGrfsThatResizeTable()
3426 : {
3427 0 : return pTable ? pTable->IncGrfsThatResize() : 0;
3428 : }
3429 :
3430 0 : void SwHTMLParser::RegisterDrawObjectToTable( HTMLTable *pCurTable,
3431 : SdrObject *pObj, sal_uInt8 nPrcWidth )
3432 : {
3433 0 : pCurTable->RegisterDrawObject( pObj, nPrcWidth );
3434 0 : }
3435 :
3436 286 : void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions,
3437 : bool bHead )
3438 : {
3439 286 : if( !IsParserWorking() && !pPendStack )
3440 0 : return;
3441 :
3442 : _CellSaveStruct* pSaveStruct;
3443 :
3444 286 : int nToken = 0;
3445 286 : bool bPending = false;
3446 286 : if( pPendStack )
3447 : {
3448 0 : pSaveStruct = static_cast<_CellSaveStruct*>(pPendStack->pData);
3449 :
3450 0 : SwPendingStack* pTmp = pPendStack->pNext;
3451 0 : delete pPendStack;
3452 0 : pPendStack = pTmp;
3453 0 : nToken = pPendStack ? pPendStack->nToken : GetSaveToken();
3454 0 : bPending = SVPAR_ERROR == eState && pPendStack != 0;
3455 :
3456 0 : SaveState( nToken );
3457 : }
3458 : else
3459 : {
3460 : // <TH> bzw. <TD> wurde bereits gelesen
3461 286 : if( pTable->IsOverflowing() )
3462 : {
3463 0 : SaveState( 0 );
3464 0 : return;
3465 : }
3466 :
3467 286 : if( !pCurTable->GetContext() )
3468 : {
3469 6 : bool bTopTable = pTable==pCurTable;
3470 :
3471 : // die Tabelle besitzt noch keinen Inhalt, d.h. die eigentliche
3472 : // Tabelle muss erst noch angelegt werden
3473 :
3474 : static sal_uInt16 aWhichIds[] =
3475 : {
3476 : RES_PARATR_SPLIT, RES_PARATR_SPLIT,
3477 : RES_PAGEDESC, RES_PAGEDESC,
3478 : RES_BREAK, RES_BREAK,
3479 : RES_BACKGROUND, RES_BACKGROUND,
3480 : RES_KEEP, RES_KEEP,
3481 : RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT,
3482 : RES_FRAMEDIR, RES_FRAMEDIR,
3483 : 0
3484 : };
3485 :
3486 6 : SfxItemSet aItemSet( pDoc->GetAttrPool(), aWhichIds );
3487 12 : SvxCSS1PropertyInfo aPropInfo;
3488 :
3489 6 : bool bStyleParsed = ParseStyleOptions( pCurTable->GetStyle(),
3490 6 : pCurTable->GetId(),
3491 6 : pCurTable->GetClass(),
3492 : aItemSet, aPropInfo,
3493 12 : 0, &pCurTable->GetDirection() );
3494 6 : const SfxPoolItem *pItem = 0;
3495 6 : if( bStyleParsed )
3496 : {
3497 4 : if( SfxItemState::SET == aItemSet.GetItemState(
3498 4 : RES_BACKGROUND, false, &pItem ) )
3499 : {
3500 0 : pCurTable->SetBGBrush( *static_cast<const SvxBrushItem *>(pItem) );
3501 0 : aItemSet.ClearItem( RES_BACKGROUND );
3502 : }
3503 4 : if( SfxItemState::SET == aItemSet.GetItemState(
3504 4 : RES_PARATR_SPLIT, false, &pItem ) )
3505 : {
3506 : aItemSet.Put(
3507 : SwFormatLayoutSplit( static_cast<const SvxFormatSplitItem *>(pItem)
3508 0 : ->GetValue() ) );
3509 0 : aItemSet.ClearItem( RES_PARATR_SPLIT );
3510 : }
3511 : }
3512 :
3513 : // Den linken/rechten Absatzeinzug ermitteln
3514 6 : sal_uInt16 nLeftSpace = 0;
3515 6 : sal_uInt16 nRightSpace = 0;
3516 : short nIndent;
3517 6 : GetMarginsFromContextWithNumBul( nLeftSpace, nRightSpace, nIndent );
3518 :
3519 : // die aktuelle Position an die wir irgendwann zurueckkehren
3520 6 : SwPosition *pSavePos = 0;
3521 6 : bool bForceFrame = false;
3522 6 : bool bAppended = false;
3523 6 : bool bParentLFStripped = false;
3524 6 : if( bTopTable )
3525 : {
3526 6 : SvxAdjust eTableAdjust = pTable->GetTableAdjust(false);
3527 :
3528 : // Wenn die Tabelle links oder rechts ausgerivchtet ist,
3529 : // oder in einen Rahmen soll, dann kommt sie auch in einen
3530 : // solchen.
3531 6 : bForceFrame = eTableAdjust == SVX_ADJUST_LEFT ||
3532 12 : eTableAdjust == SVX_ADJUST_RIGHT ||
3533 12 : pCurTable->HasToFly();
3534 :
3535 : // Entweder kommt die Tabelle in keinen Rahmen und befindet
3536 : // sich in keinem Rahmen (wird also durch Zellen simuliert),
3537 : // oder es gibt bereits Inhalt an der entsprechenden Stelle.
3538 : OSL_ENSURE( !bForceFrame || pCurTable->HasParentSection(),
3539 : "Tabelle im Rahmen hat keine Umgebung!" );
3540 :
3541 6 : bool bAppend = false;
3542 6 : if( bForceFrame )
3543 : {
3544 : // Wenn die Tabelle in einen Rahmen kommt, muss
3545 : // nur ein neuer Absatz aufgemacht werden, wenn
3546 : // der Absatz Rahmen ohne Umlauf enthaelt.
3547 0 : bAppend = HasCurrentParaFlys(true);
3548 : }
3549 : else
3550 : {
3551 : // Sonst muss ein neuer Absatz aufgemacht werden,
3552 : // wenn der Absatz nicht leer ist, oder Rahmen
3553 : // oder text::Bookmarks enthaelt.
3554 : bAppend =
3555 10 : pPam->GetPoint()->nContent.GetIndex() ||
3556 10 : HasCurrentParaFlys() ||
3557 10 : HasCurrentParaBookmarks();
3558 : }
3559 6 : if( bAppend )
3560 : {
3561 2 : if( !pPam->GetPoint()->nContent.GetIndex() )
3562 : {
3563 : //Set default to CJK and CTL
3564 : pDoc->SetTextFormatColl( *pPam,
3565 0 : pCSS1Parser->GetTextCollFromPool(RES_POOLCOLL_STANDARD) );
3566 0 : SvxFontHeightItem aFontHeight( 40, 100, RES_CHRATR_FONTSIZE );
3567 :
3568 : _HTMLAttr* pTmp =
3569 0 : new _HTMLAttr( *pPam->GetPoint(), aFontHeight );
3570 0 : aSetAttrTab.push_back( pTmp );
3571 :
3572 0 : SvxFontHeightItem aFontHeightCJK( 40, 100, RES_CHRATR_CJK_FONTSIZE );
3573 : pTmp =
3574 0 : new _HTMLAttr( *pPam->GetPoint(), aFontHeightCJK );
3575 0 : aSetAttrTab.push_back( pTmp );
3576 :
3577 0 : SvxFontHeightItem aFontHeightCTL( 40, 100, RES_CHRATR_CTL_FONTSIZE );
3578 : pTmp =
3579 0 : new _HTMLAttr( *pPam->GetPoint(), aFontHeightCTL );
3580 0 : aSetAttrTab.push_back( pTmp );
3581 :
3582 0 : pTmp = new _HTMLAttr( *pPam->GetPoint(),
3583 0 : SvxULSpaceItem( 0, 0, RES_UL_SPACE ) );
3584 0 : aSetAttrTab.push_front( pTmp ); // ja, 0, weil schon
3585 : // vom Tabellenende vorher
3586 : // was gesetzt sein kann.
3587 : }
3588 2 : AppendTextNode( AM_NOSPACE );
3589 2 : bAppended = true;
3590 : }
3591 4 : else if( !aParaAttrs.empty() )
3592 : {
3593 0 : if( !bForceFrame )
3594 : {
3595 : // Der Absatz wird gleich hinter die Tabelle
3596 : // verschoben. Deshalb entfernen wir alle harten
3597 : // Attribute des Absatzes
3598 :
3599 0 : for( size_t i=0; i<aParaAttrs.size(); i++ )
3600 0 : aParaAttrs[i]->Invalidate();
3601 : }
3602 :
3603 0 : aParaAttrs.clear();
3604 : }
3605 :
3606 6 : pSavePos = new SwPosition( *pPam->GetPoint() );
3607 : }
3608 0 : else if( pCurTable->HasParentSection() )
3609 : {
3610 0 : bParentLFStripped = StripTrailingLF() > 0;
3611 :
3612 : // Absaetze bzw. ueberschriften beeenden
3613 0 : nOpenParaToken = 0;
3614 0 : nFontStHeadStart = nFontStMin;
3615 :
3616 : // die harten Attribute an diesem Absatz werden nie mehr ungueltig
3617 0 : if( !aParaAttrs.empty() )
3618 0 : aParaAttrs.clear();
3619 : }
3620 :
3621 : // einen Tabellen Kontext anlegen
3622 : _HTMLTableContext *pTCntxt =
3623 : new _HTMLTableContext( pSavePos, nContextStMin,
3624 6 : nContextStAttrMin );
3625 :
3626 : // alle noch offenen Attribute beenden und hinter der Tabelle
3627 : // neu aufspannen
3628 6 : _HTMLAttrs *pPostIts = 0;
3629 6 : if( !bForceFrame && (bTopTable || pCurTable->HasParentSection()) )
3630 : {
3631 6 : SplitAttrTab( pTCntxt->aAttrTab, bTopTable );
3632 : // Wenn wir einen schon vorhandenen Absatz verwenden, duerfen
3633 : // in den keine PostIts eingefuegt werden, weil der Absatz
3634 : // ja hinter die Tabelle wandert. Sie werden deshalb in den
3635 : // ersten Absatz der Tabelle verschoben.
3636 : // Bei Tabellen in Tabellen duerfen ebenfalls keine PostIts
3637 : // in einen noch leeren Absatz eingefuegt werden, weil
3638 : // der sonat nicht geloescht wird.
3639 12 : if( (bTopTable && !bAppended) ||
3640 2 : (!bTopTable && !bParentLFStripped &&
3641 0 : !pPam->GetPoint()->nContent.GetIndex()) )
3642 4 : pPostIts = new _HTMLAttrs;
3643 6 : SetAttr( bTopTable, bTopTable, pPostIts );
3644 : }
3645 : else
3646 : {
3647 0 : SaveAttrTab( pTCntxt->aAttrTab );
3648 0 : if( bTopTable && !bAppended )
3649 : {
3650 0 : pPostIts = new _HTMLAttrs;
3651 0 : SetAttr( true, true, pPostIts );
3652 : }
3653 : }
3654 6 : bNoParSpace = false;
3655 :
3656 : // Aktuelle Numerierung retten und auschalten.
3657 6 : pTCntxt->SetNumInfo( GetNumInfo() );
3658 6 : GetNumInfo().Clear();
3659 6 : pTCntxt->SavePREListingXMP( *this );
3660 :
3661 6 : if( bTopTable )
3662 : {
3663 6 : if( bForceFrame )
3664 : {
3665 : // Die Tabelle soll in einen Rahmen geschaufelt werden.
3666 :
3667 0 : SfxItemSet aFrmSet( pDoc->GetAttrPool(),
3668 0 : RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
3669 0 : if( !pCurTable->IsNewDoc() )
3670 0 : Reader::ResetFrameFormatAttrs( aFrmSet );
3671 :
3672 0 : SwSurround eSurround = SURROUND_NONE;
3673 : sal_Int16 eHori;
3674 :
3675 0 : switch( pCurTable->GetTableAdjust(true) )
3676 : {
3677 : case SVX_ADJUST_RIGHT:
3678 0 : eHori = text::HoriOrientation::RIGHT;
3679 0 : eSurround = SURROUND_LEFT;
3680 0 : break;
3681 : case SVX_ADJUST_CENTER:
3682 0 : eHori = text::HoriOrientation::CENTER;
3683 0 : break;
3684 : case SVX_ADJUST_LEFT:
3685 0 : eSurround = SURROUND_RIGHT;
3686 : //fall-through
3687 : default:
3688 0 : eHori = text::HoriOrientation::LEFT;
3689 0 : break;
3690 : }
3691 : SetAnchorAndAdjustment( text::VertOrientation::NONE, eHori, aFrmSet,
3692 0 : true );
3693 0 : aFrmSet.Put( SwFormatSurround(eSurround) );
3694 :
3695 0 : SwFormatFrmSize aFrmSize( ATT_VAR_SIZE, 20*MM50, MINLAY );
3696 0 : aFrmSize.SetWidthPercent( 100 );
3697 0 : aFrmSet.Put( aFrmSize );
3698 :
3699 0 : sal_uInt16 nSpace = pCurTable->GetHSpace();
3700 0 : if( nSpace )
3701 0 : aFrmSet.Put( SvxLRSpaceItem(nSpace,nSpace, 0, 0, RES_LR_SPACE) );
3702 0 : nSpace = pCurTable->GetVSpace();
3703 0 : if( nSpace )
3704 0 : aFrmSet.Put( SvxULSpaceItem(nSpace,nSpace, RES_UL_SPACE) );
3705 :
3706 : RndStdIds eAnchorId = static_cast<const SwFormatAnchor&>(aFrmSet.
3707 0 : Get( RES_ANCHOR )).
3708 0 : GetAnchorId();
3709 : SwFrameFormat *pFrameFormat = pDoc->MakeFlySection(
3710 0 : eAnchorId, pPam->GetPoint(), &aFrmSet );
3711 :
3712 0 : pTCntxt->SetFrameFormat( pFrameFormat );
3713 0 : const SwFormatContent& rFlyContent = pFrameFormat->GetContent();
3714 0 : pPam->GetPoint()->nNode = *rFlyContent.GetContentIdx();
3715 : SwContentNode *pCNd =
3716 0 : pDoc->GetNodes().GoNext( &(pPam->GetPoint()->nNode) );
3717 0 : pPam->GetPoint()->nContent.Assign( pCNd, 0 );
3718 :
3719 : }
3720 :
3721 : // eine SwTable mit einer Box anlegen und den PaM in den
3722 : // Inhalt der Box-Section bewegen (der Ausrichtungs-Parameter
3723 : // ist erstmal nur ein Dummy und wird spaeter noch richtig
3724 : // gesetzt)
3725 : OSL_ENSURE( !pPam->GetPoint()->nContent.GetIndex(),
3726 : "Der Absatz hinter der Tabelle ist nicht leer!" );
3727 : const SwTable* pSwTable = pDoc->InsertTable(
3728 : SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 1 ),
3729 6 : *pPam->GetPoint(), 1, 1, text::HoriOrientation::LEFT );
3730 :
3731 6 : if( bForceFrame )
3732 : {
3733 0 : SwNodeIndex aDstIdx( pPam->GetPoint()->nNode );
3734 0 : pPam->Move( fnMoveBackward );
3735 0 : pDoc->GetNodes().Delete( aDstIdx );
3736 : }
3737 : else
3738 : {
3739 6 : if( bStyleParsed )
3740 : {
3741 4 : pCSS1Parser->SetFormatBreak( aItemSet, aPropInfo );
3742 4 : pSwTable->GetFrameFormat()->SetFormatAttr( aItemSet );
3743 : }
3744 6 : pPam->Move( fnMoveBackward );
3745 : }
3746 :
3747 6 : SwNode const*const pNd = & pPam->GetPoint()->nNode.GetNode();
3748 6 : if( !bAppended && !bForceFrame )
3749 : {
3750 : SwTextNode *const pOldTextNd =
3751 4 : pSavePos->nNode.GetNode().GetTextNode();
3752 : OSL_ENSURE( pOldTextNd, "Wieso stehen wir in keinem Text-Node?" );
3753 4 : SwFrameFormat *pFrameFormat = pSwTable->GetFrameFormat();
3754 :
3755 : const SfxPoolItem* pItem2;
3756 8 : if( SfxItemState::SET == pOldTextNd->GetSwAttrSet()
3757 4 : .GetItemState( RES_PAGEDESC, false, &pItem2 ) &&
3758 0 : static_cast<const SwFormatPageDesc *>(pItem2)->GetPageDesc() )
3759 : {
3760 0 : pFrameFormat->SetFormatAttr( *pItem2 );
3761 0 : pOldTextNd->ResetAttr( RES_PAGEDESC );
3762 : }
3763 8 : if( SfxItemState::SET == pOldTextNd->GetSwAttrSet()
3764 4 : .GetItemState( RES_BREAK, true, &pItem2 ) )
3765 : {
3766 0 : switch( static_cast<const SvxFormatBreakItem *>(pItem2)->GetBreak() )
3767 : {
3768 : case SVX_BREAK_PAGE_BEFORE:
3769 : case SVX_BREAK_PAGE_AFTER:
3770 : case SVX_BREAK_PAGE_BOTH:
3771 0 : pFrameFormat->SetFormatAttr( *pItem2 );
3772 0 : pOldTextNd->ResetAttr( RES_BREAK );
3773 : default:
3774 : ;
3775 : }
3776 : }
3777 : }
3778 :
3779 6 : if( !bAppended && pPostIts )
3780 : {
3781 : // noch vorhandene PostIts in den ersten Absatz
3782 : // der Tabelle setzen
3783 4 : InsertAttrs( *pPostIts );
3784 4 : delete pPostIts;
3785 4 : pPostIts = 0;
3786 : }
3787 :
3788 6 : pTCntxt->SetTableNode( const_cast<SwTableNode *>(pNd->FindTableNode()) );
3789 :
3790 6 : pCurTable->SetTable( pTCntxt->GetTableNode(), pTCntxt,
3791 : nLeftSpace, nRightSpace,
3792 12 : pSwTable, bForceFrame );
3793 :
3794 : OSL_ENSURE( !pPostIts, "ubenutzte PostIts" );
3795 : }
3796 : else
3797 : {
3798 : // noch offene Bereiche muessen noch entfernt werden
3799 0 : if( EndSections( bParentLFStripped ) )
3800 0 : bParentLFStripped = false;
3801 :
3802 0 : if( pCurTable->HasParentSection() )
3803 : {
3804 : // dannach entfernen wir ein ggf. zu viel vorhandenen
3805 : // leeren Absatz, aber nur, wenn er schon vor dem
3806 : // entfernen von LFs leer war
3807 0 : if( !bParentLFStripped )
3808 0 : StripTrailingPara();
3809 :
3810 0 : if( pPostIts )
3811 : {
3812 : // noch vorhandene PostIts an das Ende des jetzt
3813 : // aktuellen Absatzes schieben
3814 0 : InsertAttrs( *pPostIts );
3815 0 : delete pPostIts;
3816 0 : pPostIts = 0;
3817 : }
3818 : }
3819 :
3820 0 : SwNode const*const pNd = & pPam->GetPoint()->nNode.GetNode();
3821 : const SwStartNode *pStNd = (pTable->bFirstCell ? pNd->FindTableNode()
3822 0 : : pNd->FindTableBoxStartNode() );
3823 :
3824 0 : pCurTable->SetTable( pStNd, pTCntxt, nLeftSpace, nRightSpace );
3825 : }
3826 :
3827 : // Den Kontext-Stack einfrieren, denn es koennen auch mal
3828 : // irgendwo ausserhalb von Zellen Attribute gesetzt werden.
3829 : // Darf nicht frueher passieren, weil eventuell noch im
3830 : // Stack gesucht wird!!!
3831 6 : nContextStMin = aContexts.size();
3832 12 : nContextStAttrMin = nContextStMin;
3833 : }
3834 :
3835 : pSaveStruct = new _CellSaveStruct( *this, pCurTable, bHead,
3836 286 : bReadOptions );
3837 :
3838 : // ist beim ersten GetNextToken schon pending, muss bei
3839 : // wiederaufsetzen auf jedenfall neu gelesen werden!
3840 286 : SaveState( 0 );
3841 : }
3842 :
3843 286 : if( !nToken )
3844 286 : nToken = GetNextToken(); // Token nach <TABLE>
3845 :
3846 286 : bool bDone = false;
3847 2498 : while( (IsParserWorking() && !bDone) || bPending )
3848 : {
3849 1926 : SaveState( nToken );
3850 :
3851 1926 : nToken = FilterToken( nToken );
3852 :
3853 : OSL_ENSURE( pPendStack || !bCallNextToken || pSaveStruct->IsInSection(),
3854 : "Wo ist die Section gebieben?" );
3855 1926 : if( !pPendStack && bCallNextToken && pSaveStruct->IsInSection() )
3856 : {
3857 : // NextToken direkt aufrufen (z.B. um den Inhalt von
3858 : // Floating-Frames oder Applets zu ignorieren)
3859 0 : NextToken( nToken );
3860 : }
3861 1926 : else switch( nToken )
3862 : {
3863 : case HTML_TABLEHEADER_ON:
3864 : case HTML_TABLEDATA_ON:
3865 : case HTML_TABLEROW_ON:
3866 : case HTML_TABLEROW_OFF:
3867 : case HTML_THEAD_ON:
3868 : case HTML_THEAD_OFF:
3869 : case HTML_TFOOT_ON:
3870 : case HTML_TFOOT_OFF:
3871 : case HTML_TBODY_ON:
3872 : case HTML_TBODY_OFF:
3873 : case HTML_TABLE_OFF:
3874 0 : SkipToken(-1);
3875 : //fall-through
3876 : case HTML_TABLEHEADER_OFF:
3877 : case HTML_TABLEDATA_OFF:
3878 286 : bDone = true;
3879 286 : break;
3880 : case HTML_TABLE_ON:
3881 : {
3882 0 : bool bHasToFly = false;
3883 0 : SvxAdjust eTabAdjust = SVX_ADJUST_END;
3884 0 : if( !pPendStack )
3885 : {
3886 : // nur wenn eine neue Tabelle aufgemacht wird, aber
3887 : // nicht wenn nach einem Pending in der Tabelle
3888 : // weitergelesen wird!
3889 0 : pSaveStruct->m_pTable = pTable;
3890 :
3891 : // HACK: Eine Section fuer eine Tabelle anlegen, die
3892 : // in einen Rahmen kommt.
3893 0 : if( !pSaveStruct->IsInSection() )
3894 : {
3895 : // Diese Schleife muss vorwartes sein, weil die
3896 : // erste Option immer gewinnt.
3897 0 : bool bNeedsSection = false;
3898 0 : const HTMLOptions& rHTMLOptions = GetOptions();
3899 0 : for (size_t i = 0; i < rHTMLOptions.size(); ++i)
3900 : {
3901 0 : const HTMLOption& rOption = rHTMLOptions[i];
3902 0 : if( HTML_O_ALIGN==rOption.GetToken() )
3903 : {
3904 : SvxAdjust eAdjust =
3905 : (SvxAdjust)rOption.GetEnum(
3906 0 : aHTMLPAlignTable, SVX_ADJUST_END );
3907 0 : bNeedsSection = SVX_ADJUST_LEFT == eAdjust ||
3908 0 : SVX_ADJUST_RIGHT == eAdjust;
3909 0 : break;
3910 : }
3911 : }
3912 0 : if( bNeedsSection )
3913 : {
3914 : pSaveStruct->AddContents(
3915 0 : InsertTableContents(bHead ) );
3916 : }
3917 : }
3918 : else
3919 : {
3920 : // Wenn im aktuellen Absatz Flys verankert sind,
3921 : // muss die neue Tabelle in einen Rahmen.
3922 0 : bHasToFly = HasCurrentParaFlys(false,true);
3923 : }
3924 :
3925 : // in der Zelle kann sich ein Bereich befinden!
3926 : eTabAdjust = aAttrTab.pAdjust
3927 0 : ? static_cast<const SvxAdjustItem&>(aAttrTab.pAdjust->GetItem()).
3928 : GetAdjust()
3929 0 : : SVX_ADJUST_END;
3930 : }
3931 :
3932 : HTMLTable *pSubTable = BuildTable( eTabAdjust,
3933 : bHead,
3934 0 : pSaveStruct->IsInSection(),
3935 0 : bHasToFly );
3936 0 : if( SVPAR_PENDING != GetStatus() )
3937 : {
3938 : // nur wenn die Tabelle wirklich zu Ende ist!
3939 0 : if( pSubTable )
3940 : {
3941 : OSL_ENSURE( pSubTable->GetTableAdjust(false)!= SVX_ADJUST_LEFT &&
3942 : pSubTable->GetTableAdjust(false)!= SVX_ADJUST_RIGHT,
3943 : "links oder rechts ausgerichtete Tabellen gehoehren in Rahmen" );
3944 :
3945 : HTMLTableCnts *pParentContents =
3946 0 : pSubTable->GetParentContents();
3947 0 : if( pParentContents )
3948 : {
3949 : OSL_ENSURE( !pSaveStruct->IsInSection(),
3950 : "Wo ist die Section geblieben" );
3951 :
3952 : // Wenn jetzt keine Tabelle kommt haben wir eine
3953 : // Section
3954 0 : pSaveStruct->AddContents( pParentContents );
3955 : }
3956 :
3957 : const SwStartNode *pCapStNd =
3958 0 : pSubTable->GetCaptionStartNode();
3959 :
3960 0 : if( pSubTable->GetContext() )
3961 : {
3962 : OSL_ENSURE( !pSubTable->GetContext()->GetFrameFormat(),
3963 : "Tabelle steht im Rahmen" );
3964 :
3965 0 : if( pCapStNd && pSubTable->IsTopCaption() )
3966 : {
3967 : pSaveStruct->AddContents(
3968 0 : new HTMLTableCnts(pCapStNd) );
3969 : }
3970 :
3971 : pSaveStruct->AddContents(
3972 0 : new HTMLTableCnts(pSubTable) );
3973 :
3974 0 : if( pCapStNd && !pSubTable->IsTopCaption() )
3975 : {
3976 : pSaveStruct->AddContents(
3977 0 : new HTMLTableCnts(pCapStNd) );
3978 : }
3979 :
3980 : // Jetzt haben wir keine Section mehr
3981 0 : pSaveStruct->ClearIsInSection();
3982 : }
3983 0 : else if( pCapStNd )
3984 : {
3985 : // Da wir diese Sction nicht mehr loeschen
3986 : // koennen (sie koeente zur erster Box
3987 : // gehoeren), fuegen wir sie ein.
3988 : pSaveStruct->AddContents(
3989 0 : new HTMLTableCnts(pCapStNd) );
3990 :
3991 : // Jetzt haben wir keine Section mehr
3992 0 : pSaveStruct->ClearIsInSection();
3993 : }
3994 : }
3995 :
3996 0 : pTable = pSaveStruct->m_pTable;
3997 : }
3998 : }
3999 0 : break;
4000 :
4001 : case HTML_NOBR_ON:
4002 : // HACK fuer MS: Steht das <NOBR> zu beginn der Zelle?
4003 0 : pSaveStruct->StartNoBreak( *pPam->GetPoint() );
4004 0 : break;
4005 :
4006 : case HTML_NOBR_OFF:
4007 0 : pSaveStruct->EndNoBreak( *pPam->GetPoint() );
4008 0 : break;
4009 :
4010 : case HTML_COMMENT:
4011 : // Mit Kommentar-Feldern werden Spaces nicht mehr geloescht
4012 : // ausserdem wollen wir fuer einen Kommentar keine neue Zelle
4013 : // anlegen !!!
4014 0 : NextToken( nToken );
4015 0 : break;
4016 :
4017 : case HTML_MARQUEE_ON:
4018 0 : if( !pSaveStruct->IsInSection() )
4019 : {
4020 : // eine neue Section anlegen, der PaM steht dann darin
4021 : pSaveStruct->AddContents(
4022 0 : InsertTableContents( bHead ) );
4023 : }
4024 0 : bCallNextToken = true;
4025 0 : NewMarquee( pCurTable );
4026 0 : break;
4027 :
4028 : case HTML_TEXTTOKEN:
4029 : // keine Section fuer einen leeren String anlegen
4030 1094 : if( !pSaveStruct->IsInSection() && 1==aToken.getLength() &&
4031 283 : ' '==aToken[0] )
4032 263 : break;
4033 : default:
4034 1377 : if( !pSaveStruct->IsInSection() )
4035 : {
4036 : // eine neue Section anlegen, der PaM steht dann darin
4037 : pSaveStruct->AddContents(
4038 283 : InsertTableContents( bHead ) );
4039 : }
4040 :
4041 1377 : if( IsParserWorking() || bPending )
4042 1377 : NextToken( nToken );
4043 1377 : break;
4044 : }
4045 :
4046 : OSL_ENSURE( !bPending || !pPendStack,
4047 : "SwHTMLParser::BuildTableCell: Es gibt wieder einen Pend-Stack" );
4048 1926 : bPending = false;
4049 1926 : if( IsParserWorking() )
4050 1926 : SaveState( 0 );
4051 :
4052 1926 : if( !bDone )
4053 1640 : nToken = GetNextToken();
4054 : }
4055 :
4056 286 : if( SVPAR_PENDING == GetStatus() )
4057 : {
4058 : pPendStack = new SwPendingStack( bHead ? HTML_TABLEHEADER_ON
4059 0 : : HTML_TABLEDATA_ON, pPendStack );
4060 0 : pPendStack->pData = pSaveStruct;
4061 :
4062 0 : return;
4063 : }
4064 :
4065 : // Falls der Inhalt der Zelle leer war, muessen wir noch einen
4066 : // leeren Inhalt anlegen. Ausserdem legen wir einen leeren Inhalt
4067 : // an, wenn die Zelle mit einer Tabelle aufgehoert hat und keine
4068 : // COL-Tags hatte (sonst wurde sie wahrscheinlich von uns exportiert,
4069 : // und dann wollen wir natuerlich keinen zusaetzlichen Absatz haben).
4070 572 : if( !pSaveStruct->GetFirstContents() ||
4071 283 : (!pSaveStruct->IsInSection() && !pCurTable->HasColTags()) )
4072 : {
4073 : OSL_ENSURE( pSaveStruct->GetFirstContents() ||
4074 : !pSaveStruct->IsInSection(),
4075 : "Section oder nicht, das ist hier die Frage" );
4076 : const SwStartNode *pStNd =
4077 3 : InsertTableSection( static_cast< sal_uInt16 >(pSaveStruct->IsHeaderCell()
4078 : ? RES_POOLCOLL_TABLE_HDLN
4079 3 : : RES_POOLCOLL_TABLE ));
4080 3 : const SwEndNode *pEndNd = pStNd->EndOfSectionNode();
4081 3 : SwContentNode *pCNd = pDoc->GetNodes()[pEndNd->GetIndex()-1] ->GetContentNode();
4082 : //Added defaults to CJK and CTL
4083 3 : SvxFontHeightItem aFontHeight( 40, 100, RES_CHRATR_FONTSIZE );
4084 3 : pCNd->SetAttr( aFontHeight );
4085 6 : SvxFontHeightItem aFontHeightCJK( 40, 100, RES_CHRATR_CJK_FONTSIZE );
4086 3 : pCNd->SetAttr( aFontHeightCJK );
4087 6 : SvxFontHeightItem aFontHeightCTL( 40, 100, RES_CHRATR_CTL_FONTSIZE );
4088 3 : pCNd->SetAttr( aFontHeightCTL );
4089 :
4090 3 : pSaveStruct->AddContents( new HTMLTableCnts(pStNd) );
4091 6 : pSaveStruct->ClearIsInSection();
4092 : }
4093 :
4094 286 : if( pSaveStruct->IsInSection() )
4095 : {
4096 283 : pSaveStruct->CheckNoBreak( *pPam->GetPoint(), pDoc );
4097 :
4098 : // Alle noch offenen Kontexte beenden. Wir nehmen hier
4099 : // AttrMin, weil nContxtStMin evtl. veraendert wurde.
4100 : // Da es durch EndContext wieder restauriert wird, geht das.
4101 566 : while( aContexts.size() > nContextStAttrMin+1 )
4102 : {
4103 0 : _HTMLAttrContext *pCntxt = PopContext();
4104 0 : EndContext( pCntxt );
4105 0 : delete pCntxt;
4106 : }
4107 :
4108 : // LFs am Absatz-Ende entfernen
4109 283 : if( StripTrailingLF()==0 && !pPam->GetPoint()->nContent.GetIndex() )
4110 263 : StripTrailingPara();
4111 :
4112 : // falls fuer die Zelle eine Ausrichtung gesetzt wurde, muessen
4113 : // wir die beenden
4114 283 : _HTMLAttrContext *pCntxt = PopContext();
4115 283 : EndContext( pCntxt );
4116 283 : delete pCntxt;
4117 : }
4118 : else
4119 : {
4120 : // Alle noch offenen Kontexte beenden
4121 9 : while( aContexts.size() > nContextStAttrMin )
4122 : {
4123 3 : _HTMLAttrContext *pCntxt = PopContext();
4124 3 : ClearContext( pCntxt );
4125 3 : delete pCntxt;
4126 : }
4127 : }
4128 :
4129 : // auch eine Numerierung muss beendet werden
4130 286 : GetNumInfo().Clear();
4131 :
4132 286 : SetAttr( false );
4133 :
4134 286 : pSaveStruct->InsertCell( *this, pCurTable );
4135 :
4136 : // wir stehen jetzt (wahrschenlich) vor <TH>, <TD>, <TR> oder </TABLE>
4137 286 : delete pSaveStruct;
4138 : }
4139 :
4140 140 : class _RowSaveStruct : public SwPendingStackData
4141 : {
4142 : public:
4143 : SvxAdjust eAdjust;
4144 : sal_Int16 eVertOri;
4145 : bool bHasCells;
4146 :
4147 70 : _RowSaveStruct() :
4148 70 : eAdjust( SVX_ADJUST_END ), eVertOri( text::VertOrientation::TOP ), bHasCells( false )
4149 70 : {}
4150 : };
4151 :
4152 64 : void SwHTMLParser::BuildTableRow( HTMLTable *pCurTable, bool bReadOptions,
4153 : SvxAdjust eGrpAdjust,
4154 : sal_Int16 eGrpVertOri )
4155 : {
4156 : // <TR> wurde bereist gelesen
4157 :
4158 64 : if( !IsParserWorking() && !pPendStack )
4159 64 : return;
4160 :
4161 64 : int nToken = 0;
4162 : _RowSaveStruct* pSaveStruct;
4163 :
4164 64 : bool bPending = false;
4165 64 : if( pPendStack )
4166 : {
4167 0 : pSaveStruct = static_cast<_RowSaveStruct*>(pPendStack->pData);
4168 :
4169 0 : SwPendingStack* pTmp = pPendStack->pNext;
4170 0 : delete pPendStack;
4171 0 : pPendStack = pTmp;
4172 0 : nToken = pPendStack ? pPendStack->nToken : GetSaveToken();
4173 0 : bPending = SVPAR_ERROR == eState && pPendStack != 0;
4174 :
4175 0 : SaveState( nToken );
4176 : }
4177 : else
4178 : {
4179 64 : SvxAdjust eAdjust = eGrpAdjust;
4180 64 : sal_Int16 eVertOri = eGrpVertOri;
4181 64 : Color aBGColor;
4182 128 : OUString aBGImage, aStyle, aId, aClass;
4183 64 : bool bBGColor = false;
4184 64 : pSaveStruct = new _RowSaveStruct;
4185 :
4186 64 : if( bReadOptions )
4187 : {
4188 64 : const HTMLOptions& rHTMLOptions = GetOptions();
4189 180 : for (size_t i = rHTMLOptions.size(); i; )
4190 : {
4191 52 : const HTMLOption& rOption = rHTMLOptions[--i];
4192 52 : switch( rOption.GetToken() )
4193 : {
4194 : case HTML_O_ID:
4195 0 : aId = rOption.GetString();
4196 0 : break;
4197 : case HTML_O_ALIGN:
4198 : eAdjust = (SvxAdjust)rOption.GetEnum(
4199 0 : aHTMLPAlignTable, static_cast< sal_uInt16 >(eAdjust) );
4200 0 : break;
4201 : case HTML_O_VALIGN:
4202 : eVertOri = rOption.GetEnum(
4203 52 : aHTMLTableVAlignTable, eVertOri );
4204 52 : break;
4205 : case HTML_O_BGCOLOR:
4206 : // Leere BGCOLOR bei <TABLE>, <TR> und <TD>/<TH> wie Netsc.
4207 : // ignorieren, bei allen anderen Tags *wirklich* nicht.
4208 0 : if( !rOption.GetString().isEmpty() )
4209 : {
4210 0 : rOption.GetColor( aBGColor );
4211 0 : bBGColor = true;
4212 : }
4213 0 : break;
4214 : case HTML_O_BACKGROUND:
4215 0 : aBGImage = rOption.GetString();
4216 0 : break;
4217 : case HTML_O_STYLE:
4218 0 : aStyle = rOption.GetString();
4219 0 : break;
4220 : case HTML_O_CLASS:
4221 0 : aClass= rOption.GetString();
4222 0 : break;
4223 : }
4224 : }
4225 : }
4226 :
4227 64 : if( !aId.isEmpty() )
4228 0 : InsertBookmark( aId );
4229 :
4230 : SvxBrushItem *pBrushItem =
4231 : CreateBrushItem( bBGColor ? &aBGColor : 0, aBGImage, aStyle,
4232 64 : aId, aClass );
4233 64 : pCurTable->OpenRow( eAdjust, eVertOri, pBrushItem );
4234 : // ist beim ersten GetNextToken schon pending, muss bei
4235 : // wiederaufsetzen auf jedenfall neu gelesen werden!
4236 128 : SaveState( 0 );
4237 : }
4238 :
4239 64 : if( !nToken )
4240 64 : nToken = GetNextToken(); // naechstes Token
4241 :
4242 64 : bool bDone = false;
4243 812 : while( (IsParserWorking() && !bDone) || bPending )
4244 : {
4245 684 : SaveState( nToken );
4246 :
4247 684 : nToken = FilterToken( nToken );
4248 :
4249 : OSL_ENSURE( pPendStack || !bCallNextToken ||
4250 : pCurTable->GetContext() || pCurTable->HasParentSection(),
4251 : "Wo ist die Section gebieben?" );
4252 684 : if( !pPendStack && bCallNextToken &&
4253 0 : (pCurTable->GetContext() || pCurTable->HasParentSection()) )
4254 : {
4255 : // NextToken direkt aufrufen (z.B. um den Inhalt von
4256 : // Floating-Frames oder Applets zu ignorieren)
4257 0 : NextToken( nToken );
4258 : }
4259 684 : else switch( nToken )
4260 : {
4261 : case HTML_TABLE_ON:
4262 0 : if( !pCurTable->GetContext() )
4263 : {
4264 0 : SkipToken( -1 );
4265 0 : bDone = true;
4266 : }
4267 :
4268 0 : break;
4269 : case HTML_TABLEROW_ON:
4270 : case HTML_THEAD_ON:
4271 : case HTML_THEAD_OFF:
4272 : case HTML_TBODY_ON:
4273 : case HTML_TBODY_OFF:
4274 : case HTML_TFOOT_ON:
4275 : case HTML_TFOOT_OFF:
4276 : case HTML_TABLE_OFF:
4277 0 : SkipToken( -1 );
4278 : //fall-through
4279 : case HTML_TABLEROW_OFF:
4280 64 : bDone = true;
4281 64 : break;
4282 : case HTML_TABLEHEADER_ON:
4283 : case HTML_TABLEDATA_ON:
4284 286 : BuildTableCell( pCurTable, true, HTML_TABLEHEADER_ON==nToken );
4285 286 : if( SVPAR_PENDING != GetStatus() )
4286 : {
4287 286 : pSaveStruct->bHasCells = true;
4288 286 : bDone = pTable->IsOverflowing();
4289 : }
4290 286 : break;
4291 : case HTML_CAPTION_ON:
4292 0 : BuildTableCaption( pCurTable );
4293 0 : bDone = pTable->IsOverflowing();
4294 0 : break;
4295 : case HTML_CAPTION_OFF:
4296 : case HTML_TABLEHEADER_OFF:
4297 : case HTML_TABLEDATA_OFF:
4298 : case HTML_COLGROUP_ON:
4299 : case HTML_COLGROUP_OFF:
4300 : case HTML_COL_ON:
4301 : case HTML_COL_OFF:
4302 : // wo keine Zelle anfing kann auch keine aufhoehren, oder?
4303 : // und die ganzen anderen Tokens haben hier auch nicht zu
4304 : // suchen und machen nur die Tabelle kaputt
4305 0 : break;
4306 : case HTML_MULTICOL_ON:
4307 : // spaltige Rahmen koennen wir hier leider nicht einguegen
4308 0 : break;
4309 : case HTML_FORM_ON:
4310 0 : NewForm( false ); // keinen neuen Absatz aufmachen!
4311 0 : break;
4312 : case HTML_FORM_OFF:
4313 0 : EndForm( false ); // keinen neuen Absatz aufmachen!
4314 0 : break;
4315 : case HTML_COMMENT:
4316 0 : NextToken( nToken );
4317 0 : break;
4318 : case HTML_MAP_ON:
4319 : // eine Image-Map fuegt nichts ein, deshalb koennen wir sie
4320 : // problemlos auch ohne Zelle parsen
4321 0 : NextToken( nToken );
4322 0 : break;
4323 : case HTML_TEXTTOKEN:
4324 673 : if( (pCurTable->GetContext() ||
4325 334 : !pCurTable->HasParentSection()) &&
4326 992 : 1==aToken.getLength() && ' '==aToken[0] )
4327 329 : break;
4328 : default:
4329 5 : pCurTable->MakeParentContents();
4330 5 : NextToken( nToken );
4331 5 : break;
4332 : }
4333 :
4334 : OSL_ENSURE( !bPending || !pPendStack,
4335 : "SwHTMLParser::BuildTableRow: Es gibt wieder einen Pend-Stack" );
4336 684 : bPending = false;
4337 684 : if( IsParserWorking() )
4338 684 : SaveState( 0 );
4339 :
4340 684 : if( !bDone )
4341 620 : nToken = GetNextToken();
4342 : }
4343 :
4344 64 : if( SVPAR_PENDING == GetStatus() )
4345 : {
4346 0 : pPendStack = new SwPendingStack( HTML_TABLEROW_ON, pPendStack );
4347 0 : pPendStack->pData = pSaveStruct;
4348 : }
4349 : else
4350 : {
4351 64 : pCurTable->CloseRow( !pSaveStruct->bHasCells );
4352 64 : delete pSaveStruct;
4353 : }
4354 :
4355 : // wir stehen jetzt (wahrscheinlich) vor <TR> oder </TABLE>
4356 : }
4357 :
4358 6 : void SwHTMLParser::BuildTableSection( HTMLTable *pCurTable,
4359 : bool bReadOptions,
4360 : bool bHead )
4361 : {
4362 : // <THEAD>, <TBODY> bzw. <TFOOT> wurde bereits gelesen
4363 6 : if( !IsParserWorking() && !pPendStack )
4364 6 : return;
4365 :
4366 6 : int nToken = 0;
4367 6 : bool bPending = false;
4368 : _RowSaveStruct* pSaveStruct;
4369 :
4370 6 : if( pPendStack )
4371 : {
4372 0 : pSaveStruct = static_cast<_RowSaveStruct*>(pPendStack->pData);
4373 :
4374 0 : SwPendingStack* pTmp = pPendStack->pNext;
4375 0 : delete pPendStack;
4376 0 : pPendStack = pTmp;
4377 0 : nToken = pPendStack ? pPendStack->nToken : GetSaveToken();
4378 0 : bPending = SVPAR_ERROR == eState && pPendStack != 0;
4379 :
4380 0 : SaveState( nToken );
4381 : }
4382 : else
4383 : {
4384 6 : pSaveStruct = new _RowSaveStruct;
4385 :
4386 6 : if( bReadOptions )
4387 : {
4388 0 : const HTMLOptions& rHTMLOptions = GetOptions();
4389 0 : for (size_t i = rHTMLOptions.size(); i; )
4390 : {
4391 0 : const HTMLOption& rOption = rHTMLOptions[--i];
4392 0 : switch( rOption.GetToken() )
4393 : {
4394 : case HTML_O_ID:
4395 0 : InsertBookmark( rOption.GetString() );
4396 0 : break;
4397 : case HTML_O_ALIGN:
4398 : pSaveStruct->eAdjust =
4399 : (SvxAdjust)rOption.GetEnum( aHTMLPAlignTable,
4400 0 : static_cast< sal_uInt16 >(pSaveStruct->eAdjust) );
4401 0 : break;
4402 : case HTML_O_VALIGN:
4403 : pSaveStruct->eVertOri =
4404 : rOption.GetEnum( aHTMLTableVAlignTable,
4405 0 : pSaveStruct->eVertOri );
4406 0 : break;
4407 : }
4408 : }
4409 : }
4410 :
4411 : // ist beim ersten GetNextToken schon pending, muss bei
4412 : // wiederaufsetzen auf jedenfall neu gelesen werden!
4413 6 : SaveState( 0 );
4414 : }
4415 :
4416 6 : if( !nToken )
4417 6 : nToken = GetNextToken(); // naechstes Token
4418 :
4419 6 : bool bDone = false;
4420 146 : while( (IsParserWorking() && !bDone) || bPending )
4421 : {
4422 134 : SaveState( nToken );
4423 :
4424 134 : nToken = FilterToken( nToken );
4425 :
4426 : OSL_ENSURE( pPendStack || !bCallNextToken ||
4427 : pCurTable->GetContext() || pCurTable->HasParentSection(),
4428 : "Wo ist die Section gebieben?" );
4429 134 : if( !pPendStack && bCallNextToken &&
4430 0 : (pCurTable->GetContext() || pCurTable->HasParentSection()) )
4431 : {
4432 : // NextToken direkt aufrufen (z.B. um den Inhalt von
4433 : // Floating-Frames oder Applets zu ignorieren)
4434 0 : NextToken( nToken );
4435 : }
4436 134 : else switch( nToken )
4437 : {
4438 : case HTML_TABLE_ON:
4439 0 : if( !pCurTable->GetContext() )
4440 : {
4441 0 : SkipToken( -1 );
4442 0 : bDone = true;
4443 : }
4444 :
4445 0 : break;
4446 : case HTML_THEAD_ON:
4447 : case HTML_TFOOT_ON:
4448 : case HTML_TBODY_ON:
4449 : case HTML_TABLE_OFF:
4450 6 : SkipToken( -1 );
4451 : //fall-through
4452 : case HTML_THEAD_OFF:
4453 : case HTML_TBODY_OFF:
4454 : case HTML_TFOOT_OFF:
4455 6 : bDone = true;
4456 6 : break;
4457 : case HTML_CAPTION_ON:
4458 0 : BuildTableCaption( pCurTable );
4459 0 : bDone = pTable->IsOverflowing();
4460 0 : break;
4461 : case HTML_CAPTION_OFF:
4462 0 : break;
4463 : case HTML_TABLEHEADER_ON:
4464 : case HTML_TABLEDATA_ON:
4465 0 : SkipToken( -1 );
4466 : BuildTableRow( pCurTable, false, pSaveStruct->eAdjust,
4467 0 : pSaveStruct->eVertOri );
4468 0 : bDone = pTable->IsOverflowing();
4469 0 : break;
4470 : case HTML_TABLEROW_ON:
4471 : BuildTableRow( pCurTable, true, pSaveStruct->eAdjust,
4472 64 : pSaveStruct->eVertOri );
4473 64 : bDone = pTable->IsOverflowing();
4474 64 : break;
4475 : case HTML_MULTICOL_ON:
4476 : // spaltige Rahmen koennen wir hier leider nicht einguegen
4477 0 : break;
4478 : case HTML_FORM_ON:
4479 0 : NewForm( false ); // keinen neuen Absatz aufmachen!
4480 0 : break;
4481 : case HTML_FORM_OFF:
4482 0 : EndForm( false ); // keinen neuen Absatz aufmachen!
4483 0 : break;
4484 : case HTML_TEXTTOKEN:
4485 : // Blank-Strings sind Folge von CR+LF und kein Text
4486 128 : if( (pCurTable->GetContext() ||
4487 64 : !pCurTable->HasParentSection()) &&
4488 192 : 1==aToken.getLength() && ' ' == aToken[0] )
4489 64 : break;
4490 : default:
4491 0 : pCurTable->MakeParentContents();
4492 0 : NextToken( nToken );
4493 : }
4494 :
4495 : OSL_ENSURE( !bPending || !pPendStack,
4496 : "SwHTMLParser::BuildTableSection: Es gibt wieder einen Pend-Stack" );
4497 134 : bPending = false;
4498 134 : if( IsParserWorking() )
4499 134 : SaveState( 0 );
4500 :
4501 134 : if( !bDone )
4502 128 : nToken = GetNextToken();
4503 : }
4504 :
4505 6 : if( SVPAR_PENDING == GetStatus() )
4506 : {
4507 : pPendStack = new SwPendingStack( bHead ? HTML_THEAD_ON
4508 0 : : HTML_TBODY_ON, pPendStack );
4509 0 : pPendStack->pData = pSaveStruct;
4510 : }
4511 : else
4512 : {
4513 6 : pCurTable->CloseSection( bHead );
4514 6 : delete pSaveStruct;
4515 : }
4516 :
4517 : // now we stand (perhaps) in front of <TBODY>,... or </TABLE>
4518 : }
4519 :
4520 8 : struct _TableColGrpSaveStruct : public SwPendingStackData
4521 : {
4522 : sal_uInt16 nColGrpSpan;
4523 : sal_uInt16 nColGrpWidth;
4524 : bool bRelColGrpWidth;
4525 : SvxAdjust eColGrpAdjust;
4526 : sal_Int16 eColGrpVertOri;
4527 :
4528 : inline _TableColGrpSaveStruct();
4529 :
4530 : inline void CloseColGroup( HTMLTable *pTable );
4531 : };
4532 :
4533 4 : inline _TableColGrpSaveStruct::_TableColGrpSaveStruct() :
4534 : nColGrpSpan( 1 ), nColGrpWidth( 0 ),
4535 : bRelColGrpWidth( false ), eColGrpAdjust( SVX_ADJUST_END ),
4536 4 : eColGrpVertOri( text::VertOrientation::TOP )
4537 4 : {}
4538 :
4539 4 : inline void _TableColGrpSaveStruct::CloseColGroup( HTMLTable *pTable )
4540 : {
4541 : pTable->CloseColGroup( nColGrpSpan, nColGrpWidth,
4542 4 : bRelColGrpWidth, eColGrpAdjust, eColGrpVertOri );
4543 4 : }
4544 :
4545 4 : void SwHTMLParser::BuildTableColGroup( HTMLTable *pCurTable,
4546 : bool bReadOptions )
4547 : {
4548 : // <COLGROUP> wurde bereits gelesen, wenn bReadOptions
4549 :
4550 4 : if( !IsParserWorking() && !pPendStack )
4551 4 : return;
4552 :
4553 4 : int nToken = 0;
4554 4 : bool bPending = false;
4555 : _TableColGrpSaveStruct* pSaveStruct;
4556 :
4557 4 : if( pPendStack )
4558 : {
4559 0 : pSaveStruct = static_cast<_TableColGrpSaveStruct*>(pPendStack->pData);
4560 :
4561 0 : SwPendingStack* pTmp = pPendStack->pNext;
4562 0 : delete pPendStack;
4563 0 : pPendStack = pTmp;
4564 0 : nToken = pPendStack ? pPendStack->nToken : GetSaveToken();
4565 0 : bPending = SVPAR_ERROR == eState && pPendStack != 0;
4566 :
4567 0 : SaveState( nToken );
4568 : }
4569 : else
4570 : {
4571 :
4572 4 : pSaveStruct = new _TableColGrpSaveStruct;
4573 4 : if( bReadOptions )
4574 : {
4575 0 : const HTMLOptions& rColGrpOptions = GetOptions();
4576 0 : for (size_t i = rColGrpOptions.size(); i; )
4577 : {
4578 0 : const HTMLOption& rOption = rColGrpOptions[--i];
4579 0 : switch( rOption.GetToken() )
4580 : {
4581 : case HTML_O_ID:
4582 0 : InsertBookmark( rOption.GetString() );
4583 0 : break;
4584 : case HTML_O_SPAN:
4585 0 : pSaveStruct->nColGrpSpan = (sal_uInt16)rOption.GetNumber();
4586 0 : break;
4587 : case HTML_O_WIDTH:
4588 0 : pSaveStruct->nColGrpWidth = (sal_uInt16)rOption.GetNumber();
4589 : pSaveStruct->bRelColGrpWidth =
4590 0 : (rOption.GetString().indexOf('*') != -1);
4591 0 : break;
4592 : case HTML_O_ALIGN:
4593 : pSaveStruct->eColGrpAdjust =
4594 : (SvxAdjust)rOption.GetEnum( aHTMLPAlignTable,
4595 0 : static_cast< sal_uInt16 >(pSaveStruct->eColGrpAdjust) );
4596 0 : break;
4597 : case HTML_O_VALIGN:
4598 : pSaveStruct->eColGrpVertOri =
4599 : rOption.GetEnum( aHTMLTableVAlignTable,
4600 0 : pSaveStruct->eColGrpVertOri );
4601 0 : break;
4602 : }
4603 : }
4604 : }
4605 : // ist beim ersten GetNextToken schon pending, muss bei
4606 : // wiederaufsetzen auf jedenfall neu gelesen werden!
4607 4 : SaveState( 0 );
4608 : }
4609 :
4610 4 : if( !nToken )
4611 4 : nToken = GetNextToken(); // naechstes Token
4612 :
4613 4 : bool bDone = false;
4614 28 : while( (IsParserWorking() && !bDone) || bPending )
4615 : {
4616 20 : SaveState( nToken );
4617 :
4618 20 : nToken = FilterToken( nToken );
4619 :
4620 : OSL_ENSURE( pPendStack || !bCallNextToken ||
4621 : pCurTable->GetContext() || pCurTable->HasParentSection(),
4622 : "Wo ist die Section gebieben?" );
4623 20 : if( !pPendStack && bCallNextToken &&
4624 0 : (pCurTable->GetContext() || pCurTable->HasParentSection()) )
4625 : {
4626 : // NextToken direkt aufrufen (z.B. um den Inhalt von
4627 : // Floating-Frames oder Applets zu ignorieren)
4628 0 : NextToken( nToken );
4629 : }
4630 20 : else switch( nToken )
4631 : {
4632 : case HTML_TABLE_ON:
4633 0 : if( !pCurTable->GetContext() )
4634 : {
4635 0 : SkipToken( -1 );
4636 0 : bDone = true;
4637 : }
4638 :
4639 0 : break;
4640 : case HTML_COLGROUP_ON:
4641 : case HTML_THEAD_ON:
4642 : case HTML_TFOOT_ON:
4643 : case HTML_TBODY_ON:
4644 : case HTML_TABLEROW_ON:
4645 : case HTML_TABLE_OFF:
4646 4 : SkipToken( -1 );
4647 : //fall-through
4648 : case HTML_COLGROUP_OFF:
4649 4 : bDone = true;
4650 4 : break;
4651 : case HTML_COL_ON:
4652 : {
4653 8 : sal_uInt16 nColSpan = 1;
4654 8 : sal_uInt16 nColWidth = pSaveStruct->nColGrpWidth;
4655 8 : bool bRelColWidth = pSaveStruct->bRelColGrpWidth;
4656 8 : SvxAdjust eColAdjust = pSaveStruct->eColGrpAdjust;
4657 8 : sal_Int16 eColVertOri = pSaveStruct->eColGrpVertOri;
4658 :
4659 8 : const HTMLOptions& rColOptions = GetOptions();
4660 24 : for (size_t i = rColOptions.size(); i; )
4661 : {
4662 8 : const HTMLOption& rOption = rColOptions[--i];
4663 8 : switch( rOption.GetToken() )
4664 : {
4665 : case HTML_O_ID:
4666 0 : InsertBookmark( rOption.GetString() );
4667 0 : break;
4668 : case HTML_O_SPAN:
4669 0 : nColSpan = (sal_uInt16)rOption.GetNumber();
4670 0 : break;
4671 : case HTML_O_WIDTH:
4672 8 : nColWidth = (sal_uInt16)rOption.GetNumber();
4673 : bRelColWidth =
4674 8 : (rOption.GetString().indexOf('*') != -1);
4675 8 : break;
4676 : case HTML_O_ALIGN:
4677 : eColAdjust =
4678 : (SvxAdjust)rOption.GetEnum( aHTMLPAlignTable,
4679 0 : static_cast< sal_uInt16 >(eColAdjust) );
4680 0 : break;
4681 : case HTML_O_VALIGN:
4682 : eColVertOri =
4683 : rOption.GetEnum( aHTMLTableVAlignTable,
4684 0 : eColVertOri );
4685 0 : break;
4686 : }
4687 : }
4688 : pCurTable->InsertCol( nColSpan, nColWidth, bRelColWidth,
4689 8 : eColAdjust, eColVertOri );
4690 :
4691 : // die Angaben in <COLGRP> sollen ignoriert werden, wenn
4692 : // <COL>-Elemente existieren
4693 8 : pSaveStruct->nColGrpSpan = 0;
4694 : }
4695 8 : break;
4696 : case HTML_COL_OFF:
4697 0 : break; // Ignorieren
4698 : case HTML_MULTICOL_ON:
4699 : // spaltige Rahmen koennen wir hier leider nicht einguegen
4700 0 : break;
4701 : case HTML_TEXTTOKEN:
4702 24 : if( (pCurTable->GetContext() ||
4703 8 : !pCurTable->HasParentSection()) &&
4704 8 : 1==aToken.getLength() && ' '==aToken[0] )
4705 0 : break;
4706 : default:
4707 8 : pCurTable->MakeParentContents();
4708 8 : NextToken( nToken );
4709 : }
4710 :
4711 : OSL_ENSURE( !bPending || !pPendStack,
4712 : "SwHTMLParser::BuildTableColGrp: Es gibt wieder einen Pend-Stack" );
4713 20 : bPending = false;
4714 20 : if( IsParserWorking() )
4715 20 : SaveState( 0 );
4716 :
4717 20 : if( !bDone )
4718 16 : nToken = GetNextToken();
4719 : }
4720 :
4721 4 : if( SVPAR_PENDING == GetStatus() )
4722 : {
4723 0 : pPendStack = new SwPendingStack( HTML_COL_ON, pPendStack );
4724 0 : pPendStack->pData = pSaveStruct;
4725 : }
4726 : else
4727 : {
4728 4 : pSaveStruct->CloseColGroup( pCurTable );
4729 4 : delete pSaveStruct;
4730 : }
4731 : }
4732 :
4733 : class _CaptionSaveStruct : public _SectionSaveStruct
4734 : {
4735 : SwPosition aSavePos;
4736 : SwHTMLNumRuleInfo aNumRuleInfo; // gueltige Numerierung
4737 :
4738 : public:
4739 :
4740 : _HTMLAttrTable aAttrTab; // und die Attribute
4741 :
4742 0 : _CaptionSaveStruct( SwHTMLParser& rParser, const SwPosition& rPos ) :
4743 0 : _SectionSaveStruct( rParser ), aSavePos( rPos )
4744 : {
4745 0 : rParser.SaveAttrTab( aAttrTab );
4746 :
4747 : // Die aktuelle Numerierung wurde gerettet und muss nur
4748 : // noch beendet werden.
4749 0 : aNumRuleInfo.Set( rParser.GetNumInfo() );
4750 0 : rParser.GetNumInfo().Clear();
4751 0 : }
4752 :
4753 0 : const SwPosition& GetPos() const { return aSavePos; }
4754 :
4755 0 : void RestoreAll( SwHTMLParser& rParser )
4756 : {
4757 : // Die alten Stack wiederherstellen
4758 0 : Restore( rParser );
4759 :
4760 : // Die alte Attribut-Tabelle wiederherstellen
4761 0 : rParser.RestoreAttrTab( aAttrTab );
4762 :
4763 : // Die alte Numerierung wieder aufspannen
4764 0 : rParser.GetNumInfo().Set( aNumRuleInfo );
4765 0 : }
4766 :
4767 : virtual ~_CaptionSaveStruct();
4768 : };
4769 :
4770 0 : _CaptionSaveStruct::~_CaptionSaveStruct()
4771 0 : {}
4772 :
4773 0 : void SwHTMLParser::BuildTableCaption( HTMLTable *pCurTable )
4774 : {
4775 : // <CAPTION> wurde bereits gelesen
4776 :
4777 0 : if( !IsParserWorking() && !pPendStack )
4778 0 : return;
4779 :
4780 0 : int nToken = 0;
4781 : _CaptionSaveStruct* pSaveStruct;
4782 :
4783 0 : if( pPendStack )
4784 : {
4785 0 : pSaveStruct = static_cast<_CaptionSaveStruct*>(pPendStack->pData);
4786 :
4787 0 : SwPendingStack* pTmp = pPendStack->pNext;
4788 0 : delete pPendStack;
4789 0 : pPendStack = pTmp;
4790 0 : nToken = pPendStack ? pPendStack->nToken : GetSaveToken();
4791 : OSL_ENSURE( !pPendStack, "Wo kommt hier ein Pending-Stack her?" );
4792 :
4793 0 : SaveState( nToken );
4794 : }
4795 : else
4796 : {
4797 0 : if( pTable->IsOverflowing() )
4798 : {
4799 0 : SaveState( 0 );
4800 0 : return;
4801 : }
4802 :
4803 0 : bool bTop = true;
4804 0 : const HTMLOptions& rHTMLOptions = GetOptions();
4805 0 : for ( size_t i = rHTMLOptions.size(); i; )
4806 : {
4807 0 : const HTMLOption& rOption = rHTMLOptions[--i];
4808 0 : if( HTML_O_ALIGN == rOption.GetToken() )
4809 : {
4810 0 : if (rOption.GetString().equalsIgnoreAsciiCase(
4811 : OOO_STRING_SVTOOLS_HTML_VA_bottom))
4812 : {
4813 0 : bTop = false;
4814 : }
4815 : }
4816 : }
4817 :
4818 : // Alte PaM-Position retten.
4819 0 : pSaveStruct = new _CaptionSaveStruct( *this, *pPam->GetPoint() );
4820 :
4821 : // Eine Text-Section im Icons-Bereich als Container fuer die
4822 : // Ueberschrift anlegen und PaM dort reinstellen.
4823 : const SwStartNode *pStNd;
4824 0 : if( pTable == pCurTable )
4825 0 : pStNd = InsertTempTableCaptionSection();
4826 : else
4827 0 : pStNd = InsertTableSection( RES_POOLCOLL_TEXT );
4828 :
4829 0 : _HTMLAttrContext *pCntxt = new _HTMLAttrContext( HTML_CAPTION_ON );
4830 :
4831 : // Tabellen-Ueberschriften sind immer zentriert.
4832 0 : NewAttr( &aAttrTab.pAdjust, SvxAdjustItem(SVX_ADJUST_CENTER, RES_PARATR_ADJUST) );
4833 :
4834 0 : _HTMLAttrs &rAttrs = pCntxt->GetAttrs();
4835 0 : rAttrs.push_back( aAttrTab.pAdjust );
4836 :
4837 0 : PushContext( pCntxt );
4838 :
4839 : // StartNode der Section an der Tabelle merken.
4840 0 : pCurTable->SetCaption( pStNd, bTop );
4841 :
4842 : // ist beim ersten GetNextToken schon pending, muss bei
4843 : // wiederaufsetzen auf jedenfall neu gelesen werden!
4844 0 : SaveState( 0 );
4845 : }
4846 :
4847 0 : if( !nToken )
4848 0 : nToken = GetNextToken(); // naechstes Token
4849 :
4850 : // </CAPTION> wird laut DTD benoetigt
4851 0 : bool bDone = false;
4852 0 : while( IsParserWorking() && !bDone )
4853 : {
4854 0 : SaveState( nToken );
4855 :
4856 0 : nToken = FilterToken( nToken );
4857 :
4858 0 : switch( nToken )
4859 : {
4860 : case HTML_TABLE_ON:
4861 0 : if( !pPendStack )
4862 : {
4863 0 : pSaveStruct->m_pTable = pTable;
4864 0 : bool bHasToFly = pSaveStruct->m_pTable!=pCurTable;
4865 : BuildTable( pCurTable->GetTableAdjust( true ),
4866 0 : false, true, bHasToFly );
4867 : }
4868 : else
4869 : {
4870 0 : BuildTable( SVX_ADJUST_END );
4871 : }
4872 0 : if( SVPAR_PENDING != GetStatus() )
4873 : {
4874 0 : pTable = pSaveStruct->m_pTable;
4875 : }
4876 0 : break;
4877 : case HTML_TABLE_OFF:
4878 : case HTML_COLGROUP_ON:
4879 : case HTML_THEAD_ON:
4880 : case HTML_TFOOT_ON:
4881 : case HTML_TBODY_ON:
4882 : case HTML_TABLEROW_ON:
4883 0 : SkipToken( -1 );
4884 0 : bDone = true;
4885 0 : break;
4886 :
4887 : case HTML_CAPTION_OFF:
4888 0 : bDone = true;
4889 0 : break;
4890 : default:
4891 0 : if( pPendStack )
4892 : {
4893 0 : SwPendingStack* pTmp = pPendStack->pNext;
4894 0 : delete pPendStack;
4895 0 : pPendStack = pTmp;
4896 :
4897 : OSL_ENSURE( !pTmp, "weiter kann es nicht gehen!" );
4898 : }
4899 :
4900 0 : if( IsParserWorking() )
4901 0 : NextToken( nToken );
4902 0 : break;
4903 : }
4904 :
4905 0 : if( IsParserWorking() )
4906 0 : SaveState( 0 );
4907 :
4908 0 : if( !bDone )
4909 0 : nToken = GetNextToken();
4910 : }
4911 :
4912 0 : if( SVPAR_PENDING==GetStatus() )
4913 : {
4914 0 : pPendStack = new SwPendingStack( HTML_CAPTION_ON, pPendStack );
4915 0 : pPendStack->pData = pSaveStruct;
4916 0 : return;
4917 : }
4918 :
4919 : // Alle noch offenen Kontexte beenden
4920 0 : while( aContexts.size() > nContextStAttrMin+1 )
4921 : {
4922 0 : _HTMLAttrContext *pCntxt = PopContext();
4923 0 : EndContext( pCntxt );
4924 0 : delete pCntxt;
4925 : }
4926 :
4927 : // LF am Absatz-Ende entfernen
4928 0 : bool bLFStripped = StripTrailingLF() > 0;
4929 :
4930 0 : if( pTable==pCurTable )
4931 : {
4932 : // Beim spaeteren verschieben der Beschriftung vor oder hinter
4933 : // die Tabelle wird der letzte Absatz nicht mitverschoben.
4934 : // Deshalb muss sich am Ende der Section immer ein leerer
4935 : // Absatz befinden.
4936 0 : if( pPam->GetPoint()->nContent.GetIndex() || bLFStripped )
4937 0 : AppendTextNode( AM_NOSPACE );
4938 : }
4939 : else
4940 : {
4941 : // LFs am Absatz-Ende entfernen
4942 0 : if( !pPam->GetPoint()->nContent.GetIndex() && !bLFStripped )
4943 0 : StripTrailingPara();
4944 : }
4945 :
4946 : // falls fuer die Zelle eine Ausrichtung gesetzt wurde, muessen
4947 : // wir die beenden
4948 0 : _HTMLAttrContext *pCntxt = PopContext();
4949 0 : EndContext( pCntxt );
4950 0 : delete pCntxt;
4951 :
4952 0 : SetAttr( false );
4953 :
4954 : // Stacks und Attribut-Tabelle wiederherstellen
4955 0 : pSaveStruct->RestoreAll( *this );
4956 :
4957 : // PaM wiederherstellen.
4958 0 : *pPam->GetPoint() = pSaveStruct->GetPos();
4959 :
4960 0 : delete pSaveStruct;
4961 : }
4962 :
4963 : class _TableSaveStruct : public SwPendingStackData
4964 : {
4965 : public:
4966 : HTMLTable *m_pCurrentTable;
4967 :
4968 6 : explicit _TableSaveStruct( HTMLTable *pCurTable ) :
4969 6 : m_pCurrentTable( pCurTable )
4970 6 : {}
4971 :
4972 : virtual ~_TableSaveStruct();
4973 :
4974 : // Aufbau der Tabelle anstossen und die Tabelle ggf. in einen
4975 : // Rahmen packen. Wenn true zurueckgegeben wird muss noch ein
4976 : // Absatz eingefuegt werden!
4977 : void MakeTable( sal_uInt16 nWidth, SwPosition& rPos, SwDoc *pDoc );
4978 : };
4979 :
4980 12 : _TableSaveStruct::~_TableSaveStruct()
4981 12 : {}
4982 :
4983 6 : void _TableSaveStruct::MakeTable( sal_uInt16 nWidth, SwPosition& rPos, SwDoc *pDoc )
4984 : {
4985 6 : m_pCurrentTable->MakeTable(0, nWidth);
4986 :
4987 6 : _HTMLTableContext *pTCntxt = m_pCurrentTable->GetContext();
4988 : OSL_ENSURE( pTCntxt, "Wo ist der Tabellen-Kontext" );
4989 :
4990 6 : SwTableNode *pTableNd = pTCntxt->GetTableNode();
4991 : OSL_ENSURE( pTableNd, "Wo ist der Tabellen-Node" );
4992 :
4993 6 : if( pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() && pTableNd )
4994 : {
4995 : // Existiert schon ein Layout, dann muss an dieser Tabelle die
4996 : // BoxFrames neu erzeugt werden.
4997 :
4998 0 : if( pTCntxt->GetFrameFormat() )
4999 : {
5000 0 : pTCntxt->GetFrameFormat()->DelFrms();
5001 0 : pTableNd->DelFrms();
5002 0 : pTCntxt->GetFrameFormat()->MakeFrms();
5003 : }
5004 : else
5005 : {
5006 0 : pTableNd->DelFrms();
5007 0 : SwNodeIndex aIdx( *pTableNd->EndOfSectionNode(), 1 );
5008 : OSL_ENSURE( aIdx.GetIndex() <= pTCntxt->GetPos()->nNode.GetIndex(),
5009 : "unerwarteter Node fuer das Tabellen-Layout" );
5010 0 : pTableNd->MakeFrms( &aIdx );
5011 : }
5012 : }
5013 :
5014 6 : rPos = *pTCntxt->GetPos();
5015 6 : }
5016 :
5017 6 : HTMLTableOptions::HTMLTableOptions( const HTMLOptions& rOptions,
5018 : SvxAdjust eParentAdjust ) :
5019 : nCols( 0 ),
5020 : nWidth( 0 ), nHeight( 0 ),
5021 : nCellPadding( USHRT_MAX ), nCellSpacing( USHRT_MAX ),
5022 : nBorder( USHRT_MAX ),
5023 : nHSpace( 0 ), nVSpace( 0 ),
5024 : eAdjust( eParentAdjust ), eVertOri( text::VertOrientation::CENTER ),
5025 : eFrame( HTML_TF_VOID ), eRules( HTML_TR_NONE ),
5026 : bPrcWidth( false ),
5027 : bTableAdjust( false ),
5028 : bBGColor( false ),
5029 6 : aBorderColor( COL_GRAY )
5030 : {
5031 6 : bool bBorderColor = false;
5032 6 : bool bHasFrame = false, bHasRules = false;
5033 :
5034 33 : for (size_t i = rOptions.size(); i; )
5035 : {
5036 21 : const HTMLOption& rOption = rOptions[--i];
5037 21 : switch( rOption.GetToken() )
5038 : {
5039 : case HTML_O_ID:
5040 0 : aId = rOption.GetString();
5041 0 : break;
5042 : case HTML_O_COLS:
5043 0 : nCols = (sal_uInt16)rOption.GetNumber();
5044 0 : break;
5045 : case HTML_O_WIDTH:
5046 6 : nWidth = (sal_uInt16)rOption.GetNumber();
5047 6 : bPrcWidth = (rOption.GetString().indexOf('%') != -1);
5048 6 : if( bPrcWidth && nWidth>100 )
5049 0 : nWidth = 100;
5050 6 : break;
5051 : case HTML_O_HEIGHT:
5052 0 : nHeight = (sal_uInt16)rOption.GetNumber();
5053 0 : if( rOption.GetString().indexOf('%') != -1 )
5054 0 : nHeight = 0; // keine %-Anagben benutzen!!!
5055 0 : break;
5056 : case HTML_O_CELLPADDING:
5057 6 : nCellPadding = (sal_uInt16)rOption.GetNumber();
5058 6 : break;
5059 : case HTML_O_CELLSPACING:
5060 4 : nCellSpacing = (sal_uInt16)rOption.GetNumber();
5061 4 : break;
5062 : case HTML_O_ALIGN:
5063 : {
5064 0 : sal_uInt16 nAdjust = static_cast< sal_uInt16 >(eAdjust);
5065 0 : if( rOption.GetEnum( nAdjust, aHTMLPAlignTable ) )
5066 : {
5067 0 : eAdjust = (SvxAdjust)nAdjust;
5068 0 : bTableAdjust = true;
5069 : }
5070 : }
5071 0 : break;
5072 : case HTML_O_VALIGN:
5073 0 : eVertOri = rOption.GetEnum( aHTMLTableVAlignTable, eVertOri );
5074 0 : break;
5075 : case HTML_O_BORDER:
5076 : // BORDER und BORDER=BORDER wie BORDER=1 behandeln
5077 0 : if (!rOption.GetString().isEmpty() &&
5078 0 : !rOption.GetString().equalsIgnoreAsciiCase(
5079 0 : OOO_STRING_SVTOOLS_HTML_O_border))
5080 : {
5081 0 : nBorder = (sal_uInt16)rOption.GetNumber();
5082 : }
5083 : else
5084 0 : nBorder = 1;
5085 :
5086 0 : if( !bHasFrame )
5087 0 : eFrame = ( nBorder ? HTML_TF_BOX : HTML_TF_VOID );
5088 0 : if( !bHasRules )
5089 0 : eRules = ( nBorder ? HTML_TR_ALL : HTML_TR_NONE );
5090 0 : break;
5091 : case HTML_O_FRAME:
5092 0 : eFrame = rOption.GetTableFrame();
5093 0 : bHasFrame = true;
5094 0 : break;
5095 : case HTML_O_RULES:
5096 0 : eRules = rOption.GetTableRules();
5097 0 : bHasRules = true;
5098 0 : break;
5099 : case HTML_O_BGCOLOR:
5100 : // Leere BGCOLOR bei <TABLE>, <TR> und <TD>/<TH> wie Netscape
5101 : // ignorieren, bei allen anderen Tags *wirklich* nicht.
5102 1 : if( !rOption.GetString().isEmpty() )
5103 : {
5104 1 : rOption.GetColor( aBGColor );
5105 1 : bBGColor = true;
5106 : }
5107 1 : break;
5108 : case HTML_O_BACKGROUND:
5109 0 : aBGImage = rOption.GetString();
5110 0 : break;
5111 : case HTML_O_BORDERCOLOR:
5112 0 : rOption.GetColor( aBorderColor );
5113 0 : bBorderColor = true;
5114 0 : break;
5115 : case HTML_O_BORDERCOLORDARK:
5116 0 : if( !bBorderColor )
5117 0 : rOption.GetColor( aBorderColor );
5118 0 : break;
5119 : case HTML_O_STYLE:
5120 4 : aStyle = rOption.GetString();
5121 4 : break;
5122 : case HTML_O_CLASS:
5123 0 : aClass = rOption.GetString();
5124 0 : break;
5125 : case HTML_O_DIR:
5126 0 : aDir = rOption.GetString();
5127 0 : break;
5128 : case HTML_O_HSPACE:
5129 0 : nHSpace = (sal_uInt16)rOption.GetNumber();
5130 0 : break;
5131 : case HTML_O_VSPACE:
5132 0 : nVSpace = (sal_uInt16)rOption.GetNumber();
5133 0 : break;
5134 : }
5135 : }
5136 :
5137 6 : if( nCols && !nWidth )
5138 : {
5139 0 : nWidth = 100;
5140 0 : bPrcWidth = true;
5141 : }
5142 :
5143 : // Wenn BORDER=0 oder kein BORDER gegeben ist, daan darf es auch
5144 : // keine Umrandung geben
5145 6 : if( 0==nBorder || USHRT_MAX==nBorder )
5146 : {
5147 6 : eFrame = HTML_TF_VOID;
5148 6 : eRules = HTML_TR_NONE;
5149 : }
5150 6 : }
5151 :
5152 6 : HTMLTable *SwHTMLParser::BuildTable( SvxAdjust eParentAdjust,
5153 : bool bIsParentHead,
5154 : bool bHasParentSection,
5155 : bool bHasToFly )
5156 : {
5157 6 : if( !IsParserWorking() && !pPendStack )
5158 0 : return 0;
5159 :
5160 6 : int nToken = 0;
5161 6 : bool bPending = false;
5162 : _TableSaveStruct* pSaveStruct;
5163 :
5164 6 : if( pPendStack )
5165 : {
5166 0 : pSaveStruct = static_cast<_TableSaveStruct*>(pPendStack->pData);
5167 :
5168 0 : SwPendingStack* pTmp = pPendStack->pNext;
5169 0 : delete pPendStack;
5170 0 : pPendStack = pTmp;
5171 0 : nToken = pPendStack ? pPendStack->nToken : GetSaveToken();
5172 0 : bPending = SVPAR_ERROR == eState && pPendStack != 0;
5173 :
5174 0 : SaveState( nToken );
5175 : }
5176 : else
5177 : {
5178 6 : pTable = 0;
5179 : HTMLTableOptions *pTableOptions =
5180 6 : new HTMLTableOptions( GetOptions(), eParentAdjust );
5181 :
5182 6 : if( !pTableOptions->aId.isEmpty() )
5183 0 : InsertBookmark( pTableOptions->aId );
5184 :
5185 : HTMLTable *pCurTable = new HTMLTable( this, pTable,
5186 : bIsParentHead,
5187 : bHasParentSection,
5188 : bHasToFly,
5189 6 : pTableOptions );
5190 6 : if( !pTable )
5191 6 : pTable = pCurTable;
5192 :
5193 6 : pSaveStruct = new _TableSaveStruct( pCurTable );
5194 :
5195 6 : delete pTableOptions;
5196 :
5197 : // ist beim ersten GetNextToken schon pending, muss bei
5198 : // wiederaufsetzen auf jedenfall neu gelesen werden!
5199 6 : SaveState( 0 );
5200 : }
5201 :
5202 6 : HTMLTable *pCurTable = pSaveStruct->m_pCurrentTable;
5203 :
5204 : // </TABLE> wird laut DTD benoetigt
5205 6 : if( !nToken )
5206 6 : nToken = GetNextToken(); // naechstes Token
5207 :
5208 6 : bool bDone = false;
5209 34 : while( (IsParserWorking() && !bDone) || bPending )
5210 : {
5211 22 : SaveState( nToken );
5212 :
5213 22 : nToken = FilterToken( nToken );
5214 :
5215 : OSL_ENSURE( pPendStack || !bCallNextToken ||
5216 : pCurTable->GetContext() || pCurTable->HasParentSection(),
5217 : "Wo ist die Section gebieben?" );
5218 22 : if( !pPendStack && bCallNextToken &&
5219 0 : (pCurTable->GetContext() || pCurTable->HasParentSection()) )
5220 : {
5221 : // NextToken direkt aufrufen (z.B. um den Inhalt von
5222 : // Floating-Frames oder Applets zu ignorieren)
5223 0 : NextToken( nToken );
5224 : }
5225 22 : else switch( nToken )
5226 : {
5227 : case HTML_TABLE_ON:
5228 0 : if( !pCurTable->GetContext() )
5229 : {
5230 : // Wenn noch keine Tabelle eingefuegt wurde,
5231 : // die naechste Tabelle lesen
5232 0 : SkipToken( -1 );
5233 0 : bDone = true;
5234 : }
5235 :
5236 0 : break;
5237 : case HTML_TABLE_OFF:
5238 6 : bDone = true;
5239 6 : break;
5240 : case HTML_CAPTION_ON:
5241 0 : BuildTableCaption( pCurTable );
5242 0 : bDone = pTable->IsOverflowing();
5243 0 : break;
5244 : case HTML_COL_ON:
5245 4 : SkipToken( -1 );
5246 4 : BuildTableColGroup( pCurTable, false );
5247 4 : break;
5248 : case HTML_COLGROUP_ON:
5249 0 : BuildTableColGroup( pCurTable, true );
5250 0 : break;
5251 : case HTML_TABLEROW_ON:
5252 : case HTML_TABLEHEADER_ON:
5253 : case HTML_TABLEDATA_ON:
5254 6 : SkipToken( -1 );
5255 6 : BuildTableSection( pCurTable, false, false );
5256 6 : bDone = pTable->IsOverflowing();
5257 6 : break;
5258 : case HTML_THEAD_ON:
5259 : case HTML_TFOOT_ON:
5260 : case HTML_TBODY_ON:
5261 0 : BuildTableSection( pCurTable, true, HTML_THEAD_ON==nToken );
5262 0 : bDone = pTable->IsOverflowing();
5263 0 : break;
5264 : case HTML_MULTICOL_ON:
5265 : // spaltige Rahmen koennen wir hier leider nicht einguegen
5266 0 : break;
5267 : case HTML_FORM_ON:
5268 0 : NewForm( false ); // keinen neuen Absatz aufmachen!
5269 0 : break;
5270 : case HTML_FORM_OFF:
5271 0 : EndForm( false ); // keinen neuen Absatz aufmachen!
5272 0 : break;
5273 : case HTML_TEXTTOKEN:
5274 : // Blank-Strings sind u. U. eine Folge von CR+LF und kein Text
5275 18 : if( (pCurTable->GetContext() ||
5276 6 : !pCurTable->HasParentSection()) &&
5277 6 : 1==aToken.getLength() && ' '==aToken[0] )
5278 0 : break;
5279 : default:
5280 6 : pCurTable->MakeParentContents();
5281 6 : NextToken( nToken );
5282 6 : break;
5283 : }
5284 :
5285 : OSL_ENSURE( !bPending || !pPendStack,
5286 : "SwHTMLParser::BuildTable: Es gibt wieder einen Pend-Stack" );
5287 22 : bPending = false;
5288 22 : if( IsParserWorking() )
5289 22 : SaveState( 0 );
5290 :
5291 22 : if( !bDone )
5292 16 : nToken = GetNextToken();
5293 : }
5294 :
5295 6 : if( SVPAR_PENDING == GetStatus() )
5296 : {
5297 0 : pPendStack = new SwPendingStack( HTML_TABLE_ON, pPendStack );
5298 0 : pPendStack->pData = pSaveStruct;
5299 0 : return 0;
5300 : }
5301 :
5302 6 : _HTMLTableContext *pTCntxt = pCurTable->GetContext();
5303 6 : if( pTCntxt )
5304 : {
5305 : // Die Tabelle wurde auch angelegt
5306 :
5307 : // Tabellen-Struktur anpassen
5308 6 : pCurTable->CloseTable();
5309 :
5310 : // ausserhalb von Zellen begonnene Kontexte beenden
5311 : // muss vor(!) dem Umsetzten der Attribut Tabelle existieren,
5312 : // weil die aktuelle danach nicht mehr existiert
5313 12 : while( aContexts.size() > nContextStAttrMin )
5314 : {
5315 0 : _HTMLAttrContext *pCntxt = PopContext();
5316 0 : ClearContext( pCntxt );
5317 0 : delete pCntxt;
5318 : }
5319 :
5320 6 : nContextStMin = pTCntxt->GetContextStMin();
5321 6 : nContextStAttrMin = pTCntxt->GetContextStAttrMin();
5322 :
5323 6 : if( pTable==pCurTable )
5324 : {
5325 : // Tabellen-Beschriftung setzen
5326 6 : const SwStartNode *pCapStNd = pTable->GetCaptionStartNode();
5327 6 : if( pCapStNd )
5328 : {
5329 : // Der letzte Absatz der Section wird nie mitkopiert. Deshalb
5330 : // muss die Section mindestens zwei Absaetze enthalten.
5331 :
5332 0 : if( pCapStNd->EndOfSectionIndex() - pCapStNd->GetIndex() > 2 )
5333 : {
5334 : // Start-Node und letzten Absatz nicht mitkopieren.
5335 : SwNodeRange aSrcRg( *pCapStNd, 1,
5336 0 : *pCapStNd->EndOfSectionNode(), -1 );
5337 :
5338 0 : bool bTop = pTable->IsTopCaption();
5339 0 : SwStartNode *pTableStNd = pTCntxt->GetTableNode();
5340 :
5341 : OSL_ENSURE( pTableStNd, "Wo ist der Tabellen-Node" );
5342 : OSL_ENSURE( pTableStNd==pPam->GetNode().FindTableNode(),
5343 : "Stehen wir in der falschen Tabelle?" );
5344 :
5345 : SwNode* pNd;
5346 0 : if( bTop )
5347 0 : pNd = pTableStNd;
5348 : else
5349 0 : pNd = pTableStNd->EndOfSectionNode();
5350 0 : SwNodeIndex aDstIdx( *pNd, bTop ? 0 : 1 );
5351 :
5352 0 : pDoc->getIDocumentContentOperations().MoveNodeRange( aSrcRg, aDstIdx,
5353 0 : SwMoveFlags::DEFAULT );
5354 :
5355 : // Wenn die Caption vor der Tabelle eingefuegt wurde muss
5356 : // eine an der Tabelle gestzte Seitenvorlage noch in den
5357 : // ersten Absatz der Ueberschrift verschoben werden.
5358 : // Ausserdem muessen alle gemerkten Indizes, die auf den
5359 : // Tabellen-Node zeigen noch verschoben werden.
5360 0 : if( bTop )
5361 : {
5362 : MovePageDescAttrs( pTableStNd, aSrcRg.aStart.GetIndex(),
5363 0 : false );
5364 0 : }
5365 : }
5366 :
5367 : // Die Section wird jetzt nicht mehr gebraucht.
5368 0 : pPam->SetMark();
5369 0 : pPam->DeleteMark();
5370 0 : pDoc->getIDocumentContentOperations().DeleteSection( const_cast<SwStartNode *>(pCapStNd) );
5371 0 : pTable->SetCaption( 0, false );
5372 : }
5373 :
5374 : // SwTable aufbereiten
5375 6 : sal_uInt16 nBrowseWidth = (sal_uInt16)GetCurrentBrowseWidth();
5376 6 : pSaveStruct->MakeTable( nBrowseWidth, *pPam->GetPoint(), pDoc );
5377 : }
5378 :
5379 6 : GetNumInfo().Set( pTCntxt->GetNumInfo() );
5380 6 : pTCntxt->RestorePREListingXMP( *this );
5381 6 : RestoreAttrTab( pTCntxt->aAttrTab );
5382 :
5383 6 : if( pTable==pCurTable )
5384 : {
5385 : // oberen Absatz-Abstand einstellen
5386 6 : bUpperSpace = true;
5387 6 : SetTextCollAttrs();
5388 :
5389 12 : nParaCnt = nParaCnt - std::min(nParaCnt,
5390 12 : pTCntxt->GetTableNode()->GetTable().GetTabSortBoxes().size());
5391 :
5392 : // ggfs. eine Tabelle anspringen
5393 18 : if( JUMPTO_TABLE == eJumpTo && pTable->GetSwTable() &&
5394 6 : pTable->GetSwTable()->GetFrameFormat()->GetName() == sJmpMark )
5395 : {
5396 0 : bChkJumpMark = true;
5397 0 : eJumpTo = JUMPTO_NONE;
5398 : }
5399 :
5400 : // Wenn Import abgebrochen wurde kein erneutes Show
5401 : // aufrufen, weil die SwViewShell schon geloescht wurde!
5402 : // Genuegt nicht. Auch im ACCEPTING_STATE darf
5403 : // kein Show aufgerufen werden, weil sonst waehrend des
5404 : // Reschedules der Parser zerstoert wird, wenn noch ein
5405 : // DataAvailable-Link kommt. Deshalb: Nur im WORKING-State.
5406 6 : if( !nParaCnt && SVPAR_WORKING == GetStatus() )
5407 3 : Show();
5408 : }
5409 : }
5410 0 : else if( pTable==pCurTable )
5411 : {
5412 : // Es wurde gar keine Tabelle gelesen.
5413 :
5414 : // Dann muss eine evtl gelesene Beschriftung noch geloescht werden.
5415 0 : const SwStartNode *pCapStNd = pCurTable->GetCaptionStartNode();
5416 0 : if( pCapStNd )
5417 : {
5418 0 : pPam->SetMark();
5419 0 : pPam->DeleteMark();
5420 0 : pDoc->getIDocumentContentOperations().DeleteSection( const_cast<SwStartNode *>(pCapStNd) );
5421 0 : pCurTable->SetCaption( 0, false );
5422 : }
5423 : }
5424 :
5425 6 : if( pTable == pCurTable )
5426 : {
5427 6 : delete pSaveStruct->m_pCurrentTable;
5428 6 : pSaveStruct->m_pCurrentTable = 0;
5429 6 : pTable = 0;
5430 : }
5431 :
5432 6 : HTMLTable* pRetTable = pSaveStruct->m_pCurrentTable;
5433 6 : delete pSaveStruct;
5434 :
5435 6 : return pRetTable;
5436 177 : }
5437 :
5438 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|