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