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