Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Protected Member Functions | Protected Attributes | Friends
nsCellMap Class Reference

nsCellMap is a support class for nsTablePart. More...

#include <nsCellMap.h>

Collaboration diagram for nsCellMap:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsCellMap (nsTableRowGroupFrame &aRowGroupFrame)
 constructor
 ~nsCellMap ()
 destructor NOT VIRTUAL BECAUSE THIS CLASS SHOULD NEVER BE SUBCLASSED
nsCellMapGetNextSibling () const
void SetNextSibling (nsCellMap *aSibling)
nsTableRowGroupFrameGetRowGroup () const
nsTableCellFrameGetCellFrame (PRInt32 aRowIndex, PRInt32 aColIndex, CellData &aData, PRBool aUseRowSpanIfOverlap) const
CellDataAppendCell (nsTableCellMap &aMap, nsTableCellFrame *aCellFrame, PRInt32 aRowIndex, PRBool aRebuildIfNecessary, nsRect &aDamageArea, PRInt32 *aBeginSearchAtCol=nsnull)
 append the cellFrame at an empty or dead cell or finally at the end of the row at aRowIndex and return a pointer to the celldata entry in the cellmap
void InsertCells (nsTableCellMap &aMap, nsVoidArray &aCellFrames, PRInt32 aRowIndex, PRInt32 aColIndexBefore, nsRect &aDamageArea)
void RemoveCell (nsTableCellMap &aMap, nsTableCellFrame *aCellFrame, PRInt32 aRowIndex, nsRect &aDamageArea)
void InsertRows (nsTableCellMap &aMap, nsVoidArray &aRows, PRInt32 aFirstRowIndex, PRBool aConsiderSpans, nsRect &aDamageArea)
void RemoveRows (nsTableCellMap &aMap, PRInt32 aFirstRowIndex, PRInt32 aNumRowsToRemove, PRBool aConsiderSpans, nsRect &aDamageArea)
PRInt32 GetNumCellsOriginatingInRow (PRInt32 aRowIndex) const
PRInt32 GetNumCellsOriginatingInCol (PRInt32 aColIndex) const
PRInt32 GetRowCount (PRBool aConsiderDeadRowSpanRows=PR_FALSE) const
 return the number of rows in the table represented by this CellMap
nsTableCellFrameGetCellInfoAt (nsTableCellMap &aMap, PRInt32 aRowX, PRInt32 aColX, PRBool *aOriginates=nsnull, PRInt32 *aColSpan=nsnull)
PRBool RowIsSpannedInto (nsTableCellMap &aMap, PRInt32 aRowIndex)
PRBool RowHasSpanningCells (nsTableCellMap &aMap, PRInt32 aRowIndex)
PRBool ColHasSpanningCells (nsTableCellMap &aMap, PRInt32 aColIndex)
PRBool HasMoreThanOneCell (nsTableCellMap &aMap, PRInt32 aRowIndex)
 indicate whether the row has more than one cell that either originates or is spanned from the rows above
PRInt32 GetRowSpan (nsTableCellMap &aMap, PRInt32 aRowIndex, PRInt32 aColIndex, PRBool aGetEffective, PRBool &aIsZeroRowSpan)
PRInt32 GetEffectiveColSpan (nsTableCellMap &aMap, PRInt32 aRowIndex, PRInt32 aColIndex, PRBool &aIsZeroColSpan)

Protected Member Functions

PRBool Grow (nsTableCellMap &aMap, PRInt32 aNumRows, PRInt32 aRowIndex=-1)
void GrowRow (nsVoidArray &aRow, PRInt32 aNumCols)
void SetDataAt (nsTableCellMap &aMap, CellData &aCellData, PRInt32 aMapRowIndex, PRInt32 aColIndex, PRBool aCountZeroSpanAsSpan)
 assign aCellData to the cell at (aRow,aColumn)
CellDataGetDataAt (nsTableCellMap &aMap, PRInt32 aMapRowIndex, PRInt32 aColIndex, PRBool aUpdateZeroSpan)
PRInt32 GetNumCellsIn (PRInt32 aColIndex) const
void ExpandWithRows (nsTableCellMap &aMap, nsVoidArray &aRowFrames, PRInt32 aStartRowIndex, nsRect &aDamageArea)
void ExpandWithCells (nsTableCellMap &aMap, nsVoidArray &aCellFrames, PRInt32 aRowIndex, PRInt32 aColIndex, PRInt32 aRowSpan, PRBool aRowSpanIsZero, nsRect &aDamageArea)
void ShrinkWithoutRows (nsTableCellMap &aMap, PRInt32 aFirstRowIndex, PRInt32 aNumRowsToRemove, nsRect &aDamageArea)
void ShrinkWithoutCell (nsTableCellMap &aMap, nsTableCellFrame &aCellFrame, PRInt32 aRowIndex, PRInt32 aColIndex, nsRect &aDamageArea)
void RebuildConsideringRows (nsTableCellMap &aMap, PRInt32 aStartRowIndex, nsVoidArray *aRowsToInsert, PRInt32 aNumRowsToRemove, nsRect &aDamageArea)
void RebuildConsideringCells (nsTableCellMap &aMap, PRInt32 aNumOrigCols, nsVoidArray *aCellFrames, PRInt32 aRowIndex, PRInt32 aColIndex, PRBool aInsert, nsRect &aDamageArea)
PRBool CellsSpanOut (nsVoidArray &aNewRows)
PRBool CellsSpanInOrOut (nsTableCellMap &aMap, PRInt32 aStartRowIndex, PRInt32 aEndRowIndex, PRInt32 aStartColIndex, PRInt32 aEndColIndex)
 If a cell spans out of the area defined by aStartRowIndex, aEndRowIndex and aStartColIndex, aEndColIndex the cellmap changes are more severe so the corresponding routines needs to be called.
void ExpandForZeroSpan (nsTableCellFrame *aCellFrame, PRInt32 aNumColsInTable)
PRBool CreateEmptyRow (PRInt32 aRowIndex, PRInt32 aNumCols)
PRInt32 GetRowSpanForNewCell (nsTableCellFrame &aCellFrameToAdd, PRInt32 aRowIndex, PRBool &aIsZeroRowSpan)
PRInt32 GetColSpanForNewCell (nsTableCellFrame &aCellFrameToAdd, PRInt32 aColIndex, PRInt32 aNumColsInTable, PRBool &aIsZeroColSpan)
void AdjustForZeroSpan (nsTableCellMap &aMap, PRInt32 aRowIndex, PRInt32 aColIndex)
PRBool IsZeroColSpan (PRInt32 aRowIndex, PRInt32 aColIndex) const

Protected Attributes

nsAutoVoidArray mRows
 an array containing col array.
PRInt32 mRowCount
 the number of rows in the table (content) which is not indentical to the number of rows in the cell map due to row spans extending beyond the end of thetable (dead rows) or empty tr tags
nsTableRowGroupFramemRowGroupFrame
nsCellMapmNextSibling

Friends

class nsTableCellMap
 dump a representation of the cell map to stdout for debugging
class BCMapCellIterator
class BCMapBorderIterator
class nsTableFrame

Detailed Description

nsCellMap is a support class for nsTablePart.

It maintains an Rows x Columns grid onto which the cells of the table are mapped. This makes processing of rowspan and colspan attributes much easier. Each cell is represented by a CellData object.

See also:
CellData
nsTableFrame::AddCellToMap
nsTableFrame::GrowCellMap
nsTableFrame::BuildCellIntoMap

mRows is an array of rows. a row cannot be null. each row is an array of cells. a cell can be null.

Definition at line 249 of file nsCellMap.h.


Constructor & Destructor Documentation

constructor

Parameters:
aNumRows- initial number of rows
aNumColumns- initial number of columns

Definition at line 1169 of file nsCellMap.cpp.

destructor NOT VIRTUAL BECAUSE THIS CLASS SHOULD NEVER BE SUBCLASSED

Definition at line 1175 of file nsCellMap.cpp.

{
  MOZ_COUNT_DTOR(nsCellMap);
  
  PRInt32 mapRowCount = mRows.Count();
  for (PRInt32 rowX = 0; rowX < mapRowCount; rowX++) {
    nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(rowX));
    PRInt32 colCount = row->Count();
    for (PRInt32 colX = 0; colX < colCount; colX++) {
      CellData* data = (CellData *)(row->ElementAt(colX));
      if (data) {
        delete data;
      } 
    }
    delete row;
  }
}

