layout/tables/nsTableFrame.h

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5 #ifndef nsTableFrame_h__
michael@0 6 #define nsTableFrame_h__
michael@0 7
michael@0 8 #include "mozilla/Attributes.h"
michael@0 9 #include "celldata.h"
michael@0 10 #include "nscore.h"
michael@0 11 #include "nsContainerFrame.h"
michael@0 12 #include "nsStyleCoord.h"
michael@0 13 #include "nsStyleConsts.h"
michael@0 14 #include "nsTableColFrame.h"
michael@0 15 #include "nsTableColGroupFrame.h"
michael@0 16 #include "nsCellMap.h"
michael@0 17 #include "nsGkAtoms.h"
michael@0 18 #include "nsDisplayList.h"
michael@0 19
michael@0 20 class nsTableCellFrame;
michael@0 21 class nsTableCellMap;
michael@0 22 class nsTableColFrame;
michael@0 23 class nsColGroupFrame;
michael@0 24 class nsTableRowGroupFrame;
michael@0 25 class nsTableRowFrame;
michael@0 26 class nsTableColGroupFrame;
michael@0 27 class nsITableLayoutStrategy;
michael@0 28 class nsStyleContext;
michael@0 29
michael@0 30 struct nsTableReflowState;
michael@0 31 struct nsStylePosition;
michael@0 32 struct BCPropertyData;
michael@0 33
michael@0 34 static inline bool IS_TABLE_CELL(nsIAtom* frameType) {
michael@0 35 return nsGkAtoms::tableCellFrame == frameType ||
michael@0 36 nsGkAtoms::bcTableCellFrame == frameType;
michael@0 37 }
michael@0 38
michael@0 39 static inline bool FrameHasBorderOrBackground(nsIFrame* f) {
michael@0 40 return (f->StyleVisibility()->IsVisible() &&
michael@0 41 (!f->StyleBackground()->IsTransparent() ||
michael@0 42 f->StyleDisplay()->mAppearance ||
michael@0 43 f->StyleBorder()->HasBorder()));
michael@0 44 }
michael@0 45
michael@0 46 class nsDisplayTableItem : public nsDisplayItem
michael@0 47 {
michael@0 48 public:
michael@0 49 nsDisplayTableItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) :
michael@0 50 nsDisplayItem(aBuilder, aFrame),
michael@0 51 mPartHasFixedBackground(false) {}
michael@0 52
michael@0 53 virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
michael@0 54 nsIFrame* aFrame) MOZ_OVERRIDE;
michael@0 55 // With collapsed borders, parts of the collapsed border can extend outside
michael@0 56 // the table part frames, so allow this display element to blow out to our
michael@0 57 // overflow rect. This is also useful for row frames that have spanning
michael@0 58 // cells extending outside them.
michael@0 59 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
michael@0 60
michael@0 61 void UpdateForFrameBackground(nsIFrame* aFrame);
michael@0 62
michael@0 63 private:
michael@0 64 bool mPartHasFixedBackground;
michael@0 65 };
michael@0 66
michael@0 67 class nsAutoPushCurrentTableItem
michael@0 68 {
michael@0 69 public:
michael@0 70 nsAutoPushCurrentTableItem() : mBuilder(nullptr) {}
michael@0 71
michael@0 72 void Push(nsDisplayListBuilder* aBuilder, nsDisplayTableItem* aPushItem)
michael@0 73 {
michael@0 74 mBuilder = aBuilder;
michael@0 75 mOldCurrentItem = aBuilder->GetCurrentTableItem();
michael@0 76 aBuilder->SetCurrentTableItem(aPushItem);
michael@0 77 #ifdef DEBUG
michael@0 78 mPushedItem = aPushItem;
michael@0 79 #endif
michael@0 80 }
michael@0 81 ~nsAutoPushCurrentTableItem() {
michael@0 82 if (!mBuilder)
michael@0 83 return;
michael@0 84 #ifdef DEBUG
michael@0 85 NS_ASSERTION(mBuilder->GetCurrentTableItem() == mPushedItem,
michael@0 86 "Someone messed with the current table item behind our back!");
michael@0 87 #endif
michael@0 88 mBuilder->SetCurrentTableItem(mOldCurrentItem);
michael@0 89 }
michael@0 90
michael@0 91 private:
michael@0 92 nsDisplayListBuilder* mBuilder;
michael@0 93 nsDisplayTableItem* mOldCurrentItem;
michael@0 94 #ifdef DEBUG
michael@0 95 nsDisplayTableItem* mPushedItem;
michael@0 96 #endif
michael@0 97 };
michael@0 98
michael@0 99 /* ============================================================================ */
michael@0 100
michael@0 101 /**
michael@0 102 * nsTableFrame maps the inner portion of a table (everything except captions.)
michael@0 103 * Used as a pseudo-frame within nsTableOuterFrame, it may also be used
michael@0 104 * stand-alone as the top-level frame.
michael@0 105 *
michael@0 106 * The principal child list contains row group frames. There is also an
michael@0 107 * additional child list, kColGroupList, which contains the col group frames.
michael@0 108 */
michael@0 109 class nsTableFrame : public nsContainerFrame
michael@0 110 {
michael@0 111 public:
michael@0 112 NS_DECL_FRAMEARENA_HELPERS
michael@0 113
michael@0 114 static void DestroyPositionedTablePartArray(void* aPropertyValue);
michael@0 115 NS_DECLARE_FRAME_PROPERTY(PositionedTablePartArray, DestroyPositionedTablePartArray)
michael@0 116
michael@0 117 /** nsTableOuterFrame has intimate knowledge of the inner table frame */
michael@0 118 friend class nsTableOuterFrame;
michael@0 119
michael@0 120 /** instantiate a new instance of nsTableRowFrame.
michael@0 121 * @param aPresShell the pres shell for this frame
michael@0 122 *
michael@0 123 * @return the frame that was created
michael@0 124 */
michael@0 125 friend nsIFrame* NS_NewTableFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
michael@0 126
michael@0 127 /** sets defaults for table-specific style.
michael@0 128 * @see nsIFrame::Init
michael@0 129 */
michael@0 130 virtual void Init(nsIContent* aContent,
michael@0 131 nsIFrame* aParent,
michael@0 132 nsIFrame* aPrevInFlow) MOZ_OVERRIDE;
michael@0 133
michael@0 134 static float GetTwipsToPixels(nsPresContext* aPresContext);
michael@0 135
michael@0 136 // Return true if aParentReflowState.frame or any of its ancestors within
michael@0 137 // the containing table have non-auto height. (e.g. pct or fixed height)
michael@0 138 static bool AncestorsHaveStyleHeight(const nsHTMLReflowState& aParentReflowState);
michael@0 139
michael@0 140 // See if a special height reflow will occur due to having a pct height when
michael@0 141 // the pct height basis may not yet be valid.
michael@0 142 static void CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState);
michael@0 143
michael@0 144 // Notify the frame and its ancestors (up to the containing table) that a special
michael@0 145 // height reflow will occur.
michael@0 146 static void RequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState);
michael@0 147
michael@0 148 static void RePositionViews(nsIFrame* aFrame);
michael@0 149
michael@0 150 static bool PageBreakAfter(nsIFrame* aSourceFrame,
michael@0 151 nsIFrame* aNextFrame);
michael@0 152
michael@0 153 // Register a positioned table part with its nsTableFrame. These objects will
michael@0 154 // be visited by FixupPositionedTableParts after reflow is complete. (See that
michael@0 155 // function for more explanation.) Should be called during frame construction.
michael@0 156 static void RegisterPositionedTablePart(nsIFrame* aFrame);
michael@0 157
michael@0 158 // Unregister a positioned table part with its nsTableFrame.
michael@0 159 static void UnregisterPositionedTablePart(nsIFrame* aFrame,
michael@0 160 nsIFrame* aDestructRoot);
michael@0 161
michael@0 162 nsPoint GetFirstSectionOrigin(const nsHTMLReflowState& aReflowState) const;
michael@0 163 /*
michael@0 164 * Notification that aAttribute has changed for content inside a table (cell, row, etc)
michael@0 165 */
michael@0 166 void AttributeChangedFor(nsIFrame* aFrame,
michael@0 167 nsIContent* aContent,
michael@0 168 nsIAtom* aAttribute);
michael@0 169
michael@0 170 /** @see nsIFrame::DestroyFrom */
michael@0 171 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
michael@0 172
michael@0 173 /** @see nsIFrame::DidSetStyleContext */
michael@0 174 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
michael@0 175
michael@0 176 virtual nsresult AppendFrames(ChildListID aListID,
michael@0 177 nsFrameList& aFrameList) MOZ_OVERRIDE;
michael@0 178 virtual nsresult InsertFrames(ChildListID aListID,
michael@0 179 nsIFrame* aPrevFrame,
michael@0 180 nsFrameList& aFrameList) MOZ_OVERRIDE;
michael@0 181 virtual nsresult RemoveFrame(ChildListID aListID,
michael@0 182 nsIFrame* aOldFrame) MOZ_OVERRIDE;
michael@0 183
michael@0 184 virtual nsMargin GetUsedBorder() const MOZ_OVERRIDE;
michael@0 185 virtual nsMargin GetUsedPadding() const MOZ_OVERRIDE;
michael@0 186 virtual nsMargin GetUsedMargin() const MOZ_OVERRIDE;
michael@0 187
michael@0 188 // Get the offset from the border box to the area where the row groups fit
michael@0 189 nsMargin GetChildAreaOffset(const nsHTMLReflowState* aReflowState) const;
michael@0 190
michael@0 191 /** helper method to find the table parent of any table frame object */
michael@0 192 static nsTableFrame* GetTableFrame(nsIFrame* aSourceFrame);
michael@0 193
michael@0 194 /* Like GetTableFrame, but will return nullptr if we don't pass through
michael@0 195 * aMustPassThrough on the way to the table.
michael@0 196 */
michael@0 197 static nsTableFrame* GetTableFramePassingThrough(nsIFrame* aMustPassThrough,
michael@0 198 nsIFrame* aSourceFrame);
michael@0 199
michael@0 200 typedef void (* DisplayGenericTablePartTraversal)
michael@0 201 (nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
michael@0 202 const nsRect& aDirtyRect, const nsDisplayListSet& aLists);
michael@0 203 static void GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
michael@0 204 const nsRect& aDirtyRect, const nsDisplayListSet& aLists);
michael@0 205
michael@0 206 /**
michael@0 207 * Helper method to handle display common to table frames, rowgroup frames
michael@0 208 * and row frames. It creates a background display item for handling events
michael@0 209 * if necessary, an outline display item if necessary, and displays
michael@0 210 * all the the frame's children.
michael@0 211 * @param aDisplayItem the display item created for this part, or null
michael@0 212 * if this part's border/background painting is delegated to an ancestor
michael@0 213 * @param aTraversal a function that gets called to traverse the table
michael@0 214 * part's child frames and add their display list items to a
michael@0 215 * display list set.
michael@0 216 */
michael@0 217 static void DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
michael@0 218 nsFrame* aFrame,
michael@0 219 const nsRect& aDirtyRect,
michael@0 220 const nsDisplayListSet& aLists,
michael@0 221 nsDisplayTableItem* aDisplayItem,
michael@0 222 DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
michael@0 223
michael@0 224 // Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
michael@0 225 // of type aChildType.
michael@0 226 static nsIFrame* GetFrameAtOrBefore(nsIFrame* aParentFrame,
michael@0 227 nsIFrame* aPriorChildFrame,
michael@0 228 nsIAtom* aChildType);
michael@0 229 bool IsAutoHeight();
michael@0 230
michael@0 231 /** @return true if aDisplayType represents a rowgroup of any sort
michael@0 232 * (header, footer, or body)
michael@0 233 */
michael@0 234 bool IsRowGroup(int32_t aDisplayType) const;
michael@0 235
michael@0 236 /** Initialize the table frame with a set of children.
michael@0 237 * @see nsIFrame::SetInitialChildList
michael@0 238 */
michael@0 239 virtual nsresult SetInitialChildList(ChildListID aListID,
michael@0 240 nsFrameList& aChildList) MOZ_OVERRIDE;
michael@0 241
michael@0 242 virtual const nsFrameList& GetChildList(ChildListID aListID) const MOZ_OVERRIDE;
michael@0 243 virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE;
michael@0 244
michael@0 245 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
michael@0 246 const nsRect& aDirtyRect,
michael@0 247 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
michael@0 248
michael@0 249 /**
michael@0 250 * Paint the background of the table and its parts (column groups,
michael@0 251 * columns, row groups, rows, and cells), and the table border, and all
michael@0 252 * internal borders if border-collapse is on.
michael@0 253 */
michael@0 254 void PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
michael@0 255 const nsRect& aDirtyRect,
michael@0 256 nsPoint aPt, uint32_t aBGPaintFlags);
michael@0 257
michael@0 258 /**
michael@0 259 * Determines if any table part has a background image that is currently not
michael@0 260 * decoded. Does not look into cell contents (ie only table parts).
michael@0 261 */
michael@0 262 static bool AnyTablePartHasUndecodedBackgroundImage(nsIFrame* aStart,
michael@0 263 nsIFrame* aEnd);
michael@0 264
michael@0 265 /** Get the outer half (i.e., the part outside the height and width of
michael@0 266 * the table) of the largest segment (?) of border-collapsed border on
michael@0 267 * the table on each side, or 0 for non border-collapsed tables.
michael@0 268 */
michael@0 269 nsMargin GetOuterBCBorder() const;
michael@0 270
michael@0 271 /** Same as above, but only if it's included from the border-box width
michael@0 272 * of the table.
michael@0 273 */
michael@0 274 nsMargin GetIncludedOuterBCBorder() const;
michael@0 275
michael@0 276 /** Same as above, but only if it's excluded from the border-box width
michael@0 277 * of the table. This is the area that leaks out into the margin
michael@0 278 * (or potentially past it, if there is no margin).
michael@0 279 */
michael@0 280 nsMargin GetExcludedOuterBCBorder() const;
michael@0 281
michael@0 282 /**
michael@0 283 * In quirks mode, the size of the table background is reduced
michael@0 284 * by the outer BC border. Compute the reduction needed.
michael@0 285 */
michael@0 286 nsMargin GetDeflationForBackground(nsPresContext* aPresContext) const;
michael@0 287
michael@0 288 /** Get width of table + colgroup + col collapse: elements that
michael@0 289 * continue along the length of the whole left side.
michael@0 290 * see nsTablePainter about continuous borders
michael@0 291 */
michael@0 292 nscoord GetContinuousLeftBCBorderWidth() const;
michael@0 293 void SetContinuousLeftBCBorderWidth(nscoord aValue);
michael@0 294
michael@0 295 friend class nsDelayedCalcBCBorders;
michael@0 296
michael@0 297 void AddBCDamageArea(const nsIntRect& aValue);
michael@0 298 bool BCRecalcNeeded(nsStyleContext* aOldStyleContext,
michael@0 299 nsStyleContext* aNewStyleContext);
michael@0 300 void PaintBCBorders(nsRenderingContext& aRenderingContext,
michael@0 301 const nsRect& aDirtyRect);
michael@0 302
michael@0 303 virtual void MarkIntrinsicWidthsDirty() MOZ_OVERRIDE;
michael@0 304 // For border-collapse tables, the caller must not add padding and
michael@0 305 // border to the results of these functions.
michael@0 306 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
michael@0 307 virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
michael@0 308 virtual IntrinsicWidthOffsetData
michael@0 309 IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE;
michael@0 310
michael@0 311 virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
michael@0 312 nsSize aCBSize, nscoord aAvailableWidth,
michael@0 313 nsSize aMargin, nsSize aBorder, nsSize aPadding,
michael@0 314 uint32_t aFlags) MOZ_OVERRIDE;
michael@0 315 virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext,
michael@0 316 nsSize aCBSize, nscoord aAvailableWidth,
michael@0 317 nsSize aMargin, nsSize aBorder,
michael@0 318 nsSize aPadding, bool aShrinkWrap) MOZ_OVERRIDE;
michael@0 319 /**
michael@0 320 * A copy of nsFrame::ShrinkWidthToFit that calls a different
michael@0 321 * GetPrefWidth, since tables have two different ones.
michael@0 322 */
michael@0 323 nscoord TableShrinkWidthToFit(nsRenderingContext *aRenderingContext,
michael@0 324 nscoord aWidthInCB);
michael@0 325
michael@0 326 // XXXldb REWRITE THIS COMMENT!
michael@0 327 /** inner tables are reflowed in two steps.
michael@0 328 * <pre>
michael@0 329 * if mFirstPassValid is false, this is our first time through since content was last changed
michael@0 330 * set pass to 1
michael@0 331 * do pass 1
michael@0 332 * get min/max info for all cells in an infinite space
michael@0 333 * do column balancing
michael@0 334 * set mFirstPassValid to true
michael@0 335 * do pass 2
michael@0 336 * use column widths to Reflow cells
michael@0 337 * </pre>
michael@0 338 *
michael@0 339 * @see nsIFrame::Reflow
michael@0 340 */
michael@0 341 virtual nsresult Reflow(nsPresContext* aPresContext,
michael@0 342 nsHTMLReflowMetrics& aDesiredSize,
michael@0 343 const nsHTMLReflowState& aReflowState,
michael@0 344 nsReflowStatus& aStatus) MOZ_OVERRIDE;
michael@0 345
michael@0 346 nsresult ReflowTable(nsHTMLReflowMetrics& aDesiredSize,
michael@0 347 const nsHTMLReflowState& aReflowState,
michael@0 348 nscoord aAvailHeight,
michael@0 349 nsIFrame*& aLastChildReflowed,
michael@0 350 nsReflowStatus& aStatus);
michael@0 351
michael@0 352 nsFrameList& GetColGroups();
michael@0 353
michael@0 354 virtual nsIFrame* GetParentStyleContextFrame() const MOZ_OVERRIDE;
michael@0 355
michael@0 356 /**
michael@0 357 * Get the "type" of the frame
michael@0 358 *
michael@0 359 * @see nsGkAtoms::tableFrame
michael@0 360 */
michael@0 361 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
michael@0 362
michael@0 363 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
michael@0 364 {
michael@0 365 if (aFlags & eSupportsCSSTransforms) {
michael@0 366 return false;
michael@0 367 }
michael@0 368 return nsContainerFrame::IsFrameOfType(aFlags);
michael@0 369 }
michael@0 370
michael@0 371 #ifdef DEBUG_FRAME_DUMP
michael@0 372 /** @see nsIFrame::GetFrameName */
michael@0 373 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
michael@0 374 #endif
michael@0 375
michael@0 376 /** return the width of the column at aColIndex */
michael@0 377 int32_t GetColumnWidth(int32_t aColIndex);
michael@0 378
michael@0 379 /** helper to get the cell spacing X style value */
michael@0 380 nscoord GetCellSpacingX();
michael@0 381
michael@0 382 /** helper to get the cell spacing Y style value */
michael@0 383 nscoord GetCellSpacingY();
michael@0 384
michael@0 385 virtual nscoord GetBaseline() const MOZ_OVERRIDE;
michael@0 386 /** return the row span of a cell, taking into account row span magic at the bottom
michael@0 387 * of a table. The row span equals the number of rows spanned by aCell starting at
michael@0 388 * aStartRowIndex, and can be smaller if aStartRowIndex is greater than the row
michael@0 389 * index in which aCell originates.
michael@0 390 *
michael@0 391 * @param aStartRowIndex the cell
michael@0 392 * @param aCell the cell
michael@0 393 *
michael@0 394 * @return the row span, correcting for row spans that extend beyond the bottom
michael@0 395 * of the table.
michael@0 396 */
michael@0 397 int32_t GetEffectiveRowSpan(int32_t aStartRowIndex,
michael@0 398 const nsTableCellFrame& aCell) const;
michael@0 399 int32_t GetEffectiveRowSpan(const nsTableCellFrame& aCell,
michael@0 400 nsCellMap* aCellMap = nullptr);
michael@0 401
michael@0 402 /** return the col span of a cell, taking into account col span magic at the edge
michael@0 403 * of a table.
michael@0 404 *
michael@0 405 * @param aCell the cell
michael@0 406 *
michael@0 407 * @return the col span, correcting for col spans that extend beyond the edge
michael@0 408 * of the table.
michael@0 409 */
michael@0 410 int32_t GetEffectiveColSpan(const nsTableCellFrame& aCell,
michael@0 411 nsCellMap* aCellMap = nullptr) const;
michael@0 412
michael@0 413 /** indicate whether the row has more than one cell that either originates
michael@0 414 * or is spanned from the rows above
michael@0 415 */
michael@0 416 bool HasMoreThanOneCell(int32_t aRowIndex) const;
michael@0 417
michael@0 418 /** return the column frame associated with aColIndex
michael@0 419 * returns nullptr if the col frame has not yet been allocated, or if
michael@0 420 * aColIndex is out of range
michael@0 421 */
michael@0 422 nsTableColFrame* GetColFrame(int32_t aColIndex) const;
michael@0 423
michael@0 424 /** Insert a col frame reference into the colframe cache and adapt the cellmap
michael@0 425 * @param aColFrame - the column frame
michael@0 426 * @param aColIndex - index where the column should be inserted into the
michael@0 427 * colframe cache
michael@0 428 */
michael@0 429 void InsertCol(nsTableColFrame& aColFrame,
michael@0 430 int32_t aColIndex);
michael@0 431
michael@0 432 nsTableColGroupFrame* CreateAnonymousColGroupFrame(nsTableColGroupType aType);
michael@0 433
michael@0 434 int32_t DestroyAnonymousColFrames(int32_t aNumFrames);
michael@0 435
michael@0 436 // Append aNumColsToAdd anonymous col frames of type eColAnonymousCell to our
michael@0 437 // last eColGroupAnonymousCell colgroup. If we have no such colgroup, then
michael@0 438 // create one.
michael@0 439 void AppendAnonymousColFrames(int32_t aNumColsToAdd);
michael@0 440
michael@0 441 // Append aNumColsToAdd anonymous col frames of type aColType to
michael@0 442 // aColGroupFrame. If aAddToTable is true, also call AddColsToTable on the
michael@0 443 // new cols.
michael@0 444 void AppendAnonymousColFrames(nsTableColGroupFrame* aColGroupFrame,
michael@0 445 int32_t aNumColsToAdd,
michael@0 446 nsTableColType aColType,
michael@0 447 bool aAddToTable);
michael@0 448
michael@0 449 void MatchCellMapToColCache(nsTableCellMap* aCellMap);
michael@0 450 /** empty the column frame cache */
michael@0 451 void ClearColCache();
michael@0 452
michael@0 453 void DidResizeColumns();
michael@0 454
michael@0 455 void AppendCell(nsTableCellFrame& aCellFrame,
michael@0 456 int32_t aRowIndex);
michael@0 457
michael@0 458 void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
michael@0 459 int32_t aRowIndex,
michael@0 460 int32_t aColIndexBefore);
michael@0 461
michael@0 462 void RemoveCell(nsTableCellFrame* aCellFrame,
michael@0 463 int32_t aRowIndex);
michael@0 464
michael@0 465 void AppendRows(nsTableRowGroupFrame* aRowGroupFrame,
michael@0 466 int32_t aRowIndex,
michael@0 467 nsTArray<nsTableRowFrame*>& aRowFrames);
michael@0 468
michael@0 469 int32_t InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
michael@0 470 nsTArray<nsTableRowFrame*>& aFrames,
michael@0 471 int32_t aRowIndex,
michael@0 472 bool aConsiderSpans);
michael@0 473
michael@0 474 void RemoveRows(nsTableRowFrame& aFirstRowFrame,
michael@0 475 int32_t aNumRowsToRemove,
michael@0 476 bool aConsiderSpans);
michael@0 477
michael@0 478 /** Insert multiple rowgroups into the table cellmap handling
michael@0 479 * @param aRowGroups - iterator that iterates over the rowgroups to insert
michael@0 480 */
michael@0 481 void InsertRowGroups(const nsFrameList::Slice& aRowGroups);
michael@0 482
michael@0 483 void InsertColGroups(int32_t aStartColIndex,
michael@0 484 const nsFrameList::Slice& aColgroups);
michael@0 485
michael@0 486 void RemoveCol(nsTableColGroupFrame* aColGroupFrame,
michael@0 487 int32_t aColIndex,
michael@0 488 bool aRemoveFromCache,
michael@0 489 bool aRemoveFromCellMap);
michael@0 490
michael@0 491 bool ColumnHasCellSpacingBefore(int32_t aColIndex) const;
michael@0 492
michael@0 493 bool HasPctCol() const;
michael@0 494 void SetHasPctCol(bool aValue);
michael@0 495
michael@0 496 bool HasCellSpanningPctCol() const;
michael@0 497 void SetHasCellSpanningPctCol(bool aValue);
michael@0 498
michael@0 499 /**
michael@0 500 * To be called on a frame by its parent after setting its size/position and
michael@0 501 * calling DidReflow (possibly via FinishReflowChild()). This can also be
michael@0 502 * used for child frames which are not being reflowed but did have their size
michael@0 503 * or position changed.
michael@0 504 *
michael@0 505 * @param aFrame The frame to invalidate
michael@0 506 * @param aOrigRect The original rect of aFrame (before the change).
michael@0 507 * @param aOrigVisualOverflow The original overflow rect of aFrame.
michael@0 508 * @param aIsFirstReflow True if the size/position change is due to the
michael@0 509 * first reflow of aFrame.
michael@0 510 */
michael@0 511 static void InvalidateTableFrame(nsIFrame* aFrame,
michael@0 512 const nsRect& aOrigRect,
michael@0 513 const nsRect& aOrigVisualOverflow,
michael@0 514 bool aIsFirstReflow);
michael@0 515
michael@0 516 virtual bool UpdateOverflow() MOZ_OVERRIDE;
michael@0 517
michael@0 518 protected:
michael@0 519
michael@0 520 /** protected constructor.
michael@0 521 * @see NewFrame
michael@0 522 */
michael@0 523 nsTableFrame(nsStyleContext* aContext);
michael@0 524
michael@0 525 /** destructor, responsible for mColumnLayoutData */
michael@0 526 virtual ~nsTableFrame();
michael@0 527
michael@0 528 void InitChildReflowState(nsHTMLReflowState& aReflowState);
michael@0 529
michael@0 530 virtual int GetLogicalSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE;
michael@0 531
michael@0 532 public:
michael@0 533 bool IsRowInserted() const;
michael@0 534 void SetRowInserted(bool aValue);
michael@0 535
michael@0 536 protected:
michael@0 537
michael@0 538 // A helper function to reflow a header or footer with unconstrained height
michael@0 539 // to see if it should be made repeatable and also to determine its desired
michael@0 540 // height.
michael@0 541 nsresult SetupHeaderFooterChild(const nsTableReflowState& aReflowState,
michael@0 542 nsTableRowGroupFrame* aFrame,
michael@0 543 nscoord* aDesiredHeight);
michael@0 544
michael@0 545 nsresult ReflowChildren(nsTableReflowState& aReflowState,
michael@0 546 nsReflowStatus& aStatus,
michael@0 547 nsIFrame*& aLastChildReflowed,
michael@0 548 nsOverflowAreas& aOverflowAreas);
michael@0 549
michael@0 550 // This calls the col group and column reflow methods, which do two things:
michael@0 551 // (1) set all the dimensions to 0
michael@0 552 // (2) notify the table about colgroups or columns with hidden visibility
michael@0 553 void ReflowColGroups(nsRenderingContext* aRenderingContext);
michael@0 554
michael@0 555 /** return the width of the table taking into account visibility collapse
michael@0 556 * on columns and colgroups
michael@0 557 * @param aBorderPadding the border and padding of the table
michael@0 558 */
michael@0 559 nscoord GetCollapsedWidth(nsMargin aBorderPadding);
michael@0 560
michael@0 561
michael@0 562 /** Adjust the table for visibility.collapse set on rowgroups, rows,
michael@0 563 * colgroups and cols
michael@0 564 * @param aDesiredSize the metrics of the table
michael@0 565 * @param aBorderPadding the border and padding of the table
michael@0 566 */
michael@0 567 void AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize,
michael@0 568 nsMargin aBorderPadding);
michael@0 569
michael@0 570 /** FixupPositionedTableParts is called at the end of table reflow to reflow
michael@0 571 * the absolutely positioned descendants of positioned table parts. This is
michael@0 572 * necessary because the dimensions of table parts may change after they've
michael@0 573 * been reflowed (e.g. in AdjustForCollapsingRowsCols).
michael@0 574 */
michael@0 575 void FixupPositionedTableParts(nsPresContext* aPresContext,
michael@0 576 nsHTMLReflowMetrics& aDesiredSize,
michael@0 577 const nsHTMLReflowState& aReflowState);
michael@0 578
michael@0 579 // Clears the list of positioned table parts.
michael@0 580 void ClearAllPositionedTableParts();
michael@0 581
michael@0 582 nsITableLayoutStrategy* LayoutStrategy() const {
michael@0 583 return static_cast<nsTableFrame*>(FirstInFlow())->
michael@0 584 mTableLayoutStrategy;
michael@0 585 }
michael@0 586
michael@0 587 // Helper for InsertFrames.
michael@0 588 void HomogenousInsertFrames(ChildListID aListID,
michael@0 589 nsIFrame* aPrevFrame,
michael@0 590 nsFrameList& aFrameList);
michael@0 591 private:
michael@0 592 /* Handle a row that got inserted during reflow. aNewHeight is the
michael@0 593 new height of the table after reflow. */
michael@0 594 void ProcessRowInserted(nscoord aNewHeight);
michael@0 595
michael@0 596 // WIDTH AND HEIGHT CALCULATION
michael@0 597
michael@0 598 public:
michael@0 599
michael@0 600 // calculate the computed height of aFrame including its border and padding given
michael@0 601 // its reflow state.
michael@0 602 nscoord CalcBorderBoxHeight(const nsHTMLReflowState& aReflowState);
michael@0 603
michael@0 604 protected:
michael@0 605
michael@0 606 // update the desired height of this table taking into account the current
michael@0 607 // reflow state, the table attributes and the content driven rowgroup heights
michael@0 608 // this function can change the overflow area
michael@0 609 void CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize);
michael@0 610
michael@0 611 // The following is a helper for CalcDesiredHeight
michael@0 612
michael@0 613 void DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
michael@0 614 nscoord aAmount);
michael@0 615
michael@0 616 void PlaceChild(nsTableReflowState& aReflowState,
michael@0 617 nsIFrame* aKidFrame,
michael@0 618 nsHTMLReflowMetrics& aKidDesiredSize,
michael@0 619 const nsRect& aOriginalKidRect,
michael@0 620 const nsRect& aOriginalKidVisualOverflow);
michael@0 621 void PlaceRepeatedFooter(nsTableReflowState& aReflowState,
michael@0 622 nsTableRowGroupFrame *aTfoot,
michael@0 623 nscoord aFooterHeight);
michael@0 624
michael@0 625 nsIFrame* GetFirstBodyRowGroupFrame();
michael@0 626 public:
michael@0 627 typedef nsAutoTArray<nsTableRowGroupFrame*, 8> RowGroupArray;
michael@0 628 /**
michael@0 629 * Push all our child frames from the aRowGroups array, in order, starting
michael@0 630 * from the frame at aPushFrom to the end of the array. The frames are put on
michael@0 631 * our overflow list or moved directly to our next-in-flow if one exists.
michael@0 632 */
michael@0 633 protected:
michael@0 634 void PushChildren(const RowGroupArray& aRowGroups, int32_t aPushFrom);
michael@0 635
michael@0 636 public:
michael@0 637 // put the children frames in the display order (e.g. thead before tbodies
michael@0 638 // before tfoot). This will handle calling GetRowGroupFrame() on the
michael@0 639 // children, and not append nulls, so the array is guaranteed to contain
michael@0 640 // nsTableRowGroupFrames. If there are multiple theads or tfoots, all but
michael@0 641 // the first one are treated as tbodies instead.
michael@0 642
michael@0 643 void OrderRowGroups(RowGroupArray& aChildren,
michael@0 644 nsTableRowGroupFrame** aHead = nullptr,
michael@0 645 nsTableRowGroupFrame** aFoot = nullptr) const;
michael@0 646
michael@0 647 // Return the thead, if any
michael@0 648 nsTableRowGroupFrame* GetTHead() const;
michael@0 649
michael@0 650 // Return the tfoot, if any
michael@0 651 nsTableRowGroupFrame* GetTFoot() const;
michael@0 652
michael@0 653 // Returns true if there are any cells above the row at
michael@0 654 // aRowIndex and spanning into the row at aRowIndex, the number of
michael@0 655 // effective columns limits the search up to that column
michael@0 656 bool RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols);
michael@0 657
michael@0 658 // Returns true if there is a cell originating in aRowIndex
michael@0 659 // which spans into the next row, the number of effective
michael@0 660 // columns limits the search up to that column
michael@0 661 bool RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols);
michael@0 662
michael@0 663 protected:
michael@0 664
michael@0 665 bool HaveReflowedColGroups() const;
michael@0 666 void SetHaveReflowedColGroups(bool aValue);
michael@0 667
michael@0 668 public:
michael@0 669 bool IsBorderCollapse() const;
michael@0 670
michael@0 671 bool NeedToCalcBCBorders() const;
michael@0 672 void SetNeedToCalcBCBorders(bool aValue);
michael@0 673
michael@0 674 bool NeedToCollapse() const;
michael@0 675 void SetNeedToCollapse(bool aValue);
michael@0 676
michael@0 677 bool HasZeroColSpans() const;
michael@0 678 void SetHasZeroColSpans(bool aValue);
michael@0 679
michael@0 680 bool NeedColSpanExpansion() const;
michael@0 681 void SetNeedColSpanExpansion(bool aValue);
michael@0 682
michael@0 683 /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame
michael@0 684 * state bit, which implies that all descendants are dirty. The
michael@0 685 * GeometryDirty still implies that all the parts of the table are
michael@0 686 * dirty, but resizing optimizations should still apply to the
michael@0 687 * contents of the individual cells.
michael@0 688 */
michael@0 689 void SetGeometryDirty() { mBits.mGeometryDirty = true; }
michael@0 690 void ClearGeometryDirty() { mBits.mGeometryDirty = false; }
michael@0 691 bool IsGeometryDirty() const { return mBits.mGeometryDirty; }
michael@0 692
michael@0 693 /** Get the cell map for this table frame. It is not always mCellMap.
michael@0 694 * Only the firstInFlow has a legit cell map
michael@0 695 */
michael@0 696 nsTableCellMap* GetCellMap() const;
michael@0 697
michael@0 698 /** Iterate over the row groups and adjust the row indices of all rows
michael@0 699 * whose index is >= aRowIndex.
michael@0 700 * @param aRowIndex - start adjusting with this index
michael@0 701 * @param aAdjustment - shift the row index by this amount
michael@0 702 */
michael@0 703 void AdjustRowIndices(int32_t aRowIndex,
michael@0 704 int32_t aAdjustment);
michael@0 705
michael@0 706 /** Reset the rowindices of all rows as they might have changed due to
michael@0 707 * rowgroup reordering, exclude new row group frames that show in the
michael@0 708 * reordering but are not yet inserted into the cellmap
michael@0 709 * @param aRowGroupsToExclude - an iterator that will produce the row groups
michael@0 710 * to exclude.
michael@0 711 */
michael@0 712 void ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude);
michael@0 713
michael@0 714 nsTArray<nsTableColFrame*>& GetColCache();
michael@0 715
michael@0 716
michael@0 717 protected:
michael@0 718
michael@0 719 void SetBorderCollapse(bool aValue);
michael@0 720
michael@0 721 BCPropertyData* GetBCProperty(bool aCreateIfNecessary = false) const;
michael@0 722 void SetFullBCDamageArea();
michael@0 723 void CalcBCBorders();
michael@0 724
michael@0 725 void ExpandBCDamageArea(nsIntRect& aRect) const;
michael@0 726
michael@0 727 void SetColumnDimensions(nscoord aHeight,
michael@0 728 const nsMargin& aReflowState);
michael@0 729
michael@0 730 int32_t CollectRows(nsIFrame* aFrame,
michael@0 731 nsTArray<nsTableRowFrame*>& aCollection);
michael@0 732
michael@0 733 public: /* ----- Cell Map public methods ----- */
michael@0 734
michael@0 735 int32_t GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame);
michael@0 736
michael@0 737 /** returns the number of rows in this table.
michael@0 738 */
michael@0 739 int32_t GetRowCount () const
michael@0 740 {
michael@0 741 return GetCellMap()->GetRowCount();
michael@0 742 }
michael@0 743
michael@0 744 /** returns the number of columns in this table after redundant columns have been removed
michael@0 745 */
michael@0 746 int32_t GetEffectiveColCount() const;
michael@0 747
michael@0 748 /* return the col count including dead cols */
michael@0 749 int32_t GetColCount () const
michael@0 750 {
michael@0 751 return GetCellMap()->GetColCount();
michael@0 752 }
michael@0 753
michael@0 754 // return the last col index which isn't of type eColAnonymousCell
michael@0 755 int32_t GetIndexOfLastRealCol();
michael@0 756
michael@0 757 /** returns true if table-layout:auto */
michael@0 758 bool IsAutoLayout();
michael@0 759
michael@0 760 public:
michael@0 761
michael@0 762 #ifdef DEBUG
michael@0 763 void Dump(bool aDumpRows,
michael@0 764 bool aDumpCols,
michael@0 765 bool aDumpCellMap);
michael@0 766 #endif
michael@0 767
michael@0 768 protected:
michael@0 769 /**
michael@0 770 * Helper method for RemoveFrame.
michael@0 771 */
michael@0 772 void DoRemoveFrame(ChildListID aListID, nsIFrame* aOldFrame);
michael@0 773 #ifdef DEBUG
michael@0 774 void DumpRowGroup(nsIFrame* aChildFrame);
michael@0 775 #endif
michael@0 776 // DATA MEMBERS
michael@0 777 nsAutoTArray<nsTableColFrame*, 8> mColFrames;
michael@0 778
michael@0 779 struct TableBits {
michael@0 780 uint32_t mHaveReflowedColGroups:1; // have the col groups gotten their initial reflow
michael@0 781 uint32_t mHasPctCol:1; // does any cell or col have a pct width
michael@0 782 uint32_t mCellSpansPctCol:1; // does any cell span a col with a pct width (or containing a cell with a pct width)
michael@0 783 uint32_t mIsBorderCollapse:1; // border collapsing model vs. separate model
michael@0 784 uint32_t mRowInserted:1;
michael@0 785 uint32_t mNeedToCalcBCBorders:1;
michael@0 786 uint32_t mGeometryDirty:1;
michael@0 787 uint32_t mLeftContBCBorder:8;
michael@0 788 uint32_t mNeedToCollapse:1; // rows, cols that have visibility:collapse need to be collapsed
michael@0 789 uint32_t mHasZeroColSpans:1;
michael@0 790 uint32_t mNeedColSpanExpansion:1;
michael@0 791 uint32_t mResizedColumns:1; // have we resized columns since last reflow?
michael@0 792 } mBits;
michael@0 793
michael@0 794 nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
michael@0 795 nsITableLayoutStrategy* mTableLayoutStrategy;// the layout strategy for this frame
michael@0 796 nsFrameList mColGroups; // the list of colgroup frames
michael@0 797 };
michael@0 798
michael@0 799
michael@0 800 inline bool nsTableFrame::IsRowGroup(int32_t aDisplayType) const
michael@0 801 {
michael@0 802 return bool((NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == aDisplayType) ||
michael@0 803 (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == aDisplayType) ||
michael@0 804 (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == aDisplayType));
michael@0 805 }
michael@0 806
michael@0 807 inline void nsTableFrame::SetHaveReflowedColGroups(bool aValue)
michael@0 808 {
michael@0 809 mBits.mHaveReflowedColGroups = aValue;
michael@0 810 }
michael@0 811
michael@0 812 inline bool nsTableFrame::HaveReflowedColGroups() const
michael@0 813 {
michael@0 814 return (bool)mBits.mHaveReflowedColGroups;
michael@0 815 }
michael@0 816
michael@0 817 inline bool nsTableFrame::HasPctCol() const
michael@0 818 {
michael@0 819 return (bool)mBits.mHasPctCol;
michael@0 820 }
michael@0 821
michael@0 822 inline void nsTableFrame::SetHasPctCol(bool aValue)
michael@0 823 {
michael@0 824 mBits.mHasPctCol = (unsigned)aValue;
michael@0 825 }
michael@0 826
michael@0 827 inline bool nsTableFrame::HasCellSpanningPctCol() const
michael@0 828 {
michael@0 829 return (bool)mBits.mCellSpansPctCol;
michael@0 830 }
michael@0 831
michael@0 832 inline void nsTableFrame::SetHasCellSpanningPctCol(bool aValue)
michael@0 833 {
michael@0 834 mBits.mCellSpansPctCol = (unsigned)aValue;
michael@0 835 }
michael@0 836
michael@0 837 inline bool nsTableFrame::IsRowInserted() const
michael@0 838 {
michael@0 839 return (bool)mBits.mRowInserted;
michael@0 840 }
michael@0 841
michael@0 842 inline void nsTableFrame::SetRowInserted(bool aValue)
michael@0 843 {
michael@0 844 mBits.mRowInserted = (unsigned)aValue;
michael@0 845 }
michael@0 846
michael@0 847 inline void nsTableFrame::SetNeedToCollapse(bool aValue)
michael@0 848 {
michael@0 849 static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse = (unsigned)aValue;
michael@0 850 }
michael@0 851
michael@0 852 inline bool nsTableFrame::NeedToCollapse() const
michael@0 853 {
michael@0 854 return (bool) static_cast<nsTableFrame*>(FirstInFlow())->mBits.mNeedToCollapse;
michael@0 855 }
michael@0 856
michael@0 857 inline void nsTableFrame::SetHasZeroColSpans(bool aValue)
michael@0 858 {
michael@0 859 mBits.mHasZeroColSpans = (unsigned)aValue;
michael@0 860 }
michael@0 861
michael@0 862 inline bool nsTableFrame::HasZeroColSpans() const
michael@0 863 {
michael@0 864 return (bool)mBits.mHasZeroColSpans;
michael@0 865 }
michael@0 866
michael@0 867 inline void nsTableFrame::SetNeedColSpanExpansion(bool aValue)
michael@0 868 {
michael@0 869 mBits.mNeedColSpanExpansion = (unsigned)aValue;
michael@0 870 }
michael@0 871
michael@0 872 inline bool nsTableFrame::NeedColSpanExpansion() const
michael@0 873 {
michael@0 874 return (bool)mBits.mNeedColSpanExpansion;
michael@0 875 }
michael@0 876
michael@0 877
michael@0 878 inline nsFrameList& nsTableFrame::GetColGroups()
michael@0 879 {
michael@0 880 return static_cast<nsTableFrame*>(FirstInFlow())->mColGroups;
michael@0 881 }
michael@0 882
michael@0 883 inline nsTArray<nsTableColFrame*>& nsTableFrame::GetColCache()
michael@0 884 {
michael@0 885 return mColFrames;
michael@0 886 }
michael@0 887
michael@0 888 inline bool nsTableFrame::IsBorderCollapse() const
michael@0 889 {
michael@0 890 return (bool)mBits.mIsBorderCollapse;
michael@0 891 }
michael@0 892
michael@0 893 inline void nsTableFrame::SetBorderCollapse(bool aValue)
michael@0 894 {
michael@0 895 mBits.mIsBorderCollapse = aValue;
michael@0 896 }
michael@0 897
michael@0 898 inline bool nsTableFrame::NeedToCalcBCBorders() const
michael@0 899 {
michael@0 900 return (bool)mBits.mNeedToCalcBCBorders;
michael@0 901 }
michael@0 902
michael@0 903 inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue)
michael@0 904 {
michael@0 905 mBits.mNeedToCalcBCBorders = (unsigned)aValue;
michael@0 906 }
michael@0 907
michael@0 908 inline nscoord
michael@0 909 nsTableFrame::GetContinuousLeftBCBorderWidth() const
michael@0 910 {
michael@0 911 int32_t aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
michael@0 912 return BC_BORDER_RIGHT_HALF_COORD(aPixelsToTwips, mBits.mLeftContBCBorder);
michael@0 913 }
michael@0 914
michael@0 915 inline void nsTableFrame::SetContinuousLeftBCBorderWidth(nscoord aValue)
michael@0 916 {
michael@0 917 mBits.mLeftContBCBorder = (unsigned) aValue;
michael@0 918 }
michael@0 919
michael@0 920 class nsTableIterator
michael@0 921 {
michael@0 922 public:
michael@0 923 nsTableIterator(nsIFrame& aSource);
michael@0 924 nsTableIterator(nsFrameList& aSource);
michael@0 925 nsIFrame* First();
michael@0 926 nsIFrame* Next();
michael@0 927 bool IsLeftToRight();
michael@0 928 int32_t Count();
michael@0 929
michael@0 930 protected:
michael@0 931 void Init(nsIFrame* aFirstChild);
michael@0 932 bool mLeftToRight;
michael@0 933 nsIFrame* mFirstListChild;
michael@0 934 nsIFrame* mFirstChild;
michael@0 935 nsIFrame* mCurrentChild;
michael@0 936 int32_t mCount;
michael@0 937 };
michael@0 938
michael@0 939 #define ABORT0() \
michael@0 940 {NS_ASSERTION(false, "CellIterator program error"); \
michael@0 941 return;}
michael@0 942
michael@0 943 #define ABORT1(aReturn) \
michael@0 944 {NS_ASSERTION(false, "CellIterator program error"); \
michael@0 945 return aReturn;}
michael@0 946
michael@0 947 #endif

mercurial