1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: htmltab.cxx,v $
10 * $Revision: 1.28.186.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
36 #include "hintids.hxx"
37 #include <vcl/svapp.hxx>
38 #ifndef _WRKWIN_HXX //autogen
39 #include <vcl/wrkwin.hxx>
41 #include <svx/boxitem.hxx>
42 #include <svx/brshitem.hxx>
43 #include <svx/adjitem.hxx>
44 #include <svx/fhgtitem.hxx>
45 #include <svx/ulspitem.hxx>
46 #include <svx/lrspitem.hxx>
47 #include <svx/brkitem.hxx>
48 #include <svx/spltitem.hxx>
49 #include <svtools/htmltokn.h>
50 #include <svtools/htmlkywd.hxx>
51 #include <svtools/urihelper.hxx>
54 #include <fmtornt.hxx>
56 #include <fmtfsize.hxx>
57 #include <fmtsrnd.hxx>
58 #include <fmtpdsc.hxx>
59 #include <fmtcntnt.hxx>
60 #include <fmtanchr.hxx>
61 #include <fmtlsplt.hxx>
66 #include "shellio.hxx"
67 #include "poolfmt.hxx"
68 #include "swtable.hxx"
69 #include "cellatr.hxx"
73 #include "htmltbl.hxx"
74 #include "swtblfmt.hxx"
75 #include "htmlnum.hxx"
78 #include <numrule.hxx>
80 #define NETSCAPE_DFLT_BORDER 1
81 #define NETSCAPE_DFLT_CELLPADDING 1
82 #define NETSCAPE_DFLT_CELLSPACING 2
86 using namespace ::com::sun::star
;
89 static HTMLOptionEnum __FAR_DATA aHTMLTblVAlignTable
[] =
91 { OOO_STRING_SVTOOLS_HTML_VA_top
, text::VertOrientation::NONE
},
92 { OOO_STRING_SVTOOLS_HTML_VA_middle
, text::VertOrientation::CENTER
},
93 { OOO_STRING_SVTOOLS_HTML_VA_bottom
, text::VertOrientation::BOTTOM
},
100 // Die Optionen eines Table-Tags
102 struct HTMLTableOptions
107 sal_uInt16 nCellPadding
;
108 sal_uInt16 nCellSpacing
;
115 HTMLTableFrame eFrame
;
116 HTMLTableRules eRules
;
118 sal_Bool bPrcWidth
: 1;
119 sal_Bool bTableAdjust
: 1;
120 sal_Bool bBGColor
: 1;
125 String aBGImage
, aStyle
, aId
, aClass
, aDir
;
127 HTMLTableOptions( const HTMLOptions
*pOptions
, SvxAdjust eParentAdjust
);
132 class _HTMLTableContext
134 SwHTMLNumRuleInfo aNumRuleInfo
; // Vor der Tabelle gueltige Numerierung
136 SwTableNode
*pTblNd
; // der Tabellen-Node
137 SwFrmFmt
*pFrmFmt
; // der Fly frame::Frame, in dem die Tabelle steht
138 SwPosition
*pPos
; // die Position hinter der Tabelle
140 sal_uInt16 nContextStAttrMin
;
141 sal_uInt16 nContextStMin
;
143 sal_Bool bRestartPRE
: 1;
144 sal_Bool bRestartXMP
: 1;
145 sal_Bool bRestartListing
: 1;
149 _HTMLAttrTable aAttrTab
; // und die Attribute
151 _HTMLTableContext( SwPosition
*pPs
, sal_uInt16 nCntxtStMin
,
152 sal_uInt16 nCntxtStAttrMin
) :
156 nContextStAttrMin( nCntxtStAttrMin
),
157 nContextStMin( nCntxtStMin
),
158 bRestartPRE( sal_False
),
159 bRestartXMP( sal_False
),
160 bRestartListing( sal_False
)
162 memset( &aAttrTab
, 0, sizeof( _HTMLAttrTable
));
165 ~_HTMLTableContext();
167 void SetNumInfo( const SwHTMLNumRuleInfo
& rInf
) { aNumRuleInfo
.Set(rInf
); }
168 const SwHTMLNumRuleInfo
& GetNumInfo() const { return aNumRuleInfo
; };
170 void SavePREListingXMP( SwHTMLParser
& rParser
);
171 void RestorePREListingXMP( SwHTMLParser
& rParser
);
173 SwPosition
*GetPos() const { return pPos
; }
175 void SetTableNode( SwTableNode
*pNd
) { pTblNd
= pNd
; }
176 SwTableNode
*GetTableNode() const { return pTblNd
; }
178 void SetFrmFmt( SwFrmFmt
*pFmt
) { pFrmFmt
= pFmt
; }
179 SwFrmFmt
*GetFrmFmt() const { return pFrmFmt
; }
181 sal_uInt16
GetContextStMin() const { return nContextStMin
; }
182 sal_uInt16
GetContextStAttrMin() const { return nContextStAttrMin
; }
187 // der Inhalt einer Zelle ist eine verkettete Liste mit SwStartNodes und
192 HTMLTableCnts
*pNext
; // der naechste Inhalt
194 // von den beiden naechsten Pointern darf nur einer gesetzt sein!
195 const SwStartNode
*pStartNode
; // ein Abastz
196 HTMLTable
*pTable
; // eine Tabelle
198 SwHTMLTableLayoutCnts
* pLayoutInfo
;
206 HTMLTableCnts( const SwStartNode
* pStNd
);
207 HTMLTableCnts( HTMLTable
* pTab
);
209 ~HTMLTableCnts(); // nur in ~HTMLTableCell erlaubt
211 // Ermitteln des SwStartNode bzw. der HTMLTable
212 const SwStartNode
*GetStartNode() const { return pStartNode
; }
213 const HTMLTable
*GetTable() const { return pTable
; }
214 HTMLTable
*GetTable() { return pTable
; }
216 // hinzufuegen eines neuen Knotens am Listenende
217 void Add( HTMLTableCnts
* pNewCnts
);
219 // Ermitteln des naechsten Knotens
220 const HTMLTableCnts
*Next() const { return pNext
; }
221 HTMLTableCnts
*Next() { return pNext
; }
223 inline void SetTableBox( SwTableBox
*pBox
);
225 void SetNoBreak() { bNoBreak
= sal_True
; }
227 SwHTMLTableLayoutCnts
*CreateLayoutInfo();
232 // Eine Zelle der HTML-Tabelle
236 // !!!ACHTUNG!!!!! Fuer jeden neuen Pointer muss die SetProtected-
237 // Methode (und natuerlich der Destruktor) bearbeitet werden.
238 HTMLTableCnts
*pContents
; // der Inhalt der Zelle
239 SvxBrushItem
*pBGBrush
; // Hintergrund der Zelle
243 sal_uInt16 nRowSpan
; // ROWSPAN der Zelle
244 sal_uInt16 nColSpan
; // COLSPAN der Zelle
245 sal_uInt16 nWidth
; // WIDTH der Zelle
247 sal_Int16 eVertOri
; // vertikale Ausrichtung der Zelle
248 sal_Bool bProtected
: 1; // Zelle darf nicht belegt werden
249 sal_Bool bRelWidth
: 1; // nWidth ist %-Angabe
250 sal_Bool bHasNumFmt
: 1;
251 sal_Bool bHasValue
: 1;
252 sal_Bool bNoWrap
: 1;
253 sal_Bool mbCovered
: 1;
257 HTMLTableCell(); // neue Zellen sind immer leer
259 ~HTMLTableCell(); // nur in ~HTMLTableRow erlaubt
261 // Belegen einer nicht-leeren Zelle
262 void Set( HTMLTableCnts
*pCnts
, sal_uInt16 nRSpan
, sal_uInt16 nCSpan
,
263 sal_Int16 eVertOri
, SvxBrushItem
*pBGBrush
,
264 sal_Bool bHasNumFmt
, sal_uInt32 nNumFmt
,
265 sal_Bool bHasValue
, double nValue
, sal_Bool bNoWrap
, sal_Bool bCovered
);
267 // Schuetzen einer leeren 1x1-Zelle
270 // Setzen/Ermitteln des Inhalts einer Zelle
271 void SetContents( HTMLTableCnts
*pCnts
) { pContents
= pCnts
; }
272 const HTMLTableCnts
*GetContents() const { return pContents
; }
273 HTMLTableCnts
*GetContents() { return pContents
; }
275 // ROWSPAN/COLSPAN der Zelle Setzen/Ermitteln
276 void SetRowSpan( sal_uInt16 nRSpan
) { nRowSpan
= nRSpan
; }
277 sal_uInt16
GetRowSpan() const { return nRowSpan
; }
279 void SetColSpan( sal_uInt16 nCSpan
) { nColSpan
= nCSpan
; }
280 sal_uInt16
GetColSpan() const { return nColSpan
; }
282 inline void SetWidth( sal_uInt16 nWidth
, sal_Bool bRelWidth
);
284 const SvxBrushItem
*GetBGBrush() const { return pBGBrush
; }
286 inline sal_Bool
GetNumFmt( sal_uInt32
& rNumFmt
) const;
287 inline sal_Bool
GetValue( double& rValue
) const;
289 sal_Int16
GetVertOri() const { return eVertOri
; }
291 // Ist die Zelle belegt oder geschuetzt?
292 sal_Bool
IsUsed() const { return pContents
!=0 || bProtected
; }
294 SwHTMLTableLayoutCell
*CreateLayoutInfo();
296 sal_Bool
IsCovered() const { return mbCovered
; }
301 // Eine Zeile der HTML-Tabelle
303 typedef HTMLTableCell
* HTMLTableCellPtr
;
304 SV_DECL_PTRARR_DEL(HTMLTableCells
,HTMLTableCellPtr
,5,5)
308 HTMLTableCells
*pCells
; // die Zellen der Zeile
310 sal_Bool bIsEndOfGroup
: 1;
311 sal_Bool bSplitable
: 1;
313 sal_uInt16 nHeight
; // Optionen von <TR>/<TD>
314 sal_uInt16 nEmptyRows
; // wieviele Leere Zeilen folgen
318 SvxBrushItem
*pBGBrush
; // Hintergrund der Zelle aus STYLE
322 sal_Bool bBottomBorder
; // kommt hinter der Zeile eine Linie?
324 HTMLTableRow( sal_uInt16 nCells
=0 ); // die Zellen der Zeile sind leer
328 inline void SetHeight( sal_uInt16 nHeight
);
329 sal_uInt16
GetHeight() const { return nHeight
; }
331 // Ermitteln einer Zelle
332 inline HTMLTableCell
*GetCell( sal_uInt16 nCell
) const;
333 inline const HTMLTableCells
*GetCells() const { return pCells
; }
336 inline void SetAdjust( SvxAdjust eAdj
) { eAdjust
= eAdj
; }
337 inline SvxAdjust
GetAdjust() const { return eAdjust
; }
339 inline void SetVertOri( sal_Int16 eV
) { eVertOri
= eV
; }
340 inline sal_Int16
GetVertOri() const { return eVertOri
; }
342 void SetBGBrush( SvxBrushItem
*pBrush
) { pBGBrush
= pBrush
; }
343 const SvxBrushItem
*GetBGBrush() const { return pBGBrush
; }
345 inline void SetEndOfGroup() { bIsEndOfGroup
= sal_True
; }
346 inline sal_Bool
IsEndOfGroup() const { return bIsEndOfGroup
; }
348 void IncEmptyRows() { nEmptyRows
++; }
349 sal_uInt16
GetEmptyRows() const { return nEmptyRows
; }
351 // Expandieren einer Zeile durch hinzufuegen leerer Zellen
352 void Expand( sal_uInt16 nCells
, sal_Bool bOneCell
=sal_False
);
354 // Verkuerzen einer Zeile durch loesen von leeren Zellen
355 void Shrink( sal_uInt16 nCells
);
357 void SetSplitable( sal_Bool bSet
) { bSplitable
= bSet
; }
358 sal_Bool
IsSplitable() const { return bSplitable
; }
363 // Eine Spalte der HTML-Tabelle
365 class HTMLTableColumn
367 sal_Bool bIsEndOfGroup
;
369 sal_uInt16 nWidth
; // Optionen von <COL>
375 SwFrmFmt
*aFrmFmts
[6];
377 inline sal_uInt16
GetFrmFmtIdx( sal_Bool bBorderLine
,
378 sal_Int16 eVertOri
) const;
382 sal_Bool bLeftBorder
; // kommt vor der Spalte eine Linie
386 inline void SetWidth( sal_uInt16 nWidth
, sal_Bool bRelWidth
);
388 inline void SetAdjust( SvxAdjust eAdj
) { eAdjust
= eAdj
; }
389 inline SvxAdjust
GetAdjust() const { return eAdjust
; }
391 inline void SetVertOri( sal_Int16 eV
) { eVertOri
= eV
; }
392 inline sal_Int16
GetVertOri() const { return eVertOri
; }
394 inline void SetEndOfGroup() { bIsEndOfGroup
= sal_True
; }
395 inline sal_Bool
IsEndOfGroup() const { return bIsEndOfGroup
; }
397 inline void SetFrmFmt( SwFrmFmt
*pFmt
, sal_Bool bBorderLine
,
398 sal_Int16 eVertOri
);
399 inline SwFrmFmt
*GetFrmFmt( sal_Bool bBorderLine
,
400 sal_Int16 eVertOri
) const;
402 SwHTMLTableLayoutColumn
*CreateLayoutInfo();
409 typedef HTMLTableRow
* HTMLTableRowPtr
;
410 SV_DECL_PTRARR_DEL(HTMLTableRows
,HTMLTableRowPtr
,5,5)
412 typedef HTMLTableColumn
* HTMLTableColumnPtr
;
413 SV_DECL_PTRARR_DEL(HTMLTableColumns
,HTMLTableColumnPtr
,5,5)
415 SV_DECL_PTRARR(SdrObjects
,SdrObject
*,1,1)
424 SdrObjects
*pResizeDrawObjs
;// SDR-Objekte
425 SvUShorts
*pDrawObjPrcWidths
; // Spalte des Zeichen-Objekts und dessen
428 HTMLTableRows
*pRows
; // die Zeilen der Tabelle
429 HTMLTableColumns
*pColumns
; // die Spalten der Tabelle
431 sal_uInt16 nRows
; // Anzahl Zeilen
432 sal_uInt16 nCols
; // Anzahl Spalten
433 sal_uInt16 nFilledCols
; // Anzahl tatsaechlich gefuellter Spalten
435 sal_uInt16 nCurRow
; // aktuelle Zeile
436 sal_uInt16 nCurCol
; // aktuelle Spalte
438 sal_uInt16 nLeftMargin
; // Abstand zum linken Rand (aus Absatz)
439 sal_uInt16 nRightMargin
; // Abstand zum rechten Rand (aus Absatz)
441 sal_uInt16 nCellPadding
; // Abstand Umrandung zum Text
442 sal_uInt16 nCellSpacing
; // Abstand zwischen zwei Zellen
446 sal_uInt16 nBoxes
; // Wievele Boxen enthaelt die Tabelle
448 const SwStartNode
*pPrevStNd
; // der Table-Node oder der Start-Node
449 // der vorhergehenden Section
450 const SwTable
*pSwTable
; // die SW-Tabelle (nur auf dem Top-Level)
451 SwTableBox
*pBox1
; // die TableBox, die beim Erstellen
452 // der Top-Level-Tabelle angelegt wird
454 SwTableBoxFmt
*pBoxFmt
; // das frame::Frame-Format einer SwTableBox
455 SwTableLineFmt
*pLineFmt
; // das frame::Frame-Format einer SwTableLine
456 SwTableLineFmt
*pLineFrmFmtNoHeight
;
457 SvxBrushItem
*pBGBrush
; // Hintergrund der Tabelle
458 SvxBrushItem
*pInhBGBrush
; // "geerbter" Hintergrund der Tabelle
459 const SwStartNode
*pCaptionStartNode
; // Start-Node der Tabellen-Ueberschrift
461 SvxBorderLine aTopBorderLine
; // die Linie fuer die Umrandung
462 SvxBorderLine aBottomBorderLine
;// die Linie fuer die Umrandung
463 SvxBorderLine aLeftBorderLine
; // die Linie fuer die Umrandung
464 SvxBorderLine aRightBorderLine
; // die Linie fuer die Umrandung
465 SvxBorderLine aBorderLine
; // die Linie fuer die Umrandung
466 SvxBorderLine aInhLeftBorderLine
; // die Linie fuer die Umrandung
467 SvxBorderLine aInhRightBorderLine
; // die Linie fuer die Umrandung
468 sal_Bool bTopBorder
; // besitzt die Tabelle oben eine Linie
469 sal_Bool bRightBorder
; // besitzt die Tabelle rechts eine Linie
470 sal_Bool bTopAlwd
; // duerfen die Raender gesetzt werden?
472 sal_Bool bFillerTopBorder
; // bekommt eine linke/rechter Filler-
473 sal_Bool bFillerBottomBorder
; // Zelle eine obere/untere Umrandung?
474 sal_Bool bInhLeftBorder
;
475 sal_Bool bInhRightBorder
;
476 sal_Bool bBordersSet
; // die Umrandung wurde bereits gesetzt
477 sal_Bool bForceFrame
;
478 sal_Bool bTableAdjustOfTag
; // stammt nTableAdjust aus <TABLE>?
479 sal_uInt32 nHeadlineRepeat
; // repeating rows
480 sal_Bool bIsParentHead
;
481 sal_Bool bHasParentSection
;
482 sal_Bool bMakeTopSubTable
;
485 sal_Bool bColSpec
; // Gab es COL(GROUP)-Elemente?
486 sal_Bool bPrcWidth
; // Breite ist eine %-Angabe
488 SwHTMLParser
*pParser
; // der aktuelle Parser
489 HTMLTable
*pTopTable
; // die Tabelle auf dem Top-Level
490 HTMLTableCnts
*pParentContents
;
492 _HTMLTableContext
*pContext
; // der Kontext der Tabelle
494 SwHTMLTableLayout
*pLayoutInfo
;
497 // die folgenden Parameter stammen aus der dem <TABLE>-Tag
498 sal_uInt16 nWidth
; // die Breite der Tabelle
499 sal_uInt16 nHeight
; // absolute Hoehe der Tabelle
500 SvxAdjust eTableAdjust
; // drawing::Alignment der Tabelle
501 sal_Int16 eVertOri
; // Default vertikale Ausr. der Zellen
502 sal_uInt16 nBorder
; // Breite der auesseren Umrandung
503 HTMLTableFrame eFrame
; // Rahmen um die Tabelle
504 HTMLTableRules eRules
; // Ramhen in der Tabelle
505 sal_Bool bTopCaption
; // Ueberschrift ueber der Tabelle
507 void InitCtor( const HTMLTableOptions
*pOptions
);
509 // Korigieren des Row-Spans fuer alle Zellen oberhalb der
510 // angegeben Zelle und der Zelle selbst, fuer die den anegebenen
511 // Inhalt besitzen. Die angegeben Zelle bekommt den Row-Span 1
512 void FixRowSpan( sal_uInt16 nRow
, sal_uInt16 nCol
, const HTMLTableCnts
*pCnts
);
514 // Schuetzen der angegeben Zelle und den darunterliegenden
515 void ProtectRowSpan( sal_uInt16 nRow
, sal_uInt16 nCol
, sal_uInt16 nRowSpan
);
517 // Suchen des SwStartNodes der logisch vorhergehenden Box
518 // bei nRow==nCell==USHRT_MAX wird der allerletzte Start-Node
519 // der Tabelle zurueckgegeben
520 const SwStartNode
* GetPrevBoxStartNode( sal_uInt16 nRow
, sal_uInt16 nCell
) const;
522 sal_uInt16
GetTopCellSpace( sal_uInt16 nRow
, sal_uInt16 nRowSpan
,
523 sal_Bool bSwBorders
=sal_True
) const;
524 sal_uInt16
GetBottomCellSpace( sal_uInt16 nRow
, sal_uInt16 nRowSpan
,
525 sal_Bool bSwBorders
=sal_True
) const;
527 // Anpassen des frame::Frame-Formates einer Box
528 void FixFrameFmt( SwTableBox
*pBox
, sal_uInt16 nRow
, sal_uInt16 nCol
,
529 sal_uInt16 nRowSpan
, sal_uInt16 nColSpan
,
530 sal_Bool bFirstPara
=sal_True
, sal_Bool bLastPara
=sal_True
) const;
531 void FixFillerFrameFmt( SwTableBox
*pBox
, sal_Bool bRight
) const;
533 // den Inhalt (Lines/Boxen) eine Tabelle erstellen
534 void _MakeTable( SwTableBox
*pUpper
=0 );
536 // Anlegen einer neuen SwTableBox, die einen SwStartNode enthaelt
537 SwTableBox
*NewTableBox( const SwStartNode
*pStNd
,
538 SwTableLine
*pUpper
) const;
540 // Erstellen einer SwTableLine aus den Zellen des Rechtecks
541 // (nTopRow/nLeftCol) inklusive bis (nBottomRow/nRightRow) exklusive
542 SwTableLine
*MakeTableLine( SwTableBox
*pUpper
,
543 sal_uInt16 nTopRow
, sal_uInt16 nLeftCol
,
544 sal_uInt16 nBottomRow
, sal_uInt16 nRightCol
);
546 // Erstellen einer SwTableBox aus dem Inhalt einer Zelle
547 SwTableBox
*MakeTableBox( SwTableLine
*pUpper
,
548 HTMLTableCnts
*pCnts
,
549 sal_uInt16 nTopRow
, sal_uInt16 nLeftCol
,
550 sal_uInt16 nBootomRow
, sal_uInt16 nRightCol
);
552 // der Autolayout-Algorithmus
554 // Setzen der Umrandung anhand der Vorgaben der Parent-Tabelle
555 void InheritBorders( const HTMLTable
*pParent
,
556 sal_uInt16 nRow
, sal_uInt16 nCol
,
557 sal_uInt16 nRowSpan
, sal_uInt16 nColSpan
,
558 sal_Bool bFirstPara
, sal_Bool bLastPara
);
560 // Linke und rechte Umrandung der umgebenen Tabelle erben
561 void InheritVertBorders( const HTMLTable
*pParent
,
562 sal_uInt16 nCol
, sal_uInt16 nColSpan
);
565 // Setzen der Umrandung anhand der Benutzervorgaben
568 // wurde die Umrandung der Tabelle schon gesetzt
569 sal_Bool
BordersSet() const { return bBordersSet
; }
571 const SvxBrushItem
*GetBGBrush() const { return pBGBrush
; }
572 const SvxBrushItem
*GetInhBGBrush() const { return pInhBGBrush
; }
574 sal_uInt16
GetBorderWidth( const SvxBorderLine
& rBLine
,
575 sal_Bool bWithDistance
=sal_False
) const;
579 sal_Bool bFirstCell
; // wurde schon eine Zelle angelegt?
581 HTMLTable( SwHTMLParser
* pPars
, HTMLTable
*pTopTab
,
582 sal_Bool bParHead
, sal_Bool bHasParentSec
,
583 sal_Bool bTopTbl
, sal_Bool bHasToFly
,
584 const HTMLTableOptions
*pOptions
);
588 // Ermitteln einer Zelle
589 inline HTMLTableCell
*GetCell( sal_uInt16 nRow
, sal_uInt16 nCell
) const;
591 // Ueberschrift setzen/ermitteln
592 inline void SetCaption( const SwStartNode
*pStNd
, sal_Bool bTop
);
593 const SwStartNode
*GetCaptionStartNode() const { return pCaptionStartNode
; }
594 sal_Bool
IsTopCaption() const { return bTopCaption
; }
596 SvxAdjust
GetTableAdjust( sal_Bool bAny
) const
598 return (bTableAdjustOfTag
|| bAny
) ? eTableAdjust
: SVX_ADJUST_END
;
600 sal_Int16
GetVertOri() const { return eVertOri
; }
602 sal_uInt16
GetHSpace() const { return nHSpace
; }
603 sal_uInt16
GetVSpace() const { return nVSpace
; }
605 sal_Bool
HasPrcWidth() const { return bPrcWidth
; }
606 sal_uInt8
GetPrcWidth() const { return bPrcWidth
? (sal_uInt8
)nWidth
: 0; }
608 sal_uInt16
GetMinWidth() const
610 sal_uInt32 nMin
= pLayoutInfo
->GetMin();
611 return nMin
< USHRT_MAX
? (sal_uInt16
)nMin
: USHRT_MAX
;
614 // von Zeilen oder Spalten geerbtes drawing::Alignment holen
615 SvxAdjust
GetInheritedAdjust() const;
616 sal_Int16
GetInheritedVertOri() const;
618 // Einfuegen einer Zelle an der aktuellen Position
619 void InsertCell( HTMLTableCnts
*pCnts
, sal_uInt16 nRowSpan
, sal_uInt16 nColSpan
,
620 sal_uInt16 nWidth
, sal_Bool bRelWidth
, sal_uInt16 nHeight
,
621 sal_Int16 eVertOri
, SvxBrushItem
*pBGBrush
,
622 sal_Bool bHasNumFmt
, sal_uInt32 nNumFmt
,
623 sal_Bool bHasValue
, double nValue
, sal_Bool bNoWrap
);
625 // Start/Ende einer neuen Zeile bekanntgeben
626 void OpenRow( SvxAdjust eAdjust
, sal_Int16 eVertOri
,
627 SvxBrushItem
*pBGBrush
);
628 void CloseRow( sal_Bool bEmpty
);
630 // Ende einer neuen Section bekanntgeben
631 inline void CloseSection( sal_Bool bHead
);
633 // Ende einer Spalten-Gruppe bekanntgeben
634 inline void CloseColGroup( sal_uInt16 nSpan
, sal_uInt16 nWidth
, sal_Bool bRelWidth
,
635 SvxAdjust eAdjust
, sal_Int16 eVertOri
);
637 // Einfuegen einer Spalte
638 void InsertCol( sal_uInt16 nSpan
, sal_uInt16 nWidth
, sal_Bool bRelWidth
,
639 SvxAdjust eAdjust
, sal_Int16 eVertOri
);
641 // Beenden einer Tab-Definition (MUSS fuer ALLE Tabs aufgerufen werden)
644 // SwTable konstruieren (inkl. der Child-Tabellen)
645 void MakeTable( SwTableBox
*pUpper
, sal_uInt16 nAbsAvail
,
646 sal_uInt16 nRelAvail
=0, sal_uInt16 nAbsLeftSpace
=0,
647 sal_uInt16 nAbsRightSpace
=0, sal_uInt16 nInhAbsSpace
=0 );
649 inline sal_Bool
IsNewDoc() const { return pParser
->IsNewDoc(); }
651 void SetHasParentSection( sal_Bool bSet
) { bHasParentSection
= bSet
; }
652 sal_Bool
HasParentSection() const { return bHasParentSection
; }
654 void SetParentContents( HTMLTableCnts
*pCnts
) { pParentContents
= pCnts
; }
655 HTMLTableCnts
*GetParentContents() const { return pParentContents
; }
657 void MakeParentContents();
659 sal_Bool
GetIsParentHeader() const { return bIsParentHead
; }
661 sal_Bool
IsMakeTopSubTable() const { return bMakeTopSubTable
; }
662 void SetHasToFly() { bHasToFly
=sal_True
; }
663 sal_Bool
HasToFly() const { return bHasToFly
; }
665 void SetTable( const SwStartNode
*pStNd
, _HTMLTableContext
*pCntxt
,
666 sal_uInt16 nLeft
, sal_uInt16 nRight
,
667 const SwTable
*pSwTab
=0, sal_Bool bFrcFrame
=sal_False
);
669 _HTMLTableContext
*GetContext() const { return pContext
; }
671 SwHTMLTableLayout
*CreateLayoutInfo();
673 sal_Bool
HasColTags() const { return bColSpec
; }
675 sal_uInt16
IncGrfsThatResize() { return pSwTable
? ((SwTable
*)pSwTable
)->IncGrfsThatResize() : 0; }
677 void RegisterDrawObject( SdrObject
*pObj
, sal_uInt8 nPrcWidth
);
679 const SwTable
*GetSwTable() const { return pSwTable
; }
681 void SetBGBrush( const SvxBrushItem
& rBrush
) { delete pBGBrush
; pBGBrush
= new SvxBrushItem( rBrush
); }
683 const String
& GetId() const { return aId
; }
684 const String
& GetClass() const { return aClass
; }
685 const String
& GetStyle() const { return aStyle
; }
686 const String
& GetDirection() const { return aDir
; }
688 void IncBoxCount() { nBoxes
++; }
689 sal_Bool
IsOverflowing() const { return nBoxes
> 64000; }
692 SV_IMPL_PTRARR(HTMLTableCells
,HTMLTableCellPtr
)
693 SV_IMPL_PTRARR(HTMLTableRows
,HTMLTableRowPtr
)
694 SV_IMPL_PTRARR(HTMLTableColumns
,HTMLTableColumnPtr
)
699 void HTMLTableCnts::InitCtor()
704 bNoBreak
= sal_False
;
707 HTMLTableCnts::HTMLTableCnts( const SwStartNode
* pStNd
):
708 pStartNode(pStNd
), pTable(0)
713 HTMLTableCnts::HTMLTableCnts( HTMLTable
* pTab
):
714 pStartNode(0), pTable(pTab
)
719 HTMLTableCnts::~HTMLTableCnts()
721 delete pTable
; // die Tabellen brauchen wir nicht mehr
725 void HTMLTableCnts::Add( HTMLTableCnts
* pNewCnts
)
727 HTMLTableCnts
*pCnts
= this;
729 while( pCnts
->pNext
)
730 pCnts
= pCnts
->pNext
;
732 pCnts
->pNext
= pNewCnts
;
735 inline void HTMLTableCnts::SetTableBox( SwTableBox
*pBox
)
737 ASSERT( pLayoutInfo
, "Da sit noch keine Layout-Info" );
739 pLayoutInfo
->SetTableBox( pBox
);
742 SwHTMLTableLayoutCnts
*HTMLTableCnts::CreateLayoutInfo()
746 SwHTMLTableLayoutCnts
*pNextInfo
= pNext
? pNext
->CreateLayoutInfo() : 0;
747 SwHTMLTableLayout
*pTableInfo
= pTable
? pTable
->CreateLayoutInfo() : 0;
749 pLayoutInfo
= new SwHTMLTableLayoutCnts( pStartNode
, pTableInfo
,
750 bNoBreak
, pNextInfo
);
758 HTMLTableCell::HTMLTableCell():
766 eVertOri( text::VertOrientation::NONE
),
767 bProtected(sal_False
),
768 bRelWidth( sal_False
),
769 bHasNumFmt(sal_False
),
770 bHasValue(sal_False
),
774 HTMLTableCell::~HTMLTableCell()
776 // der Inhalt ist in mehrere Zellen eingetragen, darf aber nur einmal
778 if( 1==nRowSpan
&& 1==nColSpan
)
785 void HTMLTableCell::Set( HTMLTableCnts
*pCnts
, sal_uInt16 nRSpan
, sal_uInt16 nCSpan
,
786 sal_Int16 eVert
, SvxBrushItem
*pBrush
,
787 sal_Bool bHasNF
, sal_uInt32 nNF
, sal_Bool bHasV
, double nVal
,
788 sal_Bool bNWrap
, sal_Bool bCovered
)
793 bProtected
= sal_False
;
803 mbCovered
= bCovered
;
806 inline void HTMLTableCell::SetWidth( sal_uInt16 nWdth
, sal_Bool bRelWdth
)
809 bRelWidth
= bRelWdth
;
812 void HTMLTableCell::SetProtected()
814 // Die Inhalte dieser Zelle mussen nich irgenwo anders verankert
815 // sein, weil sie nicht geloescht werden!!!
820 // Hintergrundfarbe kopieren.
822 pBGBrush
= new SvxBrushItem( *pBGBrush
);
826 bProtected
= sal_True
;
829 inline sal_Bool
HTMLTableCell::GetNumFmt( sal_uInt32
& rNumFmt
) const
835 inline sal_Bool
HTMLTableCell::GetValue( double& rValue
) const
841 SwHTMLTableLayoutCell
*HTMLTableCell::CreateLayoutInfo()
843 SwHTMLTableLayoutCnts
*pCntInfo
= pContents
? pContents
->CreateLayoutInfo() : 0;
845 return new SwHTMLTableLayoutCell( pCntInfo
, nRowSpan
, nColSpan
, nWidth
,
846 bRelWidth
, bNoWrap
);
851 HTMLTableRow::HTMLTableRow( sal_uInt16 nCells
):
852 pCells(new HTMLTableCells
),
853 bIsEndOfGroup(sal_False
),
854 bSplitable( sal_False
),
857 eAdjust(SVX_ADJUST_END
),
858 eVertOri(text::VertOrientation::TOP
),
860 bBottomBorder(sal_False
)
862 for( sal_uInt16 i
=0; i
<nCells
; i
++ )
864 pCells
->Insert( new HTMLTableCell
, pCells
->Count() );
867 ASSERT( nCells
==pCells
->Count(),
868 "Zellenzahl in neuer HTML-Tabellenzeile stimmt nicht" );
871 HTMLTableRow::~HTMLTableRow()
877 inline void HTMLTableRow::SetHeight( sal_uInt16 nHght
)
879 if( nHght
> nHeight
)
883 inline HTMLTableCell
*HTMLTableRow::GetCell( sal_uInt16 nCell
) const
885 ASSERT( nCell
<pCells
->Count(),
886 "ungueltiger Zellen-Index in HTML-Tabellenzeile" );
887 return (*pCells
)[nCell
];
890 void HTMLTableRow::Expand( sal_uInt16 nCells
, sal_Bool bOneCell
)
892 // die Zeile wird mit einer einzigen Zelle aufgefuellt, wenn
893 // bOneCell gesetzt ist. Das geht, nur fuer Zeilen, in die keine
894 // Zellen mehr eingefuegt werden!
896 sal_uInt16 nColSpan
= nCells
-pCells
->Count();
897 for( sal_uInt16 i
=pCells
->Count(); i
<nCells
; i
++ )
899 HTMLTableCell
*pCell
= new HTMLTableCell
;
901 pCell
->SetColSpan( nColSpan
);
903 pCells
->Insert( pCell
, pCells
->Count() );
907 ASSERT( nCells
==pCells
->Count(),
908 "Zellenzahl in expandierter HTML-Tabellenzeile stimmt nicht" );
911 void HTMLTableRow::Shrink( sal_uInt16 nCells
)
913 ASSERT( nCells
< pCells
->Count(), "Anzahl Zellen falsch" );
916 sal_uInt16 nEnd
= pCells
->Count();
918 // The colspan of empty cells at the end has to be fixed to the new
923 HTMLTableCell
*pCell
= (*pCells
)[--i
];
924 if( !pCell
->GetContents() )
926 ASSERT( pCell
->GetColSpan() == nEnd
- i
,
927 "invalid col span for empty cell at row end" );
928 pCell
->SetColSpan( nCells
-i
);
934 for( i
=nCells
; i
<nEnd
; i
++ )
936 HTMLTableCell
*pCell
= (*pCells
)[i
];
937 ASSERT( pCell
->GetRowSpan() == 1,
938 "RowSpan von zu loesender Zelle ist falsch" );
939 ASSERT( pCell
->GetColSpan() == nEnd
- i
,
940 "ColSpan von zu loesender Zelle ist falsch" );
941 ASSERT( !pCell
->GetContents(), "Zu loeschende Zelle hat Inhalt" );
945 pCells
->DeleteAndDestroy( nCells
, pCells
->Count()-nCells
);
950 HTMLTableColumn::HTMLTableColumn():
951 bIsEndOfGroup(sal_False
),
952 nWidth(0), bRelWidth(sal_False
),
953 eAdjust(SVX_ADJUST_END
), eVertOri(text::VertOrientation::TOP
),
954 bLeftBorder(sal_False
)
956 for( sal_uInt16 i
=0; i
<6; i
++ )
960 inline void HTMLTableColumn::SetWidth( sal_uInt16 nWdth
, sal_Bool bRelWdth
)
962 if( bRelWidth
==bRelWdth
)
969 bRelWidth
= bRelWdth
;
972 inline SwHTMLTableLayoutColumn
*HTMLTableColumn::CreateLayoutInfo()
974 return new SwHTMLTableLayoutColumn( nWidth
, bRelWidth
, bLeftBorder
);
977 inline sal_uInt16
HTMLTableColumn::GetFrmFmtIdx( sal_Bool bBorderLine
,
978 sal_Int16 eVertOrient
) const
980 ASSERT( text::VertOrientation::TOP
!= eVertOrient
, "Top ist nicht erlaubt" );
981 sal_uInt16 n
= bBorderLine
? 3 : 0;
982 switch( eVertOrient
)
984 case text::VertOrientation::CENTER
: n
+=1; break;
985 case text::VertOrientation::BOTTOM
: n
+=2; break;
992 inline void HTMLTableColumn::SetFrmFmt( SwFrmFmt
*pFmt
, sal_Bool bBorderLine
,
993 sal_Int16 eVertOrient
)
995 aFrmFmts
[GetFrmFmtIdx(bBorderLine
,eVertOrient
)] = pFmt
;
998 inline SwFrmFmt
*HTMLTableColumn::GetFrmFmt( sal_Bool bBorderLine
,
999 sal_Int16 eVertOrient
) const
1001 return aFrmFmts
[GetFrmFmtIdx(bBorderLine
,eVertOrient
)];
1007 void HTMLTable::InitCtor( const HTMLTableOptions
*pOptions
)
1009 pResizeDrawObjs
= 0;
1010 pDrawObjPrcWidths
= 0;
1012 pRows
= new HTMLTableRows
;
1013 pColumns
= new HTMLTableColumns
;
1015 nCurRow
= 0; nCurCol
= 0;
1018 pBoxFmt
= 0; pLineFmt
= 0;
1019 pLineFrmFmtNoHeight
= 0;
1025 bTopBorder
= sal_False
; bRightBorder
= sal_False
;
1026 bTopAlwd
= sal_True
; bRightAlwd
= sal_True
;
1027 bFillerTopBorder
= sal_False
; bFillerBottomBorder
= sal_False
;
1028 bInhLeftBorder
= sal_False
; bInhRightBorder
= sal_False
;
1029 bBordersSet
= sal_False
;
1030 bForceFrame
= sal_False
;
1031 nHeadlineRepeat
= 0;
1036 const Color
& rBorderColor
= pOptions
->aBorderColor
;
1038 long nBorderOpt
= (long)pOptions
->nBorder
;
1039 long nPWidth
= nBorderOpt
==USHRT_MAX
? NETSCAPE_DFLT_BORDER
1041 long nPHeight
= nBorderOpt
==USHRT_MAX
? 0 : nBorderOpt
;
1042 SvxCSS1Parser::PixelToTwip( nPWidth
, nPHeight
);
1044 // nBorder gibt die Breite der Umrandung an, wie sie in die
1045 // Breitenberechnung in Netscape einfliesst. Wenn pOption->nBorder
1046 // == USHRT_MAX, wurde keine BORDER-Option angegeben. Trotzdem fliesst
1047 // eine 1 Pixel breite Umrandung in die Breitenberechnung mit ein.
1048 nBorder
= (sal_uInt16
)nPWidth
;
1049 if( nBorderOpt
==USHRT_MAX
)
1052 // HACK: ein Pixel-breite Linien sollen zur Haarlinie werden, wenn
1053 // wir mit doppelter Umrandung arbeiten
1054 if( pOptions
->nCellSpacing
!=0 && nBorderOpt
==1 )
1060 SvxCSS1Parser::SetBorderWidth( aTopBorderLine
, (sal_uInt16
)nPHeight
,
1061 pOptions
->nCellSpacing
!=0, sal_True
);
1062 aTopBorderLine
.SetColor( rBorderColor
);
1063 aBottomBorderLine
= aTopBorderLine
;
1065 if( nPWidth
== nPHeight
)
1067 aLeftBorderLine
= aTopBorderLine
;
1071 SvxCSS1Parser::SetBorderWidth( aLeftBorderLine
, (sal_uInt16
)nPWidth
,
1072 pOptions
->nCellSpacing
!=0, sal_True
);
1073 aLeftBorderLine
.SetColor( rBorderColor
);
1075 aRightBorderLine
= aLeftBorderLine
;
1077 if( pOptions
->nCellSpacing
!= 0 )
1079 aBorderLine
.SetOutWidth( DEF_DOUBLE_LINE7_OUT
);
1080 aBorderLine
.SetInWidth( DEF_DOUBLE_LINE7_IN
);
1081 aBorderLine
.SetDistance( DEF_DOUBLE_LINE7_DIST
);
1085 aBorderLine
.SetOutWidth( DEF_LINE_WIDTH_1
);
1087 aBorderLine
.SetColor( rBorderColor
);
1091 if( nCellPadding
==USHRT_MAX
)
1092 nCellPadding
= MIN_BORDER_DIST
; // default
1095 nCellPadding
= pParser
->ToTwips( nCellPadding
);
1096 if( nCellPadding
<MIN_BORDER_DIST
)
1097 nCellPadding
= MIN_BORDER_DIST
;
1102 if( nCellSpacing
==USHRT_MAX
)
1103 nCellSpacing
= NETSCAPE_DFLT_CELLSPACING
;
1104 nCellSpacing
= pParser
->ToTwips( nCellSpacing
);
1107 nPWidth
= pOptions
->nHSpace
;
1108 nPHeight
= pOptions
->nVSpace
;
1109 SvxCSS1Parser::PixelToTwip( nPWidth
, nPHeight
);
1110 nHSpace
= (sal_uInt16
)nPWidth
;
1111 nVSpace
= (sal_uInt16
)nPHeight
;
1113 bColSpec
= sal_False
;
1115 pBGBrush
= pParser
->CreateBrushItem(
1116 pOptions
->bBGColor
? &(pOptions
->aBGColor
) : 0,
1117 pOptions
->aBGImage
, aEmptyStr
, aEmptyStr
, aEmptyStr
);
1120 pParentContents
= 0;
1122 aId
= pOptions
->aId
;
1123 aClass
= pOptions
->aClass
;
1124 aStyle
= pOptions
->aStyle
;
1125 aDir
= pOptions
->aDir
;
1128 HTMLTable::HTMLTable( SwHTMLParser
* pPars
, HTMLTable
*pTopTab
,
1130 sal_Bool bHasParentSec
, sal_Bool bTopTbl
, sal_Bool bHasToFlw
,
1131 const HTMLTableOptions
*pOptions
) :
1132 nCols( pOptions
->nCols
),
1134 nCellPadding( pOptions
->nCellPadding
),
1135 nCellSpacing( pOptions
->nCellSpacing
),
1137 pCaptionStartNode( 0 ),
1138 bTableAdjustOfTag( pTopTab
? sal_False
: pOptions
->bTableAdjust
),
1139 bIsParentHead( bParHead
),
1140 bHasParentSection( bHasParentSec
),
1141 bMakeTopSubTable( bTopTbl
),
1142 bHasToFly( bHasToFlw
),
1143 bFixedCols( pOptions
->nCols
>0 ),
1144 bPrcWidth( pOptions
->bPrcWidth
),
1146 pTopTable( pTopTab
? pTopTab
: this ),
1148 nWidth( pOptions
->nWidth
),
1149 nHeight( pTopTab
? 0 : pOptions
->nHeight
),
1150 eTableAdjust( pOptions
->eAdjust
),
1151 eVertOri( pOptions
->eVertOri
),
1152 eFrame( pOptions
->eFrame
),
1153 eRules( pOptions
->eRules
),
1154 bTopCaption( sal_False
),
1155 bFirstCell( !pTopTab
)
1157 InitCtor( pOptions
);
1159 for( sal_uInt16 i
=0; i
<nCols
; i
++ )
1160 pColumns
->Insert( new HTMLTableColumn
, pColumns
->Count() );
1164 HTMLTable::~HTMLTable()
1166 delete pResizeDrawObjs
;
1167 delete pDrawObjPrcWidths
;
1176 // pLayoutInfo wurde entweder bereits geloescht oder muss aber es
1177 // in den Besitz der SwTable uebergegangen.
1180 SwHTMLTableLayout
*HTMLTable::CreateLayoutInfo()
1182 sal_uInt16 nW
= bPrcWidth
? nWidth
: pParser
->ToTwips( nWidth
);
1184 sal_uInt16 nBorderWidth
= GetBorderWidth( aBorderLine
, sal_True
);
1185 sal_uInt16 nLeftBorderWidth
=
1186 ((*pColumns
)[0])->bLeftBorder
? GetBorderWidth( aLeftBorderLine
, sal_True
) : 0;
1187 sal_uInt16 nRightBorderWidth
=
1188 bRightBorder
? GetBorderWidth( aRightBorderLine
, sal_True
) : 0;
1189 sal_uInt16 nInhLeftBorderWidth
= 0;
1190 sal_uInt16 nInhRightBorderWidth
= 0;
1192 pLayoutInfo
= new SwHTMLTableLayout(
1194 nRows
, nCols
, bFixedCols
, bColSpec
,
1195 nW
, bPrcWidth
, nBorder
, nCellPadding
,
1196 nCellSpacing
, eTableAdjust
,
1197 nLeftMargin
, nRightMargin
,
1198 nBorderWidth
, nLeftBorderWidth
, nRightBorderWidth
,
1199 nInhLeftBorderWidth
, nInhRightBorderWidth
);
1201 sal_Bool bExportable
= sal_True
;
1203 for( i
=0; i
<nRows
; i
++ )
1205 HTMLTableRow
*pRow
= (*pRows
)[i
];
1206 for( sal_uInt16 j
=0; j
<nCols
; j
++ )
1208 SwHTMLTableLayoutCell
*pLayoutCell
=
1209 pRow
->GetCell(j
)->CreateLayoutInfo();
1211 pLayoutInfo
->SetCell( pLayoutCell
, i
, j
);
1215 SwHTMLTableLayoutCnts
*pLayoutCnts
=
1216 pLayoutCell
->GetContents();
1217 bExportable
= !pLayoutCnts
||
1218 ( pLayoutCnts
->GetStartNode() &&
1219 !pLayoutCnts
->GetNext() );
1224 pLayoutInfo
->SetExportable( bExportable
);
1226 for( i
=0; i
<nCols
; i
++ )
1227 pLayoutInfo
->SetColumn( ((*pColumns
)[i
])->CreateLayoutInfo(), i
);
1232 inline void HTMLTable::SetCaption( const SwStartNode
*pStNd
, sal_Bool bTop
)
1234 pCaptionStartNode
= pStNd
;
1238 void HTMLTable::FixRowSpan( sal_uInt16 nRow
, sal_uInt16 nCol
,
1239 const HTMLTableCnts
*pCnts
)
1241 sal_uInt16 nRowSpan
=1;
1242 HTMLTableCell
*pCell
;
1243 while( ( pCell
=GetCell(nRow
,nCol
), pCell
->GetContents()==pCnts
) )
1245 pCell
->SetRowSpan( nRowSpan
);
1247 pLayoutInfo
->GetCell(nRow
,nCol
)->SetRowSpan( nRowSpan
);
1254 void HTMLTable::ProtectRowSpan( sal_uInt16 nRow
, sal_uInt16 nCol
, sal_uInt16 nRowSpan
)
1256 for( sal_uInt16 i
=0; i
<nRowSpan
; i
++ )
1258 GetCell(nRow
+i
,nCol
)->SetProtected();
1260 pLayoutInfo
->GetCell(nRow
+i
,nCol
)->SetProtected();
1265 // Suchen des SwStartNodes der letzten belegten Vorgaengerbox
1266 const SwStartNode
* HTMLTable::GetPrevBoxStartNode( sal_uInt16 nRow
, sal_uInt16 nCol
) const
1268 const HTMLTableCnts
*pPrevCnts
= 0;
1272 // immer die Vorgaenger-Zelle
1274 pPrevCnts
= GetCell( 0, nCol
-1 )->GetContents();
1278 else if( USHRT_MAX
==nRow
&& USHRT_MAX
==nCol
)
1279 // der Contents der letzten Zelle
1280 pPrevCnts
= GetCell( nRows
-1, nCols
-1 )->GetContents();
1284 HTMLTableRow
*pPrevRow
= (*pRows
)[nRow
-1];
1286 // evtl. eine Zelle in der aktuellen Zeile
1291 if( 1 == pPrevRow
->GetCell(i
)->GetRowSpan() )
1293 pPrevCnts
= GetCell(nRow
,i
)->GetContents();
1298 // sonst die letzte gefuellte Zelle der Zeile davor suchen
1302 while( !pPrevCnts
&& i
)
1305 pPrevCnts
= pPrevRow
->GetCell(i
)->GetContents();
1309 ASSERT( pPrevCnts
, "keine gefuellte Vorgaenger-Zelle gefunden" );
1312 pPrevCnts
= GetCell(0,0)->GetContents();
1317 while( pPrevCnts
->Next() )
1318 pPrevCnts
= pPrevCnts
->Next();
1320 return ( pPrevCnts
->GetStartNode() ? pPrevCnts
->GetStartNode()
1321 : pPrevCnts
->GetTable()->GetPrevBoxStartNode( USHRT_MAX
, USHRT_MAX
) );
1325 static sal_Bool
IsBoxEmpty( const SwTableBox
*pBox
)
1327 const SwStartNode
*pSttNd
= pBox
->GetSttNd();
1329 pSttNd
->GetIndex() + 2 == pSttNd
->EndOfSectionIndex() )
1331 const SwCntntNode
*pCNd
=
1332 pSttNd
->GetNodes()[pSttNd
->GetIndex()+1]->GetCntntNode();
1333 if( pCNd
&& !pCNd
->Len() )
1340 sal_uInt16
HTMLTable::GetTopCellSpace( sal_uInt16 nRow
, sal_uInt16 nRowSpan
,
1341 sal_Bool bSwBorders
) const
1343 sal_uInt16 nSpace
= nCellPadding
;
1347 nSpace
+= nBorder
+ nCellSpacing
;
1350 sal_uInt16 nTopBorderWidth
=
1351 GetBorderWidth( aTopBorderLine
, sal_True
);
1352 if( nSpace
< nTopBorderWidth
)
1353 nSpace
= nTopBorderWidth
;
1356 else if( bSwBorders
&& ((*pRows
)[nRow
+nRowSpan
-1])->bBottomBorder
&&
1357 nSpace
< MIN_BORDER_DIST
)
1359 ASSERT( !nCellPadding
, "GetTopCellSpace: CELLPADDING!=0" );
1360 // Wenn die Gegenueberliegende Seite umrandet ist muessen
1361 // wir zumindest den minimalen Abstand zum Inhalt
1362 // beruecksichtigen. (Koennte man zusaetzlich auch an
1363 // nCellPadding festmachen.)
1364 nSpace
= MIN_BORDER_DIST
;
1370 sal_uInt16
HTMLTable::GetBottomCellSpace( sal_uInt16 nRow
, sal_uInt16 nRowSpan
,
1371 sal_Bool bSwBorders
) const
1373 sal_uInt16 nSpace
= nCellSpacing
+ nCellPadding
;
1375 if( nRow
+nRowSpan
== nRows
)
1377 nSpace
= nSpace
+ nBorder
;
1381 sal_uInt16 nBottomBorderWidth
=
1382 GetBorderWidth( aBottomBorderLine
, sal_True
);
1383 if( nSpace
< nBottomBorderWidth
)
1384 nSpace
= nBottomBorderWidth
;
1387 else if( bSwBorders
)
1389 if( ((*pRows
)[nRow
+nRowSpan
+1])->bBottomBorder
)
1391 sal_uInt16 nBorderWidth
= GetBorderWidth( aBorderLine
, sal_True
);
1392 if( nSpace
< nBorderWidth
)
1393 nSpace
= nBorderWidth
;
1395 else if( nRow
==0 && bTopBorder
&& nSpace
< MIN_BORDER_DIST
)
1397 ASSERT( GetBorderWidth( aTopBorderLine
, sal_True
) > 0,
1398 "GetBottomCellSpace: |aTopLine| == 0" );
1399 ASSERT( !nCellPadding
, "GetBottomCellSpace: CELLPADDING!=0" );
1400 // Wenn die Gegenueberliegende Seite umrandet ist muessen
1401 // wir zumindest den minimalen Abstand zum Inhalt
1402 // beruecksichtigen. (Koennte man zusaetzlich auch an
1403 // nCellPadding festmachen.)
1404 nSpace
= MIN_BORDER_DIST
;
1411 void HTMLTable::FixFrameFmt( SwTableBox
*pBox
,
1412 sal_uInt16 nRow
, sal_uInt16 nCol
,
1413 sal_uInt16 nRowSpan
, sal_uInt16 nColSpan
,
1414 sal_Bool bFirstPara
, sal_Bool bLastPara
) const
1416 SwFrmFmt
*pFrmFmt
= 0; // frame::Frame-Format
1417 sal_Int16 eVOri
= text::VertOrientation::NONE
;
1418 const SvxBrushItem
*pBGBrushItem
= 0; // Hintergrund
1419 sal_Bool bTopLine
= sal_False
, bBottomLine
= sal_False
, bLastBottomLine
= sal_False
;
1420 sal_Bool bReUsable
= sal_False
; // Format nochmals verwendbar?
1421 sal_uInt16 nEmptyRows
= 0;
1422 sal_Bool bHasNumFmt
= sal_False
;
1423 sal_Bool bHasValue
= sal_False
;
1424 sal_uInt32 nNumFmt
= 0;
1425 double nValue
= 0.0;
1427 HTMLTableColumn
*pColumn
= (*pColumns
)[nCol
];
1429 if( pBox
->GetSttNd() )
1431 // die Hintergrundfarbe/-grafik bestimmen
1432 const HTMLTableCell
*pCell
= GetCell( nRow
, nCol
);
1433 pBGBrushItem
= pCell
->GetBGBrush();
1436 // Wenn die Zelle ueber mehrere Zeilen geht muss ein evtl.
1437 // an der Zeile gesetzter Hintergrund an die Zelle uebernommen
1440 // Wenn es sich um eine Tabelle in der Tabelle handelt und
1441 // die Zelle ueber die gesamte Heoehe der Tabelle geht muss
1442 // ebenfalls der Hintergrund der Zeile uebernommen werden, weil
1443 // die Line von der GC (zu Recht) wegoptimiert wird.
1444 if( nRowSpan
> 1 || (this != pTopTable
&& nRowSpan
==nRows
) )
1449 pBGBrushItem
= ((*pRows
)[nRow
])->GetBGBrush();
1450 if( !pBGBrushItem
&& this != pTopTable
)
1452 pBGBrushItem
= GetBGBrush();
1454 pBGBrushItem
= GetInhBGBrush();
1459 bTopLine
= 0==nRow
&& bTopBorder
&& bFirstPara
;
1460 if( ((*pRows
)[nRow
+nRowSpan
-1])->bBottomBorder
&& bLastPara
)
1462 nEmptyRows
= ((*pRows
)[nRow
+nRowSpan
-1])->GetEmptyRows();
1463 if( nRow
+nRowSpan
== nRows
)
1464 bLastBottomLine
= sal_True
;
1466 bBottomLine
= sal_True
;
1469 eVOri
= pCell
->GetVertOri();
1470 bHasNumFmt
= pCell
->GetNumFmt( nNumFmt
);
1472 bHasValue
= pCell
->GetValue( nValue
);
1474 if( nColSpan
==1 && !bTopLine
&& !bLastBottomLine
&& !nEmptyRows
&&
1475 !pBGBrushItem
&& !bHasNumFmt
)
1477 pFrmFmt
= pColumn
->GetFrmFmt( bBottomLine
, eVOri
);
1478 bReUsable
= !pFrmFmt
;
1484 pFrmFmt
= pBox
->ClaimFrmFmt();
1486 // die Breite der Box berechnen
1487 SwTwips nFrmWidth
= (SwTwips
)pLayoutInfo
->GetColumn(nCol
)
1489 for( sal_uInt16 i
=1; i
<nColSpan
; i
++ )
1490 nFrmWidth
+= (SwTwips
)pLayoutInfo
->GetColumn(nCol
+i
)
1493 // die Umrandung nur an Edit-Boxen setzen (bei der oberen und unteren
1494 // Umrandung muss beruecks. werden, ob es sich um den ersten oder
1495 // letzen Absatz der Zelle handelt)
1496 if( pBox
->GetSttNd() )
1498 sal_Bool bSet
= (nCellPadding
> 0);
1500 SvxBoxItem
aBoxItem( RES_BOX
);
1501 long nInnerFrmWidth
= nFrmWidth
;
1505 aBoxItem
.SetLine( &aTopBorderLine
, BOX_LINE_TOP
);
1508 if( bLastBottomLine
)
1510 aBoxItem
.SetLine( &aBottomBorderLine
, BOX_LINE_BOTTOM
);
1513 else if( bBottomLine
)
1515 if( nEmptyRows
&& !aBorderLine
.GetInWidth() )
1517 // Leere Zeilen koennen zur Zeit nur dann ueber
1518 // dicke Linien simuliert werden, wenn die Linie
1520 SvxBorderLine
aThickBorderLine( aBorderLine
);
1522 sal_uInt16 nBorderWidth
= aBorderLine
.GetOutWidth();
1523 nBorderWidth
*= (nEmptyRows
+ 1);
1524 SvxCSS1Parser::SetBorderWidth( aThickBorderLine
,
1525 nBorderWidth
, sal_False
);
1526 aBoxItem
.SetLine( &aThickBorderLine
, BOX_LINE_BOTTOM
);
1530 aBoxItem
.SetLine( &aBorderLine
, BOX_LINE_BOTTOM
);
1534 if( ((*pColumns
)[nCol
])->bLeftBorder
)
1536 const SvxBorderLine
& rBorderLine
=
1537 0==nCol
? aLeftBorderLine
: aBorderLine
;
1538 aBoxItem
.SetLine( &rBorderLine
, BOX_LINE_LEFT
);
1539 nInnerFrmWidth
-= GetBorderWidth( rBorderLine
);
1542 if( nCol
+nColSpan
== nCols
&& bRightBorder
)
1544 aBoxItem
.SetLine( &aRightBorderLine
, BOX_LINE_RIGHT
);
1545 nInnerFrmWidth
-= GetBorderWidth( aRightBorderLine
);
1551 // fix #30588#: BorderDist nicht mehr Bestandteil
1552 // einer Zelle mit fixer Breite
1553 sal_uInt16 nBDist
= static_cast< sal_uInt16
>(
1554 (2*nCellPadding
<= nInnerFrmWidth
) ? nCellPadding
1555 : (nInnerFrmWidth
/ 2) );
1556 // wir setzen das Item nur, wenn es eine Umrandung gibt
1557 // oder eine sheet::Border-Distanz vorgegeben ist. Fehlt letztere,
1558 // dann gibt es eine Umrandung, und wir muessen die Distanz
1560 aBoxItem
.SetDistance( nBDist
? nBDist
: MIN_BORDER_DIST
);
1561 pFrmFmt
->SetFmtAttr( aBoxItem
);
1564 pFrmFmt
->ResetFmtAttr( RES_BOX
);
1568 pFrmFmt
->SetFmtAttr( *pBGBrushItem
);
1571 pFrmFmt
->ResetFmtAttr( RES_BACKGROUND
);
1573 // fix #41003#: Format nur setzten, wenn es auch einen Value
1574 // gibt oder die Box leer ist.
1575 if( bHasNumFmt
&& (bHasValue
|| IsBoxEmpty(pBox
)) )
1577 sal_Bool bLock
= pFrmFmt
->GetDoc()->GetNumberFormatter()
1578 ->IsTextFormat( nNumFmt
);
1579 SfxItemSet
aItemSet( *pFrmFmt
->GetAttrSet().GetPool(),
1580 RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
1581 SvxAdjust eAdjust
= SVX_ADJUST_END
;
1582 SwCntntNode
*pCNd
= 0;
1585 const SwStartNode
*pSttNd
= pBox
->GetSttNd();
1586 pCNd
= pSttNd
->GetNodes()[pSttNd
->GetIndex()+1]
1588 const SfxPoolItem
*pItem
;
1589 if( pCNd
&& pCNd
->HasSwAttrSet() &&
1590 SFX_ITEM_SET
==pCNd
->GetpSwAttrSet()->GetItemState(
1591 RES_PARATR_ADJUST
, sal_False
, &pItem
) )
1593 eAdjust
= ((const SvxAdjustItem
*)pItem
)
1597 aItemSet
.Put( SwTblBoxNumFormat(nNumFmt
) );
1599 aItemSet
.Put( SwTblBoxValue(nValue
) );
1602 pFrmFmt
->LockModify();
1603 pFrmFmt
->SetFmtAttr( aItemSet
);
1605 pFrmFmt
->UnlockModify();
1606 else if( pCNd
&& SVX_ADJUST_END
!= eAdjust
)
1608 SvxAdjustItem
aAdjItem( eAdjust
, RES_PARATR_ADJUST
);
1609 pCNd
->SetAttr( aAdjItem
);
1613 pFrmFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
);
1615 ASSERT( eVOri
!= text::VertOrientation::TOP
, "text::VertOrientation::TOP ist nicht erlaubt!" );
1616 if( text::VertOrientation::NONE
!= eVOri
)
1618 pFrmFmt
->SetFmtAttr( SwFmtVertOrient( 0, eVOri
) );
1621 pFrmFmt
->ResetFmtAttr( RES_VERT_ORIENT
);
1624 pColumn
->SetFrmFmt( pFrmFmt
, bBottomLine
, eVOri
);
1628 pFrmFmt
->ResetFmtAttr( RES_BOX
);
1629 pFrmFmt
->ResetFmtAttr( RES_BACKGROUND
);
1630 pFrmFmt
->ResetFmtAttr( RES_VERT_ORIENT
);
1631 pFrmFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
);
1636 ASSERT( pBox
->GetSttNd() ||
1637 SFX_ITEM_SET
!=pFrmFmt
->GetAttrSet().GetItemState(
1638 RES_VERT_ORIENT
, sal_False
),
1639 "Box ohne Inhalt hat vertikale Ausrichtung" );
1640 pBox
->ChgFrmFmt( (SwTableBoxFmt
*)pFrmFmt
);
1645 void HTMLTable::FixFillerFrameFmt( SwTableBox
*pBox
, sal_Bool bRight
) const
1647 SwFrmFmt
*pFrmFmt
= pBox
->ClaimFrmFmt();
1649 if( bFillerTopBorder
|| bFillerBottomBorder
||
1650 (!bRight
&& bInhLeftBorder
) || (bRight
&& bInhRightBorder
) )
1652 SvxBoxItem
aBoxItem( RES_BOX
);
1653 if( bFillerTopBorder
)
1654 aBoxItem
.SetLine( &aTopBorderLine
, BOX_LINE_TOP
);
1655 if( bFillerBottomBorder
)
1656 aBoxItem
.SetLine( &aBottomBorderLine
, BOX_LINE_BOTTOM
);
1657 if( !bRight
&& bInhLeftBorder
)
1658 aBoxItem
.SetLine( &aInhLeftBorderLine
, BOX_LINE_LEFT
);
1659 if( bRight
&& bInhRightBorder
)
1660 aBoxItem
.SetLine( &aInhRightBorderLine
, BOX_LINE_RIGHT
);
1661 aBoxItem
.SetDistance( MIN_BORDER_DIST
);
1662 pFrmFmt
->SetFmtAttr( aBoxItem
);
1666 pFrmFmt
->ResetFmtAttr( RES_BOX
);
1669 if( GetInhBGBrush() )
1670 pFrmFmt
->SetFmtAttr( *GetInhBGBrush() );
1672 pFrmFmt
->ResetFmtAttr( RES_BACKGROUND
);
1674 pFrmFmt
->ResetFmtAttr( RES_VERT_ORIENT
);
1675 pFrmFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
);
1678 SwTableBox
*HTMLTable::NewTableBox( const SwStartNode
*pStNd
,
1679 SwTableLine
*pUpper
) const
1683 if( pTopTable
->pBox1
&&
1684 pTopTable
->pBox1
->GetSttNd() == pStNd
)
1686 // wenn der StartNode dem StartNode der initial angelegten Box
1687 // entspricht nehmen wir diese Box
1688 pBox
= pTopTable
->pBox1
;
1689 pBox
->SetUpper( pUpper
);
1690 pTopTable
->pBox1
= 0;
1693 pBox
= new SwTableBox( pBoxFmt
, *pStNd
, pUpper
);
1699 static void ResetLineFrmFmtAttrs( SwFrmFmt
*pFrmFmt
)
1701 pFrmFmt
->ResetFmtAttr( RES_FRM_SIZE
);
1702 pFrmFmt
->ResetFmtAttr( RES_BACKGROUND
);
1703 ASSERT( SFX_ITEM_SET
!=pFrmFmt
->GetAttrSet().GetItemState(
1704 RES_VERT_ORIENT
, sal_False
),
1705 "Zeile hat vertikale Ausrichtung" );
1708 // !!! kann noch vereinfacht werden
1709 SwTableLine
*HTMLTable::MakeTableLine( SwTableBox
*pUpper
,
1710 sal_uInt16 nTopRow
, sal_uInt16 nLeftCol
,
1711 sal_uInt16 nBottomRow
, sal_uInt16 nRightCol
)
1714 if( this==pTopTable
&& !pUpper
&& 0==nTopRow
)
1715 pLine
= (pSwTable
->GetTabLines())[0];
1717 pLine
= new SwTableLine( pLineFrmFmtNoHeight
? pLineFrmFmtNoHeight
1721 HTMLTableRow
*pTopRow
= (*pRows
)[nTopRow
];
1722 sal_uInt16 nRowHeight
= pTopRow
->GetHeight();
1723 const SvxBrushItem
*pBGBrushItem
= 0;
1725 if( this == pTopTable
|| nTopRow
>0 || nBottomRow
<nRows
)
1727 // An der Line eine Frabe zu setzen macht keinen Sinn, wenn sie
1728 // die auesserste und gleichzeitig einzige Zeile einer Tabelle in
1731 pBGBrushItem
= pTopRow
->GetBGBrush();
1733 if( !pBGBrushItem
&& this != pTopTable
)
1735 // Ein an einer Tabellen in der Tabelle gesetzter Hintergrund
1736 // wird an den Rows gesetzt. Das gilt auch fuer den Hintergrund
1737 // der Zelle, in dem die Tabelle vorkommt.
1738 pBGBrushItem
= GetBGBrush();
1740 pBGBrushItem
= GetInhBGBrush();
1745 if( nTopRow
==nBottomRow
-1 && (nRowHeight
|| pBGBrushItem
) )
1747 SwTableLineFmt
*pFrmFmt
= (SwTableLineFmt
*)pLine
->ClaimFrmFmt();
1748 ResetLineFrmFmtAttrs( pFrmFmt
);
1752 // Tabellenhoehe einstellen. Da es sich um eine
1753 // Mindesthoehe handelt, kann sie genauso wie in
1754 // Netscape berechnet werden, also ohne Beruecksichtigung
1755 // der tatsaechlichen Umrandungsbreite.
1756 nRowHeight
+= GetTopCellSpace( nTopRow
, 1, sal_False
) +
1757 GetBottomCellSpace( nTopRow
, 1, sal_False
);
1759 pFrmFmt
->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE
, 0, nRowHeight
) );
1764 pFrmFmt
->SetFmtAttr( *pBGBrushItem
);
1768 else if( !pLineFrmFmtNoHeight
)
1770 // sonst muessen wir die Hoehe aus dem Attribut entfernen
1771 // und koennen uns das Format merken
1772 pLineFrmFmtNoHeight
= (SwTableLineFmt
*)pLine
->ClaimFrmFmt();
1774 ResetLineFrmFmtAttrs( pLineFrmFmtNoHeight
);
1778 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
1780 sal_uInt16 nStartCol
= nLeftCol
;
1781 while( nStartCol
<nRightCol
)
1783 sal_uInt16 nCol
= nStartCol
;
1784 sal_uInt16 nSplitCol
= nRightCol
;
1785 sal_Bool bSplitted
= sal_False
;
1788 ASSERT( nCol
< nRightCol
, "Zu weit gelaufen" );
1790 HTMLTableCell
*pCell
= GetCell(nTopRow
,nCol
);
1791 const sal_Bool bSplit
= 1 == pCell
->GetColSpan();
1794 if( nCol
== nRightCol
-1 )
1796 ASSERT( bSplit
, "Split-Flag falsch" );
1801 SwTableBox
* pBox
= 0;
1802 HTMLTableCell
*pCell2
= GetCell( nTopRow
, nStartCol
);
1803 if( pCell2
->GetColSpan() == (nCol
+1-nStartCol
) )
1805 // Die HTML-Tabellen-Zellen bilden genau eine Box.
1806 // Dann muss hinter der Box gesplittet werden
1807 nSplitCol
= nCol
+ 1;
1809 long nBoxRowSpan
= pCell2
->GetRowSpan();
1810 if ( !pCell2
->GetContents() || pCell2
->IsCovered() )
1812 if ( pCell2
->IsCovered() )
1813 nBoxRowSpan
= -1 * nBoxRowSpan
;
1815 const SwStartNode
* pPrevStartNd
=
1816 GetPrevBoxStartNode( nTopRow
, nStartCol
);
1817 HTMLTableCnts
*pCnts
= new HTMLTableCnts(
1818 pParser
->InsertTableSection(pPrevStartNd
) );
1819 SwHTMLTableLayoutCnts
*pCntsLayoutInfo
=
1820 pCnts
->CreateLayoutInfo();
1822 pCell2
->SetContents( pCnts
);
1823 SwHTMLTableLayoutCell
*pCurrCell
= pLayoutInfo
->GetCell( nTopRow
, nStartCol
);
1824 pCurrCell
->SetContents( pCntsLayoutInfo
);
1825 if( nBoxRowSpan
< 0 )
1826 pCurrCell
->SetRowSpan( 0 );
1828 // ggf. COLSPAN beachten
1829 for( sal_uInt16 j
=nStartCol
+1; j
<nSplitCol
; j
++ )
1831 GetCell(nTopRow
,j
)->SetContents( pCnts
);
1832 pLayoutInfo
->GetCell( nTopRow
, j
)
1833 ->SetContents( pCntsLayoutInfo
);
1837 pBox
= MakeTableBox( pLine
, pCell2
->GetContents(),
1839 nBottomRow
, nSplitCol
);
1841 if ( 1 != nBoxRowSpan
)
1842 pBox
->setRowSpan( nBoxRowSpan
);
1844 bSplitted
= sal_True
;
1847 ASSERT( pBox
, "Colspan trouble" )
1850 rBoxes
.C40_INSERT( SwTableBox
, pBox
, rBoxes
.Count() );
1854 nStartCol
= nSplitCol
;
1860 SwTableBox
*HTMLTable::MakeTableBox( SwTableLine
*pUpper
,
1861 HTMLTableCnts
*pCnts
,
1862 sal_uInt16 nTopRow
, sal_uInt16 nLeftCol
,
1863 sal_uInt16 nBottomRow
, sal_uInt16 nRightCol
)
1866 sal_uInt16 nColSpan
= nRightCol
- nLeftCol
;
1867 sal_uInt16 nRowSpan
= nBottomRow
- nTopRow
;
1869 if( !pCnts
->Next() )
1871 // nur eine Inhalts-Section
1872 if( pCnts
->GetStartNode() )
1874 // und die ist keine Tabelle
1875 pBox
= NewTableBox( pCnts
->GetStartNode(), pUpper
);
1876 pCnts
->SetTableBox( pBox
);
1880 pCnts
->GetTable()->InheritVertBorders( this, nLeftCol
,
1881 nRightCol
-nLeftCol
);
1882 // und die ist eine Tabelle: dann bauen wir eine neue
1883 // Box und fuegen die Zeilen der Tabelle in die Zeilen
1885 pBox
= new SwTableBox( pBoxFmt
, 0, pUpper
);
1886 sal_uInt16 nAbs
, nRel
;
1887 pLayoutInfo
->GetAvail( nLeftCol
, nColSpan
, nAbs
, nRel
);
1888 sal_uInt16 nLSpace
= pLayoutInfo
->GetLeftCellSpace( nLeftCol
, nColSpan
);
1889 sal_uInt16 nRSpace
= pLayoutInfo
->GetRightCellSpace( nLeftCol
, nColSpan
);
1890 sal_uInt16 nInhSpace
= pLayoutInfo
->GetInhCellSpace( nLeftCol
, nColSpan
);
1891 pCnts
->GetTable()->MakeTable( pBox
, nAbs
, nRel
, nLSpace
, nRSpace
,
1897 // mehrere Inhalts Sections: dann brauchen wir eine Box mit Zeilen
1898 pBox
= new SwTableBox( pBoxFmt
, 0, pUpper
);
1899 SwTableLines
& rLines
= pBox
->GetTabLines();
1900 sal_Bool bFirstPara
= sal_True
;
1904 if( pCnts
->GetStartNode() )
1906 // normale Absaetze werden zu einer Box in einer Zeile
1907 SwTableLine
*pLine
=
1908 new SwTableLine( pLineFrmFmtNoHeight
? pLineFrmFmtNoHeight
1909 : pLineFmt
, 0, pBox
);
1910 if( !pLineFrmFmtNoHeight
)
1912 // Wenn es noch kein Line-Format ohne Hoehe gibt, koennen
1913 // wir uns dieses her als soleches merken
1914 pLineFrmFmtNoHeight
= (SwTableLineFmt
*)pLine
->ClaimFrmFmt();
1916 ResetLineFrmFmtAttrs( pLineFrmFmtNoHeight
);
1919 SwTableBox
* pCntBox
= NewTableBox( pCnts
->GetStartNode(),
1921 pCnts
->SetTableBox( pCntBox
);
1922 FixFrameFmt( pCntBox
, nTopRow
, nLeftCol
, nRowSpan
, nColSpan
,
1923 bFirstPara
, 0==pCnts
->Next() );
1924 pLine
->GetTabBoxes().C40_INSERT( SwTableBox
, pCntBox
,
1925 pLine
->GetTabBoxes().Count() );
1927 rLines
.C40_INSERT( SwTableLine
, pLine
, rLines
.Count() );
1931 pCnts
->GetTable()->InheritVertBorders( this, nLeftCol
,
1932 nRightCol
-nLeftCol
);
1933 // Tabellen werden direkt eingetragen
1934 sal_uInt16 nAbs
, nRel
;
1935 pLayoutInfo
->GetAvail( nLeftCol
, nColSpan
, nAbs
, nRel
);
1936 sal_uInt16 nLSpace
= pLayoutInfo
->GetLeftCellSpace( nLeftCol
,
1938 sal_uInt16 nRSpace
= pLayoutInfo
->GetRightCellSpace( nLeftCol
,
1940 sal_uInt16 nInhSpace
= pLayoutInfo
->GetInhCellSpace( nLeftCol
, nColSpan
);
1941 pCnts
->GetTable()->MakeTable( pBox
, nAbs
, nRel
, nLSpace
,
1942 nRSpace
, nInhSpace
);
1945 pCnts
= pCnts
->Next();
1946 bFirstPara
= sal_False
;
1950 FixFrameFmt( pBox
, nTopRow
, nLeftCol
, nRowSpan
, nColSpan
);
1955 void HTMLTable::InheritBorders( const HTMLTable
*pParent
,
1956 sal_uInt16 nRow
, sal_uInt16 nCol
,
1957 sal_uInt16 nRowSpan
, sal_uInt16
/*nColSpan*/,
1958 sal_Bool bFirstPara
, sal_Bool bLastPara
)
1960 ASSERT( nRows
>0 && nCols
>0 && nCurRow
==nRows
,
1961 "Wurde CloseTable nicht aufgerufen?" );
1963 // Die Child-Tabelle muss einen Rahmen bekommen, wenn die umgebende
1964 // Zelle einen Rand an der betreffenden Seite besitzt.
1965 // Der obere bzw. untere Rand wird nur gesetzt, wenn die Tabelle
1966 // ale erster bzw. letzter Absatz in der Zelle vorkommt. Ansonsten
1967 // Fuer den linken/rechten Rand kann noch nicht entschieden werden,
1968 // ob eine Umrandung der Tabelle noetig/moeglich ist, weil das davon
1969 // abhaengt, ob "Filler"-Zellen eingefuegt werden. Hier werden deshalb
1970 // erstmal nur Informationen gesammelt
1972 if( 0==nRow
&& pParent
->bTopBorder
&& bFirstPara
)
1974 bTopBorder
= sal_True
;
1975 bFillerTopBorder
= sal_True
; // auch Filler bekommt eine Umrandung
1976 aTopBorderLine
= pParent
->aTopBorderLine
;
1978 if( ((*pParent
->pRows
)[nRow
+nRowSpan
-1])->bBottomBorder
&& bLastPara
)
1980 ((*pRows
)[nRows
-1])->bBottomBorder
= sal_True
;
1981 bFillerBottomBorder
= sal_True
; // auch Filler bekommt eine Umrandung
1983 nRow
+nRowSpan
==pParent
->nRows
? pParent
->aBottomBorderLine
1984 : pParent
->aBorderLine
;
1988 // Die Child Tabelle darf keinen oberen oder linken Rahmen bekommen,
1989 // wenn der bereits durch die umgebende Tabelle gesetzt ist.
1990 // Sie darf jedoch immer einen oberen Rand bekommen, wenn die Tabelle
1991 // nicht der erste Absatz in der Zelle ist.
1992 bTopAlwd
= ( !bFirstPara
|| (pParent
->bTopAlwd
&&
1993 (0==nRow
|| !((*pParent
->pRows
)[nRow
-1])->bBottomBorder
)) );
1995 // die Child-Tabelle muss die Farbe der Zelle erben, in der sie
1996 // vorkommt, wenn sie keine eigene besitzt
1997 const SvxBrushItem
*pInhBG
= pParent
->GetCell(nRow
,nCol
)->GetBGBrush();
1998 if( !pInhBG
&& pParent
!= pTopTable
&&
1999 pParent
->GetCell(nRow
,nCol
)->GetRowSpan() == pParent
->nRows
)
2001 // die ganze umgebende Tabelle ist eine Tabelle in der Tabelle
2002 // und besteht nur aus einer Line, die bei der GC (zu Recht)
2003 // wegoptimiert wird. Deshalb muss der Hintergrund der Line in
2004 // diese Tabelle uebernommen werden.
2005 pInhBG
= ((*pParent
->pRows
)[nRow
])->GetBGBrush();
2007 pInhBG
= pParent
->GetBGBrush();
2009 pInhBG
= pParent
->GetInhBGBrush();
2012 pInhBGBrush
= new SvxBrushItem( *pInhBG
);
2015 void HTMLTable::InheritVertBorders( const HTMLTable
*pParent
,
2016 sal_uInt16 nCol
, sal_uInt16 nColSpan
)
2018 sal_uInt16 nInhLeftBorderWidth
= 0;
2019 sal_uInt16 nInhRightBorderWidth
= 0;
2021 if( nCol
+nColSpan
==pParent
->nCols
&& pParent
->bRightBorder
)
2023 bInhRightBorder
= sal_True
; // erstmal nur merken
2024 aInhRightBorderLine
= pParent
->aRightBorderLine
;
2025 nInhRightBorderWidth
=
2026 GetBorderWidth( aInhRightBorderLine
, sal_True
) + MIN_BORDER_DIST
;
2029 if( ((*pParent
->pColumns
)[nCol
])->bLeftBorder
)
2031 bInhLeftBorder
= sal_True
; // erstmal nur merken
2032 aInhLeftBorderLine
= 0==nCol
? pParent
->aLeftBorderLine
2033 : pParent
->aBorderLine
;
2034 nInhLeftBorderWidth
=
2035 GetBorderWidth( aInhLeftBorderLine
, sal_True
) + MIN_BORDER_DIST
;
2038 if( !bInhLeftBorder
&& (bFillerTopBorder
|| bFillerBottomBorder
) )
2039 nInhLeftBorderWidth
= 2 * MIN_BORDER_DIST
;
2040 if( !bInhRightBorder
&& (bFillerTopBorder
|| bFillerBottomBorder
) )
2041 nInhRightBorderWidth
= 2 * MIN_BORDER_DIST
;
2042 pLayoutInfo
->SetInhBorderWidths( nInhLeftBorderWidth
,
2043 nInhRightBorderWidth
);
2045 bRightAlwd
= ( pParent
->bRightAlwd
&&
2046 (nCol
+nColSpan
==pParent
->nCols
||
2047 !((*pParent
->pColumns
)[nCol
+nColSpan
])->bLeftBorder
) );
2050 void HTMLTable::SetBorders()
2053 for( i
=1; i
<nCols
; i
++ )
2054 if( HTML_TR_ALL
==eRules
|| HTML_TR_COLS
==eRules
||
2055 ((HTML_TR_ROWS
==eRules
|| HTML_TR_GROUPS
==eRules
) &&
2056 ((*pColumns
)[i
-1])->IsEndOfGroup()) )
2057 ((*pColumns
)[i
])->bLeftBorder
= sal_True
;
2059 for( i
=0; i
<nRows
-1; i
++ )
2060 if( HTML_TR_ALL
==eRules
|| HTML_TR_ROWS
==eRules
||
2061 ((HTML_TR_COLS
==eRules
|| HTML_TR_GROUPS
==eRules
) &&
2062 ((*pRows
)[i
])->IsEndOfGroup()) )
2063 ((*pRows
)[i
])->bBottomBorder
= sal_True
;
2065 if( bTopAlwd
&& (HTML_TF_ABOVE
==eFrame
|| HTML_TF_HSIDES
==eFrame
||
2066 HTML_TF_BOX
==eFrame
) )
2067 bTopBorder
= sal_True
;
2068 if( HTML_TF_BELOW
==eFrame
|| HTML_TF_HSIDES
==eFrame
||
2069 HTML_TF_BOX
==eFrame
)
2070 ((*pRows
)[nRows
-1])->bBottomBorder
= sal_True
;
2071 if( /*bRightAlwd &&*/ (HTML_TF_RHS
==eFrame
|| HTML_TF_VSIDES
==eFrame
||
2072 HTML_TF_BOX
==eFrame
) )
2073 bRightBorder
= sal_True
;
2074 if( HTML_TF_LHS
==eFrame
|| HTML_TF_VSIDES
==eFrame
|| HTML_TF_BOX
==eFrame
)
2075 ((*pColumns
)[0])->bLeftBorder
= sal_True
;
2077 for( i
=0; i
<nRows
; i
++ )
2079 HTMLTableRow
*pRow
= (*pRows
)[i
];
2080 for( sal_uInt16 j
=0; j
<nCols
; j
++ )
2082 HTMLTableCell
*pCell
= pRow
->GetCell(j
);
2083 if( pCell
->GetContents() )
2085 HTMLTableCnts
*pCnts
= pCell
->GetContents();
2086 sal_Bool bFirstPara
= sal_True
;
2089 HTMLTable
*pTable
= pCnts
->GetTable();
2090 if( pTable
&& !pTable
->BordersSet() )
2092 pTable
->InheritBorders( this, i
, j
,
2093 pCell
->GetRowSpan(),
2094 pCell
->GetColSpan(),
2097 pTable
->SetBorders();
2099 bFirstPara
= sal_False
;
2100 pCnts
= pCnts
->Next();
2106 bBordersSet
= sal_True
;
2109 sal_uInt16
HTMLTable::GetBorderWidth( const SvxBorderLine
& rBLine
,
2110 sal_Bool bWithDistance
) const
2112 sal_uInt16 nBorderWidth
= rBLine
.GetOutWidth() + rBLine
.GetInWidth() +
2113 rBLine
.GetDistance();
2117 nBorderWidth
= nBorderWidth
+ nCellPadding
;
2118 else if( nBorderWidth
)
2119 nBorderWidth
= nBorderWidth
+ MIN_BORDER_DIST
;
2122 return nBorderWidth
;
2125 inline HTMLTableCell
*HTMLTable::GetCell( sal_uInt16 nRow
,
2126 sal_uInt16 nCell
) const
2128 ASSERT( nRow
<pRows
->Count(),
2129 "ungueltiger Zeilen-Index in HTML-Tabelle" );
2130 return ((*pRows
)[nRow
])->GetCell( nCell
);
2135 SvxAdjust
HTMLTable::GetInheritedAdjust() const
2137 SvxAdjust eAdjust
= (nCurCol
<nCols
? ((*pColumns
)[nCurCol
])->GetAdjust()
2139 if( SVX_ADJUST_END
==eAdjust
)
2140 eAdjust
= ((*pRows
)[nCurRow
])->GetAdjust();
2145 sal_Int16
HTMLTable::GetInheritedVertOri() const
2147 // text::VertOrientation::TOP ist der default!
2148 sal_Int16 eVOri
= ((*pRows
)[nCurRow
])->GetVertOri();
2149 if( text::VertOrientation::TOP
==eVOri
&& nCurCol
<nCols
)
2150 eVOri
= ((*pColumns
)[nCurCol
])->GetVertOri();
2151 if( text::VertOrientation::TOP
==eVOri
)
2154 ASSERT( eVertOri
!= text::VertOrientation::TOP
, "text::VertOrientation::TOP ist nicht erlaubt!" );
2158 void HTMLTable::InsertCell( HTMLTableCnts
*pCnts
,
2159 sal_uInt16 nRowSpan
, sal_uInt16 nColSpan
,
2160 sal_uInt16 nCellWidth
, sal_Bool bRelWidth
, sal_uInt16 nCellHeight
,
2161 sal_Int16 eVertOrient
, SvxBrushItem
*pBGBrushItem
,
2162 sal_Bool bHasNumFmt
, sal_uInt32 nNumFmt
,
2163 sal_Bool bHasValue
, double nValue
, sal_Bool bNoWrap
)
2165 if( !nRowSpan
|| (sal_uInt32
)nCurRow
+ nRowSpan
> USHRT_MAX
)
2168 if( !nColSpan
|| (sal_uInt32
)nCurCol
+ nColSpan
> USHRT_MAX
)
2171 sal_uInt16 nColsReq
= nCurCol
+ nColSpan
; // benoetigte Spalten
2172 sal_uInt16 nRowsReq
= nCurRow
+ nRowSpan
; // benoetigte Zeilen
2175 // falls wir mehr Spalten benoetigen als wir zur Zeit haben,
2176 // muessen wir in allen Zeilen noch Zellen hinzufuegen
2177 if( nCols
< nColsReq
)
2179 for( i
=nCols
; i
<nColsReq
; i
++ )
2180 pColumns
->Insert( new HTMLTableColumn
, pColumns
->Count() );
2181 for( i
=0; i
<nRows
; i
++ )
2182 ((*pRows
)[i
])->Expand( nColsReq
, i
<nCurRow
);
2184 ASSERT( pColumns
->Count()==nCols
,
2185 "Anzahl der Spalten nach Expandieren stimmt nicht" );
2187 if( nColsReq
> nFilledCols
)
2188 nFilledCols
= nColsReq
;
2190 // falls wir mehr Zeilen benoetigen als wir zur Zeit haben,
2191 // muessen wir noch neue Zeilen hinzufuegen
2192 if( nRows
< nRowsReq
)
2194 for( i
=nRows
; i
<nRowsReq
; i
++ )
2195 pRows
->Insert( new HTMLTableRow(nCols
), pRows
->Count() );
2197 ASSERT( nRows
==pRows
->Count(), "Zeilenzahl in Insert stimmt nicht" );
2200 // Testen, ob eine Ueberschneidung vorliegt und diese
2201 // gegebenfalls beseitigen
2202 sal_uInt16 nSpanedCols
= 0;
2205 HTMLTableRow
*pCurRow
= (*pRows
)[nCurRow
];
2206 for( i
=nCurCol
; i
<nColsReq
; i
++ )
2208 HTMLTableCell
*pCell
= pCurRow
->GetCell(i
);
2209 if( pCell
->GetContents() )
2211 // Der Inhalt reicht von einer weiter oben stehenden Zelle
2212 // hier herein. Inhalt und Farbe der Zelle sind deshalb in
2213 // jedem Fall noch dort verankert und koennen deshalb
2214 // ueberschrieben werden bzw. von ProtectRowSpan geloescht
2215 // (Inhalt) oder kopiert (Farbe) werden.
2216 nSpanedCols
= i
+ pCell
->GetColSpan();
2217 FixRowSpan( nCurRow
-1, i
, pCell
->GetContents() );
2218 if( pCell
->GetRowSpan() > nRowSpan
)
2219 ProtectRowSpan( nRowsReq
, i
,
2220 pCell
->GetRowSpan()-nRowSpan
);
2223 for( i
=nColsReq
; i
<nSpanedCols
; i
++ )
2225 // Auch diese Inhalte sind in jedem Fall nich in der Zeile
2226 // darueber verankert.
2227 HTMLTableCell
*pCell
= pCurRow
->GetCell(i
);
2228 FixRowSpan( nCurRow
-1, i
, pCell
->GetContents() );
2229 ProtectRowSpan( nCurRow
, i
, pCell
->GetRowSpan() );
2234 for( i
=nColSpan
; i
>0; i
-- )
2236 for( j
=nRowSpan
; j
>0; j
-- )
2238 const bool bCovered
= i
!= nColSpan
|| j
!= nRowSpan
;
2239 GetCell( nRowsReq
-j
, nColsReq
-i
)
2240 ->Set( pCnts
, j
, i
, eVertOrient
, pBGBrushItem
,
2241 bHasNumFmt
, nNumFmt
, bHasValue
, nValue
, bNoWrap
, bCovered
);
2245 Size
aTwipSz( bRelWidth
? 0 : nCellWidth
, nCellHeight
);
2246 if( (aTwipSz
.Width() || aTwipSz
.Height()) && Application::GetDefaultDevice() )
2248 aTwipSz
= Application::GetDefaultDevice()
2249 ->PixelToLogic( aTwipSz
, MapMode( MAP_TWIP
) );
2252 // die Breite nur in die erste Zelle setzen!
2255 sal_uInt16 nTmp
= bRelWidth
? nCellWidth
: (sal_uInt16
)aTwipSz
.Width();
2256 GetCell( nCurRow
, nCurCol
)->SetWidth( nTmp
, bRelWidth
);
2259 // Ausserdem noch die Hoehe merken
2260 if( nCellHeight
&& 1==nRowSpan
)
2262 if( nCellHeight
< MINLAY
)
2263 nCellHeight
= MINLAY
;
2264 ((*pRows
)[nCurRow
])->SetHeight( (sal_uInt16
)aTwipSz
.Height() );
2267 // den Spaltenzaehler hinter die neuen Zellen setzen
2269 if( nSpanedCols
> nCurCol
)
2270 nCurCol
= nSpanedCols
;
2272 // und die naechste freie Zelle suchen
2273 while( nCurCol
<nCols
&& GetCell(nCurRow
,nCurCol
)->IsUsed() )
2277 inline void HTMLTable::CloseSection( sal_Bool bHead
)
2279 // die vorhergende Section beenden, falls es schon eine Zeile gibt
2280 ASSERT( nCurRow
<=nRows
, "ungeultige aktuelle Zeile" );
2281 if( nCurRow
>0 && nCurRow
<=nRows
)
2282 ((*pRows
)[nCurRow
-1])->SetEndOfGroup();
2283 if( bHead
/*&& nCurRow==1*/ )
2284 // bHeadlineRepeat = sal_True;
2285 nHeadlineRepeat
= nCurRow
;
2288 void HTMLTable::OpenRow( SvxAdjust eAdjust
, sal_Int16 eVertOrient
,
2289 SvxBrushItem
*pBGBrushItem
)
2291 sal_uInt16 nRowsReq
= nCurRow
+1; // Anzahl benoetigter Zeilen;
2293 // die naechste Zeile anlegen, falls sie nicht schon da ist
2294 if( nRows
<nRowsReq
)
2296 for( sal_uInt16 i
=nRows
; i
<nRowsReq
; i
++ )
2297 pRows
->Insert( new HTMLTableRow(nCols
), pRows
->Count() );
2299 ASSERT( nRows
==pRows
->Count(),
2300 "Zeilenzahl in OpenRow stimmt nicht" );
2303 HTMLTableRow
*pCurRow
= ((*pRows
)[nCurRow
]);
2304 pCurRow
->SetAdjust( eAdjust
);
2305 pCurRow
->SetVertOri( eVertOrient
);
2307 ((*pRows
)[nCurRow
])->SetBGBrush( pBGBrushItem
);
2309 // den Spaltenzaehler wieder an den Anfang setzen
2312 // und die naechste freie Zelle suchen
2313 while( nCurCol
<nCols
&& GetCell(nCurRow
,nCurCol
)->IsUsed() )
2317 void HTMLTable::CloseRow( sal_Bool bEmpty
)
2319 ASSERT( nCurRow
<nRows
, "aktulle Zeile hinter dem Tabellenende" );
2321 // leere Zellen bekommen einfach einen etwas dickeren unteren Rand!
2325 ((*pRows
)[nCurRow
-1])->IncEmptyRows();
2329 HTMLTableRow
*pRow
= (*pRows
)[nCurRow
];
2331 // den COLSPAN aller leeren Zellen am Zeilenende so anpassen, dass
2332 // eine Zelle daraus wird. Das kann man hier machen (und auf keinen
2333 // Fall frueher), weill jetzt keine Zellen mehr in die Zeile eingefuegt
2338 HTMLTableCell
*pCell
= pRow
->GetCell(--i
);
2339 if( !pCell
->GetContents() )
2341 sal_uInt16 nColSpan
= nCols
-i
;
2343 pCell
->SetColSpan( nColSpan
);
2353 inline void HTMLTable::CloseColGroup( sal_uInt16 nSpan
, sal_uInt16 _nWidth
,
2354 sal_Bool bRelWidth
, SvxAdjust eAdjust
,
2355 sal_Int16 eVertOrient
)
2358 InsertCol( nSpan
, _nWidth
, bRelWidth
, eAdjust
, eVertOrient
);
2360 ASSERT( nCurCol
<=nCols
, "ungueltige Spalte" );
2361 if( nCurCol
>0 && nCurCol
<=nCols
)
2362 ((*pColumns
)[nCurCol
-1])->SetEndOfGroup();
2365 void HTMLTable::InsertCol( sal_uInt16 nSpan
, sal_uInt16 nColWidth
, sal_Bool bRelWidth
,
2366 SvxAdjust eAdjust
, sal_Int16 eVertOrient
)
2368 // --> OD, MIB 2004-11-08 #i35143# - no columns, if rows already exist.
2378 sal_uInt16 nColsReq
= nCurCol
+ nSpan
; // benoetigte Spalten
2380 if( nCols
< nColsReq
)
2382 for( i
=nCols
; i
<nColsReq
; i
++ )
2383 pColumns
->Insert( new HTMLTableColumn
, pColumns
->Count() );
2387 Size
aTwipSz( bRelWidth
? 0 : nColWidth
, 0 );
2388 if( aTwipSz
.Width() && Application::GetDefaultDevice() )
2390 aTwipSz
= Application::GetDefaultDevice()
2391 ->PixelToLogic( aTwipSz
, MapMode( MAP_TWIP
) );
2394 for( i
=nCurCol
; i
<nColsReq
; i
++ )
2396 HTMLTableColumn
*pCol
= (*pColumns
)[i
];
2397 sal_uInt16 nTmp
= bRelWidth
? nColWidth
: (sal_uInt16
)aTwipSz
.Width();
2398 pCol
->SetWidth( nTmp
, bRelWidth
);
2399 pCol
->SetAdjust( eAdjust
);
2400 pCol
->SetVertOri( eVertOrient
);
2403 bColSpec
= sal_True
;
2409 void HTMLTable::CloseTable()
2413 // Die Anzahl der Tabellenzeilen richtet sich nur nach den
2414 // <TR>-Elementen (d.h. nach nCurRow). Durch ROWSPAN aufgespannte
2415 // Zeilen hinter Zeile nCurRow muessen wir deshalb loeschen
2416 // und vor allem aber den ROWSPAN in den darueberliegenden Zeilen
2420 HTMLTableRow
*pPrevRow
= (*pRows
)[nCurRow
-1];
2421 HTMLTableCell
*pCell
;
2422 for( i
=0; i
<nCols
; i
++ )
2423 if( ( pCell
=pPrevRow
->GetCell(i
), pCell
->GetRowSpan() > 1 ) )
2425 FixRowSpan( nCurRow
-1, i
, pCell
->GetContents() );
2426 ProtectRowSpan( nCurRow
, i
, (*pRows
)[nCurRow
]->GetCell(i
)->GetRowSpan() );
2428 for( i
=nRows
-1; i
>=nCurRow
; i
-- )
2429 pRows
->DeleteAndDestroy(i
);
2433 // falls die Tabelle keine Spalte hat, muessen wir eine hinzufuegen
2436 pColumns
->Insert( new HTMLTableColumn
, pColumns
->Count() );
2437 for( i
=0; i
<nRows
; i
++ )
2438 ((*pRows
)[i
])->Expand(1);
2443 // falls die Tabelle keine Zeile hat, muessen wir eine hinzufuegen
2446 pRows
->Insert( new HTMLTableRow(nCols
), pRows
->Count() );
2451 if( nFilledCols
< nCols
)
2453 pColumns
->DeleteAndDestroy( nFilledCols
, nCols
-nFilledCols
);
2454 for( i
=0; i
<nRows
; i
++ )
2455 ((*pRows
)[i
])->Shrink( nFilledCols
);
2456 nCols
= nFilledCols
;
2460 void HTMLTable::_MakeTable( SwTableBox
*pBox
)
2462 SwTableLines
& rLines
= (pBox
? pBox
->GetTabLines()
2463 : ((SwTable
*)pSwTable
)->GetTabLines() );
2465 // jetzt geht's richtig los ...
2467 for( sal_uInt16 i
=0; i
<nRows
; i
++ )
2469 SwTableLine
*pLine
= MakeTableLine( pBox
, i
, 0, i
+1, nCols
);
2471 rLines
.C40_INSERT( SwTableLine
, pLine
, rLines
.Count() );
2475 /* Wie werden Tabellen ausgerichtet?
2477 erste Zeile: ohne Absatz-Einzuege
2478 zweite Zeile: mit Absatz-Einzuegen
2480 ALIGN= LEFT RIGHT CENTER -
2481 -------------------------------------------------------------------------
2482 xxx bei Tabellen mit WIDTH=nn% ist die Prozent-Angabe von Bedeutung:
2483 xxx nn = 100 text::HoriOrientation::FULL text::HoriOrientation::FULL text::HoriOrientation::FULL text::HoriOrientation::FULL %
2484 xxx text::HoriOrientation::NONE text::HoriOrientation::NONE text::HoriOrientation::NONE % text::HoriOrientation::NONE %
2485 xxx nn < 100 Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::LEFT %
2486 xxx Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::NONE %
2488 bei Tabellen mit WIDTH=nn% ist die Prozent-Angabe von Bedeutung:
2489 nn = 100 text::HoriOrientation::LEFT text::HoriOrientation::RIGHT text::HoriOrientation::CENTER % text::HoriOrientation::LEFT %
2490 text::HoriOrientation::LEFT_AND text::HoriOrientation::RIGHT text::HoriOrientation::CENTER % text::HoriOrientation::LEFT_AND %
2491 nn < 100 Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::LEFT %
2492 Rahmen F Rahmen F text::HoriOrientation::CENTER % text::HoriOrientation::NONE %
2494 sonst die berechnete Breite w
2495 w = avail* text::HoriOrientation::LEFT text::HoriOrientation::RIGHT text::HoriOrientation::CENTER text::HoriOrientation::LEFT
2496 HORI_LEDT_AND text::HoriOrientation::RIGHT text::HoriOrientation::CENTER text::HoriOrientation::LEFT_AND
2497 w < avail Rahmen L Rahmen L text::HoriOrientation::CENTER text::HoriOrientation::LEFT
2498 Rahmen L Rahmen L text::HoriOrientation::CENTER text::HoriOrientation::NONE
2500 xxx *) wenn fuer die Tabelle keine Groesse angegeben wurde, wird immer
2501 xxx text::HoriOrientation::FULL genommen
2505 void HTMLTable::MakeTable( SwTableBox
*pBox
, sal_uInt16 nAbsAvail
,
2506 sal_uInt16 nRelAvail
, sal_uInt16 nAbsLeftSpace
,
2507 sal_uInt16 nAbsRightSpace
, sal_uInt16 nInhAbsSpace
)
2509 ASSERT( nRows
>0 && nCols
>0 && nCurRow
==nRows
,
2510 "Wurde CloseTable nicht aufgerufen?" );
2512 ASSERT( (pLayoutInfo
==0) == (this==pTopTable
),
2513 "Top-Tabelle hat keine Layout-Info oder umgekehrt" );
2515 if( this==pTopTable
)
2517 // Umrandung der Tabelle und aller in ihr enthaltenen berechnen
2520 // Schritt 1: Die benoetigten Layout-Strukturen werden angelegt
2521 // (inklusive Tabellen in Tabellen).
2524 // Schritt 2: Die minimalen und maximalen Spaltenbreiten werden
2525 // berechnet (inklusive Tabellen in Tabellen). Da wir noch keine
2526 // Boxen haben, arabeiten wir noch auf den Start-Nodes.
2527 pLayoutInfo
->AutoLayoutPass1();
2530 // Schritt 3: Die tatsaechlichen Spaltenbreiten dieser Tabelle werden
2531 // berechnet (nicht von Tabellen in Tabellen). Dies muss jetzt schon
2532 // sein, damit wir entscheiden koennen ob Filler-Zellen benoetigt werden
2533 // oder nicht (deshalb war auch Pass1 schon noetig).
2534 pLayoutInfo
->AutoLayoutPass2( nAbsAvail
, nRelAvail
, nAbsLeftSpace
,
2535 nAbsRightSpace
, nInhAbsSpace
);
2537 if( this!=pTopTable
)
2539 // die linke und rechte Umrandung der Tabelle kann jetzt entgueltig
2540 // festgelegt werden
2541 if( pLayoutInfo
->GetRelRightFill() == 0 )
2545 // linke Umrandung von auesserer Tabelle uebernehmen
2546 if( bInhRightBorder
)
2548 bRightBorder
= sal_True
;
2549 aRightBorderLine
= aInhRightBorderLine
;
2554 // Umrandung nur setzen, wenn es erlaubt ist
2555 bRightBorder
= bRightAlwd
;
2559 if( pLayoutInfo
->GetRelLeftFill() == 0 &&
2560 !((*pColumns
)[0])->bLeftBorder
&&
2563 // ggf. rechte Umrandung von auesserer Tabelle uebernehmen
2564 ((*pColumns
)[0])->bLeftBorder
= sal_True
;
2565 aLeftBorderLine
= aInhLeftBorderLine
;
2569 // Fuer die Top-Table muss die Ausrichtung gesetzt werden
2570 if( this==pTopTable
)
2575 // Die Tabelle soll in einen Rahmen und ist auch schmaler
2576 // als der verfuegbare Platz und nicht 100% breit.
2577 // Dann kommt sie in einen Rahmen
2578 eHoriOri
= bPrcWidth
? text::HoriOrientation::FULL
: text::HoriOrientation::LEFT
;
2580 else switch( eTableAdjust
)
2582 // Die Tabelle passt entweder auf die Seite, soll aber in keinen
2583 // Rahmen oder sie ist Breiter als die Seite und soll deshalb
2586 case SVX_ADJUST_RIGHT
:
2587 // in rechtsbuendigen Tabellen kann nicht auf den rechten
2588 // Rand Ruecksicht genommen werden
2589 eHoriOri
= text::HoriOrientation::RIGHT
;
2591 case SVX_ADJUST_CENTER
:
2592 // zentrierte Tabellen nehmen keine Ruecksicht auf Raender!
2593 eHoriOri
= text::HoriOrientation::CENTER
;
2595 case SVX_ADJUST_LEFT
:
2597 // linksbuendige Tabellen nehmen nur auf den linken Rand
2599 eHoriOri
= nLeftMargin
? text::HoriOrientation::LEFT_AND_WIDTH
: text::HoriOrientation::LEFT
;
2603 // das Tabellenform holen und anpassen
2604 SwFrmFmt
*pFrmFmt
= pSwTable
->GetFrmFmt();
2605 pFrmFmt
->SetFmtAttr( SwFmtHoriOrient(0,eHoriOri
) );
2606 if( text::HoriOrientation::LEFT_AND_WIDTH
==eHoriOri
)
2608 ASSERT( nLeftMargin
|| nRightMargin
,
2609 "Da gibt's wohl noch Reste von relativen Breiten" );
2611 // The right margin will be ignored anyway.
2612 SvxLRSpaceItem
aLRItem( pSwTable
->GetFrmFmt()->GetLRSpace() );
2613 aLRItem
.SetLeft( nLeftMargin
);
2614 aLRItem
.SetRight( nRightMargin
);
2615 pFrmFmt
->SetFmtAttr( aLRItem
);
2618 if( bPrcWidth
&& text::HoriOrientation::FULL
!=eHoriOri
)
2620 pFrmFmt
->LockModify();
2621 SwFmtFrmSize
aFrmSize( pFrmFmt
->GetFrmSize() );
2622 aFrmSize
.SetWidthPercent( (sal_uInt8
)nWidth
);
2623 pFrmFmt
->SetFmtAttr( aFrmSize
);
2624 pFrmFmt
->UnlockModify();
2628 // die Default Line- und Box-Formate holen
2629 if( this==pTopTable
)
2631 // die erste Box merken und aus der ersten Zeile ausketten
2632 SwTableLine
*pLine1
= (pSwTable
->GetTabLines())[0];
2633 pBox1
= (pLine1
->GetTabBoxes())[0];
2634 pLine1
->GetTabBoxes().Remove(0);
2636 pLineFmt
= (SwTableLineFmt
*)pLine1
->GetFrmFmt();
2637 pBoxFmt
= (SwTableBoxFmt
*)pBox1
->GetFrmFmt();
2641 pLineFmt
= (SwTableLineFmt
*)pTopTable
->pLineFmt
;
2642 pBoxFmt
= (SwTableBoxFmt
*)pTopTable
->pBoxFmt
;
2645 // ggf. muessen fuer Tabellen in Tabellen "Filler"-Zellen eingefuegt
2647 if( this != pTopTable
&&
2648 ( pLayoutInfo
->GetRelLeftFill() > 0 ||
2649 pLayoutInfo
->GetRelRightFill() > 0 ) )
2651 ASSERT( pBox
, "kein TableBox fuer Tabelle in Tabelle" );
2653 SwTableLines
& rLines
= pBox
->GetTabLines();
2655 // dazu brauchen wir erstmal ein eine neue Table-Line in der Box
2656 SwTableLine
*pLine
=
2657 new SwTableLine( pLineFrmFmtNoHeight
? pLineFrmFmtNoHeight
2658 : pLineFmt
, 0, pBox
);
2659 rLines
.C40_INSERT( SwTableLine
, pLine
, rLines
.Count() );
2661 // Sicherstellen, dass wie ein Format ohne Hoehe erwischt haben
2662 if( !pLineFrmFmtNoHeight
)
2664 // sonst muessen wir die Hoehe aus dem Attribut entfernen
2665 // und koennen uns das Format merken
2666 pLineFrmFmtNoHeight
= (SwTableLineFmt
*)pLine
->ClaimFrmFmt();
2668 ResetLineFrmFmtAttrs( pLineFrmFmtNoHeight
);
2671 SwTableBoxes
& rBoxes
= pLine
->GetTabBoxes();
2672 SwTableBox
*pNewBox
;
2674 // ggf. links eine Zelle einfuegen
2675 if( pLayoutInfo
->GetRelLeftFill() > 0 )
2677 // pPrevStNd ist der Vorgaenger-Start-Node der Tabelle. Den
2678 // "Filler"-Node fuegen wir einfach dahinter ein ...
2679 pPrevStNd
= pParser
->InsertTableSection( pPrevStNd
);
2681 pNewBox
= NewTableBox( pPrevStNd
, pLine
);
2682 rBoxes
.C40_INSERT( SwTableBox
, pNewBox
, rBoxes
.Count() );
2683 FixFillerFrameFmt( pNewBox
, sal_False
);
2684 pLayoutInfo
->SetLeftFillerBox( pNewBox
);
2687 // jetzt die Tabelle bearbeiten
2688 pNewBox
= new SwTableBox( pBoxFmt
, 0, pLine
);
2689 rBoxes
.C40_INSERT( SwTableBox
, pNewBox
, rBoxes
.Count() );
2691 SwFrmFmt
*pFrmFmt
= pNewBox
->ClaimFrmFmt();
2692 pFrmFmt
->ResetFmtAttr( RES_BOX
);
2693 pFrmFmt
->ResetFmtAttr( RES_BACKGROUND
);
2694 pFrmFmt
->ResetFmtAttr( RES_VERT_ORIENT
);
2695 pFrmFmt
->ResetFmtAttr( RES_BOXATR_FORMAT
);
2698 _MakeTable( pNewBox
);
2700 // und noch ggf. rechts eine Zelle einfuegen
2701 if( pLayoutInfo
->GetRelRightFill() > 0 )
2703 const SwStartNode
*pStNd
=
2704 GetPrevBoxStartNode( USHRT_MAX
, USHRT_MAX
);
2705 pStNd
= pParser
->InsertTableSection( pStNd
);
2707 pNewBox
= NewTableBox( pStNd
, pLine
);
2708 rBoxes
.C40_INSERT( SwTableBox
, pNewBox
, rBoxes
.Count() );
2710 FixFillerFrameFmt( pNewBox
, sal_True
);
2711 pLayoutInfo
->SetRightFillerBox( pNewBox
);
2719 // zum Schluss fuehren wir noch eine Garbage-Collection fuer die
2720 // Top-Level-Tabelle durch
2721 if( this==pTopTable
)
2723 if( 1==nRows
&& nHeight
&& 1==pSwTable
->GetTabLines().Count() )
2725 // Hoehe einer einzeiligen Tabelle als Mindesthoehe der
2726 // Zeile setzen. (War mal fixe Hoehe, aber das gibt manchmal
2727 // Probleme (fix #34972#) und ist auch nicht Netscape 4.0
2729 nHeight
= pParser
->ToTwips( nHeight
);
2730 if( nHeight
< MINLAY
)
2733 (pSwTable
->GetTabLines())[0]->ClaimFrmFmt();
2734 (pSwTable
->GetTabLines())[0]->GetFrmFmt()
2735 ->SetFmtAttr( SwFmtFrmSize( ATT_MIN_SIZE
, 0, nHeight
) );
2739 pSwTable
->GetFrmFmt()->SetFmtAttr( *GetBGBrush() );
2741 ((SwTable
*)pSwTable
)->SetRowsToRepeat( static_cast< USHORT
>(nHeadlineRepeat
) );
2742 ((SwTable
*)pSwTable
)->GCLines();
2744 sal_Bool bIsInFlyFrame
= pContext
&& pContext
->GetFrmFmt();
2745 if( bIsInFlyFrame
&& !nWidth
)
2747 SvxAdjust eTblAdjust
= GetTableAdjust(sal_False
);
2748 if( eTblAdjust
!= SVX_ADJUST_LEFT
&&
2749 eTblAdjust
!= SVX_ADJUST_RIGHT
)
2751 // Wenn eine Tabelle ohne Breitenangabe nicht links oder
2752 // rechts umflossen werden soll, dann stacken wir sie
2753 // in einem Rahmen mit 100%-Breite, damit ihre Groesse
2754 // angepasst wird. Der Rahmen darf nicht angepasst werden.
2755 ASSERT( HasToFly(), "Warum ist die Tabelle in einem Rahmen?" );
2756 sal_uInt32 nMin
= pLayoutInfo
->GetMin();
2757 if( nMin
> USHRT_MAX
)
2759 SwFmtFrmSize
aFlyFrmSize( ATT_VAR_SIZE
, (SwTwips
)nMin
, MINLAY
);
2760 aFlyFrmSize
.SetWidthPercent( 100 );
2761 pContext
->GetFrmFmt()->SetFmtAttr( aFlyFrmSize
);
2762 bIsInFlyFrame
= sal_False
;
2766 // Links und rechts ausgerichtete Tabellen ohne Breite
2767 // duerfen leider nicht in der Breite angepasst werden, denn
2768 // sie wuerden nur schrumpfen aber nie wachsen.
2769 pLayoutInfo
->SetMustNotRecalc( sal_True
);
2770 if( pContext
->GetFrmFmt()->GetAnchor().GetCntntAnchor()
2771 ->nNode
.GetNode().FindTableNode() )
2773 sal_uInt32 nMax
= pLayoutInfo
->GetMax();
2774 if( nMax
> USHRT_MAX
)
2776 SwFmtFrmSize
aFlyFrmSize( ATT_VAR_SIZE
, (SwTwips
)nMax
, MINLAY
);
2777 pContext
->GetFrmFmt()->SetFmtAttr( aFlyFrmSize
);
2778 bIsInFlyFrame
= sal_False
;
2782 pLayoutInfo
->SetMustNotResize( sal_True
);
2786 pLayoutInfo
->SetMayBeInFlyFrame( bIsInFlyFrame
);
2788 // Nur Tabellen mit relativer Breite oder ohne Breite muessen
2789 // angepasst werden.
2790 pLayoutInfo
->SetMustResize( bPrcWidth
|| !nWidth
);
2792 pLayoutInfo
->SetWidths();
2794 ((SwTable
*)pSwTable
)->SetHTMLTableLayout( pLayoutInfo
);
2796 if( pResizeDrawObjs
)
2798 sal_uInt16 nCount
= pResizeDrawObjs
->Count();
2799 for( sal_uInt16 i
=0; i
<nCount
; i
++ )
2801 SdrObject
*pObj
= (*pResizeDrawObjs
)[i
];
2802 sal_uInt16 nRow
= (*pDrawObjPrcWidths
)[3*i
];
2803 sal_uInt16 nCol
= (*pDrawObjPrcWidths
)[3*i
+1];
2804 sal_uInt8 nPrcWidth
= (sal_uInt8
)(*pDrawObjPrcWidths
)[3*i
+2];
2806 SwHTMLTableLayoutCell
*pLayoutCell
=
2807 pLayoutInfo
->GetCell( nRow
, nCol
);
2808 sal_uInt16 nColSpan
= pLayoutCell
->GetColSpan();
2810 sal_uInt16 nWidth2
, nDummy
;
2811 pLayoutInfo
->GetAvail( nCol
, nColSpan
, nWidth2
, nDummy
);
2812 nWidth2
= nWidth2
- pLayoutInfo
->GetLeftCellSpace( nCol
, nColSpan
);
2813 nWidth2
= nWidth2
- pLayoutInfo
->GetRightCellSpace( nCol
, nColSpan
);
2814 nWidth2
= static_cast< sal_uInt16
>(((long)nWidth
* nPrcWidth
) / 100);
2816 pParser
->ResizeDrawObject( pObj
, nWidth2
);
2822 void HTMLTable::SetTable( const SwStartNode
*pStNd
, _HTMLTableContext
*pCntxt
,
2823 sal_uInt16 nLeft
, sal_uInt16 nRight
,
2824 const SwTable
*pSwTab
, sal_Bool bFrcFrame
)
2830 nLeftMargin
= nLeft
;
2831 nRightMargin
= nRight
;
2833 bForceFrame
= bFrcFrame
;
2836 void HTMLTable::RegisterDrawObject( SdrObject
*pObj
, sal_uInt8 nPrcWidth
)
2838 if( !pResizeDrawObjs
)
2839 pResizeDrawObjs
= new SdrObjects
;
2840 pResizeDrawObjs
->C40_INSERT( SdrObject
, pObj
, pResizeDrawObjs
->Count() );
2842 if( !pDrawObjPrcWidths
)
2843 pDrawObjPrcWidths
= new SvUShorts
;
2844 pDrawObjPrcWidths
->Insert( nCurRow
, pDrawObjPrcWidths
->Count() );
2845 pDrawObjPrcWidths
->Insert( nCurCol
, pDrawObjPrcWidths
->Count() );
2846 pDrawObjPrcWidths
->Insert( (sal_uInt16
)nPrcWidth
, pDrawObjPrcWidths
->Count() );
2849 void HTMLTable::MakeParentContents()
2851 if( !GetContext() && !HasParentSection() )
2854 pParser
->InsertTableContents( GetIsParentHeader() ) );
2856 SetHasParentSection( sal_True
);
2860 _HTMLTableContext::~_HTMLTableContext()
2865 void _HTMLTableContext::SavePREListingXMP( SwHTMLParser
& rParser
)
2867 bRestartPRE
= rParser
.IsReadPRE();
2868 bRestartXMP
= rParser
.IsReadXMP();
2869 bRestartListing
= rParser
.IsReadListing();
2870 rParser
.FinishPREListingXMP();
2873 void _HTMLTableContext::RestorePREListingXMP( SwHTMLParser
& rParser
)
2875 rParser
.FinishPREListingXMP();
2883 if( bRestartListing
)
2884 rParser
.StartListing();
2889 const SwStartNode
*SwHTMLParser::InsertTableSection
2890 ( const SwStartNode
*pPrevStNd
)
2892 ASSERT( pPrevStNd
, "Start-Node ist NULL" );
2894 pCSS1Parser
->SetTDTagStyles();
2895 SwTxtFmtColl
*pColl
= pCSS1Parser
->GetTxtCollFromPool( RES_POOLCOLL_TABLE
);
2897 const SwStartNode
*pStNd
;
2898 if( pTable
&& pTable
->bFirstCell
)
2900 SwNode
*pNd
= pDoc
->GetNodes()[pPam
->GetPoint()->nNode
];
2901 pNd
->GetTxtNode()->ChgFmtColl( pColl
);
2902 pStNd
= pNd
->FindTableBoxStartNode();
2903 pTable
->bFirstCell
= sal_False
;
2908 if( pPrevStNd
->IsTableNode() )
2911 pNd
= pPrevStNd
->EndOfSectionNode();
2912 SwNodeIndex
nIdx( *pNd
, 1 );
2913 pStNd
= pDoc
->GetNodes().MakeTextSection( nIdx
, SwTableBoxStartNode
,
2915 pTable
->IncBoxCount();
2918 SwCntntNode
*pCNd
= pDoc
->GetNodes()[pStNd
->GetIndex()+1] ->GetCntntNode();
2919 SvxFontHeightItem
aFontHeight( 40, 100, RES_CHRATR_FONTSIZE
);
2920 pCNd
->SetAttr( aFontHeight
);
2921 aFontHeight
.SetWhich( RES_CHRATR_CJK_FONTSIZE
);
2922 pCNd
->SetAttr( aFontHeight
);
2923 aFontHeight
.SetWhich( RES_CHRATR_CTL_FONTSIZE
);
2924 pCNd
->SetAttr( aFontHeight
);
2929 const SwStartNode
*SwHTMLParser::InsertTableSection( sal_uInt16 nPoolId
)
2933 case RES_POOLCOLL_TABLE_HDLN
:
2934 pCSS1Parser
->SetTHTagStyles();
2936 case RES_POOLCOLL_TABLE
:
2937 pCSS1Parser
->SetTDTagStyles();
2941 SwTxtFmtColl
*pColl
= pCSS1Parser
->GetTxtCollFromPool( nPoolId
);
2943 SwNode
*pNd
= pDoc
->GetNodes()[pPam
->GetPoint()->nNode
];
2944 const SwStartNode
*pStNd
;
2945 if( pTable
&& pTable
->bFirstCell
)
2947 pNd
->GetTxtNode()->ChgFmtColl( pColl
);
2948 pTable
->bFirstCell
= sal_False
;
2949 pStNd
= pNd
->FindTableBoxStartNode();
2953 SwTableNode
*pTblNd
= pNd
->FindTableNode();
2954 if( pTblNd
->GetTable().GetHTMLTableLayout() )
2955 { // if there is already a HTMTableLayout, this table is already finished
2956 // and we have to look for the right table in the environment
2957 SwTableNode
*pOutTbl
= pTblNd
;
2960 pOutTbl
= pOutTbl
->StartOfSectionNode()->FindTableNode();
2961 } while( pOutTbl
&& pTblNd
->GetTable().GetHTMLTableLayout() );
2963 SwNodeIndex
aIdx( *pTblNd
->EndOfSectionNode() );
2964 pStNd
= pDoc
->GetNodes().MakeTextSection( aIdx
, SwTableBoxStartNode
,
2967 pPam
->GetPoint()->nNode
= pStNd
->GetIndex() + 1;
2968 SwTxtNode
*pTxtNd
= pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
2969 pPam
->GetPoint()->nContent
.Assign( pTxtNd
, 0 );
2970 pTable
->IncBoxCount();
2976 SwStartNode
*SwHTMLParser::InsertTempTableCaptionSection()
2978 SwTxtFmtColl
*pColl
= pCSS1Parser
->GetTxtCollFromPool( RES_POOLCOLL_TEXT
);
2979 SwNodeIndex
& rIdx
= pPam
->GetPoint()->nNode
;
2980 rIdx
= pDoc
->GetNodes().GetEndOfExtras();
2981 SwStartNode
*pStNd
= pDoc
->GetNodes().MakeTextSection( rIdx
,
2982 SwNormalStartNode
, pColl
);
2984 rIdx
= pStNd
->GetIndex() + 1;
2985 pPam
->GetPoint()->nContent
.Assign( rIdx
.GetNode().GetTxtNode(), 0 );
2991 xub_StrLen
SwHTMLParser::StripTrailingLF()
2993 xub_StrLen nStripped
= 0;
2995 xub_StrLen nLen
= pPam
->GetPoint()->nContent
.GetIndex();
2998 SwTxtNode
* pTxtNd
= pPam
->GetPoint()->nNode
.GetNode().GetTxtNode();
2999 // vorsicht, wenn Kommentare nicht uebrlesen werden!!!
3002 xub_StrLen nPos
= nLen
;
3003 xub_StrLen nLFCount
= 0;
3004 while( nPos
&& '\x0a' == (pTxtNd
->GetTxt()).GetChar(--nPos
) )
3009 // MIB 6.6.97: Warum sollte man bei leeren Absaetzen nur ein LF loeschen?
3010 // Das stimmt doch irgendwi nicht ...
3011 // if( nLFCount == nLen )
3013 // // nur Lfs, dann nur ein LF loeschen
3016 // else if( nLFCount > 2 )
3019 // Bei Netscape entspricht ein Absatz-Ende zwei LFs
3020 // (mit einem kommt man in die naechste Zeile, das
3021 // zweite erzeugt eine Leerzeile) Diesen Abstand
3022 // erreichen wie aber schon mit dem unteren
3023 // Absatz-Abstand. Wenn nach den <BR> ein neuer
3024 // Absatz aufgemacht wird, wird das Maximum des Abstands,
3025 // der sich aus den BR und dem P ergibt genommen.
3026 // Deshalb muessen wir 2 bzw. alle bei weniger
3027 // als zweien loeschen
3031 nPos
= nLen
- nLFCount
;
3032 SwIndex
nIdx( pTxtNd
, nPos
);
3033 pTxtNd
->EraseText( nIdx
, nLFCount
);
3034 nStripped
= nLFCount
;
3042 SvxBrushItem
* SwHTMLParser::CreateBrushItem( const Color
*pColor
,
3043 const String
& rImageURL
,
3044 const String
& rStyle
,
3046 const String
& rClass
)
3048 SvxBrushItem
*pBrushItem
= 0;
3050 if( rStyle
.Len() || rId
.Len() || rClass
.Len() )
3052 SfxItemSet
aItemSet( pDoc
->GetAttrPool(), RES_BACKGROUND
,
3054 SvxCSS1PropertyInfo aPropInfo
;
3058 String
aClass( rClass
);
3059 SwCSS1Parser::GetScriptFromClass( aClass
);
3060 SvxCSS1MapEntry
*pClass
= pCSS1Parser
->GetClass( aClass
);
3062 aItemSet
.Put( pClass
->GetItemSet() );
3067 SvxCSS1MapEntry
*pId
= pCSS1Parser
->GetId( rId
);
3069 aItemSet
.Put( pId
->GetItemSet() );
3072 pCSS1Parser
->ParseStyleOption( rStyle
, aItemSet
, aPropInfo
);
3073 const SfxPoolItem
*pItem
= 0;
3074 if( SFX_ITEM_SET
== aItemSet
.GetItemState( RES_BACKGROUND
, sal_False
,
3077 pBrushItem
= new SvxBrushItem( *((const SvxBrushItem
*)pItem
) );
3081 if( !pBrushItem
&& (pColor
|| rImageURL
.Len()) )
3083 pBrushItem
= new SvxBrushItem(RES_BACKGROUND
);
3086 pBrushItem
->SetColor(*pColor
);
3088 if( rImageURL
.Len() )
3090 pBrushItem
->SetGraphicLink( URIHelper::SmartRel2Abs( INetURLObject(sBaseURL
), rImageURL
, Link(), false) );
3091 pBrushItem
->SetGraphicPos( GPOS_TILED
);
3100 class _SectionSaveStruct
: public SwPendingStackData
3102 sal_uInt16 nBaseFontStMinSave
, nFontStMinSave
, nFontStHeadStartSave
;
3103 sal_uInt16 nDefListDeepSave
, nContextStMinSave
, nContextStAttrMinSave
;
3109 _SectionSaveStruct( SwHTMLParser
& rParser
);
3110 virtual ~_SectionSaveStruct();
3112 sal_uInt16
GetContextStAttrMin() const { return nContextStAttrMinSave
; }
3114 void Restore( SwHTMLParser
& rParser
);
3117 _SectionSaveStruct::_SectionSaveStruct( SwHTMLParser
& rParser
) :
3118 nBaseFontStMinSave(0), nFontStMinSave(0), nFontStHeadStartSave(0),
3119 nDefListDeepSave(0), nContextStMinSave(0), nContextStAttrMinSave(0),
3122 // Font-Stacks einfrieren
3123 nBaseFontStMinSave
= rParser
.nBaseFontStMin
;
3124 rParser
.nBaseFontStMin
= rParser
.aBaseFontStack
.Count();
3126 nFontStMinSave
= rParser
.nFontStMin
;
3127 nFontStHeadStartSave
= rParser
.nFontStHeadStart
;
3128 rParser
.nFontStMin
= rParser
.aFontStack
.Count();
3130 // Kontext-Stack einfrieren
3131 nContextStMinSave
= rParser
.nContextStMin
;
3132 nContextStAttrMinSave
= rParser
.nContextStAttrMin
;
3133 rParser
.nContextStMin
= rParser
.aContexts
.Count();
3134 rParser
.nContextStAttrMin
= rParser
.nContextStMin
;
3136 // und noch ein par Zaehler retten
3137 nDefListDeepSave
= rParser
.nDefListDeep
;
3138 rParser
.nDefListDeep
= 0;
3141 _SectionSaveStruct::~_SectionSaveStruct()
3144 void _SectionSaveStruct::Restore( SwHTMLParser
& rParser
)
3146 // Font-Stacks wieder auftauen
3147 sal_uInt16 nMin
= rParser
.nBaseFontStMin
;
3148 if( rParser
.aBaseFontStack
.Count() > nMin
)
3149 rParser
.aBaseFontStack
.Remove( nMin
,
3150 rParser
.aBaseFontStack
.Count() - nMin
);
3151 rParser
.nBaseFontStMin
= nBaseFontStMinSave
;
3154 nMin
= rParser
.nFontStMin
;
3155 if( rParser
.aFontStack
.Count() > nMin
)
3156 rParser
.aFontStack
.Remove( nMin
,
3157 rParser
.aFontStack
.Count() - nMin
);
3158 rParser
.nFontStMin
= nFontStMinSave
;
3159 rParser
.nFontStHeadStart
= nFontStHeadStartSave
;
3161 // Der Kontext-Stack muss schon aufgeraeumt sein!
3162 ASSERT( rParser
.aContexts
.Count() == rParser
.nContextStMin
&&
3163 rParser
.aContexts
.Count() == rParser
.nContextStAttrMin
,
3164 "Der Kontext-Stack wurde nicht aufgeraeumt" );
3165 rParser
.nContextStMin
= nContextStMinSave
;
3166 rParser
.nContextStAttrMin
= nContextStAttrMinSave
;
3168 // und noch ein par Zaehler rekonstruieren
3169 rParser
.nDefListDeep
= nDefListDeepSave
;
3171 // und ein par Flags zuruecksetzen
3172 rParser
.bNoParSpace
= sal_False
;
3173 rParser
.nOpenParaToken
= 0;
3175 if( rParser
.aParaAttrs
.Count() )
3176 rParser
.aParaAttrs
.Remove( 0, rParser
.aParaAttrs
.Count() );
3181 class _CellSaveStruct
: public _SectionSaveStruct
3183 String aStyle
, aId
, aClass
, aLang
, aDir
;
3187 HTMLTableCnts
* pCnts
; // Liste aller Inhalte
3188 HTMLTableCnts
* pCurrCnts
; // der aktuelle Inhalt oder 0
3189 SwNodeIndex
*pNoBreakEndParaIdx
;// Absatz-Index eines </NOBR>
3195 sal_uInt16 nRowSpan
, nColSpan
, nWidth
, nHeight
;
3196 xub_StrLen nNoBreakEndCntntPos
; // Zeichen-Index eines </NOBR>
3202 sal_Bool bPrcWidth
: 1;
3203 sal_Bool bHasNumFmt
: 1;
3204 sal_Bool bHasValue
: 1;
3205 sal_Bool bBGColor
: 1;
3206 sal_Bool bNoWrap
: 1; // NOWRAP-Option
3207 sal_Bool bNoBreak
: 1; // NOBREAK-Tag
3211 _CellSaveStruct( SwHTMLParser
& rParser
, HTMLTable
*pCurTable
, sal_Bool bHd
,
3212 sal_Bool bReadOpt
);
3214 virtual ~_CellSaveStruct();
3216 void AddContents( HTMLTableCnts
*pNewCnts
);
3217 HTMLTableCnts
*GetFirstContents() { return pCnts
; }
3219 void ClearIsInSection() { pCurrCnts
= 0; }
3220 sal_Bool
IsInSection() const { return pCurrCnts
!=0; }
3221 HTMLTableCnts
*GetCurrContents() const { return pCurrCnts
; }
3223 void InsertCell( SwHTMLParser
& rParser
, HTMLTable
*pCurTable
);
3225 sal_Bool
IsHeaderCell() const { return bHead
; }
3227 void StartNoBreak( const SwPosition
& rPos
);
3228 void EndNoBreak( const SwPosition
& rPos
);
3229 void CheckNoBreak( const SwPosition
& rPos
, SwDoc
*pDoc
);
3233 _CellSaveStruct::_CellSaveStruct( SwHTMLParser
& rParser
, HTMLTable
*pCurTable
,
3234 sal_Bool bHd
, sal_Bool bReadOpt
) :
3235 _SectionSaveStruct( rParser
),
3238 pNoBreakEndParaIdx( 0 ),
3245 nNoBreakEndCntntPos( 0 ),
3246 eAdjust( pCurTable
->GetInheritedAdjust() ),
3247 eVertOri( pCurTable
->GetInheritedVertOri() ),
3249 bPrcWidth( sal_False
),
3250 bHasNumFmt( sal_False
),
3251 bHasValue( sal_False
),
3252 bBGColor( sal_False
),
3253 bNoWrap( sal_False
),
3254 bNoBreak( sal_False
)
3256 String aNumFmt
, aValue
;
3260 const HTMLOptions
*pOptions
= rParser
.GetOptions();
3261 for( sal_uInt16 i
= pOptions
->Count(); i
; )
3263 const HTMLOption
*pOption
= (*pOptions
)[--i
];
3264 switch( pOption
->GetToken() )
3267 aId
= pOption
->GetString();
3269 case HTML_O_COLSPAN
:
3270 nColSpan
= (sal_uInt16
)pOption
->GetNumber();
3272 case HTML_O_ROWSPAN
:
3273 nRowSpan
= (sal_uInt16
)pOption
->GetNumber();
3276 eAdjust
= (SvxAdjust
)pOption
->GetEnum(
3277 aHTMLPAlignTable
, static_cast< sal_uInt16
>(eAdjust
) );
3280 eVertOri
= pOption
->GetEnum(
3281 aHTMLTblVAlignTable
, eVertOri
);
3284 nWidth
= (sal_uInt16
)pOption
->GetNumber(); // nur fuer Netscape
3285 bPrcWidth
= (pOption
->GetString().Search('%') != STRING_NOTFOUND
);
3286 if( bPrcWidth
&& nWidth
>100 )
3290 nHeight
= (sal_uInt16
)pOption
->GetNumber(); // nur fuer Netscape
3291 if( pOption
->GetString().Search('%') != STRING_NOTFOUND
)
3292 nHeight
= 0; // keine %-Angaben beruecksichtigen
3294 case HTML_O_BGCOLOR
:
3295 // Leere BGCOLOR bei <TABLE>, <TR> und <TD>/<TH> wie Netscape
3296 // ignorieren, bei allen anderen Tags *wirklich* nicht.
3297 if( pOption
->GetString().Len() )
3299 pOption
->GetColor( aBGColor
);
3300 bBGColor
= sal_True
;
3303 case HTML_O_BACKGROUND
:
3304 aBGImage
= pOption
->GetString();
3307 aStyle
= pOption
->GetString();
3310 aClass
= pOption
->GetString();
3313 aLang
= pOption
->GetString();
3316 aDir
= pOption
->GetString();
3319 aNumFmt
= pOption
->GetString();
3320 bHasNumFmt
= sal_True
;
3323 bHasValue
= sal_True
;
3324 aValue
= pOption
->GetString();
3333 rParser
.InsertBookmark( aId
);
3339 nValue
= rParser
.GetTableDataOptionsValNum(
3340 nNumFmt
, eLang
, aValue
, aNumFmt
,
3341 *rParser
.pDoc
->GetNumberFormatter() );
3344 // einen neuen Kontext anlegen, aber das drawing::Alignment-Attribut
3345 // nicht dort verankern, weil es noch ger keine Section gibt, in der
3347 sal_uInt16 nToken
, nColl
;
3350 nToken
= HTML_TABLEHEADER_ON
;
3351 nColl
= RES_POOLCOLL_TABLE_HDLN
;
3355 nToken
= HTML_TABLEDATA_ON
;
3356 nColl
= RES_POOLCOLL_TABLE
;
3358 _HTMLAttrContext
*pCntxt
= new _HTMLAttrContext( nToken
, nColl
, aEmptyStr
, sal_True
);
3359 if( SVX_ADJUST_END
!= eAdjust
)
3360 rParser
.InsertAttr( &rParser
.aAttrTab
.pAdjust
, SvxAdjustItem(eAdjust
, RES_PARATR_ADJUST
),
3363 if( rParser
.HasStyleOptions( aStyle
, aId
, aClass
, &aLang
, &aDir
) )
3365 SfxItemSet
aItemSet( rParser
.pDoc
->GetAttrPool(),
3366 rParser
.pCSS1Parser
->GetWhichMap() );
3367 SvxCSS1PropertyInfo aPropInfo
;
3369 if( rParser
.ParseStyleOptions( aStyle
, aId
, aClass
, aItemSet
,
3370 aPropInfo
, &aLang
, &aDir
) )
3371 rParser
.InsertAttrs( aItemSet
, aPropInfo
, pCntxt
);
3374 rParser
.SplitPREListingXMP( pCntxt
);
3376 rParser
.PushContext( pCntxt
);
3379 _CellSaveStruct::~_CellSaveStruct()
3381 delete pNoBreakEndParaIdx
;
3384 void _CellSaveStruct::AddContents( HTMLTableCnts
*pNewCnts
)
3387 pCnts
->Add( pNewCnts
);
3391 pCurrCnts
= pNewCnts
;
3394 void _CellSaveStruct::InsertCell( SwHTMLParser
& rParser
,
3395 HTMLTable
*pCurTable
)
3398 // Die Attribute muessen schon beim Auefrauemen des Kontext-Stacks
3399 // entfernt worden sein, sonst ist etwas schiefgelaufen. Das
3400 // Checken wir mal eben ...
3401 // MIB 8.1.98: Wenn ausserhalb einer Zelle Attribute geoeffnet
3402 // wurden stehen diese noch in der Attribut-Tabelle und werden erst
3403 // ganz zum Schluss durch die CleanContext-Aufrufe in BuildTable
3404 // geloescht. Damit es in diesem Fall keine Asserts gibt findet dann
3405 // keine Ueberpruefung statt. Erkennen tut man diesen Fall an
3406 // nContextStAttrMin: Der gemerkte Wert nContextStAttrMinSave ist der
3407 // Wert, den nContextStAttrMin beim Start der Tabelle hatte. Und
3408 // der aktuelle Wert von nContextStAttrMin entspricht der Anzahl der
3409 // Kontexte, die beim Start der Zelle vorgefunden wurden. Sind beide
3410 // Werte unterschiedlich, wurden ausserhalb der Zelle Kontexte
3411 // angelegt und wir ueberpruefen nichts.
3413 if( rParser
.nContextStAttrMin
== GetContextStAttrMin() )
3415 _HTMLAttr
** pTbl
= (_HTMLAttr
**)&rParser
.aAttrTab
;
3417 for( sal_uInt16 nCnt
= sizeof( _HTMLAttrTable
) / sizeof( _HTMLAttr
* );
3420 ASSERT( !*pTbl
, "Die Attribut-Tabelle ist nicht leer" );
3425 // jetzt muessen wir noch die Zelle an der aktuellen Position einfuegen
3426 SvxBrushItem
*pBrushItem
=
3427 rParser
.CreateBrushItem( bBGColor
? &aBGColor
: 0, aBGImage
,
3428 aStyle
, aId
, aClass
);
3429 pCurTable
->InsertCell( pCnts
, nRowSpan
, nColSpan
, nWidth
,
3430 bPrcWidth
, nHeight
, eVertOri
, pBrushItem
,
3431 bHasNumFmt
, nNumFmt
, bHasValue
, nValue
,
3436 void _CellSaveStruct::StartNoBreak( const SwPosition
& rPos
)
3439 (!rPos
.nContent
.GetIndex() && pCurrCnts
==pCnts
&&
3440 pCnts
->GetStartNode() &&
3441 pCnts
->GetStartNode()->GetIndex() + 1 ==
3442 rPos
.nNode
.GetIndex()) )
3444 bNoBreak
= sal_True
;
3448 void _CellSaveStruct::EndNoBreak( const SwPosition
& rPos
)
3452 delete pNoBreakEndParaIdx
;
3453 pNoBreakEndParaIdx
= new SwNodeIndex( rPos
.nNode
);
3454 nNoBreakEndCntntPos
= rPos
.nContent
.GetIndex();
3455 bNoBreak
= sal_False
;
3459 void _CellSaveStruct::CheckNoBreak( const SwPosition
& rPos
, SwDoc
*pDoc
)
3461 if( pCnts
&& pCurrCnts
==pCnts
)
3465 // <NOBR> wurde nicht beendet
3466 pCnts
->SetNoBreak();
3468 else if( pNoBreakEndParaIdx
&&
3469 pNoBreakEndParaIdx
->GetIndex() == rPos
.nNode
.GetIndex() )
3471 if( nNoBreakEndCntntPos
== rPos
.nContent
.GetIndex() )
3473 // <NOBR> wurde unmittelbar vor dem Zellen-Ende beendet
3474 pCnts
->SetNoBreak();
3476 else if( nNoBreakEndCntntPos
+ 1 == rPos
.nContent
.GetIndex() )
3478 const SwTxtNode
*pTxtNd
=
3479 pDoc
->GetNodes()[rPos
.nNode
]->GetTxtNode();
3483 pTxtNd
->GetTxt().GetChar(nNoBreakEndCntntPos
);
3484 if( ' '==cLast
|| '\x0a'==cLast
)
3486 // Zwischem dem </NOBR> und dem Zellen-Ende gibt es nur
3487 // ein Blank oder einen Zeilenumbruch.
3488 pCnts
->SetNoBreak();
3498 HTMLTableCnts
*SwHTMLParser::InsertTableContents(
3501 // eine neue Section anlegen, der PaM steht dann darin
3502 const SwStartNode
*pStNd
=
3503 InsertTableSection( static_cast< USHORT
>(bHead
? RES_POOLCOLL_TABLE_HDLN
3504 : RES_POOLCOLL_TABLE
) );
3506 if( GetNumInfo().GetNumRule() )
3508 // 1. Absatz auf nicht numeriert setzen
3509 BYTE nLvl
= GetNumInfo().GetLevel();
3510 // --> OD 2008-04-02 #refactorlists#
3511 // SetNoNum(&nLvl, TRUE);
3512 // SetNodeNum( nLvl);
3513 SetNodeNum( nLvl
, false );
3516 // Attributierungs-Anfang neu setzen
3517 const SwNodeIndex
& rSttPara
= pPam
->GetPoint()->nNode
;
3518 xub_StrLen nSttCnt
= pPam
->GetPoint()->nContent
.GetIndex();
3520 _HTMLAttr
** pTbl
= (_HTMLAttr
**)&aAttrTab
;
3521 for( sal_uInt16 nCnt
= sizeof( _HTMLAttrTable
) / sizeof( _HTMLAttr
* );
3525 _HTMLAttr
*pAttr
= *pTbl
;
3528 ASSERT( !pAttr
->GetPrev(), "Attribut hat Previous-Liste" );
3529 pAttr
->nSttPara
= rSttPara
;
3530 pAttr
->nEndPara
= rSttPara
;
3531 pAttr
->nSttCntnt
= nSttCnt
;
3532 pAttr
->nEndCntnt
= nSttCnt
;
3534 pAttr
= pAttr
->GetNext();
3538 return new HTMLTableCnts( pStNd
);
3541 sal_uInt16
SwHTMLParser::IncGrfsThatResizeTable()
3543 return pTable
? pTable
->IncGrfsThatResize() : 0;
3546 void SwHTMLParser::RegisterDrawObjectToTable( HTMLTable
*pCurTable
,
3547 SdrObject
*pObj
, sal_uInt8 nPrcWidth
)
3549 pCurTable
->RegisterDrawObject( pObj
, nPrcWidth
);
3552 void SwHTMLParser::BuildTableCell( HTMLTable
*pCurTable
, sal_Bool bReadOptions
,
3555 if( !IsParserWorking() && !pPendStack
)
3558 _CellSaveStruct
* pSaveStruct
;
3561 sal_Bool bPending
= sal_False
;
3564 pSaveStruct
= (_CellSaveStruct
*)pPendStack
->pData
;
3566 SwPendingStack
* pTmp
= pPendStack
->pNext
;
3569 nToken
= pPendStack
? pPendStack
->nToken
: GetSaveToken();
3570 bPending
= SVPAR_ERROR
== eState
&& pPendStack
!= 0;
3572 SaveState( nToken
);
3576 // <TH> bzw. <TD> wurde bereits gelesen
3577 if( pTable
->IsOverflowing() )
3583 if( !pCurTable
->GetContext() )
3585 sal_Bool bTopTable
= pTable
==pCurTable
;
3587 // die Tabelle besitzt noch keinen Inhalt, d.h. die eigentliche
3588 // Tabelle muss erst noch angelegt werden
3590 static sal_uInt16 aWhichIds
[] =
3592 RES_PARATR_SPLIT
, RES_PARATR_SPLIT
,
3593 RES_PAGEDESC
, RES_PAGEDESC
,
3594 RES_BREAK
, RES_BREAK
,
3595 RES_BACKGROUND
, RES_BACKGROUND
,
3597 RES_LAYOUT_SPLIT
, RES_LAYOUT_SPLIT
,
3598 RES_FRAMEDIR
, RES_FRAMEDIR
,
3602 SfxItemSet
aItemSet( pDoc
->GetAttrPool(), aWhichIds
);
3603 SvxCSS1PropertyInfo aPropInfo
;
3605 sal_Bool bStyleParsed
= ParseStyleOptions( pCurTable
->GetStyle(),
3607 pCurTable
->GetClass(),
3608 aItemSet
, aPropInfo
,
3609 0, &pCurTable
->GetDirection() );
3610 const SfxPoolItem
*pItem
= 0;
3613 if( SFX_ITEM_SET
== aItemSet
.GetItemState(
3614 RES_BACKGROUND
, sal_False
, &pItem
) )
3616 pCurTable
->SetBGBrush( *(const SvxBrushItem
*)pItem
);
3617 aItemSet
.ClearItem( RES_BACKGROUND
);
3619 if( SFX_ITEM_SET
== aItemSet
.GetItemState(
3620 RES_PARATR_SPLIT
, sal_False
, &pItem
) )
3623 SwFmtLayoutSplit( ((const SvxFmtSplitItem
*)pItem
)
3625 aItemSet
.ClearItem( RES_PARATR_SPLIT
);
3629 // Den linken/rechten Absatzeinzug ermitteln
3630 sal_uInt16 nLeftSpace
= 0;
3631 sal_uInt16 nRightSpace
= 0;
3633 GetMarginsFromContextWithNumBul( nLeftSpace
, nRightSpace
, nIndent
);
3635 // die aktuelle Position an die wir irgendwann zurueckkehren
3636 SwPosition
*pSavePos
= 0;
3637 sal_Bool bForceFrame
= sal_False
;
3638 sal_Bool bAppended
= sal_False
;
3639 sal_Bool bParentLFStripped
= sal_False
;
3642 SvxAdjust eTblAdjust
= pTable
->GetTableAdjust(sal_False
);
3644 // Wenn die Tabelle links oder rechts ausgerivchtet ist,
3645 // oder in einen Rahmen soll, dann kommt sie auch in einen
3647 bForceFrame
= eTblAdjust
== SVX_ADJUST_LEFT
||
3648 eTblAdjust
== SVX_ADJUST_RIGHT
||
3649 pCurTable
->HasToFly();
3651 // Entweder kommt die Tabelle in keinen Rahmen und befindet
3652 // sich in keinem Rahmen (wird also durch Zellen simuliert),
3653 // oder es gibt bereits Inhalt an der entsprechenden Stelle.
3654 ASSERT( !bForceFrame
|| pCurTable
->HasParentSection(),
3655 "Tabelle im Rahmen hat keine Umgebung!" );
3656 // SCHOEN WAER'S, aber wie bekommen den Inhalt nicht zurueck
3657 // in die umgebende Zelle
3658 // if( bForceFrame && !pCurTable->HasParentSection() )
3660 // pCurTable->SetParentContents(
3661 // InsertTableContents( sal_False, SVX_ADJUST_END ) );
3662 // pCurTable->SetHasParentSection( sal_True );
3665 sal_Bool bAppend
= sal_False
;
3668 // Wenn die Tabelle in einen Rahmen kommt, muss
3669 // nur ein neuer Absatz aufgemacht werden, wenn
3670 // der Absatz Rahmen ohne Umlauf enthaelt.
3671 bAppend
= HasCurrentParaFlys(sal_True
);
3675 // Sonst muss ein neuer Absatz aufgemacht werden,
3676 // wenn der Absatz nicht leer ist, oder Rahmen
3677 // oder text::Bookmarks enthaelt.
3679 pPam
->GetPoint()->nContent
.GetIndex() ||
3680 HasCurrentParaFlys() ||
3681 HasCurrentParaBookmarks();
3685 if( !pPam
->GetPoint()->nContent
.GetIndex() )
3687 pDoc
->SetTxtFmtColl( *pPam
,
3688 pCSS1Parser
->GetTxtCollFromPool(RES_POOLCOLL_STANDARD
) );
3689 SvxFontHeightItem
aFontHeight( 40, 100, RES_CHRATR_FONTSIZE
);
3692 new _HTMLAttr( *pPam
->GetPoint(), aFontHeight
);
3693 aSetAttrTab
.Insert( pTmp
, aSetAttrTab
.Count() );
3695 aFontHeight
.SetWhich( RES_CHRATR_CJK_FONTSIZE
);
3696 pTmp
= new _HTMLAttr( *pPam
->GetPoint(), aFontHeight
);
3697 aSetAttrTab
.Insert( pTmp
, aSetAttrTab
.Count() );
3699 aFontHeight
.SetWhich( RES_CHRATR_CTL_FONTSIZE
);
3700 pTmp
= new _HTMLAttr( *pPam
->GetPoint(), aFontHeight
);
3701 aSetAttrTab
.Insert( pTmp
, aSetAttrTab
.Count() );
3703 pTmp
= new _HTMLAttr( *pPam
->GetPoint(),
3704 SvxULSpaceItem( 0, 0, RES_UL_SPACE
) );
3705 aSetAttrTab
.Insert( pTmp
, 0 ); // ja, 0, weil schon
3706 // vom Tabellenende vorher
3707 // was gesetzt sein kann.
3709 AppendTxtNode( AM_NOSPACE
);
3710 bAppended
= sal_True
;
3712 else if( aParaAttrs
.Count() )
3716 // Der Absatz wird gleich hinter die Tabelle
3717 // verschoben. Deshalb entfernen wir alle harten
3718 // Attribute des Absatzes
3720 for( sal_uInt16 i
=0; i
<aParaAttrs
.Count(); i
++ )
3721 aParaAttrs
[i
]->Invalidate();
3724 aParaAttrs
.Remove( 0, aParaAttrs
.Count() );
3727 pSavePos
= new SwPosition( *pPam
->GetPoint() );
3729 else if( pCurTable
->HasParentSection() )
3731 bParentLFStripped
= StripTrailingLF() > 0;
3733 // Absaetze bzw. ueberschriften beeenden
3735 nFontStHeadStart
= nFontStMin
;
3737 // die harten Attribute an diesem Absatz werden nie mehr ungueltig
3738 if( aParaAttrs
.Count() )
3739 aParaAttrs
.Remove( 0, aParaAttrs
.Count() );
3742 // einen Tabellen Kontext anlegen
3743 _HTMLTableContext
*pTCntxt
=
3744 new _HTMLTableContext( pSavePos
, nContextStMin
,
3745 nContextStAttrMin
);
3747 // alle noch offenen Attribute beenden und hinter der Tabelle
3749 _HTMLAttrs
*pPostIts
= 0;
3750 if( !bForceFrame
&& (bTopTable
|| pCurTable
->HasParentSection()) )
3752 SplitAttrTab( pTCntxt
->aAttrTab
, bTopTable
);
3753 // Wenn wir einen schon vorhandenen Absatz verwenden, duerfen
3754 // in den keine PostIts eingefuegt werden, weil der Absatz
3755 // ja hinter die Tabelle wandert. Sie werden deshalb in den
3756 // ersten Absatz der Tabelle verschoben.
3757 // Bei Tabellen in Tabellen duerfen ebenfalls keine PostIts
3758 // in einen noch leeren Absatz eingefuegt werden, weil
3759 // der sonat nicht geloescht wird.
3760 if( (bTopTable
&& !bAppended
) ||
3761 (!bTopTable
&& !bParentLFStripped
&&
3762 !pPam
->GetPoint()->nContent
.GetIndex()) )
3763 pPostIts
= new _HTMLAttrs
;
3764 SetAttr( bTopTable
, bTopTable
, pPostIts
);
3768 SaveAttrTab( pTCntxt
->aAttrTab
);
3769 if( bTopTable
&& !bAppended
)
3771 pPostIts
= new _HTMLAttrs
;
3772 SetAttr( sal_True
, sal_True
, pPostIts
);
3775 bNoParSpace
= sal_False
;
3777 // Aktuelle Numerierung retten und auschalten.
3778 pTCntxt
->SetNumInfo( GetNumInfo() );
3779 GetNumInfo().Clear();
3780 pTCntxt
->SavePREListingXMP( *this );
3786 // Die Tabelle soll in einen Rahmen geschaufelt werden.
3788 SfxItemSet
aFrmSet( pDoc
->GetAttrPool(),
3789 RES_FRMATR_BEGIN
, RES_FRMATR_END
-1 );
3790 if( !pCurTable
->IsNewDoc() )
3791 Reader::ResetFrmFmtAttrs( aFrmSet
);
3793 SwSurround eSurround
= SURROUND_NONE
;
3796 switch( pCurTable
->GetTableAdjust(sal_True
) )
3798 case SVX_ADJUST_RIGHT
:
3799 eHori
= text::HoriOrientation::RIGHT
;
3800 eSurround
= SURROUND_LEFT
;
3802 case SVX_ADJUST_CENTER
:
3803 eHori
= text::HoriOrientation::CENTER
;
3805 case SVX_ADJUST_LEFT
:
3806 eSurround
= SURROUND_RIGHT
;
3808 eHori
= text::HoriOrientation::LEFT
;
3811 SetAnchorAndAdjustment( text::VertOrientation::NONE
, eHori
, aFrmSet
,
3813 aFrmSet
.Put( SwFmtSurround(eSurround
) );
3815 SwFmtFrmSize
aFrmSize( ATT_VAR_SIZE
, 20*MM50
, MINLAY
);
3816 aFrmSize
.SetWidthPercent( 100 );
3817 aFrmSet
.Put( aFrmSize
);
3819 sal_uInt16 nSpace
= pCurTable
->GetHSpace();
3821 aFrmSet
.Put( SvxLRSpaceItem(nSpace
,nSpace
, 0, 0, RES_LR_SPACE
) );
3822 nSpace
= pCurTable
->GetVSpace();
3824 aFrmSet
.Put( SvxULSpaceItem(nSpace
,nSpace
, RES_UL_SPACE
) );
3826 RndStdIds eAnchorId
= ((const SwFmtAnchor
&)aFrmSet
.
3829 SwFrmFmt
*pFrmFmt
= pDoc
->MakeFlySection(
3830 eAnchorId
, pPam
->GetPoint(), &aFrmSet
);
3832 pTCntxt
->SetFrmFmt( pFrmFmt
);
3833 const SwFmtCntnt
& rFlyCntnt
= pFrmFmt
->GetCntnt();
3834 pPam
->GetPoint()->nNode
= *rFlyCntnt
.GetCntntIdx();
3836 pDoc
->GetNodes().GoNext( &(pPam
->GetPoint()->nNode
) );
3837 pPam
->GetPoint()->nContent
.Assign( pCNd
, 0 );
3839 // automatisch verankerte Rahmen muessen noch um
3840 // eine Position nach vorne verschoben werden.
3841 //if( FLY_AUTO_CNTNT==eAnchorId )
3842 // aMoveFlyFrms.C40_INSERT( SwFrmFmt, pFrmFmt,
3843 // aMoveFlyFrms.Count() );
3846 // eine SwTable mit einer Box anlegen und den PaM in den
3847 // Inhalt der Box-Section bewegen (der Ausrichtungs-Parameter
3848 // ist erstmal nur ein Dummy und wird spaeter noch richtig
3850 ASSERT( !pPam
->GetPoint()->nContent
.GetIndex(),
3851 "Der Absatz hinter der Tabelle ist nicht leer!" );
3852 const SwTable
* pSwTable
= pDoc
->InsertTable(
3853 SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER
, 1 ),
3854 *pPam
->GetPoint(), 1, 1, text::HoriOrientation::LEFT
);
3858 SwNodeIndex
aDstIdx( pPam
->GetPoint()->nNode
);
3859 pPam
->Move( fnMoveBackward
);
3860 pDoc
->GetNodes().Delete( aDstIdx
);
3866 pCSS1Parser
->SetFmtBreak( aItemSet
, aPropInfo
);
3867 pSwTable
->GetFrmFmt()->SetFmtAttr( aItemSet
);
3869 pPam
->Move( fnMoveBackward
);
3872 const SwNode
*pNd
= pDoc
->GetNodes()[pPam
->GetPoint()->nNode
];
3873 if( !bAppended
&& !bForceFrame
)
3875 SwTxtNode
* pOldTxtNd
=
3876 pDoc
->GetNodes()[pSavePos
->nNode
]->GetTxtNode();
3877 ASSERT( pOldTxtNd
, "Wieso stehen wir in keinem Txt-Node?" );
3878 SwFrmFmt
*pFrmFmt
= pSwTable
->GetFrmFmt();
3880 const SfxPoolItem
* pItem2
;
3881 if( SFX_ITEM_SET
== pOldTxtNd
->GetSwAttrSet()
3882 .GetItemState( RES_PAGEDESC
, sal_False
, &pItem2
) &&
3883 ((SwFmtPageDesc
*)pItem2
)->GetPageDesc() )
3885 pFrmFmt
->SetFmtAttr( *pItem2
);
3886 pOldTxtNd
->ResetAttr( RES_PAGEDESC
);
3888 if( SFX_ITEM_SET
== pOldTxtNd
->GetSwAttrSet()
3889 .GetItemState( RES_BREAK
, sal_True
, &pItem2
) )
3891 switch( ((SvxFmtBreakItem
*)pItem2
)->GetBreak() )
3893 case SVX_BREAK_PAGE_BEFORE
:
3894 case SVX_BREAK_PAGE_AFTER
:
3895 case SVX_BREAK_PAGE_BOTH
:
3896 pFrmFmt
->SetFmtAttr( *pItem2
);
3897 pOldTxtNd
->ResetAttr( RES_BREAK
);
3904 if( !bAppended
&& pPostIts
)
3906 // noch vorhandene PostIts in den ersten Absatz
3907 // der Tabelle setzen
3908 InsertAttrs( *pPostIts
);
3913 pTCntxt
->SetTableNode( (SwTableNode
*)pNd
->FindTableNode() );
3915 pCurTable
->SetTable( pTCntxt
->GetTableNode(), pTCntxt
,
3916 nLeftSpace
, nRightSpace
,
3917 pSwTable
, bForceFrame
);
3919 ASSERT( !pPostIts
, "ubenutzte PostIts" );
3923 // noch offene Bereiche muessen noch entfernt werden
3924 if( EndSections( bParentLFStripped
) )
3925 bParentLFStripped
= sal_False
;
3927 if( pCurTable
->HasParentSection() )
3929 // dannach entfernen wir ein ggf. zu viel vorhandenen
3930 // leeren Absatz, aber nur, wenn er schon vor dem
3931 // entfernen von LFs leer war
3932 if( !bParentLFStripped
)
3933 StripTrailingPara();
3937 // noch vorhandene PostIts an das Ende des jetzt
3938 // aktuellen Absatzes schieben
3939 InsertAttrs( *pPostIts
);
3945 const SwNode
*pNd
= pDoc
->GetNodes()[pPam
->GetPoint()->nNode
];
3946 const SwStartNode
*pStNd
= (pTable
->bFirstCell
? pNd
->FindTableNode()
3947 : pNd
->FindTableBoxStartNode() );
3949 pCurTable
->SetTable( pStNd
, pTCntxt
, nLeftSpace
, nRightSpace
);
3952 // Den Kontext-Stack einfrieren, denn es koennen auch mal
3953 // irgendwo ausserhalb von Zellen Attribute gesetzt werden.
3954 // Darf nicht frueher passieren, weil eventuell noch im
3955 // Stack gesucht wird!!!
3956 nContextStMin
= aContexts
.Count();
3957 nContextStAttrMin
= nContextStMin
;
3960 pSaveStruct
= new _CellSaveStruct( *this, pCurTable
, bHead
,
3963 // ist beim ersten GetNextToken schon pending, muss bei
3964 // wiederaufsetzen auf jedenfall neu gelesen werden!
3969 nToken
= GetNextToken(); // Token nach <TABLE>
3971 sal_Bool bDone
= sal_False
;
3972 while( (IsParserWorking() && !bDone
) || bPending
)
3974 SaveState( nToken
);
3976 nToken
= FilterToken( nToken
);
3978 ASSERT( pPendStack
|| !bCallNextToken
|| pSaveStruct
->IsInSection(),
3979 "Wo ist die Section gebieben?" );
3980 if( !pPendStack
&& bCallNextToken
&& pSaveStruct
->IsInSection() )
3982 // NextToken direkt aufrufen (z.B. um den Inhalt von
3983 // Floating-Frames oder Applets zu ignorieren)
3984 NextToken( nToken
);
3986 else switch( nToken
)
3988 case HTML_TABLEHEADER_ON
:
3989 case HTML_TABLEDATA_ON
:
3990 case HTML_TABLEROW_ON
:
3991 case HTML_TABLEROW_OFF
:
3993 case HTML_THEAD_OFF
:
3995 case HTML_TFOOT_OFF
:
3997 case HTML_TBODY_OFF
:
3998 case HTML_TABLE_OFF
:
4000 case HTML_TABLEHEADER_OFF
:
4001 case HTML_TABLEDATA_OFF
:
4006 sal_Bool bTopTable
= sal_False
;
4007 sal_Bool bHasToFly
= sal_False
;
4008 SvxAdjust eTabAdjust
= SVX_ADJUST_END
;
4011 // nur wenn eine neue Tabelle aufgemacht wird, aber
4012 // nicht wenn nach einem Pending in der Tabelle
4013 // weitergelesen wird!
4014 pSaveStruct
->pTable
= pTable
;
4016 // HACK: Eine Section fuer eine Tabelle anlegen, die
4017 // in einen Rahmen kommt.
4018 if( !pSaveStruct
->IsInSection() )
4020 // Diese Schleife muss vorwartes sein, weil die
4021 // erste Option immer gewinnt.
4022 sal_Bool bNeedsSection
= sal_False
;
4023 const HTMLOptions
*pHTMLOptions
= GetOptions();
4024 for( sal_uInt16 i
=0; i
<pHTMLOptions
->Count(); i
++ )
4026 const HTMLOption
*pOption
= (*pHTMLOptions
)[i
];
4027 if( HTML_O_ALIGN
==pOption
->GetToken() )
4030 (SvxAdjust
)pOption
->GetEnum(
4031 aHTMLPAlignTable
, SVX_ADJUST_END
);
4032 bNeedsSection
= SVX_ADJUST_LEFT
== eAdjust
||
4033 SVX_ADJUST_RIGHT
== eAdjust
;
4039 pSaveStruct
->AddContents(
4040 InsertTableContents(bHead
) );
4045 // Wenn wir mitlerweile in einem Rahmen stehen
4046 // koennen wir erneut eine echte Tabelle aufmachen.
4047 // Wir erkennen das daran, dass wir keinen
4048 // Tabellen-Node mehr finden.
4049 bTopTable
= pDoc
->GetNodes()[pPam
->GetPoint()->nNode
]
4050 ->FindTableNode() == 0;
4052 // Wenn im aktuellen Absatz Flys verankert sind,
4053 // muss die neue Tabelle in einen Rahmen.
4054 bHasToFly
= HasCurrentParaFlys(sal_False
,sal_True
);
4057 // in der Zelle kann sich ein Bereich befinden!
4058 eTabAdjust
= aAttrTab
.pAdjust
4059 ? ((const SvxAdjustItem
&)aAttrTab
.pAdjust
->GetItem()).
4064 HTMLTable
*pSubTable
= BuildTable( eTabAdjust
,
4066 pSaveStruct
->IsInSection(),
4067 bTopTable
, bHasToFly
);
4068 if( SVPAR_PENDING
!= GetStatus() )
4070 // nur wenn die Tabelle wirklich zu Ende ist!
4073 ASSERT( pSubTable
->GetTableAdjust(sal_False
)!= SVX_ADJUST_LEFT
&&
4074 pSubTable
->GetTableAdjust(sal_False
)!= SVX_ADJUST_RIGHT
,
4075 "links oder rechts ausgerichtete Tabellen gehoehren in Rahmen" );
4078 HTMLTableCnts
*pParentContents
=
4079 pSubTable
->GetParentContents();
4080 if( pParentContents
)
4082 ASSERT( !pSaveStruct
->IsInSection(),
4083 "Wo ist die Section geblieben" );
4085 // Wenn jetzt keine Tabelle kommt haben wir eine
4087 pSaveStruct
->AddContents( pParentContents
);
4090 const SwStartNode
*pCapStNd
=
4091 pSubTable
->GetCaptionStartNode();
4093 if( pSubTable
->GetContext() )
4095 ASSERT( !pSubTable
->GetContext()->GetFrmFmt(),
4096 "Tabelle steht im Rahmen" );
4098 if( pCapStNd
&& pSubTable
->IsTopCaption() )
4100 pSaveStruct
->AddContents(
4101 new HTMLTableCnts(pCapStNd
) );
4104 pSaveStruct
->AddContents(
4105 new HTMLTableCnts(pSubTable
) );
4107 if( pCapStNd
&& !pSubTable
->IsTopCaption() )
4109 pSaveStruct
->AddContents(
4110 new HTMLTableCnts(pCapStNd
) );
4113 // Jetzt haben wir keine Section mehr
4114 pSaveStruct
->ClearIsInSection();
4118 // Da wir diese Sction nicht mehr loeschen
4119 // koennen (sie koeente zur erster Box
4120 // gehoeren), fuegen wir sie ein.
4121 pSaveStruct
->AddContents(
4122 new HTMLTableCnts(pCapStNd
) );
4124 // Jetzt haben wir keine Section mehr
4125 pSaveStruct
->ClearIsInSection();
4129 pTable
= pSaveStruct
->pTable
;
4135 // HACK fuer MS: Steht das <NOBR> zu beginn der Zelle?
4136 pSaveStruct
->StartNoBreak( *pPam
->GetPoint() );
4140 pSaveStruct
->EndNoBreak( *pPam
->GetPoint() );
4144 // Mit Kommentar-Feldern werden Spaces nicht mehr geloescht
4145 // ausserdem wollen wir fuer einen Kommentar keine neue Zelle
4147 NextToken( nToken
);
4150 case HTML_MARQUEE_ON
:
4151 if( !pSaveStruct
->IsInSection() )
4153 // eine neue Section anlegen, der PaM steht dann darin
4154 pSaveStruct
->AddContents(
4155 InsertTableContents( bHead
) );
4157 bCallNextToken
= sal_True
;
4158 NewMarquee( pCurTable
);
4161 case HTML_TEXTTOKEN
:
4162 // keine Section fuer einen leeren String anlegen
4163 if( !pSaveStruct
->IsInSection() && 1==aToken
.Len() &&
4164 ' '==aToken
.GetChar(0) )
4167 if( !pSaveStruct
->IsInSection() )
4169 // eine neue Section anlegen, der PaM steht dann darin
4170 pSaveStruct
->AddContents(
4171 InsertTableContents( bHead
) );
4174 if( IsParserWorking() || bPending
)
4175 NextToken( nToken
);
4179 ASSERT( !bPending
|| !pPendStack
,
4180 "SwHTMLParser::BuildTableCell: Es gibt wieder einen Pend-Stack" );
4181 bPending
= sal_False
;
4182 if( IsParserWorking() )
4186 nToken
= GetNextToken();
4189 if( SVPAR_PENDING
== GetStatus() )
4191 pPendStack
= new SwPendingStack( bHead
? HTML_TABLEHEADER_ON
4192 : HTML_TABLEDATA_ON
, pPendStack
);
4193 pPendStack
->pData
= pSaveStruct
;
4198 // Falls der Inhalt der Zelle leer war, muessen wir noch einen
4199 // leeren Inhalt anlegen. Ausserdem legen wir einen leeren Inhalt
4200 // an, wenn die Zelle mit einer Tabelle aufgehoert hat und keine
4201 // COL-Tags hatte (sonst wurde sie wahrscheinlich von uns exportiert,
4202 // und dann wollen wir natuerlich keinen zusaetzlichen Absatz haben).
4203 if( !pSaveStruct
->GetFirstContents() ||
4204 (!pSaveStruct
->IsInSection() && !pCurTable
->HasColTags()) )
4206 ASSERT( pSaveStruct
->GetFirstContents() ||
4207 !pSaveStruct
->IsInSection(),
4208 "Section oder nicht, das ist hier die Frage" );
4209 const SwStartNode
*pStNd
=
4210 InsertTableSection( static_cast< USHORT
>(pSaveStruct
->IsHeaderCell()
4211 ? RES_POOLCOLL_TABLE_HDLN
4212 : RES_POOLCOLL_TABLE
));
4213 const SwEndNode
*pEndNd
= pStNd
->EndOfSectionNode();
4214 SwCntntNode
*pCNd
= pDoc
->GetNodes()[pEndNd
->GetIndex()-1] ->GetCntntNode();
4215 SvxFontHeightItem
aFontHeight( 40, 100, RES_CHRATR_FONTSIZE
);
4216 pCNd
->SetAttr( aFontHeight
);
4217 aFontHeight
.SetWhich( RES_CHRATR_CJK_FONTSIZE
);
4218 pCNd
->SetAttr( aFontHeight
);
4219 aFontHeight
.SetWhich( RES_CHRATR_CTL_FONTSIZE
);
4220 pCNd
->SetAttr( aFontHeight
);
4222 pSaveStruct
->AddContents( new HTMLTableCnts(pStNd
) );
4223 pSaveStruct
->ClearIsInSection();
4226 if( pSaveStruct
->IsInSection() )
4228 pSaveStruct
->CheckNoBreak( *pPam
->GetPoint(), pDoc
);
4230 // Alle noch offenen Kontexte beenden. Wir nehmen hier
4231 // AttrMin, weil nContxtStMin evtl. veraendert wurde.
4232 // Da es durch EndContext wieder restauriert wird, geht das.
4233 while( aContexts
.Count() > nContextStAttrMin
+1 )
4235 _HTMLAttrContext
*pCntxt
= PopContext();
4236 EndContext( pCntxt
);
4240 // LFs am Absatz-Ende entfernen
4241 if( StripTrailingLF()==0 && !pPam
->GetPoint()->nContent
.GetIndex() )
4242 StripTrailingPara();
4244 // falls fuer die Zelle eine Ausrichtung gesetzt wurde, muessen
4246 _HTMLAttrContext
*pCntxt
= PopContext();
4247 EndContext( pCntxt
);
4252 // Alle noch offenen Kontexte beenden
4253 while( aContexts
.Count() > nContextStAttrMin
)
4255 _HTMLAttrContext
*pCntxt
= PopContext();
4256 ClearContext( pCntxt
);
4261 // auch eine Numerierung muss beendet werden
4262 GetNumInfo().Clear();
4264 SetAttr( sal_False
);
4266 pSaveStruct
->InsertCell( *this, pCurTable
);
4268 // wir stehen jetzt (wahrschenlich) vor <TH>, <TD>, <TR> oder </TABLE>
4273 class _RowSaveStruct
: public SwPendingStackData
4281 eAdjust( SVX_ADJUST_END
), eVertOri( text::VertOrientation::TOP
), bHasCells( sal_False
)
4286 void SwHTMLParser::BuildTableRow( HTMLTable
*pCurTable
, sal_Bool bReadOptions
,
4287 SvxAdjust eGrpAdjust
,
4288 sal_Int16 eGrpVertOri
)
4290 // <TR> wurde bereist gelesen
4292 if( !IsParserWorking() && !pPendStack
)
4296 _RowSaveStruct
* pSaveStruct
;
4298 sal_Bool bPending
= sal_False
;
4301 pSaveStruct
= (_RowSaveStruct
*)pPendStack
->pData
;
4303 SwPendingStack
* pTmp
= pPendStack
->pNext
;
4306 nToken
= pPendStack
? pPendStack
->nToken
: GetSaveToken();
4307 bPending
= SVPAR_ERROR
== eState
&& pPendStack
!= 0;
4309 SaveState( nToken
);
4313 SvxAdjust eAdjust
= eGrpAdjust
;
4314 sal_Int16 eVertOri
= eGrpVertOri
;
4316 String aBGImage
, aStyle
, aId
, aClass
;
4317 sal_Bool bBGColor
= sal_False
;
4318 pSaveStruct
= new _RowSaveStruct
;
4322 const HTMLOptions
*pHTMLOptions
= GetOptions();
4323 for( sal_uInt16 i
= pHTMLOptions
->Count(); i
; )
4325 const HTMLOption
*pOption
= (*pHTMLOptions
)[--i
];
4326 switch( pOption
->GetToken() )
4329 aId
= pOption
->GetString();
4332 eAdjust
= (SvxAdjust
)pOption
->GetEnum(
4333 aHTMLPAlignTable
, static_cast< sal_uInt16
>(eAdjust
) );
4336 eVertOri
= pOption
->GetEnum(
4337 aHTMLTblVAlignTable
, eVertOri
);
4339 case HTML_O_BGCOLOR
:
4340 // Leere BGCOLOR bei <TABLE>, <TR> und <TD>/<TH> wie Netsc.
4341 // ignorieren, bei allen anderen Tags *wirklich* nicht.
4342 if( pOption
->GetString().Len() )
4344 pOption
->GetColor( aBGColor
);
4345 bBGColor
= sal_True
;
4348 case HTML_O_BACKGROUND
:
4349 aBGImage
= pOption
->GetString();
4352 aStyle
= pOption
->GetString();
4355 aClass
= pOption
->GetString();
4362 InsertBookmark( aId
);
4364 SvxBrushItem
*pBrushItem
=
4365 CreateBrushItem( bBGColor
? &aBGColor
: 0, aBGImage
, aStyle
,
4367 pCurTable
->OpenRow( eAdjust
, eVertOri
, pBrushItem
);
4368 // ist beim ersten GetNextToken schon pending, muss bei
4369 // wiederaufsetzen auf jedenfall neu gelesen werden!
4374 nToken
= GetNextToken(); // naechstes Token
4376 sal_Bool bDone
= sal_False
;
4377 while( (IsParserWorking() && !bDone
) || bPending
)
4379 SaveState( nToken
);
4381 nToken
= FilterToken( nToken
);
4383 ASSERT( pPendStack
|| !bCallNextToken
||
4384 pCurTable
->GetContext() || pCurTable
->HasParentSection(),
4385 "Wo ist die Section gebieben?" );
4386 if( !pPendStack
&& bCallNextToken
&&
4387 (pCurTable
->GetContext() || pCurTable
->HasParentSection()) )
4389 // NextToken direkt aufrufen (z.B. um den Inhalt von
4390 // Floating-Frames oder Applets zu ignorieren)
4391 NextToken( nToken
);
4393 else switch( nToken
)
4396 if( !pCurTable
->GetContext() )
4403 // NextToken( nToken );
4406 case HTML_TABLEROW_ON
:
4408 case HTML_THEAD_OFF
:
4410 case HTML_TBODY_OFF
:
4412 case HTML_TFOOT_OFF
:
4413 case HTML_TABLE_OFF
:
4415 case HTML_TABLEROW_OFF
:
4418 case HTML_TABLEHEADER_ON
:
4419 case HTML_TABLEDATA_ON
:
4420 BuildTableCell( pCurTable
, sal_True
, HTML_TABLEHEADER_ON
==nToken
);
4421 if( SVPAR_PENDING
!= GetStatus() )
4423 pSaveStruct
->bHasCells
= sal_True
;
4424 bDone
= pTable
->IsOverflowing();
4427 case HTML_CAPTION_ON
:
4428 BuildTableCaption( pCurTable
);
4429 bDone
= pTable
->IsOverflowing();
4431 case HTML_CAPTION_OFF
:
4432 case HTML_TABLEHEADER_OFF
:
4433 case HTML_TABLEDATA_OFF
:
4434 case HTML_COLGROUP_ON
:
4435 case HTML_COLGROUP_OFF
:
4438 // wo keine Zelle anfing kann auch keine aufhoehren, oder?
4439 // und die ganzen anderen Tokens haben hier auch nicht zu
4440 // suchen und machen nur die Tabelle kaputt
4442 case HTML_MULTICOL_ON
:
4443 // spaltige Rahmen koennen wir hier leider nicht einguegen
4446 NewForm( sal_False
); // keinen neuen Absatz aufmachen!
4449 EndForm( sal_False
); // keinen neuen Absatz aufmachen!
4452 NextToken( nToken
);
4455 // eine Image-Map fuegt nichts ein, deshalb koennen wir sie
4456 // problemlos auch ohne Zelle parsen
4457 NextToken( nToken
);
4459 case HTML_TEXTTOKEN
:
4460 if( (pCurTable
->GetContext() ||
4461 !pCurTable
->HasParentSection()) &&
4462 1==aToken
.Len() && ' '==aToken
.GetChar(0) )
4465 pCurTable
->MakeParentContents();
4466 NextToken( nToken
);
4470 ASSERT( !bPending
|| !pPendStack
,
4471 "SwHTMLParser::BuildTableRow: Es gibt wieder einen Pend-Stack" );
4472 bPending
= sal_False
;
4473 if( IsParserWorking() )
4477 nToken
= GetNextToken();
4480 if( SVPAR_PENDING
== GetStatus() )
4482 pPendStack
= new SwPendingStack( HTML_TABLEROW_ON
, pPendStack
);
4483 pPendStack
->pData
= pSaveStruct
;
4487 pCurTable
->CloseRow( !pSaveStruct
->bHasCells
);
4491 // wir stehen jetzt (wahrscheinlich) vor <TR> oder </TABLE>
4494 void SwHTMLParser::BuildTableSection( HTMLTable
*pCurTable
,
4495 sal_Bool bReadOptions
,
4498 // <THEAD>, <TBODY> bzw. <TFOOT> wurde bereits gelesen
4499 if( !IsParserWorking() && !pPendStack
)
4503 sal_Bool bPending
= sal_False
;
4504 _RowSaveStruct
* pSaveStruct
;
4508 pSaveStruct
= (_RowSaveStruct
*)pPendStack
->pData
;
4510 SwPendingStack
* pTmp
= pPendStack
->pNext
;
4513 nToken
= pPendStack
? pPendStack
->nToken
: GetSaveToken();
4514 bPending
= SVPAR_ERROR
== eState
&& pPendStack
!= 0;
4516 SaveState( nToken
);
4520 pSaveStruct
= new _RowSaveStruct
;
4524 const HTMLOptions
*pHTMLOptions
= GetOptions();
4525 for( sal_uInt16 i
= pHTMLOptions
->Count(); i
; )
4527 const HTMLOption
*pOption
= (*pHTMLOptions
)[--i
];
4528 switch( pOption
->GetToken() )
4531 InsertBookmark( pOption
->GetString() );
4534 pSaveStruct
->eAdjust
=
4535 (SvxAdjust
)pOption
->GetEnum( aHTMLPAlignTable
,
4536 static_cast< sal_uInt16
>(pSaveStruct
->eAdjust
) );
4539 pSaveStruct
->eVertOri
=
4540 pOption
->GetEnum( aHTMLTblVAlignTable
,
4541 pSaveStruct
->eVertOri
);
4547 // ist beim ersten GetNextToken schon pending, muss bei
4548 // wiederaufsetzen auf jedenfall neu gelesen werden!
4553 nToken
= GetNextToken(); // naechstes Token
4555 sal_Bool bDone
= sal_False
;
4556 while( (IsParserWorking() && !bDone
) || bPending
)
4558 SaveState( nToken
);
4560 nToken
= FilterToken( nToken
);
4562 ASSERT( pPendStack
|| !bCallNextToken
||
4563 pCurTable
->GetContext() || pCurTable
->HasParentSection(),
4564 "Wo ist die Section gebieben?" );
4565 if( !pPendStack
&& bCallNextToken
&&
4566 (pCurTable
->GetContext() || pCurTable
->HasParentSection()) )
4568 // NextToken direkt aufrufen (z.B. um den Inhalt von
4569 // Floating-Frames oder Applets zu ignorieren)
4570 NextToken( nToken
);
4572 else switch( nToken
)
4575 if( !pCurTable
->GetContext() )
4582 // NextToken( nToken );
4588 case HTML_TABLE_OFF
:
4590 case HTML_THEAD_OFF
:
4591 case HTML_TBODY_OFF
:
4592 case HTML_TFOOT_OFF
:
4595 case HTML_CAPTION_ON
:
4596 BuildTableCaption( pCurTable
);
4597 bDone
= pTable
->IsOverflowing();
4599 case HTML_CAPTION_OFF
:
4601 case HTML_TABLEHEADER_ON
:
4602 case HTML_TABLEDATA_ON
:
4604 BuildTableRow( pCurTable
, sal_False
, pSaveStruct
->eAdjust
,
4605 pSaveStruct
->eVertOri
);
4606 bDone
= pTable
->IsOverflowing();
4608 case HTML_TABLEROW_ON
:
4609 BuildTableRow( pCurTable
, sal_True
, pSaveStruct
->eAdjust
,
4610 pSaveStruct
->eVertOri
);
4611 bDone
= pTable
->IsOverflowing();
4613 case HTML_MULTICOL_ON
:
4614 // spaltige Rahmen koennen wir hier leider nicht einguegen
4617 NewForm( sal_False
); // keinen neuen Absatz aufmachen!
4620 EndForm( sal_False
); // keinen neuen Absatz aufmachen!
4622 case HTML_TEXTTOKEN
:
4623 // Blank-Strings sind Folge von CR+LF und kein Text
4624 if( (pCurTable
->GetContext() ||
4625 !pCurTable
->HasParentSection()) &&
4626 1==aToken
.Len() && ' '==aToken
.GetChar(0) )
4629 pCurTable
->MakeParentContents();
4630 NextToken( nToken
);
4633 ASSERT( !bPending
|| !pPendStack
,
4634 "SwHTMLParser::BuildTableSection: Es gibt wieder einen Pend-Stack" );
4635 bPending
= sal_False
;
4636 if( IsParserWorking() )
4640 nToken
= GetNextToken();
4643 if( SVPAR_PENDING
== GetStatus() )
4645 pPendStack
= new SwPendingStack( bHead
? HTML_THEAD_ON
4646 : HTML_TBODY_ON
, pPendStack
);
4647 pPendStack
->pData
= pSaveStruct
;
4651 pCurTable
->CloseSection( bHead
);
4655 // wir stehen jetzt (wahrscheinlich) vor <TBODY>,... oder </TABLE>
4658 struct _TblColGrpSaveStruct
: public SwPendingStackData
4660 sal_uInt16 nColGrpSpan
;
4661 sal_uInt16 nColGrpWidth
;
4662 sal_Bool bRelColGrpWidth
;
4663 SvxAdjust eColGrpAdjust
;
4664 sal_Int16 eColGrpVertOri
;
4666 inline _TblColGrpSaveStruct();
4669 inline void CloseColGroup( HTMLTable
*pTable
);
4672 inline _TblColGrpSaveStruct::_TblColGrpSaveStruct() :
4673 nColGrpSpan( 1 ), nColGrpWidth( 0 ),
4674 bRelColGrpWidth( sal_False
), eColGrpAdjust( SVX_ADJUST_END
),
4675 eColGrpVertOri( text::VertOrientation::TOP
)
4679 inline void _TblColGrpSaveStruct::CloseColGroup( HTMLTable
*pTable
)
4681 pTable
->CloseColGroup( nColGrpSpan
, nColGrpWidth
,
4682 bRelColGrpWidth
, eColGrpAdjust
, eColGrpVertOri
);
4685 void SwHTMLParser::BuildTableColGroup( HTMLTable
*pCurTable
,
4686 sal_Bool bReadOptions
)
4688 // <COLGROUP> wurde bereits gelesen, wenn bReadOptions
4690 if( !IsParserWorking() && !pPendStack
)
4694 sal_Bool bPending
= sal_False
;
4695 _TblColGrpSaveStruct
* pSaveStruct
;
4699 pSaveStruct
= (_TblColGrpSaveStruct
*)pPendStack
->pData
;
4701 SwPendingStack
* pTmp
= pPendStack
->pNext
;
4704 nToken
= pPendStack
? pPendStack
->nToken
: GetSaveToken();
4705 bPending
= SVPAR_ERROR
== eState
&& pPendStack
!= 0;
4707 SaveState( nToken
);
4712 pSaveStruct
= new _TblColGrpSaveStruct
;
4715 const HTMLOptions
*pColGrpOptions
= GetOptions();
4716 for( sal_uInt16 i
= pColGrpOptions
->Count(); i
; )
4718 const HTMLOption
*pColGrpOption
= (*pColGrpOptions
)[--i
];
4719 switch( pColGrpOption
->GetToken() )
4722 InsertBookmark( pColGrpOption
->GetString() );
4725 pSaveStruct
->nColGrpSpan
= (sal_uInt16
)pColGrpOption
->GetNumber();
4728 pSaveStruct
->nColGrpWidth
= (sal_uInt16
)pColGrpOption
->GetNumber();
4729 pSaveStruct
->bRelColGrpWidth
=
4730 (pColGrpOption
->GetString().Search('*') != STRING_NOTFOUND
);
4733 pSaveStruct
->eColGrpAdjust
=
4734 (SvxAdjust
)pColGrpOption
->GetEnum( aHTMLPAlignTable
,
4735 static_cast< sal_uInt16
>(pSaveStruct
->eColGrpAdjust
) );
4738 pSaveStruct
->eColGrpVertOri
=
4739 pColGrpOption
->GetEnum( aHTMLTblVAlignTable
,
4740 pSaveStruct
->eColGrpVertOri
);
4745 // ist beim ersten GetNextToken schon pending, muss bei
4746 // wiederaufsetzen auf jedenfall neu gelesen werden!
4751 nToken
= GetNextToken(); // naechstes Token
4753 sal_Bool bDone
= sal_False
;
4754 while( (IsParserWorking() && !bDone
) || bPending
)
4756 SaveState( nToken
);
4758 nToken
= FilterToken( nToken
);
4760 ASSERT( pPendStack
|| !bCallNextToken
||
4761 pCurTable
->GetContext() || pCurTable
->HasParentSection(),
4762 "Wo ist die Section gebieben?" );
4763 if( !pPendStack
&& bCallNextToken
&&
4764 (pCurTable
->GetContext() || pCurTable
->HasParentSection()) )
4766 // NextToken direkt aufrufen (z.B. um den Inhalt von
4767 // Floating-Frames oder Applets zu ignorieren)
4768 NextToken( nToken
);
4770 else switch( nToken
)
4773 if( !pCurTable
->GetContext() )
4780 // NextToken( nToken );
4783 case HTML_COLGROUP_ON
:
4787 case HTML_TABLEROW_ON
:
4788 case HTML_TABLE_OFF
:
4790 case HTML_COLGROUP_OFF
:
4795 sal_uInt16 nColSpan
= 1;
4796 sal_uInt16 nColWidth
= pSaveStruct
->nColGrpWidth
;
4797 sal_Bool bRelColWidth
= pSaveStruct
->bRelColGrpWidth
;
4798 SvxAdjust eColAdjust
= pSaveStruct
->eColGrpAdjust
;
4799 sal_Int16 eColVertOri
= pSaveStruct
->eColGrpVertOri
;
4801 const HTMLOptions
*pColOptions
= GetOptions();
4802 for( sal_uInt16 i
= pColOptions
->Count(); i
; )
4804 const HTMLOption
*pColOption
= (*pColOptions
)[--i
];
4805 switch( pColOption
->GetToken() )
4808 InsertBookmark( pColOption
->GetString() );
4811 nColSpan
= (sal_uInt16
)pColOption
->GetNumber();
4814 nColWidth
= (sal_uInt16
)pColOption
->GetNumber();
4816 (pColOption
->GetString().Search('*') != STRING_NOTFOUND
);
4820 (SvxAdjust
)pColOption
->GetEnum( aHTMLPAlignTable
,
4821 static_cast< sal_uInt16
>(eColAdjust
) );
4825 pColOption
->GetEnum( aHTMLTblVAlignTable
,
4830 pCurTable
->InsertCol( nColSpan
, nColWidth
, bRelColWidth
,
4831 eColAdjust
, eColVertOri
);
4833 // die Angaben in <COLGRP> sollen ignoriert werden, wenn
4834 // <COL>-Elemente existieren
4835 pSaveStruct
->nColGrpSpan
= 0;
4839 break; // Ignorieren
4840 case HTML_MULTICOL_ON
:
4841 // spaltige Rahmen koennen wir hier leider nicht einguegen
4843 case HTML_TEXTTOKEN
:
4844 if( (pCurTable
->GetContext() ||
4845 !pCurTable
->HasParentSection()) &&
4846 1==aToken
.Len() && ' '==aToken
.GetChar(0) )
4849 pCurTable
->MakeParentContents();
4850 NextToken( nToken
);
4853 ASSERT( !bPending
|| !pPendStack
,
4854 "SwHTMLParser::BuildTableColGrp: Es gibt wieder einen Pend-Stack" );
4855 bPending
= sal_False
;
4856 if( IsParserWorking() )
4860 nToken
= GetNextToken();
4863 if( SVPAR_PENDING
== GetStatus() )
4865 pPendStack
= new SwPendingStack( HTML_COL_ON
, pPendStack
);
4866 pPendStack
->pData
= pSaveStruct
;
4870 pSaveStruct
->CloseColGroup( pCurTable
);
4875 class _CaptionSaveStruct
: public _SectionSaveStruct
4877 SwPosition aSavePos
;
4878 SwHTMLNumRuleInfo aNumRuleInfo
; // gueltige Numerierung
4882 _HTMLAttrTable aAttrTab
; // und die Attribute
4884 _CaptionSaveStruct( SwHTMLParser
& rParser
, const SwPosition
& rPos
) :
4885 _SectionSaveStruct( rParser
), aSavePos( rPos
)
4887 rParser
.SaveAttrTab( aAttrTab
);
4889 // Die aktuelle Numerierung wurde gerettet und muss nur
4890 // noch beendet werden.
4891 aNumRuleInfo
.Set( rParser
.GetNumInfo() );
4892 rParser
.GetNumInfo().Clear();
4895 const SwPosition
& GetPos() const { return aSavePos
; }
4897 void RestoreAll( SwHTMLParser
& rParser
)
4899 // Die alten Stack wiederherstellen
4902 // Die alte Attribut-Tabelle wiederherstellen
4903 rParser
.RestoreAttrTab( aAttrTab
);
4905 // Die alte Numerierung wieder aufspannen
4906 rParser
.GetNumInfo().Set( aNumRuleInfo
);
4909 virtual ~_CaptionSaveStruct();
4912 _CaptionSaveStruct::~_CaptionSaveStruct()
4915 void SwHTMLParser::BuildTableCaption( HTMLTable
*pCurTable
)
4917 // <CAPTION> wurde bereits gelesen
4919 if( !IsParserWorking() && !pPendStack
)
4923 _CaptionSaveStruct
* pSaveStruct
;
4927 pSaveStruct
= (_CaptionSaveStruct
*)pPendStack
->pData
;
4929 SwPendingStack
* pTmp
= pPendStack
->pNext
;
4932 nToken
= pPendStack
? pPendStack
->nToken
: GetSaveToken();
4933 ASSERT( !pPendStack
, "Wo kommt hier ein Pending-Stack her?" );
4935 SaveState( nToken
);
4939 if( pTable
->IsOverflowing() )
4945 sal_Bool bTop
= sal_True
;
4946 const HTMLOptions
*pHTMLOptions
= GetOptions();
4947 for ( sal_uInt16 i
= pHTMLOptions
->Count(); i
; )
4949 const HTMLOption
*pOption
= (*pHTMLOptions
)[--i
];
4950 if( HTML_O_ALIGN
== pOption
->GetToken() )
4952 if( pOption
->GetString().EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_VA_bottom
))
4957 // Alte PaM-Position retten.
4958 pSaveStruct
= new _CaptionSaveStruct( *this, *pPam
->GetPoint() );
4960 // Eine Text-Section im Icons-Bereich als Container fuer die
4961 // Ueberschrift anlegen und PaM dort reinstellen.
4962 const SwStartNode
*pStNd
;
4963 if( pTable
== pCurTable
)
4964 pStNd
= InsertTempTableCaptionSection();
4966 pStNd
= InsertTableSection( RES_POOLCOLL_TEXT
);
4968 _HTMLAttrContext
*pCntxt
= new _HTMLAttrContext( HTML_CAPTION_ON
);
4970 // Tabellen-Ueberschriften sind immer zentriert.
4971 NewAttr( &aAttrTab
.pAdjust
, SvxAdjustItem(SVX_ADJUST_CENTER
, RES_PARATR_ADJUST
) );
4973 _HTMLAttrs
&rAttrs
= pCntxt
->GetAttrs();
4974 rAttrs
.Insert( aAttrTab
.pAdjust
, rAttrs
.Count() );
4976 PushContext( pCntxt
);
4978 // StartNode der Section an der Tabelle merken.
4979 pCurTable
->SetCaption( pStNd
, bTop
);
4981 // ist beim ersten GetNextToken schon pending, muss bei
4982 // wiederaufsetzen auf jedenfall neu gelesen werden!
4987 nToken
= GetNextToken(); // naechstes Token
4989 // </CAPTION> wird laut DTD benoetigt
4990 sal_Bool bDone
= sal_False
;
4991 while( IsParserWorking() && !bDone
)
4993 SaveState( nToken
);
4995 nToken
= FilterToken( nToken
);
5002 pSaveStruct
->pTable
= pTable
;
5003 sal_Bool bHasToFly
= pSaveStruct
->pTable
!=pCurTable
;
5004 BuildTable( pCurTable
->GetTableAdjust( sal_True
),
5005 sal_False
, sal_True
, sal_True
, bHasToFly
);
5009 BuildTable( SVX_ADJUST_END
);
5011 if( SVPAR_PENDING
!= GetStatus() )
5013 pTable
= pSaveStruct
->pTable
;
5016 case HTML_TABLE_OFF
:
5017 case HTML_COLGROUP_ON
:
5021 case HTML_TABLEROW_ON
:
5026 case HTML_CAPTION_OFF
:
5030 int nNxtToken
= nToken
;
5033 SwPendingStack
* pTmp
= pPendStack
->pNext
;
5037 ASSERT( !pTmp
, "weiter kann es nicht gehen!" );
5038 nNxtToken
= 0; // neu lesen
5041 if( IsParserWorking() )
5042 NextToken( nToken
);
5046 if( IsParserWorking() )
5050 nToken
= GetNextToken();
5053 if( SVPAR_PENDING
==GetStatus() )
5055 pPendStack
= new SwPendingStack( HTML_CAPTION_ON
, pPendStack
);
5056 pPendStack
->pData
= pSaveStruct
;
5060 // Alle noch offenen Kontexte beenden
5061 while( aContexts
.Count() > nContextStAttrMin
+1 )
5063 _HTMLAttrContext
*pCntxt
= PopContext();
5064 EndContext( pCntxt
);
5068 // LF am Absatz-Ende entfernen
5069 sal_Bool bLFStripped
= StripTrailingLF() > 0;
5071 if( pTable
==pCurTable
)
5073 // Beim spaeteren verschieben der Beschriftung vor oder hinter
5074 // die Tabelle wird der letzte Absatz nicht mitverschoben.
5075 // Deshalb muss sich am Ende der Section immer ein leerer
5077 if( pPam
->GetPoint()->nContent
.GetIndex() || bLFStripped
)
5078 AppendTxtNode( AM_NOSPACE
);
5082 // LFs am Absatz-Ende entfernen
5083 if( !pPam
->GetPoint()->nContent
.GetIndex() && !bLFStripped
)
5084 StripTrailingPara();
5087 // falls fuer die Zelle eine Ausrichtung gesetzt wurde, muessen
5089 _HTMLAttrContext
*pCntxt
= PopContext();
5090 EndContext( pCntxt
);
5093 SetAttr( sal_False
);
5095 // Stacks und Attribut-Tabelle wiederherstellen
5096 pSaveStruct
->RestoreAll( *this );
5098 // PaM wiederherstellen.
5099 *pPam
->GetPoint() = pSaveStruct
->GetPos();
5104 class _TblSaveStruct
: public SwPendingStackData
5107 HTMLTable
*pCurTable
;
5109 _TblSaveStruct( HTMLTable
*pCurTbl
) :
5110 pCurTable( pCurTbl
)
5113 virtual ~_TblSaveStruct();
5115 // Aufbau der Tabelle anstossen und die Tabelle ggf. in einen
5116 // Rahmen packen. Wenn sal_True zurueckgegeben wird muss noch ein
5117 // Absatz eingefuegt werden!
5118 void MakeTable( sal_uInt16 nWidth
, SwPosition
& rPos
, SwDoc
*pDoc
);
5121 _TblSaveStruct::~_TblSaveStruct()
5125 void _TblSaveStruct::MakeTable( sal_uInt16 nWidth
, SwPosition
& rPos
, SwDoc
*pDoc
)
5127 pCurTable
->MakeTable( 0, nWidth
);
5129 _HTMLTableContext
*pTCntxt
= pCurTable
->GetContext();
5130 ASSERT( pTCntxt
, "Wo ist der Tabellen-Kontext" );
5132 SwTableNode
*pTblNd
= pTCntxt
->GetTableNode();
5133 ASSERT( pTblNd
, "Wo ist der Tabellen-Node" );
5135 if( pDoc
->GetRootFrm() && pTblNd
)
5137 // Existiert schon ein Layout, dann muss an dieser Tabelle die
5138 // BoxFrames neu erzeugt werden.
5140 if( pTCntxt
->GetFrmFmt() )
5142 pTCntxt
->GetFrmFmt()->DelFrms();
5144 pTCntxt
->GetFrmFmt()->MakeFrms();
5149 SwNodeIndex
aIdx( *pTblNd
->EndOfSectionNode(), 1 );
5150 ASSERT( aIdx
.GetIndex() <= pTCntxt
->GetPos()->nNode
.GetIndex(),
5151 "unerwarteter Node fuer das Tabellen-Layout" );
5152 pTblNd
->MakeFrms( &aIdx
);
5156 rPos
= *pTCntxt
->GetPos();
5160 HTMLTableOptions::HTMLTableOptions( const HTMLOptions
*pOptions
,
5161 SvxAdjust eParentAdjust
) :
5163 nWidth( 0 ), nHeight( 0 ),
5164 nCellPadding( USHRT_MAX
), nCellSpacing( USHRT_MAX
),
5165 nBorder( USHRT_MAX
),
5166 nHSpace( 0 ), nVSpace( 0 ),
5167 eAdjust( eParentAdjust
), eVertOri( text::VertOrientation::CENTER
),
5168 eFrame( HTML_TF_VOID
), eRules( HTML_TR_NONE
),
5169 bPrcWidth( sal_False
),
5170 bTableAdjust( sal_False
),
5171 bBGColor( sal_False
),
5172 aBorderColor( COL_GRAY
)
5174 sal_Bool bBorderColor
= sal_False
;
5175 sal_Bool bHasFrame
= sal_False
, bHasRules
= sal_False
;
5177 for( sal_uInt16 i
= pOptions
->Count(); i
; )
5179 const HTMLOption
*pOption
= (*pOptions
)[--i
];
5180 switch( pOption
->GetToken() )
5183 aId
= pOption
->GetString();
5186 nCols
= (sal_uInt16
)pOption
->GetNumber();
5189 nWidth
= (sal_uInt16
)pOption
->GetNumber();
5190 bPrcWidth
= (pOption
->GetString().Search('%') != STRING_NOTFOUND
);
5191 if( bPrcWidth
&& nWidth
>100 )
5195 nHeight
= (sal_uInt16
)pOption
->GetNumber();
5196 if( pOption
->GetString().Search('%') != STRING_NOTFOUND
)
5197 nHeight
= 0; // keine %-Anagben benutzen!!!
5199 case HTML_O_CELLPADDING
:
5200 nCellPadding
= (sal_uInt16
)pOption
->GetNumber();
5202 case HTML_O_CELLSPACING
:
5203 nCellSpacing
= (sal_uInt16
)pOption
->GetNumber();
5207 sal_uInt16 nAdjust
= static_cast< sal_uInt16
>(eAdjust
);
5208 if( pOption
->GetEnum( nAdjust
, aHTMLPAlignTable
) )
5210 eAdjust
= (SvxAdjust
)nAdjust
;
5211 bTableAdjust
= sal_True
;
5216 eVertOri
= pOption
->GetEnum( aHTMLTblVAlignTable
, eVertOri
);
5219 // BORDER und BORDER=BORDER wie BORDER=1 behandeln
5220 if( pOption
->GetString().Len() &&
5221 !pOption
->GetString().EqualsIgnoreCaseAscii(OOO_STRING_SVTOOLS_HTML_O_border
) )
5222 nBorder
= (sal_uInt16
)pOption
->GetNumber();
5227 eFrame
= ( nBorder
? HTML_TF_BOX
: HTML_TF_VOID
);
5229 eRules
= ( nBorder
? HTML_TR_ALL
: HTML_TR_NONE
);
5232 eFrame
= pOption
->GetTableFrame();
5233 bHasFrame
= sal_True
;
5236 eRules
= pOption
->GetTableRules();
5237 bHasRules
= sal_True
;
5239 case HTML_O_BGCOLOR
:
5240 // Leere BGCOLOR bei <TABLE>, <TR> und <TD>/<TH> wie Netscape
5241 // ignorieren, bei allen anderen Tags *wirklich* nicht.
5242 if( pOption
->GetString().Len() )
5244 pOption
->GetColor( aBGColor
);
5245 bBGColor
= sal_True
;
5248 case HTML_O_BACKGROUND
:
5249 aBGImage
= pOption
->GetString();
5251 case HTML_O_BORDERCOLOR
:
5252 pOption
->GetColor( aBorderColor
);
5253 bBorderColor
= sal_True
;
5255 case HTML_O_BORDERCOLORDARK
:
5257 pOption
->GetColor( aBorderColor
);
5260 aStyle
= pOption
->GetString();
5263 aClass
= pOption
->GetString();
5266 aDir
= pOption
->GetString();
5269 nHSpace
= (sal_uInt16
)pOption
->GetNumber();
5272 nVSpace
= (sal_uInt16
)pOption
->GetNumber();
5277 if( nCols
&& !nWidth
)
5280 bPrcWidth
= sal_True
;
5283 // Wenn BORDER=0 oder kein BORDER gegeben ist, daan darf es auch
5284 // keine Umrandung geben
5285 if( 0==nBorder
|| USHRT_MAX
==nBorder
)
5287 eFrame
= HTML_TF_VOID
;
5288 eRules
= HTML_TR_NONE
;
5293 HTMLTable
*SwHTMLParser::BuildTable( SvxAdjust eParentAdjust
,
5294 sal_Bool bIsParentHead
,
5295 sal_Bool bHasParentSection
,
5296 sal_Bool bMakeTopSubTable
,
5297 sal_Bool bHasToFly
)
5299 if( !IsParserWorking() && !pPendStack
)
5303 sal_Bool bPending
= sal_False
;
5304 _TblSaveStruct
* pSaveStruct
;
5308 pSaveStruct
= (_TblSaveStruct
*)pPendStack
->pData
;
5310 SwPendingStack
* pTmp
= pPendStack
->pNext
;
5313 nToken
= pPendStack
? pPendStack
->nToken
: GetSaveToken();
5314 bPending
= SVPAR_ERROR
== eState
&& pPendStack
!= 0;
5316 SaveState( nToken
);
5321 HTMLTableOptions
*pTblOptions
=
5322 new HTMLTableOptions( GetOptions(), eParentAdjust
);
5324 if( pTblOptions
->aId
.Len() )
5325 InsertBookmark( pTblOptions
->aId
);
5327 HTMLTable
*pCurTable
= new HTMLTable( this, pTable
,
5336 pSaveStruct
= new _TblSaveStruct( pCurTable
);
5340 // ist beim ersten GetNextToken schon pending, muss bei
5341 // wiederaufsetzen auf jedenfall neu gelesen werden!
5345 HTMLTable
*pCurTable
= pSaveStruct
->pCurTable
;
5347 // </TABLE> wird laut DTD benoetigt
5349 nToken
= GetNextToken(); // naechstes Token
5351 sal_Bool bDone
= sal_False
;
5352 while( (IsParserWorking() && !bDone
) || bPending
)
5354 SaveState( nToken
);
5356 nToken
= FilterToken( nToken
);
5358 ASSERT( pPendStack
|| !bCallNextToken
||
5359 pCurTable
->GetContext() || pCurTable
->HasParentSection(),
5360 "Wo ist die Section gebieben?" );
5361 if( !pPendStack
&& bCallNextToken
&&
5362 (pCurTable
->GetContext() || pCurTable
->HasParentSection()) )
5364 // NextToken direkt aufrufen (z.B. um den Inhalt von
5365 // Floating-Frames oder Applets zu ignorieren)
5366 NextToken( nToken
);
5368 else switch( nToken
)
5371 if( !pCurTable
->GetContext() )
5373 // Wenn noch keine Tabelle eingefuegt wurde,
5374 // die naechste Tabelle lesen
5380 // NextToken( nToken );
5383 case HTML_TABLE_OFF
:
5386 case HTML_CAPTION_ON
:
5387 BuildTableCaption( pCurTable
);
5388 bDone
= pTable
->IsOverflowing();
5392 BuildTableColGroup( pCurTable
, sal_False
);
5394 case HTML_COLGROUP_ON
:
5395 BuildTableColGroup( pCurTable
, sal_True
);
5397 case HTML_TABLEROW_ON
:
5398 case HTML_TABLEHEADER_ON
:
5399 case HTML_TABLEDATA_ON
:
5401 BuildTableSection( pCurTable
, sal_False
, sal_False
);
5402 bDone
= pTable
->IsOverflowing();
5407 BuildTableSection( pCurTable
, sal_True
, HTML_THEAD_ON
==nToken
);
5408 bDone
= pTable
->IsOverflowing();
5410 case HTML_MULTICOL_ON
:
5411 // spaltige Rahmen koennen wir hier leider nicht einguegen
5414 NewForm( sal_False
); // keinen neuen Absatz aufmachen!
5417 EndForm( sal_False
); // keinen neuen Absatz aufmachen!
5419 case HTML_TEXTTOKEN
:
5420 // Blank-Strings sind u. U. eine Folge von CR+LF und kein Text
5421 if( (pCurTable
->GetContext() ||
5422 !pCurTable
->HasParentSection()) &&
5423 1==aToken
.Len() && ' '==aToken
.GetChar(0) )
5426 pCurTable
->MakeParentContents();
5427 NextToken( nToken
);
5431 ASSERT( !bPending
|| !pPendStack
,
5432 "SwHTMLParser::BuildTable: Es gibt wieder einen Pend-Stack" );
5433 bPending
= sal_False
;
5434 if( IsParserWorking() )
5438 nToken
= GetNextToken();
5441 if( SVPAR_PENDING
== GetStatus() )
5443 pPendStack
= new SwPendingStack( HTML_TABLE_ON
, pPendStack
);
5444 pPendStack
->pData
= pSaveStruct
;
5448 _HTMLTableContext
*pTCntxt
= pCurTable
->GetContext();
5451 // Die Tabelle wurde auch angelegt
5453 // Tabellen-Struktur anpassen
5454 pCurTable
->CloseTable();
5456 // ausserhalb von Zellen begonnene Kontexte beenden
5457 // muss vor(!) dem Umsetzten der Attribut Tabelle existieren,
5458 // weil die aktuelle danach nicht mehr existiert
5459 while( aContexts
.Count() > nContextStAttrMin
)
5461 _HTMLAttrContext
*pCntxt
= PopContext();
5462 ClearContext( pCntxt
);
5466 nContextStMin
= pTCntxt
->GetContextStMin();
5467 nContextStAttrMin
= pTCntxt
->GetContextStAttrMin();
5469 if( pTable
==pCurTable
)
5471 // Tabellen-Beschriftung setzen
5472 const SwStartNode
*pCapStNd
= pTable
->GetCaptionStartNode();
5475 // Der letzte Absatz der Section wird nie mitkopiert. Deshalb
5476 // muss die Section mindestens zwei Absaetze enthalten.
5478 if( pCapStNd
->EndOfSectionIndex() - pCapStNd
->GetIndex() > 2 )
5480 // Start-Node und letzten Absatz nicht mitkopieren.
5481 SwNodeRange
aSrcRg( *pCapStNd
, 1,
5482 *pCapStNd
->EndOfSectionNode(), -1 );
5484 sal_Bool bTop
= pTable
->IsTopCaption();
5485 SwStartNode
*pTblStNd
= pTCntxt
->GetTableNode();
5487 ASSERT( pTblStNd
, "Wo ist der Tabellen-Node" );
5488 ASSERT( pTblStNd
==pPam
->GetNode()->FindTableNode(),
5489 "Stehen wir in der falschen Tabelle?" );
5495 pNd
= pTblStNd
->EndOfSectionNode();
5496 SwNodeIndex
aDstIdx( *pNd
, bTop
? 0 : 1 );
5498 pDoc
->MoveNodeRange( aSrcRg
, aDstIdx
,
5499 IDocumentContentOperations::DOC_MOVEDEFAULT
);
5501 // Wenn die Caption vor der Tabelle eingefuegt wurde muss
5502 // eine an der Tabelle gestzte Seitenvorlage noch in den
5503 // ersten Absatz der Ueberschrift verschoben werden.
5504 // Ausserdem muessen alle gemerkten Indizes, die auf den
5505 // Tabellen-Node zeigen noch verschoben werden.
5508 MovePageDescAttrs( pTblStNd
, aSrcRg
.aStart
.GetIndex(),
5513 // Die Section wird jetzt nicht mehr gebraucht.
5516 pDoc
->DeleteSection( (SwStartNode
*)pCapStNd
);
5517 pTable
->SetCaption( 0, sal_False
);
5520 // SwTable aufbereiten
5521 sal_uInt16 nBrowseWidth
= (sal_uInt16
)GetCurrentBrowseWidth();
5522 pSaveStruct
->MakeTable( nBrowseWidth
, *pPam
->GetPoint(), pDoc
);
5525 const SwTable
*pSwTable
= pTable
->GetSwTable();
5526 SwHTMLTableLayout
*pLayoutInfo
=
5527 pSwTable
? ((SwTable
*)pSwTable
)->GetHTMLTableLayout() : 0;
5530 ViewShell
*pVSh
= CheckActionViewShell();
5533 CallEndAction( sal_False
, sal_False
);
5534 CallStartAction( pVSh
, sal_False
);
5536 sal_uInt16 nNewBrwoseWidth
=
5537 (sal_uInt16
)GetCurrentBrowseWidth();
5538 if( nBrowseWidth
!= nNewBrowseWidth
)
5539 pLayoutInfo
->Resize( nNewBrowseWidth
);
5545 GetNumInfo().Set( pTCntxt
->GetNumInfo() );
5546 pTCntxt
->RestorePREListingXMP( *this );
5547 RestoreAttrTab( pTCntxt
->aAttrTab
);
5549 if( pTable
==pCurTable
)
5551 // oberen Absatz-Abstand einstellen
5552 bUpperSpace
= sal_True
;
5555 nParaCnt
= nParaCnt
- Min(nParaCnt
, pTCntxt
->GetTableNode()->GetTable().GetTabSortBoxes().Count());
5557 // ggfs. eine Tabelle anspringen
5558 if( JUMPTO_TABLE
== eJumpTo
&& pTable
->GetSwTable() &&
5559 pTable
->GetSwTable()->GetFrmFmt()->GetName() == sJmpMark
)
5561 bChkJumpMark
= sal_True
;
5562 eJumpTo
= JUMPTO_NONE
;
5565 // fix #37886#: Wenn Import abgebrochen wurde kein erneutes Show
5566 // aufrufen, weil die ViewShell schon geloescht wurde!
5567 // fix #41669#: Genuegt nicht. Auch im ACCEPTING_STATE darf
5568 // kein Show aufgerufen werden, weil sonst waehrend des
5569 // Reschedules der Parser zerstoert wird, wenn noch ein
5570 // DataAvailable-Link kommt. Deshalb: Nur im WORKING-State.
5571 if( !nParaCnt
&& SVPAR_WORKING
== GetStatus() )
5575 else if( pTable
==pCurTable
)
5577 // Es wurde gar keine Tabelle gelesen.
5579 // Dann muss eine evtl gelesene Beschriftung noch geloescht werden.
5580 const SwStartNode
*pCapStNd
= pCurTable
->GetCaptionStartNode();
5585 pDoc
->DeleteSection( (SwStartNode
*)pCapStNd
);
5586 pCurTable
->SetCaption( 0, sal_False
);
5590 if( pTable
== pCurTable
)
5592 delete pSaveStruct
->pCurTable
;
5593 pSaveStruct
->pCurTable
= 0;
5597 HTMLTable
* pRetTbl
= pSaveStruct
->pCurTable
;