Here is the call graph for this function:


Member Function Documentation

void nsCellMap::AdjustForZeroSpan ( nsTableCellMap aMap,
PRInt32  aRowIndex,
PRInt32  aColIndex 
) [protected]

Definition at line 2369 of file nsCellMap.cpp.

{
  PRInt32 numColsInTable = aMap.GetColCount();
  CellData* data = GetDataAt(aMap, aRowIndex, aColIndex, PR_FALSE);
  if (!data) return;

  nsTableCellFrame* cell = (data->IsOrig()) ? data->GetCellFrame() : nsnull;
  if (!cell) return;

  PRInt32 cellRowSpan = cell->GetRowSpan();
  PRInt32 cellColSpan = cell->GetColSpan();

  PRInt32 endRowIndex = (0 == cell->GetRowSpan()) ? mRows.Count() - 1 : aRowIndex + cellRowSpan - 1;
  PRInt32 endColIndex = (0 == cell->GetColSpan()) ? numColsInTable - 1 : aColIndex + cellColSpan - 1;
  // if there is both a rowspan=0 and colspan=0 then only expand the cols to a minimum
  if ((0 == cellRowSpan) && (0 == cellColSpan)) {
    endColIndex = aColIndex + MIN_NUM_COLS_FOR_ZERO_COLSPAN - 1;
  }

  // Create span CellData objects filling out the rows to the end of the
  // map if the rowspan is 0, and/or filling out the cols to the end of 
  // table if the colspan is 0. If there is both a rowspan=0 and colspan=0
  // then only fill out the cols to a minimum value.
  for (PRInt32 colX = aColIndex; colX <= endColIndex; colX++) {
    PRInt32 rowX;
    // check to see if there is any cells originating after the cols 
    PRBool cellsOrig = PR_FALSE;
    if (colX >= aColIndex + MIN_NUM_COLS_FOR_ZERO_COLSPAN - 1) {
      for (rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
        CellData* cellData = GetDataAt(aMap, rowX, colX, PR_FALSE);
        if (cellData && cellData->IsOrig()) {
          cellsOrig = PR_TRUE;
          break; // there are cells in this col, so don't consider it
        }
      }
    }
    if (cellsOrig) break;
    for (rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
      if ((colX > aColIndex) || (rowX > aRowIndex)) {
        CellData* oldData = GetDataAt(aMap, rowX, colX, PR_FALSE); 
        if (!oldData) {
          CellData* newData = (aMap.mBCInfo) ? new BCCellData(nsnull) : new CellData(nsnull);
          if (!newData) return;
          if (colX > aColIndex) {
            newData->SetColSpanOffset(colX - aColIndex);
            newData->SetZeroColSpan(PR_TRUE);
          }
          if (rowX > aRowIndex) {
            newData->SetRowSpanOffset(rowX - aRowIndex);
            newData->SetZeroRowSpan(PR_TRUE);
          }
          // colspan=0 is only counted as spanning the 1st col to the right of its origin
          SetDataAt(aMap, *newData, rowX, colX, (colX == aColIndex + 1));
        }
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

CellData * nsCellMap::AppendCell ( nsTableCellMap aMap,
nsTableCellFrame aCellFrame,
PRInt32  aRowIndex,
PRBool  aRebuildIfNecessary,
nsRect aDamageArea,
PRInt32 aBeginSearchAtCol = nsnull 
)

append the cellFrame at an empty or dead cell or finally at the end of the row at aRowIndex and return a pointer to the celldata entry in the cellmap

Parameters:
aMap- reference to the table cell map
aCellFrame- a pointer to the cellframe which will be appended to the row
aRowIndex- to this row the celldata entry will be added
aRebuildIfNecessay- if a cell spans into a row below it might be necesserary to rebuild the cellmap as this rowspan might overlap another cell.
aDamageArea- area in cellmap coordinates which have been updated.
aColToBeginSearch- if not null contains the column number where the search for a empty or dead cell in the row should start
Returns:
- a pointer to the celldata entry inserted into the cellmap

Definition at line 1334 of file nsCellMap.cpp.

{
  PRInt32 origNumMapRows = mRows.Count();
  PRInt32 origNumCols = aMap.GetColCount();
  PRBool  zeroRowSpan;
  PRInt32 rowSpan = (aCellFrame) ? GetRowSpanForNewCell(*aCellFrame, aRowIndex, zeroRowSpan) : 1;
  // add new rows if necessary
  PRInt32 endRowIndex = aRowIndex + rowSpan - 1;
  if (endRowIndex >= origNumMapRows) {
    Grow(aMap, 1 + endRowIndex - origNumMapRows);
  }

  // get the first null or dead CellData in the desired row. It will equal origNumCols if there are none
  CellData* origData = nsnull;
  PRInt32 startColIndex = 0;
  if (aColToBeginSearch)
    startColIndex = *aColToBeginSearch;
  for (; startColIndex < origNumCols; startColIndex++) {
    CellData* data = GetDataAt(aMap, aRowIndex, startColIndex, PR_TRUE);
    if (!data) 
      break;
    if (data->IsDead()) {
      origData = data;
      break; 
    }
  }
  // We found the place to append the cell, when the next cell is appended 
  // the next search does not need to duplicate the search but can start 
  // just at the next cell.
  if (aColToBeginSearch)
    *aColToBeginSearch =  startColIndex + 1; 
  
  PRBool  zeroColSpan;
  PRInt32 colSpan = (aCellFrame) ? GetColSpanForNewCell(*aCellFrame, startColIndex, origNumCols, zeroColSpan) : 1;

  // if the new cell could potentially span into other rows and collide with 
  // originating cells there, we will play it safe and just rebuild the map
  if (aRebuildIfNecessary && (aRowIndex < mRowCount - 1) && (rowSpan > 1)) {
    nsAutoVoidArray newCellArray;
    newCellArray.AppendElement(aCellFrame);
    aMap.RebuildConsideringCells(this, &newCellArray, aRowIndex, startColIndex, PR_TRUE, aDamageArea);
    return origData;
  }
  mRowCount = PR_MAX(mRowCount, aRowIndex + 1);

  // add new cols to the table map if necessary
  PRInt32 endColIndex = startColIndex + colSpan - 1;
  if (endColIndex >= origNumCols) {
    NS_ASSERTION(aCellFrame, "dead cells should not require new columns");
    aMap.AddColsAtEnd(1 + endColIndex - origNumCols);
  }

  // Setup CellData for this cell
  if (origData) {
    NS_ASSERTION(origData->IsDead(), "replacing a non dead cell is a memory leak");
    if (aCellFrame) { // do nothing to replace a dead cell with a dead cell
      origData->Init(aCellFrame);
      // we are replacing a dead cell, increase the number of cells 
      // originating at this column
      nsColInfo* colInfo = aMap.GetColInfoAt(startColIndex);
      NS_ASSERTION(colInfo, "access to a non existing column");
      if (colInfo) { 
        colInfo->mNumCellsOrig++;
      }
    }
  }
  else {
    origData = (aMap.mBCInfo) ? new BCCellData(aCellFrame) : new CellData(aCellFrame); if (!origData) ABORT1(origData);
    SetDataAt(aMap, *origData, aRowIndex, startColIndex, PR_TRUE);
  }

  SetDamageArea(startColIndex, aRowIndex, 1 + endColIndex - startColIndex, 1 + endRowIndex - aRowIndex, aDamageArea); 

  if (!aCellFrame) {
    return origData;
  }

  // initialize the cell frame
  aCellFrame->SetColIndex(startColIndex);

  // Create CellData objects for the rows that this cell spans. Set
  // their mOrigCell to nsnull and their mSpanData to point to data.
  for (PRInt32 rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
    for (PRInt32 colX = startColIndex; colX <= endColIndex; colX++) {
      if ((rowX != aRowIndex) || (colX != startColIndex)) { // skip orig cell data done above
        CellData* cellData = GetDataAt(aMap, rowX, colX, PR_FALSE);
        if (cellData) {
          if (cellData->IsOrig()) {
            NS_ASSERTION(PR_FALSE, "cannot overlap originating cell");
            continue;
          }
          if (rowX > aRowIndex) { // row spanning into cell
            if (cellData->IsRowSpan()) {
              NS_ASSERTION(PR_FALSE, "invalid overlap");
            }
            else {
              cellData->SetRowSpanOffset(rowX - aRowIndex);
              if (zeroRowSpan) {
                cellData->SetZeroRowSpan(PR_TRUE);
              }
            }
          }
          if (colX > startColIndex) { // col spanning into cell
            if (!cellData->IsColSpan()) { 
              if (cellData->IsRowSpan()) {
                cellData->SetOverlap(PR_TRUE);
              }
              cellData->SetColSpanOffset(colX - startColIndex);
              if (zeroColSpan) {
                cellData->SetZeroColSpan(PR_TRUE);
              }
              // only count the 1st spanned col of a zero col span
              if (!zeroColSpan || (colX == startColIndex + 1)) {
                nsColInfo* colInfo = aMap.GetColInfoAt(colX);
                colInfo->mNumCellsSpan++;
              }
            }
          }
        }
        else { 
          cellData = (aMap.mBCInfo) ? new BCCellData(nsnull) : new CellData(nsnull);
          if (!cellData) return origData;
          if (rowX > aRowIndex) {
            cellData->SetRowSpanOffset(rowX - aRowIndex);
          }
          if (zeroRowSpan) {
            cellData->SetZeroRowSpan(PR_TRUE);
          }
          if (colX > startColIndex) {
            cellData->SetColSpanOffset(colX - startColIndex);
          }
          if (zeroColSpan) {
            cellData->SetZeroColSpan(PR_TRUE);
          }
          // only count the 1st spanned col of a zero col span
          SetDataAt(aMap, *cellData, rowX, colX, (colX == startColIndex + 1));
        }
      }
    }
  }
#ifdef DEBUG_TABLE_CELLMAP
  printf("appended cell=%p row=%d \n", aCellFrame, aRowIndex);
  aMap.Dump();
#endif
  return origData;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsCellMap::CellsSpanInOrOut ( nsTableCellMap aMap,
PRInt32  aStartRowIndex,
PRInt32  aEndRowIndex,
PRInt32  aStartColIndex,
PRInt32  aEndColIndex 
) [protected]

If a cell spans out of the area defined by aStartRowIndex, aEndRowIndex and aStartColIndex, aEndColIndex the cellmap changes are more severe so the corresponding routines needs to be called.

This is also necessary if cells outside spans into this region.

Parameters:
aMap- the whole table cellmap - y start index - y end index
aStartColIndex- x start index
aEndColIndex- x end index
Returns:
- true if a cell span crosses the border of the region

Definition at line 1508 of file nsCellMap.cpp.

{
  /*
   * this routine will watch the cells adjacent to the region or at the edge
   * they are marked with *. The routine will verify whether they span in or
   * are spanned out.
   *
   *                           startCol          endCol
   *             r1c1   r1c2   r1c3      r1c4    r1c5    r1rc6  r1c7
   *  startrow   r2c1   r2c2  *r2c3     *r2c4   *r2c5   *r2rc6  r2c7
   *  endrow     r3c1   r3c2  *r3c3      r3c4    r3c5   *r3rc6  r3c7
   *             r4c1   r4c2  *r4c3     *r4c4   *r4c5    r4rc6  r4c7
   *             r5c1   r5c2   r5c3      r5c4    r5c5    r5rc6  r5c7  
   */

  PRInt32 numRows = mRows.Count(); // use the cellmap rows to determine the 
                                   // current cellmap extent.
  for (PRInt32 colX = aStartColIndex; colX <= aEndColIndex; colX++) {
    CellData* cellData;
    if (aStartRowIndex > 0) {
      cellData = GetDataAt(aMap, aStartRowIndex, colX, PR_TRUE);
      if (cellData && (cellData->IsRowSpan())) {
        return PR_TRUE; // there is a row span into the region
      }
    }
    if (aEndRowIndex < numRows - 1) { // is there anything below aEndRowIndex
      cellData = GetDataAt(aMap, aEndRowIndex + 1, colX, PR_TRUE);
      if ((cellData) && (cellData->IsRowSpan())) {
        return PR_TRUE; // there is a row span out of the region
      }
    }
    else {
      cellData = GetDataAt(aMap, aEndRowIndex, colX, PR_TRUE);
      if ((cellData) && (cellData->IsRowSpan()) && (mRowCount < numRows)) {
        return PR_TRUE; // this cell might be the cause of a dead row
      }
    }
  }
  if (aStartColIndex > 0) {
    for (PRInt32 rowX = aStartRowIndex; rowX <= aEndRowIndex; rowX++) {
      CellData* cellData = GetDataAt(aMap, rowX, aStartColIndex, PR_TRUE);
      if (cellData && (cellData->IsColSpan())) {
        return PR_TRUE; // there is a col span into the region
      }
      nsVoidArray* row = (nsVoidArray *)(mRows.SafeElementAt(rowX));
      if (row) {
        cellData = (CellData *)(row->SafeElementAt(aEndColIndex + 1));
        if (cellData && (cellData->IsColSpan())) {
          return PR_TRUE; // there is a col span out of the region 
        }
      }
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsCellMap::CellsSpanOut ( nsVoidArray aNewRows) [protected]

Definition at line 1486 of file nsCellMap.cpp.

{ 
  PRInt32 numNewRows = aRows.Count();
  for (PRInt32 rowX = 0; rowX < numNewRows; rowX++) {
    nsIFrame* rowFrame = (nsIFrame *) aRows.ElementAt(rowX);
    nsIFrame* cellFrame = rowFrame->GetFirstChild(nsnull);
    while (cellFrame) {
      if (IS_TABLE_CELL(cellFrame->GetType())) {
        PRBool zeroSpan;
        PRInt32 rowSpan = GetRowSpanForNewCell((nsTableCellFrame &)*cellFrame, rowX, zeroSpan);
        if (rowX + rowSpan > numNewRows) {
          return PR_TRUE;
        }
      }
      cellFrame = cellFrame->GetNextSibling();
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2613 of file nsCellMap.cpp.

{
  PRInt32 numColsInTable = aMap.GetColCount();
  NS_PRECONDITION (aColIndex < numColsInTable, "bad col index arg");
  if ((0 > aColIndex) || (aColIndex >= numColsInTable - 1)) 
    return PR_FALSE;
 
  for (PRInt32 rowIndex = 0; rowIndex < mRowCount; rowIndex++) {
    CellData* cd = GetDataAt(aMap, rowIndex, aColIndex, PR_TRUE);
    if (cd && (cd->IsOrig())) { // cell originates 
      CellData* cd2 = GetDataAt(aMap, rowIndex, aColIndex +1, PR_TRUE);
      if (cd2 && cd2->IsColSpan()) { // cd2 is spanned by a col
        if (cd->GetCellFrame() == GetCellFrame(rowIndex , aColIndex + 1, *cd2, PR_FALSE)) {
          return PR_TRUE;
        }
      }
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsCellMap::CreateEmptyRow ( PRInt32  aRowIndex,
PRInt32  aNumCols 
) [protected]
void nsCellMap::ExpandForZeroSpan ( nsTableCellFrame aCellFrame,
PRInt32  aNumColsInTable 
) [protected]
void nsCellMap::ExpandWithCells ( nsTableCellMap aMap,
nsVoidArray aCellFrames,
PRInt32  aRowIndex,
PRInt32  aColIndex,
PRInt32  aRowSpan,
PRBool  aRowSpanIsZero,
nsRect aDamageArea 
) [protected]

Definition at line 1664 of file nsCellMap.cpp.

{
  PRInt32 endRowIndex = aRowIndex + aRowSpan - 1;
  PRInt32 startColIndex = aColIndex;
  PRInt32 endColIndex = aColIndex;
  PRInt32 numCells = aCellFrames.Count();
  PRInt32 totalColSpan = 0;

  // add cellData entries for the space taken up by the new cells
  for (PRInt32 cellX = 0; cellX < numCells; cellX++) {
    nsTableCellFrame* cellFrame = (nsTableCellFrame*) aCellFrames.ElementAt(cellX);
    CellData* origData = (aMap.mBCInfo) ? new BCCellData(cellFrame) : new CellData(cellFrame); // the originating cell
    if (!origData) return;

    // set the starting and ending col index for the new cell
    PRBool zeroColSpan = PR_FALSE;
    PRInt32 colSpan = GetColSpanForNewCell(*cellFrame, aColIndex, aMap.GetColCount(), zeroColSpan);
    totalColSpan += colSpan;
    if (cellX == 0) {
      endColIndex = aColIndex + colSpan - 1;
    }
    else {
      startColIndex = endColIndex + 1;
      endColIndex   = startColIndex + colSpan - 1;
    }
 
    // add the originating cell data and any cell data corresponding to row/col spans
    for (PRInt32 rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
      nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
      for (PRInt32 colX = aColIndex; colX <= endColIndex; colX++) {
        row->InsertElementAt(nsnull, colX);
        CellData* data = origData;
        if ((rowX != aRowIndex) || (colX != startColIndex)) {
          data = (aMap.mBCInfo) ? new BCCellData(nsnull) : new CellData(nsnull);
          if (!data) return;
          if (rowX > aRowIndex) {
            data->SetRowSpanOffset(rowX - aRowIndex);
            if (aRowSpanIsZero) {
              data->SetZeroRowSpan(PR_TRUE);
            }
          }
          if (colX > startColIndex) {
            data->SetColSpanOffset(colX - startColIndex);
            if (zeroColSpan) {
              data->SetZeroColSpan(PR_TRUE);
            }
          }
        }
        // only count 1st spanned col of colspan=0
        SetDataAt(aMap, *data, rowX, colX, (colX == aColIndex + 1)); 
      }
    }
    cellFrame->SetColIndex(startColIndex);
  }
  PRInt32 damageHeight = (aRowSpanIsZero) ? aMap.GetColCount() - aRowIndex : aRowSpan;
  SetDamageArea(aColIndex, aRowIndex, 1 + endColIndex - aColIndex, damageHeight, aDamageArea); 

  PRInt32 rowX;

  // update the row and col info due to shifting
  for (rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
    nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
    PRInt32 numCols = row->Count();
    PRInt32 colX;
    for (colX = aColIndex + totalColSpan; colX < numCols; colX++) {
      CellData* data = (CellData*) row->ElementAt(colX);
      if (data) {
        // increase the origin and span counts beyond the spanned cols
        if (data->IsOrig()) {
          // a cell that gets moved needs adjustment as well as it new orignating col
          data->GetCellFrame()->SetColIndex(colX);
          nsColInfo* colInfo = aMap.GetColInfoAt(colX);
          colInfo->mNumCellsOrig++;
        }
        // if the colspan is 0 only count the 1st spanned col
        PRBool countAsSpan = PR_FALSE;
        if (data->IsColSpan()) {
          if ( (!data->IsZeroColSpan()) ||
               ((data->IsZeroColSpan()) && (colX > aColIndex + totalColSpan) &&
                (!IsZeroColSpan(rowX, colX - 1)))) {
            nsColInfo* colInfo = aMap.GetColInfoAt(colX);
            colInfo->mNumCellsSpan++;
            countAsSpan = PR_TRUE;
          }
        }
        
        // decrease the origin and span counts within the spanned cols
        PRInt32 colX2 = colX - totalColSpan;
        nsColInfo* colInfo2 = aMap.GetColInfoAt(colX2);
        if (data->IsOrig()) {
          // the old originating col of a moved cell needs adjustment
          colInfo2->mNumCellsOrig--;
        }
        else if (countAsSpan) {
          colInfo2->mNumCellsSpan--;
        }
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::ExpandWithRows ( nsTableCellMap aMap,
nsVoidArray aRowFrames,
PRInt32  aStartRowIndex,
nsRect aDamageArea 
) [protected]

Definition at line 1631 of file nsCellMap.cpp.

{
  PRInt32 startRowIndex = (aStartRowIndexIn >= 0) ? aStartRowIndexIn : 0;
  PRInt32 numNewRows  = aRowFrames.Count();
  PRInt32 endRowIndex = startRowIndex + numNewRows - 1;

  // create the new rows first
  if (!Grow(aMap, numNewRows, startRowIndex)) {
    return;
  }
  mRowCount += numNewRows;

  PRInt32 newRowIndex = 0;
  for (PRInt32 rowX = startRowIndex; rowX <= endRowIndex; rowX++) {
    nsTableRowFrame* rFrame = (nsTableRowFrame *)aRowFrames.ElementAt(newRowIndex);
    // append cells 
    nsIFrame* cFrame = rFrame->GetFirstChild(nsnull);
    PRInt32 colIndex = 0;
    while (cFrame) {
      if (IS_TABLE_CELL(cFrame->GetType())) {
        AppendCell(aMap, (nsTableCellFrame *)cFrame, rowX, PR_FALSE, aDamageArea, &colIndex);
      }
      cFrame = cFrame->GetNextSibling();
    }
    newRowIndex++;
  }

  SetDamageArea(0, startRowIndex, aMap.GetColCount(), 1 + endRowIndex - startRowIndex, aDamageArea); 
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsTableCellFrame * nsCellMap::GetCellFrame ( PRInt32  aRowIndex,
PRInt32  aColIndex,
CellData aData,
PRBool  aUseRowSpanIfOverlap 
) const

Definition at line 1194 of file nsCellMap.cpp.

{
  PRInt32 rowIndex = aRowIndexIn - aData.GetRowSpanOffset();
  PRInt32 colIndex = aColIndexIn - aData.GetColSpanOffset();
  if (aData.IsOverlap()) {
    if (aUseRowIfOverlap) {
      colIndex = aColIndexIn;
    }
    else {
      rowIndex = aRowIndexIn;
    }
  }

  nsVoidArray* row = (nsVoidArray*) mRows.SafeElementAt(rowIndex);
  if (row) {
    CellData* data = (CellData*)row->SafeElementAt(colIndex);
    if (data) {
      return data->GetCellFrame();
    }
  }
  return nsnull;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsTableCellFrame * nsCellMap::GetCellInfoAt ( nsTableCellMap aMap,
PRInt32  aRowX,
PRInt32  aColX,
PRBool aOriginates = nsnull,
PRInt32 aColSpan = nsnull 
)

Definition at line 2536 of file nsCellMap.cpp.

{
  if (aOriginates) {
    *aOriginates = PR_FALSE;
  }
  CellData* data = GetDataAt(aMap, aRowX, aColX, PR_TRUE);
  nsTableCellFrame* cellFrame = nsnull;  
  if (data) {
    if (data->IsOrig()) {
      cellFrame = data->GetCellFrame();
      if (aOriginates)
        *aOriginates = PR_TRUE;
      if (cellFrame && aColSpan) {
        PRInt32 initialColIndex;
        cellFrame->GetColIndex(initialColIndex);
        PRBool zeroSpan;
        *aColSpan = GetEffectiveColSpan(aMap, aRowX, initialColIndex, zeroSpan);
      }
    }
    else {
      cellFrame = GetCellFrame(aRowX, aColX, *data, PR_TRUE);
      if (aColSpan)
        *aColSpan = 0;
    }
  }
  return cellFrame;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt32 nsCellMap::GetColSpanForNewCell ( nsTableCellFrame aCellFrameToAdd,
PRInt32  aColIndex,
PRInt32  aNumColsInTable,
PRBool aIsZeroColSpan 
) [protected]

Definition at line 1821 of file nsCellMap.cpp.

{
  aIsZeroColSpan = PR_FALSE;
  PRInt32 colSpan = aCellFrameToAdd.GetColSpan();
  if (0 == colSpan) {
    // use a min value for a zero colspan to make computations easier elsewhere 
    colSpan = PR_MAX(MIN_NUM_COLS_FOR_ZERO_COLSPAN, aNumColsInTable - aColIndex);
    aIsZeroColSpan = PR_TRUE;
  }
  return colSpan;
}

Here is the call graph for this function:

Here is the caller graph for this function:

CellData * nsCellMap::GetDataAt ( nsTableCellMap aMap,
PRInt32  aMapRowIndex,
PRInt32  aColIndex,
PRBool  aUpdateZeroSpan 
) [protected]

Definition at line 2431 of file nsCellMap.cpp.

{
  PRInt32 numColsInTable = aMap.GetColCount();
  if ((aMapRowIndex < 0) || (aMapRowIndex >= mRows.Count())) {
    return nsnull;
  }

  nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(aMapRowIndex));
  if (!row) return nsnull;

  CellData* data = (CellData *)(row->SafeElementAt(aColIndex));
  if (!data && aUpdateZeroSpan) {
    PRBool didZeroExpand = PR_FALSE;
    // check for special zero row span
    PRInt32 prevRowX = aMapRowIndex - 1;
    // find the last non null data in the same col
    for ( ; prevRowX > 0; prevRowX--) {
      nsVoidArray* prevRow = (nsVoidArray *)(mRows.ElementAt(prevRowX));
      CellData* prevData = (CellData *)(prevRow->SafeElementAt(aColIndex));
      if (prevData) {
        if (prevData->IsZeroRowSpan()) {
          PRInt32 rowIndex = prevRowX - prevData->GetRowSpanOffset();
          PRInt32 colIndex = 0;
          // if there is a colspan and no overlap then the rowspan offset 
          // and colspan offset point to the same cell
          if ((prevData->IsColSpan()) && (!prevData->IsOverlap())) {
            colIndex = prevData->GetColSpanOffset();
          }
          AdjustForZeroSpan(aMap, rowIndex, colIndex);
          didZeroExpand = PR_TRUE;
        }
        break;
      }
    }

    // check for special zero col span
    if (!didZeroExpand && (aColIndex > 0) && (aColIndex < numColsInTable)) { 
      PRInt32 prevColX = aColIndex - 1;
      // find the last non null data in the same row
      for ( ; prevColX > 0; prevColX--) {
        CellData* prevData = GetDataAt(aMap, aMapRowIndex, prevColX, PR_FALSE);
        if (prevData) {
          if (prevData->IsZeroColSpan()) {
            PRInt32 colIndex = prevColX - prevData->GetColSpanOffset();
            // if there were also a rowspan, it would have been handled above
            AdjustForZeroSpan(aMap, aMapRowIndex, colIndex);
            didZeroExpand = PR_TRUE;
          }
          break;
        }
      }
    }

    // if zero span adjustments were made the data may be available now
    if (!data && didZeroExpand) {
      data = GetDataAt(aMap, aMapRowIndex, aColIndex, PR_FALSE);
    }
  }
  return data;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt32 nsCellMap::GetEffectiveColSpan ( nsTableCellMap aMap,
PRInt32  aRowIndex,
PRInt32  aColIndex,
PRBool aIsZeroColSpan 
)

Definition at line 1836 of file nsCellMap.cpp.

{
  PRInt32 numColsInTable = aMap.GetColCount();
  aZeroColSpan = PR_FALSE;
  PRInt32 colSpan = 1;
  nsVoidArray* row = (nsVoidArray *)(mRows.SafeElementAt(aRowIndex));
  if (row) {
    PRInt32 colX;
    CellData* data;
    PRInt32 maxCols = numColsInTable;
    PRBool hitOverlap = PR_FALSE; // XXX this is not ever being set to PR_TRUE
    for (colX = aColIndex + 1; colX < maxCols; colX++) {
      data = GetDataAt(aMap, aRowIndex, colX, PR_TRUE);
      if (data) {
        // for an overlapping situation get the colspan from the originating cell and
        // use that as the max number of cols to iterate. Since this is rare, only 
        // pay the price of looking up the cell's colspan here.
        if (!hitOverlap && data->IsOverlap()) {
          CellData* origData = GetDataAt(aMap, aRowIndex, aColIndex, PR_TRUE);
          if (origData && origData->IsOrig()) {
            nsTableCellFrame* cellFrame = origData->GetCellFrame();
            if (cellFrame) {
              // possible change the number of colums to iterate
              maxCols = PR_MIN(aColIndex + cellFrame->GetColSpan(), maxCols);
              if (colX >= maxCols) 
                break;
            }
          }
        }
        if (data->IsColSpan()) {
          colSpan++;
          if (data->IsZeroColSpan()) {
            aZeroColSpan = PR_TRUE;
          }
        }
        else {
          break;
        }
      }
      else break;
    }
  }
  return colSpan;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsCellMap * nsCellMap::GetNextSibling ( ) const [inline]

Definition at line 495 of file nsCellMap.h.

{
  return mNextSibling;
}

Here is the caller graph for this function:

PRInt32 nsCellMap::GetNumCellsIn ( PRInt32  aColIndex) const [protected]
PRInt32 nsCellMap::GetRowCount ( PRBool  aConsiderDeadRowSpanRows = PR_FALSE) const [inline]

return the number of rows in the table represented by this CellMap

Definition at line 510 of file nsCellMap.h.

{ 
  PRInt32 rowCount = (aConsiderDeadRowSpanRows) ? mRows.Count() : mRowCount;
  return rowCount; 
}

Here is the caller graph for this function:

Definition at line 505 of file nsCellMap.h.

{
  return mRowGroupFrame;
}

Here is the caller graph for this function:

PRInt32 nsCellMap::GetRowSpan ( nsTableCellMap aMap,
PRInt32  aRowIndex,
PRInt32  aColIndex,
PRBool  aGetEffective,
PRBool aIsZeroRowSpan 
)

Definition at line 1918 of file nsCellMap.cpp.

{
  aZeroRowSpan = PR_FALSE;
  PRInt32 rowSpan = 1;
  PRInt32 rowCount = (aGetEffective) ? mRowCount : mRows.Count();
  PRInt32 rowX;
  for (rowX = aRowIndex + 1; rowX < rowCount; rowX++) {
    CellData* data = GetDataAt(aMap, rowX, aColIndex, PR_TRUE);
    if (data) {
      if (data->IsRowSpan()) {
        rowSpan++;
        if (data->IsZeroRowSpan()) {
          aZeroRowSpan = PR_TRUE;
        }
      }
      else {
        break;
      }
    } 
    else break;
  }
  if (aZeroRowSpan && (rowX < rowCount)) {
    rowSpan += rowCount - rowX;
  }
  return rowSpan;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt32 nsCellMap::GetRowSpanForNewCell ( nsTableCellFrame aCellFrameToAdd,
PRInt32  aRowIndex,
PRBool aIsZeroRowSpan 
) [protected]

Definition at line 1885 of file nsCellMap.cpp.

{
  aIsZeroRowSpan = PR_FALSE;
  PRInt32 rowSpan = aCellFrameToAdd.GetRowSpan();
  if (0 == rowSpan) {
    // use a min value of 2 for a zero rowspan to make computations easier elsewhere 
    rowSpan = PR_MAX(2, mRows.Count() - aRowIndex);
    aIsZeroRowSpan = PR_TRUE;
  }
  return rowSpan;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsCellMap::Grow ( nsTableCellMap aMap,
PRInt32  aNumRows,
PRInt32  aRowIndex = -1 
) [protected]

Definition at line 1220 of file nsCellMap.cpp.

{
  PRInt32 numCols = aMap.GetColCount();
  PRInt32 startRowIndex = (aRowIndex >= 0) ? aRowIndex : mRows.Count();
  PRInt32 endRowIndex = startRowIndex + aNumRows - 1;
  // XXX We really should have a way to say "make this voidarray at least
  // N entries long" to avoid reallocating N times.  On the other hand, the
  // number of likely allocations here isn't TOO gigantic, and we may not
  // know about many of them at a time.
  for (PRInt32 rowX = startRowIndex; rowX <= endRowIndex; rowX++) {
    nsVoidArray* row;
    row = (0 == numCols) ? new nsVoidArray(4) : new nsVoidArray(numCols);
    if (row) {
      mRows.InsertElementAt(row, rowX);
    }
    else return PR_FALSE;
  }
  return PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::GrowRow ( nsVoidArray aRow,
PRInt32  aNumCols 
) [protected]

Definition at line 1242 of file nsCellMap.cpp.

{
  for (PRInt32 colX = 0; colX < aNumCols; colX++) {
    aRow.AppendElement(nsnull);
  }
}

Here is the caller graph for this function:

indicate whether the row has more than one cell that either originates or is spanned from the rows above

Definition at line 1899 of file nsCellMap.cpp.

{
  nsVoidArray* row = (nsVoidArray *)(mRows.SafeElementAt(aRowIndex));
  if (row) {
    PRInt32 maxColIndex = row->Count();
    PRInt32 count = 0;
    PRInt32 colIndex;
    for (colIndex = 0; colIndex < maxColIndex; colIndex++) {
      CellData* cellData = GetDataAt(aMap, aRowIndex, colIndex, PR_FALSE);
      if (cellData && (cellData->GetCellFrame() || cellData->IsRowSpan()))
        count++;
      if (count > 1)
        return PR_TRUE;
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::InsertCells ( nsTableCellMap aMap,
nsVoidArray aCellFrames,
PRInt32  aRowIndex,
PRInt32  aColIndexBefore,
nsRect aDamageArea 
)

Definition at line 1568 of file nsCellMap.cpp.

{
  if (aCellFrames.Count() == 0) return;
  PRInt32 numCols = aMap.GetColCount();
  if (aColIndexBefore >= numCols) {
    NS_ERROR("Inserting instead of appending cells indicates a serious cellmap error");
    aColIndexBefore = numCols - 1;
  }

  // get the starting col index of the 1st new cells 
  PRInt32 startColIndex;
  for (startColIndex = aColIndexBefore + 1; startColIndex < numCols; startColIndex++) {
    CellData* data = GetDataAt(aMap, aRowIndex, startColIndex, PR_TRUE);
    if (!data || data->IsOrig()) { // stop unless it is a span
      break; 
    }
  }

  // record whether inserted cells are going to cause complications due 
  // to existing row spans, col spans or table sizing. 
  PRBool spansCauseRebuild = PR_FALSE;

  // check that all cells have the same row span
  PRInt32 numNewCells = aCellFrames.Count();
  PRBool zeroRowSpan = PR_FALSE;
  PRInt32 rowSpan = 0;
  for (PRInt32 cellX = 0; cellX < numNewCells; cellX++) {
    nsTableCellFrame* cell = (nsTableCellFrame*) aCellFrames.ElementAt(cellX);
    PRInt32 rowSpan2 = GetRowSpanForNewCell(*cell, aRowIndex, zeroRowSpan);
    if (rowSpan == 0) {
      rowSpan = rowSpan2;
    }
    else if (rowSpan != rowSpan2) {
      spansCauseRebuild = PR_TRUE;
      break;
    }
  }

  // check if the new cells will cause the table to add more rows
  if (!spansCauseRebuild) {
    if (mRows.Count() < aRowIndex + rowSpan) {
      spansCauseRebuild = PR_TRUE;
    }
  }

  if (!spansCauseRebuild) {
    spansCauseRebuild = CellsSpanInOrOut(aMap, aRowIndex, aRowIndex + rowSpan - 1, 
                                         startColIndex, numCols - 1);
  }

  if (spansCauseRebuild) {
    aMap.RebuildConsideringCells(this, &aCellFrames, aRowIndex, startColIndex, PR_TRUE, aDamageArea);
  }
  else {
    ExpandWithCells(aMap, aCellFrames, aRowIndex, startColIndex, rowSpan, zeroRowSpan, aDamageArea);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::InsertRows ( nsTableCellMap aMap,
nsVoidArray aRows,
PRInt32  aFirstRowIndex,
PRBool  aConsiderSpans,
nsRect aDamageArea 
)

Definition at line 1252 of file nsCellMap.cpp.

{
  PRInt32 numCols = aMap.GetColCount();
  NS_ASSERTION(aFirstRowIndex >= 0, "nsCellMap::InsertRows called with negative rowIndex");
  if (aFirstRowIndex > mRowCount) {
    // create (aFirstRowIndex - mRowCount) empty rows up to aFirstRowIndex
    PRInt32 numEmptyRows = aFirstRowIndex - mRowCount;
    if (!Grow(aMap, numEmptyRows, mRowCount)) {
      return;
    }
    // update mRowCount, since non-empty rows will be added
    mRowCount += numEmptyRows;
  }

  if (!aConsiderSpans) {
    ExpandWithRows(aMap, aRows, aFirstRowIndex, aDamageArea);
    return;
  }

  // if any cells span into or out of the row being inserted, then rebuild
  PRBool spansCauseRebuild = CellsSpanInOrOut(aMap, aFirstRowIndex, 
                                              aFirstRowIndex, 0, numCols - 1);

  // if any of the new cells span out of the new rows being added, then rebuild
  // XXX it would be better to only rebuild the portion of the map that follows the new rows
  if (!spansCauseRebuild && (aFirstRowIndex < mRows.Count())) {
    spansCauseRebuild = CellsSpanOut(aRows);
  }

  if (spansCauseRebuild) {
    aMap.RebuildConsideringRows(this, aFirstRowIndex, &aRows, 0, aDamageArea);
  }
  else {
    ExpandWithRows(aMap, aRows, aFirstRowIndex, aDamageArea);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsCellMap::IsZeroColSpan ( PRInt32  aRowIndex,
PRInt32  aColIndex 
) const [protected]

Definition at line 2355 of file nsCellMap.cpp.

{
  nsVoidArray* row = (nsVoidArray*)mRows.SafeElementAt(aRowIndex);
  if (row) {
    CellData* data = (CellData*)row->SafeElementAt(aColIndex);
    if (data && data->IsZeroColSpan()) {
      return PR_TRUE;
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::RebuildConsideringCells ( nsTableCellMap aMap,
PRInt32  aNumOrigCols,
nsVoidArray aCellFrames,
PRInt32  aRowIndex,
PRInt32  aColIndex,
PRBool  aInsert,
nsRect aDamageArea 
) [protected]

Definition at line 2123 of file nsCellMap.cpp.

{
  // copy the old cell map into a new array
  PRInt32 mRowCountOrig = mRowCount;
  PRInt32 numOrigRows   = mRows.Count();
  void** origRows = new void*[numOrigRows];
  if (!origRows) return;
  PRInt32 rowX;
  for (rowX = 0; rowX < numOrigRows; rowX++) {
    nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
    origRows[rowX] = row;
  }

  // reinitialize data members
  mRows.Clear();
  mRowCount = 0;

  PRInt32 numNewCells = (aCellFrames) ? aCellFrames->Count() : 0;
  
  // the new cells might extend the previous column number
  NS_ASSERTION(aNumOrigCols >= aColIndex, "Appending cells far beyond cellmap data?!");
  PRInt32 numCols = aInsert ? PR_MAX(aNumOrigCols, aColIndex + 1) : aNumOrigCols;  
  
  // build the new cell map 
  for (rowX = 0; rowX < numOrigRows; rowX++) {
    nsVoidArray* row = (nsVoidArray *)origRows[rowX];
    for (PRInt32 colX = 0; colX < numCols; colX++) {
      if ((rowX == aRowIndex) && (colX == aColIndex)) { 
        if (aInsert) { // put in the new cells
          for (PRInt32 cellX = 0; cellX < numNewCells; cellX++) {
            nsTableCellFrame* cell = (nsTableCellFrame*)aCellFrames->ElementAt(cellX);
            if (cell) {
              AppendCell(aMap, cell, rowX, PR_FALSE, aDamageArea);
            }
          }
        }
        else {
          continue; // do not put the deleted cell back
        }
      }
      // put in the original cell from the cell map
      CellData* data = (CellData*) row->SafeElementAt(colX);
      if (data && data->IsOrig()) {
        AppendCell(aMap, data->GetCellFrame(), rowX, PR_FALSE, aDamageArea);
      }
    }
  }

  if (aInsert && numOrigRows <= aRowIndex) { // append the new cells 
                                             // below the last original row
    NS_ASSERTION (numOrigRows == aRowIndex, 
                  "Appending cells far beyond the last row");
    for (PRInt32 cellX = 0; cellX < numNewCells; cellX++) {
      nsTableCellFrame* cell = (nsTableCellFrame*)aCellFrames->ElementAt(cellX);
      if (cell) {
        AppendCell(aMap, cell, aRowIndex, PR_FALSE, aDamageArea);
      }
    }
  }
  // For for cell deletion, since the row is not being deleted, 
  // keep mRowCount the same as before. 
  mRowCount = PR_MAX(mRowCount, mRowCountOrig);

  // delete the old cell map
  for (rowX = 0; rowX < numOrigRows; rowX++) {
    nsVoidArray* row = (nsVoidArray *)origRows[rowX];
    PRInt32 len = row->Count();
    for (PRInt32 colX = 0; colX < len; colX++) {
      CellData* data = (CellData*) row->SafeElementAt(colX);
      if(data)
        delete data;
    }
    delete row;
  }
  delete [] origRows; 
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::RebuildConsideringRows ( nsTableCellMap aMap,
PRInt32  aStartRowIndex,
nsVoidArray aRowsToInsert,
PRInt32  aNumRowsToRemove,
nsRect aDamageArea 
) [protected]

Definition at line 2030 of file nsCellMap.cpp.

{
  // copy the old cell map into a new array
  PRInt32 numOrigRows = mRows.Count();
  void** origRows = new void*[numOrigRows];
  if (!origRows) return;
  PRInt32 rowX, colX;
  // copy the orig rows
  for (rowX = 0; rowX < numOrigRows; rowX++) {
    nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
    origRows[rowX] = row;
  }

  mRows.Clear();
  // adjust mRowCount based on the function arguments as they are known to
  // be real rows.
  mRowCount -= aNumRowsToRemove;
  if (aRowsToInsert) { 
    mRowCount += aRowsToInsert->Count();
    Grow(aMap, numOrigRows); 
  }

  // aStartRowIndex might be after all existing rows so we should limit the
  // copy to the amount of exisiting rows
  PRInt32 copyEndRowIndex = PR_MIN(numOrigRows, aStartRowIndex);

  // put back the rows before the affected ones just as before
  for (rowX = 0; rowX < copyEndRowIndex; rowX++) {
    nsVoidArray* row = (nsVoidArray *)origRows[rowX];
    PRInt32 numCols = row->Count();
    for (colX = 0; colX < numCols; colX++) {
      // put in the original cell from the cell map
      CellData* data = (CellData*) row->ElementAt(colX);
      if (data && data->IsOrig()) {
        AppendCell(aMap, data->GetCellFrame(), rowX, PR_FALSE, aDamageArea);
      }
    }
  }
  PRInt32 copyStartRowIndex;
  if (aRowsToInsert) {
    // add in the new cells and create rows if necessary
    PRInt32 numNewRows = aRowsToInsert->Count();
    rowX = aStartRowIndex;
    for (PRInt32 newRowX = 0; newRowX < numNewRows; newRowX++) {
      nsTableRowFrame* rFrame = (nsTableRowFrame *)aRowsToInsert->ElementAt(newRowX);
      nsIFrame* cFrame = rFrame->GetFirstChild(nsnull);
      while (cFrame) {
        if (IS_TABLE_CELL(cFrame->GetType())) {
          AppendCell(aMap, (nsTableCellFrame *)cFrame, rowX, PR_FALSE, aDamageArea);
        }
        cFrame = cFrame->GetNextSibling();
      }
      rowX++;
    }
    copyStartRowIndex = aStartRowIndex;
  }
  else {
    rowX = aStartRowIndex;
    copyStartRowIndex = aStartRowIndex + aNumRowsToRemove;
  }
  // put back the rows after the affected ones just as before
  for (PRInt32 copyRowX = copyStartRowIndex; copyRowX < numOrigRows; copyRowX++) {
    nsVoidArray* row = (nsVoidArray *)origRows[copyRowX];
    PRInt32 numCols = row->Count();
    for (colX = 0; colX < numCols; colX++) {
      // put in the original cell from the cell map
      CellData* data = (CellData*) row->ElementAt(colX);
      if (data && data->IsOrig()) {
        AppendCell(aMap, data->GetCellFrame(), rowX, PR_FALSE, aDamageArea);
      }
    }
    rowX++;
  }

  // delete the old cell map
  for (rowX = 0; rowX < numOrigRows; rowX++) {
    nsVoidArray* row = (nsVoidArray *)origRows[rowX];
    PRInt32 len = row->Count();
    for (colX = 0; colX < len; colX++) {
      CellData* data = (CellData*) row->ElementAt(colX);
      delete data;
    }
    delete row;
  }
  delete [] origRows;

  SetDamageArea(0, 0, aMap.GetColCount(), GetRowCount(), aDamageArea); 
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::RemoveCell ( nsTableCellMap aMap,
nsTableCellFrame aCellFrame,
PRInt32  aRowIndex,
nsRect aDamageArea 
)

Definition at line 2206 of file nsCellMap.cpp.

{
  PRInt32 numRows = mRows.Count();
  if ((aRowIndex < 0) || (aRowIndex >= numRows)) {
    NS_ASSERTION(PR_FALSE, "bad arg in nsCellMap::RemoveCell");
    return;
  }
  PRInt32 numCols = aMap.GetColCount();

  // get the starting col index of the cell to remove
  PRInt32 startColIndex;
  for (startColIndex = 0; startColIndex < numCols; startColIndex++) {
    CellData* data = GetDataAt(aMap, aRowIndex, startColIndex, PR_FALSE);
    if (data && (data->IsOrig()) && (aCellFrame == data->GetCellFrame())) {
      break; // we found the col index
    }
  }

  PRBool isZeroRowSpan;
  PRInt32 rowSpan = GetRowSpan(aMap, aRowIndex, startColIndex, PR_FALSE, isZeroRowSpan);
  // record whether removing the cells is going to cause complications due 
  // to existing row spans, col spans or table sizing. 
  PRBool spansCauseRebuild = CellsSpanInOrOut(aMap, aRowIndex, aRowIndex + rowSpan - 1, 
                                              startColIndex, numCols - 1);
  // XXX if the cell has a col span to the end of the map, and the end has no originating 
  // cells, we need to assume that this the only such cell, and rebuild so that there are 
  // no extraneous cols at the end. The same is true for removing rows.
  if (!aCellFrame->GetRowSpan() || !aCellFrame->GetColSpan())
    spansCauseRebuild = PR_TRUE;

  if (spansCauseRebuild) {
    aMap.RebuildConsideringCells(this, nsnull, aRowIndex, startColIndex, PR_FALSE, aDamageArea);
  }
  else {
    ShrinkWithoutCell(aMap, *aCellFrame, aRowIndex, startColIndex, aDamageArea);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::RemoveRows ( nsTableCellMap aMap,
PRInt32  aFirstRowIndex,
PRInt32  aNumRowsToRemove,
PRBool  aConsiderSpans,
nsRect aDamageArea 
)

Definition at line 1294 of file nsCellMap.cpp.

{
  PRInt32 numRows = mRows.Count();
  PRInt32 numCols = aMap.GetColCount();

  if (aFirstRowIndex >= numRows) {
    // reduce the content based row count based on the function arguments
    // as they are known to be real rows even if the cell map did not create
    // rows for them before.
    mRowCount -= aNumRowsToRemove;
    return;
  }
  if (!aConsiderSpans) {
    ShrinkWithoutRows(aMap, aFirstRowIndex, aNumRowsToRemove, aDamageArea);
    return;
  }
  PRInt32 endRowIndex = aFirstRowIndex + aNumRowsToRemove - 1;
  if (endRowIndex >= numRows) {
    NS_ASSERTION(PR_FALSE, "nsCellMap::RemoveRows tried to remove too many rows");
    endRowIndex = numRows - 1;
  }
  PRBool spansCauseRebuild = CellsSpanInOrOut(aMap, aFirstRowIndex, endRowIndex,
                                              0, numCols - 1);

  if (spansCauseRebuild) {
    aMap.RebuildConsideringRows(this, aFirstRowIndex, nsnull, aNumRowsToRemove, aDamageArea);
  }
  else {
    ShrinkWithoutRows(aMap, aFirstRowIndex, aNumRowsToRemove, aDamageArea);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2589 of file nsCellMap.cpp.

{
  PRInt32 numColsInTable = aMap.GetColCount();
  if ((0 > aRowIndex) || (aRowIndex >= mRowCount)) {
    return PR_FALSE;
  }
  if (aRowIndex != mRowCount - 1) {
    // aRowIndex is not the last row, so we check the next row after aRowIndex for spanners
    for (PRInt32 colIndex = 0; colIndex < numColsInTable; colIndex++) {
      CellData* cd = GetDataAt(aMap, aRowIndex, colIndex, PR_TRUE);
      if (cd && (cd->IsOrig())) { // cell originates 
        CellData* cd2 = GetDataAt(aMap, aRowIndex + 1, colIndex, PR_TRUE);
        if (cd2 && cd2->IsRowSpan()) { // cd2 is spanned by a row
          if (cd->GetCellFrame() == GetCellFrame(aRowIndex + 1, colIndex, *cd2, PR_TRUE)) {
            return PR_TRUE;
          }
        }
      }
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2569 of file nsCellMap.cpp.

{
  PRInt32 numColsInTable = aMap.GetColCount();
  if ((0 > aRowIndex) || (aRowIndex >= mRowCount)) {
    return PR_FALSE;
  }
  for (PRInt32 colIndex = 0; colIndex < numColsInTable; colIndex++) {
    CellData* cd = GetDataAt(aMap, aRowIndex, colIndex, PR_TRUE);
    if (cd) { // there's really a cell at (aRowIndex, colIndex)
      if (cd->IsSpan()) { // the cell at (aRowIndex, colIndex) is the result of a span
        if (cd->IsRowSpan() && GetCellFrame(aRowIndex, colIndex, *cd, PR_TRUE)) { // XXX why the last check
          return PR_TRUE;
        }
      }
    }
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::SetDataAt ( nsTableCellMap aMap,
CellData aCellData,
PRInt32  aMapRowIndex,
PRInt32  aColIndex,
PRBool  aCountZeroSpanAsSpan 
) [protected]

assign aCellData to the cell at (aRow,aColumn)

Definition at line 2496 of file nsCellMap.cpp.

{
  nsVoidArray* row = (nsVoidArray *)(mRows.SafeElementAt(aMapRowIndex));
  if (row) {
    // the table map may need cols added
    PRInt32 numColsToAdd = aColIndex + 1 - aMap.GetColCount();
    if (numColsToAdd > 0) {
      aMap.AddColsAtEnd(numColsToAdd);
    }
    // the row may need cols added
    numColsToAdd = aColIndex + 1 - row->Count();
    if (numColsToAdd > 0) {
      GrowRow(*row, numColsToAdd);
    }

    CellData* doomedData = (CellData*)row->ElementAt(aColIndex);
    delete doomedData;

    row->ReplaceElementAt(&aNewCell, aColIndex);
    // update the originating cell counts if cell originates in this row, col
    nsColInfo* colInfo = aMap.GetColInfoAt(aColIndex);
    if (colInfo) {
      if (aNewCell.IsOrig()) { 
        colInfo->mNumCellsOrig++;
      }
      else if ((aNewCell.IsColSpan()) && 
               (!aNewCell.IsZeroColSpan() || aCountZeroSpanAsSpan)) {
        colInfo->mNumCellsSpan++;
      }
    }
    else NS_ASSERTION(PR_FALSE, "SetDataAt called with col index > table map num cols");
  }
  else NS_ASSERTION(PR_FALSE, "SetDataAt called with row index > num rows");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::SetNextSibling ( nsCellMap aSibling) [inline]

Definition at line 500 of file nsCellMap.h.

{
  mNextSibling = aSibling;
}

Here is the caller graph for this function:

void nsCellMap::ShrinkWithoutCell ( nsTableCellMap aMap,
nsTableCellFrame aCellFrame,
PRInt32  aRowIndex,
PRInt32  aColIndex,
nsRect aDamageArea 
) [protected]

Definition at line 1949 of file nsCellMap.cpp.

{
  PRInt32 colX, rowX;

  // get the rowspan and colspan from the cell map since the content may have changed
  PRBool  zeroRowSpan, zeroColSpan;
  PRInt32 numCols = aMap.GetColCount();
  PRInt32 rowSpan = GetRowSpan(aMap, aRowIndex, aColIndex, PR_FALSE, zeroRowSpan);
  PRInt32 colSpan = GetEffectiveColSpan(aMap, aRowIndex, aColIndex, zeroColSpan);
  PRInt32 endRowIndex = aRowIndex + rowSpan - 1;
  PRInt32 endColIndex = aColIndex + colSpan - 1;

  SetDamageArea(aColIndex, aRowIndex, 1 + endColIndex - aColIndex, 1 + endRowIndex - aRowIndex, aDamageArea); 

  // adjust the col counts due to the deleted cell before removing it
  for (colX = aColIndex; colX <= endColIndex; colX++) {
    nsColInfo* colInfo = aMap.GetColInfoAt(colX);
    if (colX == aColIndex) {
      colInfo->mNumCellsOrig--;
    }
    // a colspan=0 cell is only counted as a spanner in the 1st col it spans
    else if (!zeroColSpan || (zeroColSpan && (colX == aColIndex + 1))) {
      colInfo->mNumCellsSpan--;
    }
  }

  // remove the deleted cell and cellData entries for it
  for (rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
    nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
    for (colX = endColIndex; colX >= aColIndex; colX--) {
      CellData* doomedData = (CellData*) row->ElementAt(colX);
      delete doomedData;
      row->RemoveElementAt(colX);
    }
  }

  numCols = aMap.GetColCount();

  // update the row and col info due to shifting
  for (rowX = aRowIndex; rowX <= endRowIndex; rowX++) {
    nsVoidArray* row = (nsVoidArray *)mRows.ElementAt(rowX);
    PRInt32 rowCount = row->Count();
    for (colX = aColIndex; colX < numCols - colSpan; colX++) {
      CellData* data = (colX < rowCount) ? (CellData*)row->ElementAt(colX) : nsnull;
      if (data) {
        if (data->IsOrig()) {
          // a cell that gets moved to the left needs adjustment in its new location 
          data->GetCellFrame()->SetColIndex(colX);
          nsColInfo* colInfo = aMap.GetColInfoAt(colX);
          colInfo->mNumCellsOrig++;
          // a cell that gets moved to the left needs adjustment in its old location 
          colInfo = aMap.GetColInfoAt(colX + colSpan);
          if (colInfo) {
            colInfo->mNumCellsOrig--;
          }
        }
        // a colspan=0 cell is only counted as a spanner in the 1st col it spans
        else if (data->IsColSpan()) {
          if ( (!data->IsZeroColSpan()) ||
               ((data->IsZeroColSpan()) && (rowX == aRowIndex) && (!IsZeroColSpan(rowX, colX - 1)))) {
            // a cell that gets moved to the left needs adjustment in its new location 
            nsColInfo* colInfo = aMap.GetColInfoAt(colX);
            colInfo->mNumCellsSpan++;
            // a cell that gets moved to the left needs adjustment in its old location 
            colInfo = aMap.GetColInfoAt(colX + colSpan);
            if (colInfo) {
              colInfo->mNumCellsSpan--;
            }
          }
        }
      }
    }
  }
  aMap.RemoveColsAtEnd();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCellMap::ShrinkWithoutRows ( nsTableCellMap aMap,
PRInt32  aFirstRowIndex,
PRInt32  aNumRowsToRemove,
nsRect aDamageArea 
) [protected]

Definition at line 1771 of file nsCellMap.cpp.

{
  PRInt32 endRowIndex = aStartRowIndex + aNumRowsToRemove - 1;
  PRInt32 colCount = aMap.GetColCount();
  for (PRInt32 rowX = endRowIndex; rowX >= aStartRowIndex; --rowX) {
    nsVoidArray* row = (nsVoidArray *)(mRows.ElementAt(rowX));
    PRInt32 colX;
    for (colX = 0; colX < colCount; colX++) {
      CellData* data = (CellData *) row->SafeElementAt(colX);
      if (data) {
        // Adjust the column counts.
        if (data->IsOrig()) {
          // Decrement the column count.
          nsColInfo* colInfo = aMap.GetColInfoAt(colX);
          colInfo->mNumCellsOrig--;
        }
        // colspan=0 is only counted as a spanned cell in the 1st col it spans
        else if (data->IsColSpan()) {
          if ( (!data->IsZeroColSpan()) ||
               ((data->IsZeroColSpan()) && (rowX == aStartRowIndex) && (!IsZeroColSpan(rowX, colX - 1)))) {
            nsColInfo* colInfo = aMap.GetColInfoAt(colX);
            colInfo->mNumCellsSpan--;
          }
        }
      }
    }

    PRInt32 rowLength = row->Count();
    // Delete our row information.
    for (colX = 0; colX < rowLength; colX++) {
      CellData* data = (CellData *)(row->ElementAt(colX));
      if (data) {
        delete data;
      }
    }

    mRows.RemoveElementAt(rowX);
    delete row;

    // Decrement our row and next available index counts.
    mRowCount--;
  }
  aMap.RemoveColsAtEnd();

  SetDamageArea(0, aStartRowIndex, aMap.GetColCount(), 0, aDamageArea); 
}

Here is the call graph for this function:

Here is the caller graph for this function:


Friends And Related Function Documentation

friend class BCMapBorderIterator [friend]

Definition at line 367 of file nsCellMap.h.

friend class BCMapCellIterator [friend]

Definition at line 366 of file nsCellMap.h.

friend class nsTableCellMap [friend]

dump a representation of the cell map to stdout for debugging

Definition at line 365 of file nsCellMap.h.

friend class nsTableFrame [friend]

Definition at line 368 of file nsCellMap.h.


Member Data Documentation

Definition at line 485 of file nsCellMap.h.

the number of rows in the table (content) which is not indentical to the number of rows in the cell map due to row spans extending beyond the end of thetable (dead rows) or empty tr tags

Definition at line 479 of file nsCellMap.h.

Definition at line 482 of file nsCellMap.h.

nsAutoVoidArray nsCellMap::mRows [protected]

an array containing col array.

It can be larger than mRowCount due to row spans extending beyond the table

Definition at line 473 of file nsCellMap.h.


The documentation for this class was generated from the following files: