1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either of the GNU General Public License Version 2 or later (the "GPL"),
26 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 : #ifndef nsCellMap_h__
38 : #define nsCellMap_h__
39 :
40 : #include "nscore.h"
41 : #include "celldata.h"
42 : #include "nsTArray.h"
43 : #include "nsTArray.h"
44 : #include "nsRect.h"
45 : #include "nsCOMPtr.h"
46 : #include "nsAlgorithm.h"
47 : #include "nsAutoPtr.h"
48 :
49 : #undef DEBUG_TABLE_CELLMAP
50 :
51 : class nsTableColFrame;
52 : class nsTableCellFrame;
53 : class nsTableRowFrame;
54 : class nsTableRowGroupFrame;
55 : class nsTableFrame;
56 : class nsCellMap;
57 : class nsPresContext;
58 : class nsCellMapColumnIterator;
59 :
60 : struct nsColInfo
61 0 : {
62 : PRInt32 mNumCellsOrig; // number of cells originating in the col
63 : PRInt32 mNumCellsSpan; // number of cells spanning into the col via colspans (not rowspans)
64 :
65 : nsColInfo();
66 : nsColInfo(PRInt32 aNumCellsOrig,
67 : PRInt32 aNumCellsSpan);
68 : };
69 :
70 : enum Corner
71 : {
72 : eTopLeft = 0,
73 : eTopRight = 1,
74 : eBottomRight = 2,
75 : eBottomLeft = 3
76 : };
77 :
78 : struct BCInfo
79 0 : {
80 : nsTArray<BCData> mRightBorders;
81 : nsTArray<BCData> mBottomBorders;
82 : BCData mLowerRightCorner;
83 : };
84 :
85 : class nsTableCellMap
86 : {
87 : public:
88 : nsTableCellMap(nsTableFrame& aTableFrame,
89 : bool aBorderCollapse);
90 :
91 : /** destructor
92 : * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
93 : */
94 : ~nsTableCellMap();
95 :
96 : void RemoveGroupCellMap(nsTableRowGroupFrame* aRowGroup);
97 :
98 : void InsertGroupCellMap(nsTableRowGroupFrame* aNewRowGroup,
99 : nsTableRowGroupFrame*& aPrevRowGroup);
100 :
101 : /**
102 : * Get the nsCellMap for the given row group. If aStartHint is non-null,
103 : * will start looking with that cellmap and only fall back to starting at the
104 : * beginning of the list if that doesn't find us the right nsCellMap.
105 : * Otherwise, just start at the beginning.
106 : *
107 : * aRowGroup must not be null.
108 : */
109 : nsCellMap* GetMapFor(const nsTableRowGroupFrame* aRowGroup,
110 : nsCellMap* aStartHint) const;
111 :
112 : /** synchronize the cellmaps with the rowgroups again **/
113 : void Synchronize(nsTableFrame* aTableFrame);
114 :
115 : nsTableCellFrame* GetCellFrame(PRInt32 aRowIndex,
116 : PRInt32 aColIndex,
117 : CellData& aData,
118 : bool aUseRowIfOverlap) const;
119 :
120 : /** return the CellData for the cell at (aRowIndex, aColIndex) */
121 : CellData* GetDataAt(PRInt32 aRowIndex,
122 : PRInt32 aColIndex) const;
123 :
124 : // this function creates a col if needed
125 : nsColInfo* GetColInfoAt(PRInt32 aColIndex);
126 :
127 : /** append the cellFrame at the end of the row at aRowIndex and return the col index
128 : */
129 : CellData* AppendCell(nsTableCellFrame& aCellFrame,
130 : PRInt32 aRowIndex,
131 : bool aRebuildIfNecessary,
132 : nsIntRect& aDamageArea);
133 :
134 : void InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
135 : PRInt32 aRowIndex,
136 : PRInt32 aColIndexBefore,
137 : nsIntRect& aDamageArea);
138 :
139 : void RemoveCell(nsTableCellFrame* aCellFrame,
140 : PRInt32 aRowIndex,
141 : nsIntRect& aDamageArea);
142 : /** Remove the previously gathered column information */
143 : void ClearCols();
144 : void InsertRows(nsTableRowGroupFrame* aRowGroup,
145 : nsTArray<nsTableRowFrame*>& aRows,
146 : PRInt32 aFirstRowIndex,
147 : bool aConsiderSpans,
148 : nsIntRect& aDamageArea);
149 :
150 : void RemoveRows(PRInt32 aFirstRowIndex,
151 : PRInt32 aNumRowsToRemove,
152 : bool aConsiderSpans,
153 : nsIntRect& aDamageArea);
154 :
155 : PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
156 : PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
157 :
158 : /** indicate whether the row has more than one cell that either originates
159 : * or is spanned from the rows above
160 : */
161 : bool HasMoreThanOneCell(PRInt32 aRowIndex) const;
162 :
163 : PRInt32 GetEffectiveRowSpan(PRInt32 aRowIndex,
164 : PRInt32 aColIndex) const;
165 : PRInt32 GetEffectiveColSpan(PRInt32 aRowIndex,
166 : PRInt32 aColIndex) const;
167 :
168 : /** return the total number of columns in the table represented by this CellMap */
169 : PRInt32 GetColCount() const;
170 :
171 : /** return the actual number of rows in the table represented by this CellMap */
172 : PRInt32 GetRowCount() const;
173 :
174 : nsTableCellFrame* GetCellInfoAt(PRInt32 aRowX,
175 : PRInt32 aColX,
176 : bool* aOriginates = nsnull,
177 : PRInt32* aColSpan = nsnull) const;
178 :
179 : /**
180 : * Returns the index at the given row and column coordinates.
181 : *
182 : * @see nsITableLayout::GetIndexByRowAndColumn()
183 : *
184 : * @param aRow [in] the row coordinate
185 : * @param aColumn [in] the column coordinate
186 : * @returns the index for the cell
187 : */
188 : PRInt32 GetIndexByRowAndColumn(PRInt32 aRow, PRInt32 aColumn) const;
189 :
190 : /**
191 : * Retrieves the row and column coordinates for the given index.
192 : *
193 : * @see nsITableLayout::GetRowAndColumnByIndex()
194 : *
195 : * @param aIndex [in] the index for which coordinates are to be retrieved
196 : * @param aRow [out] the row coordinate to be returned
197 : * @param aColumn [out] the column coordinate to be returned
198 : */
199 : void GetRowAndColumnByIndex(PRInt32 aIndex,
200 : PRInt32 *aRow, PRInt32 *aColumn) const;
201 :
202 : void AddColsAtEnd(PRUint32 aNumCols);
203 : void RemoveColsAtEnd();
204 :
205 : bool RowIsSpannedInto(PRInt32 aRowIndex, PRInt32 aNumEffCols) const;
206 : bool RowHasSpanningCells(PRInt32 aRowIndex, PRInt32 aNumEffCols) const;
207 : void RebuildConsideringCells(nsCellMap* aCellMap,
208 : nsTArray<nsTableCellFrame*>* aCellFrames,
209 : PRInt32 aRowIndex,
210 : PRInt32 aColIndex,
211 : bool aInsert,
212 : nsIntRect& aDamageArea);
213 :
214 : protected:
215 : /**
216 : * Rebuild due to rows being inserted or deleted with cells spanning
217 : * into or out of the rows. This function can only handle insertion
218 : * or deletion but NOT both. So either aRowsToInsert must be null
219 : * or aNumRowsToRemove must be 0.
220 : *
221 : * // XXXbz are both allowed to happen? That'd be a no-op...
222 : */
223 : void RebuildConsideringRows(nsCellMap* aCellMap,
224 : PRInt32 aStartRowIndex,
225 : nsTArray<nsTableRowFrame*>* aRowsToInsert,
226 : PRInt32 aNumRowsToRemove,
227 : nsIntRect& aDamageArea);
228 :
229 : public:
230 : void ExpandZeroColSpans();
231 :
232 : void ResetTopStart(PRUint8 aSide,
233 : nsCellMap& aCellMap,
234 : PRUint32 aYPos,
235 : PRUint32 aXPos,
236 : bool aIsLowerRight = false);
237 :
238 : void SetBCBorderEdge(mozilla::css::Side aEdge,
239 : nsCellMap& aCellMap,
240 : PRUint32 aCellMapStart,
241 : PRUint32 aYPos,
242 : PRUint32 aXPos,
243 : PRUint32 aLength,
244 : BCBorderOwner aOwner,
245 : nscoord aSize,
246 : bool aChanged);
247 :
248 : void SetBCBorderCorner(Corner aCorner,
249 : nsCellMap& aCellMap,
250 : PRUint32 aCellMapStart,
251 : PRUint32 aYPos,
252 : PRUint32 aXPos,
253 : mozilla::css::Side aOwner,
254 : nscoord aSubSize,
255 : bool aBevel,
256 : bool aIsBottomRight = false);
257 :
258 : /** dump a representation of the cell map to stdout for debugging */
259 : #ifdef NS_DEBUG
260 : void Dump(char* aString = nsnull) const;
261 : #endif
262 :
263 : protected:
264 : BCData* GetRightMostBorder(PRInt32 aRowIndex);
265 : BCData* GetBottomMostBorder(PRInt32 aColIndex);
266 :
267 : friend class nsCellMap;
268 : friend class BCMapCellIterator;
269 : friend class BCPaintBorderIterator;
270 : friend class nsCellMapColumnIterator;
271 :
272 : /** Insert a row group cellmap after aPrevMap, if aPrefMap is null insert it
273 : * at the beginning, the ordering of the cellmap corresponds to the ordering of
274 : * rowgroups once OrderRowGroups has been called
275 : */
276 : void InsertGroupCellMap(nsCellMap* aPrevMap,
277 : nsCellMap& aNewMap);
278 : void DeleteRightBottomBorders();
279 :
280 : nsTableFrame& mTableFrame;
281 : nsAutoTArray<nsColInfo, 8> mCols;
282 : nsCellMap* mFirstMap;
283 : // border collapsing info
284 : BCInfo* mBCInfo;
285 : };
286 :
287 : /** nsCellMap is a support class for nsTablePart.
288 : * It maintains an Rows x Columns grid onto which the cells of the table are mapped.
289 : * This makes processing of rowspan and colspan attributes much easier.
290 : * Each cell is represented by a CellData object.
291 : *
292 : * @see CellData
293 : * @see nsTableFrame::AddCellToMap
294 : * @see nsTableFrame::GrowCellMap
295 : * @see nsTableFrame::BuildCellIntoMap
296 : *
297 : * mRows is an array of rows. Each row is an array of cells. a cell
298 : * can be null.
299 : */
300 : class nsCellMap
301 : {
302 : public:
303 : /** constructor
304 : * @param aRowGroupFrame the row group frame this is a cellmap for
305 : * @param aIsBC whether the table is doing border-collapse
306 : */
307 : nsCellMap(nsTableRowGroupFrame* aRowGroupFrame, bool aIsBC);
308 :
309 : /** destructor
310 : * NOT VIRTUAL BECAUSE THIS CLASS SHOULD **NEVER** BE SUBCLASSED
311 : */
312 : ~nsCellMap();
313 :
314 : static void Init();
315 : static void Shutdown();
316 :
317 : nsCellMap* GetNextSibling() const;
318 : void SetNextSibling(nsCellMap* aSibling);
319 :
320 : nsTableRowGroupFrame* GetRowGroup() const;
321 :
322 : nsTableCellFrame* GetCellFrame(PRInt32 aRowIndex,
323 : PRInt32 aColIndex,
324 : CellData& aData,
325 : bool aUseRowSpanIfOverlap) const;
326 :
327 : /**
328 : * Returns highest cell index within the cell map.
329 : *
330 : * @param aColCount [in] the number of columns in the table
331 : */
332 : PRInt32 GetHighestIndex(PRInt32 aColCount);
333 :
334 : /**
335 : * Returns the index of the given row and column coordinates.
336 : *
337 : * @see nsITableLayout::GetIndexByRowAndColumn()
338 : *
339 : * @param aColCount [in] the number of columns in the table
340 : * @param aRow [in] the row coordinate
341 : * @param aColumn [in] the column coordinate
342 : */
343 : PRInt32 GetIndexByRowAndColumn(PRInt32 aColCount,
344 : PRInt32 aRow, PRInt32 aColumn) const;
345 :
346 : /**
347 : * Get the row and column coordinates at the given index.
348 : *
349 : * @see nsITableLayout::GetRowAndColumnByIndex()
350 : *
351 : * @param aColCount [in] the number of columns in the table
352 : * @param aIndex [in] the index for which coordinates are to be retrieved
353 : * @param aRow [out] the row coordinate to be returned
354 : * @param aColumn [out] the column coordinate to be returned
355 : */
356 : void GetRowAndColumnByIndex(PRInt32 aColCount, PRInt32 aIndex,
357 : PRInt32 *aRow, PRInt32 *aColumn) const;
358 :
359 : /** append the cellFrame at an empty or dead cell or finally at the end of
360 : * the row at aRowIndex and return a pointer to the celldata entry in the
361 : * cellmap
362 : *
363 : * @param aMap - reference to the table cell map
364 : * @param aCellFrame - a pointer to the cellframe which will be appended
365 : * to the row
366 : * @param aRowIndex - to this row the celldata entry will be added
367 : * @param aRebuildIfNecessay - if a cell spans into a row below it might be
368 : * necesserary to rebuild the cellmap as this rowspan
369 : * might overlap another cell.
370 : * @param aDamageArea - area in cellmap coordinates which have been updated.
371 : * @param aColToBeginSearch - if not null contains the column number where
372 : * the search for a empty or dead cell in the
373 : * row should start
374 : * @return - a pointer to the celldata entry inserted into
375 : * the cellmap
376 : */
377 : CellData* AppendCell(nsTableCellMap& aMap,
378 : nsTableCellFrame* aCellFrame,
379 : PRInt32 aRowIndex,
380 : bool aRebuildIfNecessary,
381 : PRInt32 aRgFirstRowIndex,
382 : nsIntRect& aDamageArea,
383 : PRInt32* aBeginSearchAtCol = nsnull);
384 :
385 : /** Function to be called when a cell is added at a location which is spanned
386 : * to by a zero colspan. We handle this situation by collapsing the zero
387 : * colspan, since there is really no good way to deal with it (trying to
388 : * increase the number of columns to hold the new cell would just mean the
389 : * zero colspan needs to expand).
390 :
391 : * @param aMap - reference to the table cell map
392 : * @param aOrigData - zero colspanned cell that will be collapsed
393 : * @param aRowIndex - row where the first collision appears
394 : * @param aColIndex - column where the first collision appears
395 : **/
396 : void CollapseZeroColSpan(nsTableCellMap& aMap,
397 : CellData* aOrigData,
398 : PRInt32 aRowIndex,
399 : PRInt32 aColIndex);
400 :
401 : void InsertCells(nsTableCellMap& aMap,
402 : nsTArray<nsTableCellFrame*>& aCellFrames,
403 : PRInt32 aRowIndex,
404 : PRInt32 aColIndexBefore,
405 : PRInt32 aRgFirstRowIndex,
406 : nsIntRect& aDamageArea);
407 :
408 : void RemoveCell(nsTableCellMap& aMap,
409 : nsTableCellFrame* aCellFrame,
410 : PRInt32 aRowIndex,
411 : PRInt32 aRgFirstRowIndex,
412 : nsIntRect& aDamageArea);
413 :
414 : void InsertRows(nsTableCellMap& aMap,
415 : nsTArray<nsTableRowFrame*>& aRows,
416 : PRInt32 aFirstRowIndex,
417 : bool aConsiderSpans,
418 : PRInt32 aRgFirstRowIndex,
419 : nsIntRect& aDamageArea);
420 :
421 : void RemoveRows(nsTableCellMap& aMap,
422 : PRInt32 aFirstRowIndex,
423 : PRInt32 aNumRowsToRemove,
424 : bool aConsiderSpans,
425 : PRInt32 aRgFirstRowIndex,
426 : nsIntRect& aDamageArea);
427 :
428 : PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
429 : PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
430 :
431 : /** return the number of rows in the table represented by this CellMap */
432 : PRInt32 GetRowCount(bool aConsiderDeadRowSpanRows = false) const;
433 :
434 : nsTableCellFrame* GetCellInfoAt(const nsTableCellMap& aMap,
435 : PRInt32 aRowX,
436 : PRInt32 aColX,
437 : bool* aOriginates = nsnull,
438 : PRInt32* aColSpan = nsnull) const;
439 :
440 : bool RowIsSpannedInto(PRInt32 aRowIndex,
441 : PRInt32 aNumEffCols) const;
442 :
443 : bool RowHasSpanningCells(PRInt32 aRowIndex,
444 : PRInt32 aNumEffCols) const;
445 :
446 : void ExpandZeroColSpans(nsTableCellMap& aMap);
447 :
448 : /** indicate whether the row has more than one cell that either originates
449 : * or is spanned from the rows above
450 : */
451 : bool HasMoreThanOneCell(PRInt32 aRowIndex) const;
452 :
453 : /* Get the rowspan for a cell starting at aRowIndex and aColIndex.
454 : * If aGetEffective is true the size will not exceed the last content based
455 : * row. Cells can have a specified rowspan that extends below the last
456 : * content based row. This is legitimate considering incr. reflow where the
457 : * content rows will arive later.
458 : */
459 : PRInt32 GetRowSpan(PRInt32 aRowIndex,
460 : PRInt32 aColIndex,
461 : bool aGetEffective) const;
462 :
463 : PRInt32 GetEffectiveColSpan(const nsTableCellMap& aMap,
464 : PRInt32 aRowIndex,
465 : PRInt32 aColIndex,
466 : bool& aIsZeroColSpan) const;
467 :
468 : typedef nsTArray<CellData*> CellDataArray;
469 :
470 : /** dump a representation of the cell map to stdout for debugging */
471 : #ifdef NS_DEBUG
472 : void Dump(bool aIsBorderCollapse) const;
473 : #endif
474 :
475 : protected:
476 : friend class nsTableCellMap;
477 : friend class BCMapCellIterator;
478 : friend class BCPaintBorderIterator;
479 : friend class nsTableFrame;
480 : friend class nsCellMapColumnIterator;
481 :
482 : /**
483 : * Increase the number of rows in this cellmap by aNumRows. Put the
484 : * new rows at aRowIndex. If aRowIndex is -1, put them at the end.
485 : */
486 : bool Grow(nsTableCellMap& aMap,
487 : PRInt32 aNumRows,
488 : PRInt32 aRowIndex = -1);
489 :
490 : void GrowRow(CellDataArray& aRow,
491 : PRInt32 aNumCols);
492 :
493 : /** assign aCellData to the cell at (aRow,aColumn) */
494 : void SetDataAt(nsTableCellMap& aMap,
495 : CellData& aCellData,
496 : PRInt32 aMapRowIndex,
497 : PRInt32 aColIndex);
498 :
499 : CellData* GetDataAt(PRInt32 aMapRowIndex,
500 : PRInt32 aColIndex) const;
501 :
502 : PRInt32 GetNumCellsIn(PRInt32 aColIndex) const;
503 :
504 : void ExpandWithRows(nsTableCellMap& aMap,
505 : nsTArray<nsTableRowFrame*>& aRowFrames,
506 : PRInt32 aStartRowIndex,
507 : PRInt32 aRgFirstRowIndex,
508 : nsIntRect& aDamageArea);
509 :
510 : void ExpandWithCells(nsTableCellMap& aMap,
511 : nsTArray<nsTableCellFrame*>& aCellFrames,
512 : PRInt32 aRowIndex,
513 : PRInt32 aColIndex,
514 : PRInt32 aRowSpan,
515 : bool aRowSpanIsZero,
516 : PRInt32 aRgFirstRowIndex,
517 : nsIntRect& aDamageArea);
518 :
519 : void ShrinkWithoutRows(nsTableCellMap& aMap,
520 : PRInt32 aFirstRowIndex,
521 : PRInt32 aNumRowsToRemove,
522 : PRInt32 aRgFirstRowIndex,
523 : nsIntRect& aDamageArea);
524 :
525 : void ShrinkWithoutCell(nsTableCellMap& aMap,
526 : nsTableCellFrame& aCellFrame,
527 : PRInt32 aRowIndex,
528 : PRInt32 aColIndex,
529 : PRInt32 aRgFirstRowIndex,
530 : nsIntRect& aDamageArea);
531 :
532 : /**
533 : * Rebuild due to rows being inserted or deleted with cells spanning
534 : * into or out of the rows. This function can only handle insertion
535 : * or deletion but NOT both. So either aRowsToInsert must be null
536 : * or aNumRowsToRemove must be 0.
537 : *
538 : * // XXXbz are both allowed to happen? That'd be a no-op...
539 : */
540 : void RebuildConsideringRows(nsTableCellMap& aMap,
541 : PRInt32 aStartRowIndex,
542 : nsTArray<nsTableRowFrame*>* aRowsToInsert,
543 : PRInt32 aNumRowsToRemove);
544 :
545 : void RebuildConsideringCells(nsTableCellMap& aMap,
546 : PRInt32 aNumOrigCols,
547 : nsTArray<nsTableCellFrame*>* aCellFrames,
548 : PRInt32 aRowIndex,
549 : PRInt32 aColIndex,
550 : bool aInsert);
551 :
552 : bool CellsSpanOut(nsTArray<nsTableRowFrame*>& aNewRows) const;
553 :
554 : /** If a cell spans out of the area defined by aStartRowIndex, aEndRowIndex
555 : * and aStartColIndex, aEndColIndex the cellmap changes are more severe so
556 : * the corresponding routines needs to be called. This is also necessary if
557 : * cells outside spans into this region.
558 : * @aStartRowIndex - y start index
559 : * @aEndRowIndex - y end index
560 : * @param aStartColIndex - x start index
561 : * @param aEndColIndex - x end index
562 : * @return - true if a cell span crosses the border of the
563 : region
564 : */
565 : bool CellsSpanInOrOut(PRInt32 aStartRowIndex,
566 : PRInt32 aEndRowIndex,
567 : PRInt32 aStartColIndex,
568 : PRInt32 aEndColIndex) const;
569 :
570 : void ExpandForZeroSpan(nsTableCellFrame* aCellFrame,
571 : PRInt32 aNumColsInTable);
572 :
573 : bool CreateEmptyRow(PRInt32 aRowIndex,
574 : PRInt32 aNumCols);
575 :
576 : PRInt32 GetRowSpanForNewCell(nsTableCellFrame* aCellFrameToAdd,
577 : PRInt32 aRowIndex,
578 : bool& aIsZeroRowSpan) const;
579 :
580 : PRInt32 GetColSpanForNewCell(nsTableCellFrame& aCellFrameToAdd,
581 : bool& aIsZeroColSpan) const;
582 :
583 : // Destroy a CellData struct. This will handle the case of aData
584 : // actually being a BCCellData properly.
585 : void DestroyCellData(CellData* aData);
586 : // Allocate a CellData struct. This will handle needing to create a
587 : // BCCellData properly.
588 : // @param aOrigCell the originating cell to pass to the celldata constructor
589 : CellData* AllocCellData(nsTableCellFrame* aOrigCell);
590 :
591 : /** an array containing, for each row, the CellDatas for the cells
592 : * in that row. It can be larger than mContentRowCount due to row spans
593 : * extending beyond the table */
594 : // XXXbz once we have auto TArrays, we should probably use them here.
595 : nsTArray<CellDataArray> mRows;
596 :
597 : /** the number of rows in the table (content) which is not indentical to the
598 : * number of rows in the cell map due to row spans extending beyond the end
599 : * of thetable (dead rows) or empty tr tags
600 : */
601 : PRInt32 mContentRowCount;
602 :
603 : // the row group that corresponds to this map
604 : nsTableRowGroupFrame* mRowGroupFrame;
605 :
606 : // the next row group cell map
607 : nsCellMap* mNextSibling;
608 :
609 : // Whether this is a BC cellmap or not
610 : bool mIsBC;
611 :
612 : // Prescontext to deallocate and allocate celldata
613 : nsRefPtr<nsPresContext> mPresContext;
614 : };
615 :
616 : /**
617 : * A class for iterating the cells in a given column. Must be given a
618 : * non-null nsTableCellMap and a column number valid for that cellmap.
619 : */
620 : class nsCellMapColumnIterator
621 : {
622 : public:
623 0 : nsCellMapColumnIterator(const nsTableCellMap* aMap, PRInt32 aCol) :
624 : mMap(aMap), mCurMap(aMap->mFirstMap), mCurMapStart(0),
625 0 : mCurMapRow(0), mCol(aCol), mFoundCells(0)
626 : {
627 0 : NS_PRECONDITION(aMap, "Must have map");
628 0 : NS_PRECONDITION(mCol < aMap->GetColCount(), "Invalid column");
629 0 : mOrigCells = aMap->GetNumCellsOriginatingInCol(mCol);
630 0 : if (mCurMap) {
631 0 : mCurMapContentRowCount = mCurMap->GetRowCount();
632 0 : PRUint32 rowArrayLength = mCurMap->mRows.Length();
633 0 : mCurMapRelevantRowCount = NS_MIN(mCurMapContentRowCount, rowArrayLength);
634 0 : if (mCurMapRelevantRowCount == 0 && mOrigCells > 0) {
635 : // This row group is useless; advance!
636 0 : AdvanceRowGroup();
637 : }
638 : }
639 : #ifdef DEBUG
640 : else {
641 0 : NS_ASSERTION(mOrigCells == 0, "Why no rowgroups?");
642 : }
643 : #endif
644 0 : }
645 :
646 : nsTableCellFrame* GetNextFrame(PRInt32* aRow, PRInt32* aColSpan);
647 :
648 : private:
649 : void AdvanceRowGroup();
650 :
651 : // Advance the row; aIncrement is considered to be a cell's rowspan,
652 : // so if 0 is passed in we'll advance to the next rowgroup.
653 : void IncrementRow(PRInt32 aIncrement);
654 :
655 : const nsTableCellMap* mMap;
656 : const nsCellMap* mCurMap;
657 :
658 : // mCurMapStart is the row in the entire nsTableCellMap where
659 : // mCurMap starts. This is used to compute row indices to pass to
660 : // nsTableCellMap::GetDataAt, so must be a _content_ row index.
661 : PRUint32 mCurMapStart;
662 :
663 : // In steady-state mCurMapRow is the row in our current nsCellMap
664 : // that we'll use the next time GetNextFrame() is called. Due to
665 : // the way we skip over rowspans, the entry in mCurMapRow and mCol
666 : // is either null, dead, originating, or a colspan. In particular,
667 : // it cannot be a rowspan or overlap entry.
668 : PRUint32 mCurMapRow;
669 : const PRInt32 mCol;
670 : PRUint32 mOrigCells;
671 : PRUint32 mFoundCells;
672 :
673 : // The number of content rows in mCurMap. This may be bigger than the number
674 : // of "relevant" rows, or it might be smaller.
675 : PRUint32 mCurMapContentRowCount;
676 :
677 : // The number of "relevant" rows in mCurMap. That is, the number of rows
678 : // which might have an originating cell in them. Once mCurMapRow reaches
679 : // mCurMapRelevantRowCount, we should move to the next map.
680 : PRUint32 mCurMapRelevantRowCount;
681 : };
682 :
683 :
684 : /* ----- inline methods ----- */
685 0 : inline PRInt32 nsTableCellMap::GetColCount() const
686 : {
687 0 : return mCols.Length();
688 : }
689 :
690 0 : inline nsCellMap* nsCellMap::GetNextSibling() const
691 : {
692 0 : return mNextSibling;
693 : }
694 :
695 0 : inline void nsCellMap::SetNextSibling(nsCellMap* aSibling)
696 : {
697 0 : mNextSibling = aSibling;
698 0 : }
699 :
700 0 : inline nsTableRowGroupFrame* nsCellMap::GetRowGroup() const
701 : {
702 0 : return mRowGroupFrame;
703 : }
704 :
705 0 : inline PRInt32 nsCellMap::GetRowCount(bool aConsiderDeadRowSpanRows) const
706 : {
707 0 : PRInt32 rowCount = (aConsiderDeadRowSpanRows) ? mRows.Length() : mContentRowCount;
708 0 : return rowCount;
709 : }
710 :
711 : // nsColInfo
712 :
713 0 : inline nsColInfo::nsColInfo()
714 0 : :mNumCellsOrig(0), mNumCellsSpan(0)
715 0 : {}
716 :
717 : inline nsColInfo::nsColInfo(PRInt32 aNumCellsOrig,
718 : PRInt32 aNumCellsSpan)
719 : :mNumCellsOrig(aNumCellsOrig), mNumCellsSpan(aNumCellsSpan)
720 : {}
721 :
722 :
723 : #endif
|