Bug 454376 imgLoader.cpp does not compile with Sun Studio 12 on Solaris r=joedraw...
[wine-gecko.git] / layout / tables / nsTableColGroupFrame.cpp
blob62f08bc7dc4fa2dd56ef5b8ac652528d82209219
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
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/
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.
15 * The Original Code is mozilla.org code.
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.
22 * Contributor(s):
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.
36 * ***** END LICENSE BLOCK ***** */
37 #include "nsTableColGroupFrame.h"
38 #include "nsTableColFrame.h"
39 #include "nsTableFrame.h"
40 #include "nsIDOMHTMLTableColElement.h"
41 #include "nsStyleContext.h"
42 #include "nsStyleConsts.h"
43 #include "nsPresContext.h"
44 #include "nsHTMLParts.h"
45 #include "nsGkAtoms.h"
46 #include "nsCOMPtr.h"
47 #include "nsCSSRendering.h"
48 #include "nsIPresShell.h"
50 #define COL_GROUP_TYPE_BITS 0xC0000000 // uses bits 31-32 from mState
51 #define COL_GROUP_TYPE_OFFSET 30
53 nsTableColGroupType
54 nsTableColGroupFrame::GetColType() const
56 return (nsTableColGroupType)((mState & COL_GROUP_TYPE_BITS) >> COL_GROUP_TYPE_OFFSET);
59 void nsTableColGroupFrame::SetColType(nsTableColGroupType aType)
61 PRUint32 type = aType - eColGroupContent;
62 mState |= (type << COL_GROUP_TYPE_OFFSET);
65 void nsTableColGroupFrame::ResetColIndices(nsIFrame* aFirstColGroup,
66 PRInt32 aFirstColIndex,
67 nsIFrame* aStartColFrame)
69 nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame*)aFirstColGroup;
70 PRInt32 colIndex = aFirstColIndex;
71 while (colGroupFrame) {
72 if (nsGkAtoms::tableColGroupFrame == colGroupFrame->GetType()) {
73 // reset the starting col index for the first cg only if we should reset
74 // the whole colgroup (aStartColFrame defaults to nsnull) or if
75 // aFirstColIndex is smaller than the existing starting col index
76 if ((colIndex != aFirstColIndex) ||
77 (colIndex < colGroupFrame->GetStartColumnIndex()) ||
78 !aStartColFrame) {
79 colGroupFrame->SetStartColumnIndex(colIndex);
81 nsIFrame* colFrame = aStartColFrame;
82 if (!colFrame || (colIndex != aFirstColIndex)) {
83 colFrame = colGroupFrame->GetFirstChild(nsnull);
85 while (colFrame) {
86 if (nsGkAtoms::tableColFrame == colFrame->GetType()) {
87 ((nsTableColFrame*)colFrame)->SetColIndex(colIndex);
88 colIndex++;
90 colFrame = colFrame->GetNextSibling();
93 colGroupFrame = static_cast<nsTableColGroupFrame*>
94 (colGroupFrame->GetNextSibling());
99 nsresult
100 nsTableColGroupFrame::AddColsToTable(PRInt32 aFirstColIndex,
101 PRBool aResetSubsequentColIndices,
102 nsIFrame* aFirstFrame,
103 nsIFrame* aLastFrame)
105 nsresult rv = NS_OK;
106 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
107 if (!tableFrame || !aFirstFrame)
108 return NS_ERROR_NULL_POINTER;
110 // set the col indices of the col frames and and add col info to the table
111 PRInt32 colIndex = aFirstColIndex;
112 nsIFrame* kidFrame = aFirstFrame;
113 PRBool foundLastFrame = PR_FALSE;
114 while (kidFrame) {
115 if (nsGkAtoms::tableColFrame == kidFrame->GetType()) {
116 ((nsTableColFrame*)kidFrame)->SetColIndex(colIndex);
117 if (!foundLastFrame) {
118 mColCount++;
119 tableFrame->InsertCol((nsTableColFrame &)*kidFrame, colIndex);
121 colIndex++;
123 if (kidFrame == aLastFrame) {
124 foundLastFrame = PR_TRUE;
126 kidFrame = kidFrame->GetNextSibling();
128 // We have already set the colindex for all the colframes in this
129 // colgroup that come after the first inserted colframe, but there could
130 // be other colgroups following this one and their colframes need
131 // correct colindices too.
132 if (aResetSubsequentColIndices && GetNextSibling()) {
133 ResetColIndices(GetNextSibling(), colIndex);
136 return rv;
140 PRBool
141 nsTableColGroupFrame::GetLastRealColGroup(nsTableFrame* aTableFrame,
142 nsIFrame** aLastColGroup)
144 *aLastColGroup = nsnull;
145 nsFrameList colGroups = aTableFrame->GetColGroups();
147 nsIFrame* nextToLastColGroup = nsnull;
148 nsIFrame* lastColGroup = colGroups.FirstChild();
149 while(lastColGroup) {
150 nsIFrame* next = lastColGroup->GetNextSibling();
151 if (next) {
152 nextToLastColGroup = lastColGroup;
153 lastColGroup = next;
155 else {
156 break;
160 if (!lastColGroup) return PR_TRUE; // there are no col group frames
162 nsTableColGroupType lastColGroupType =
163 ((nsTableColGroupFrame *)lastColGroup)->GetColType();
164 if (eColGroupAnonymousCell == lastColGroupType) {
165 *aLastColGroup = nextToLastColGroup;
166 return PR_FALSE;
168 else {
169 *aLastColGroup = lastColGroup;
170 return PR_TRUE;
174 // don't set mColCount here, it is done in AddColsToTable
175 NS_IMETHODIMP
176 nsTableColGroupFrame::SetInitialChildList(nsIAtom* aListName,
177 nsIFrame* aChildList)
179 if (!mFrames.IsEmpty()) {
180 // We already have child frames which means we've already been
181 // initialized
182 NS_NOTREACHED("unexpected second call to SetInitialChildList");
183 return NS_ERROR_UNEXPECTED;
185 if (aListName) {
186 // All we know about is the unnamed principal child list
187 NS_NOTREACHED("unknown frame list");
188 return NS_ERROR_INVALID_ARG;
190 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
191 if (!tableFrame)
192 return NS_ERROR_NULL_POINTER;
194 if (!aChildList) {
195 nsIFrame* firstChild;
196 tableFrame->CreateAnonymousColFrames(this, GetSpan(), eColAnonymousColGroup,
197 PR_FALSE, nsnull, &firstChild);
198 if (firstChild) {
199 SetInitialChildList(aListName, firstChild);
201 return NS_OK;
204 mFrames.AppendFrames(this, aChildList);
205 return NS_OK;
208 NS_IMETHODIMP
209 nsTableColGroupFrame::AppendFrames(nsIAtom* aListName,
210 nsIFrame* aFrameList)
212 NS_ASSERTION(!aListName, "unexpected child list");
214 nsTableColFrame* col = GetFirstColumn();
215 nsTableColFrame* nextCol;
216 while (col && col->GetColType() == eColAnonymousColGroup) {
217 // this colgroup spans one or more columns but now that there is a
218 // real column below, spanned anonymous columns should be removed,
219 // since the HTML spec says to ignore the span of a colgroup if it
220 // has content columns in it.
221 nextCol = col->GetNextCol();
222 RemoveFrame(nsnull, col);
223 col = nextCol;
226 mFrames.AppendFrames(this, aFrameList);
227 InsertColsReflow(GetStartColumnIndex() + mColCount, aFrameList);
228 return NS_OK;
231 NS_IMETHODIMP
232 nsTableColGroupFrame::InsertFrames(nsIAtom* aListName,
233 nsIFrame* aPrevFrame,
234 nsIFrame* aFrameList)
236 NS_ASSERTION(!aListName, "unexpected child list");
237 NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
238 "inserting after sibling frame with different parent");
240 nsFrameList frames(aFrameList); // convience for getting last frame
241 nsIFrame* lastFrame = frames.LastChild();
243 nsTableColFrame* col = GetFirstColumn();
244 nsTableColFrame* nextCol;
245 while (col && col->GetColType() == eColAnonymousColGroup) {
246 // this colgroup spans one or more columns but now that there is a
247 // real column below, spanned anonymous columns should be removed,
248 // since the HTML spec says to ignore the span of a colgroup if it
249 // has content columns in it.
250 NS_ASSERTION(col != aPrevFrame, "Bad aPrevFrame");
251 nextCol = col->GetNextCol();
252 RemoveFrame(nsnull, col);
253 col = nextCol;
256 NS_ASSERTION(!aPrevFrame || aPrevFrame == aPrevFrame->GetLastContinuation(),
257 "Prev frame should be last in continuation chain");
258 NS_ASSERTION(!aPrevFrame || !GetNextColumn(aPrevFrame) ||
259 GetNextColumn(aPrevFrame)->GetColType() != eColAnonymousCol,
260 "Shouldn't be inserting before a spanned colframe");
262 mFrames.InsertFrames(this, aPrevFrame, aFrameList);
263 nsIFrame* prevFrame = nsTableFrame::GetFrameAtOrBefore(this, aPrevFrame,
264 nsGkAtoms::tableColFrame);
266 PRInt32 colIndex = (prevFrame) ? ((nsTableColFrame*)prevFrame)->GetColIndex() + 1 : GetStartColumnIndex();
267 InsertColsReflow(colIndex, aFrameList, lastFrame);
269 return NS_OK;
272 void
273 nsTableColGroupFrame::InsertColsReflow(PRInt32 aColIndex,
274 nsIFrame* aFirstFrame,
275 nsIFrame* aLastFrame)
277 AddColsToTable(aColIndex, PR_TRUE, aFirstFrame, aLastFrame);
279 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
280 if (!tableFrame)
281 return;
283 PresContext()->PresShell()->FrameNeedsReflow(tableFrame,
284 nsIPresShell::eTreeChange,
285 NS_FRAME_HAS_DIRTY_CHILDREN);
288 void
289 nsTableColGroupFrame::RemoveChild(nsTableColFrame& aChild,
290 PRBool aResetSubsequentColIndices)
292 PRInt32 colIndex = 0;
293 nsIFrame* nextChild = nsnull;
294 if (aResetSubsequentColIndices) {
295 colIndex = aChild.GetColIndex();
296 nextChild = aChild.GetNextSibling();
298 if (mFrames.DestroyFrame((nsIFrame*)&aChild)) {
299 mColCount--;
300 if (aResetSubsequentColIndices) {
301 if (nextChild) { // reset inside this and all following colgroups
302 ResetColIndices(this, colIndex, nextChild);
304 else {
305 nsIFrame* nextGroup = GetNextSibling();
306 if (nextGroup) // reset next and all following colgroups
307 ResetColIndices(nextGroup, colIndex);
311 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
312 if (!tableFrame)
313 return;
315 PresContext()->PresShell()->FrameNeedsReflow(tableFrame,
316 nsIPresShell::eTreeChange,
317 NS_FRAME_HAS_DIRTY_CHILDREN);
320 NS_IMETHODIMP
321 nsTableColGroupFrame::RemoveFrame(nsIAtom* aListName,
322 nsIFrame* aOldFrame)
324 NS_ASSERTION(!aListName, "unexpected child list");
326 if (!aOldFrame) return NS_OK;
328 if (nsGkAtoms::tableColFrame == aOldFrame->GetType()) {
329 nsTableColFrame* colFrame = (nsTableColFrame*)aOldFrame;
330 if (colFrame->GetColType() == eColContent) {
331 // Remove any anonymous column frames this <col> produced via a colspan
332 nsTableColFrame* col = colFrame->GetNextCol();
333 nsTableColFrame* nextCol;
334 while (col && col->GetColType() == eColAnonymousCol) {
335 NS_ASSERTION(col->GetStyleContext() == colFrame->GetStyleContext() &&
336 col->GetContent() == colFrame->GetContent(),
337 "How did that happen??");
338 nextCol = col->GetNextCol();
339 RemoveFrame(nsnull, col);
340 col = nextCol;
344 PRInt32 colIndex = colFrame->GetColIndex();
345 RemoveChild(*colFrame, PR_TRUE);
347 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
348 if (!tableFrame)
349 return NS_ERROR_NULL_POINTER;
351 tableFrame->RemoveCol(this, colIndex, PR_TRUE, PR_TRUE);
353 PresContext()->PresShell()->FrameNeedsReflow(tableFrame,
354 nsIPresShell::eTreeChange,
355 NS_FRAME_HAS_DIRTY_CHILDREN);
357 else {
358 mFrames.DestroyFrame(aOldFrame);
361 return NS_OK;
364 PRIntn
365 nsTableColGroupFrame::GetSkipSides() const
367 PRIntn skip = 0;
368 if (nsnull != GetPrevInFlow()) {
369 skip |= 1 << NS_SIDE_TOP;
371 if (nsnull != GetNextInFlow()) {
372 skip |= 1 << NS_SIDE_BOTTOM;
374 return skip;
377 NS_METHOD nsTableColGroupFrame::Reflow(nsPresContext* aPresContext,
378 nsHTMLReflowMetrics& aDesiredSize,
379 const nsHTMLReflowState& aReflowState,
380 nsReflowStatus& aStatus)
382 DO_GLOBAL_REFLOW_COUNT("nsTableColGroupFrame");
383 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
384 NS_ASSERTION(nsnull!=mContent, "bad state -- null content for frame");
385 nsresult rv=NS_OK;
387 const nsStyleVisibility* groupVis = GetStyleVisibility();
388 PRBool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupVis->mVisible);
389 if (collapseGroup) {
390 nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(this);
391 if (tableFrame) {
392 tableFrame->SetNeedToCollapse(PR_TRUE);;
395 // for every content child that (is a column thingy and does not already have a frame)
396 // create a frame and adjust it's style
398 for (nsIFrame *kidFrame = mFrames.FirstChild(); kidFrame;
399 kidFrame = kidFrame->GetNextSibling()) {
400 // Give the child frame a chance to reflow, even though we know it'll have 0 size
401 nsHTMLReflowMetrics kidSize;
402 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
403 nsSize(0,0));
405 nsReflowStatus status;
406 ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, 0, 0, 0, status);
407 FinishReflowChild(kidFrame, aPresContext, nsnull, kidSize, 0, 0, 0);
410 aDesiredSize.width=0;
411 aDesiredSize.height=0;
412 aStatus = NS_FRAME_COMPLETE;
413 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
414 return rv;
417 /* virtual */ PRBool
418 nsTableColGroupFrame::IsContainingBlock() const
420 return PR_TRUE;
423 nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
425 return GetNextColumn(nsnull);
428 nsTableColFrame * nsTableColGroupFrame::GetNextColumn(nsIFrame *aChildFrame)
430 nsTableColFrame *result = nsnull;
431 nsIFrame *childFrame = aChildFrame;
432 if (!childFrame) {
433 childFrame = mFrames.FirstChild();
435 else {
436 childFrame = childFrame->GetNextSibling();
438 while (childFrame)
440 if (NS_STYLE_DISPLAY_TABLE_COLUMN ==
441 childFrame->GetStyleDisplay()->mDisplay)
443 result = (nsTableColFrame *)childFrame;
444 break;
446 childFrame = childFrame->GetNextSibling();
448 return result;
451 PRInt32 nsTableColGroupFrame::GetSpan()
453 return GetStyleTable()->mSpan;
456 void nsTableColGroupFrame::SetContinuousBCBorderWidth(PRUint8 aForSide,
457 BCPixelSize aPixelValue)
459 switch (aForSide) {
460 case NS_SIDE_TOP:
461 mTopContBorderWidth = aPixelValue;
462 return;
463 case NS_SIDE_BOTTOM:
464 mBottomContBorderWidth = aPixelValue;
465 return;
466 default:
467 NS_ERROR("invalid side arg");
471 void nsTableColGroupFrame::GetContinuousBCBorderWidth(nsMargin& aBorder)
473 PRInt32 aPixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
474 nsTableFrame* table = nsTableFrame::GetTableFrame(this);
475 nsTableColFrame* col = table->GetColFrame(mStartColIndex + mColCount - 1);
476 col->GetContinuousBCBorderWidth(aBorder);
477 aBorder.top = BC_BORDER_BOTTOM_HALF_COORD(aPixelsToTwips,
478 mTopContBorderWidth);
479 aBorder.bottom = BC_BORDER_TOP_HALF_COORD(aPixelsToTwips,
480 mBottomContBorderWidth);
481 return;
484 /* ----- global methods ----- */
486 nsIFrame*
487 NS_NewTableColGroupFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
489 return new (aPresShell) nsTableColGroupFrame(aContext);
492 nsIAtom*
493 nsTableColGroupFrame::GetType() const
495 return nsGkAtoms::tableColGroupFrame;
498 #ifdef DEBUG
499 NS_IMETHODIMP
500 nsTableColGroupFrame::GetFrameName(nsAString& aResult) const
502 return MakeFrameName(NS_LITERAL_STRING("TableColGroup"), aResult);
505 void nsTableColGroupFrame::Dump(PRInt32 aIndent)
507 char* indent = new char[aIndent + 1];
508 if (!indent) return;
509 for (PRInt32 i = 0; i < aIndent + 1; i++) {
510 indent[i] = ' ';
512 indent[aIndent] = 0;
514 printf("%s**START COLGROUP DUMP**\n%s startcolIndex=%d colcount=%d span=%d coltype=",
515 indent, indent, GetStartColumnIndex(), GetColCount(), GetSpan());
516 nsTableColGroupType colType = GetColType();
517 switch (colType) {
518 case eColGroupContent:
519 printf(" content ");
520 break;
521 case eColGroupAnonymousCol:
522 printf(" anonymous-column ");
523 break;
524 case eColGroupAnonymousCell:
525 printf(" anonymous-cell ");
526 break;
528 // verify the colindices
529 PRInt32 j = GetStartColumnIndex();
530 nsTableColFrame* col = GetFirstColumn();
531 while (col) {
532 NS_ASSERTION(j == col->GetColIndex(), "wrong colindex on col frame");
533 col = col->GetNextCol();
534 j++;
536 NS_ASSERTION((j - GetStartColumnIndex()) == GetColCount(),
537 "number of cols out of sync");
538 printf("\n%s**END COLGROUP DUMP** ", indent);
539 delete [] indent;
541 #endif