Back to index

lightning-sunbird  0.9+nobinonly
nsFrameSetFrame.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 #include "nsCOMPtr.h"
00039 #include "nsFrameSetFrame.h"
00040 #include "nsContentUtils.h"
00041 #include "nsGenericHTMLElement.h"
00042 #include "nsLeafFrame.h"
00043 #include "nsHTMLContainerFrame.h"
00044 #include "nsPresContext.h"
00045 #include "nsIPresShell.h"
00046 #include "nsIComponentManager.h"
00047 #include "nsIStreamListener.h"
00048 #include "nsIURL.h"
00049 #include "nsIDocument.h"
00050 #include "nsINodeInfo.h"
00051 #include "nsIView.h"
00052 #include "nsIViewManager.h"
00053 #include "nsWidgetsCID.h"
00054 #include "nsHTMLAtoms.h"
00055 #include "nsIScrollableView.h"
00056 #include "nsStyleCoord.h"
00057 #include "nsStyleConsts.h"
00058 #include "nsStyleContext.h"
00059 #include "nsIDocumentLoader.h"
00060 #include "nsHTMLParts.h"
00061 #include "nsILookAndFeel.h"
00062 #include "nsWidgetsCID.h"
00063 #include "nsIComponentManager.h"
00064 #include "nsGUIEvent.h"
00065 #include "nsIRenderingContext.h"
00066 #include "nsIServiceManager.h"
00067 #include "nsIDOMMutationEvent.h"
00068 #include "nsINameSpaceManager.h"
00069 #include "nsCSSPseudoElements.h"
00070 #include "nsCSSAnonBoxes.h"
00071 #include "nsAutoPtr.h"
00072 #include "nsStyleSet.h"
00073 #include "nsLayoutAtoms.h"
00074 
00075 // masks for mEdgeVisibility
00076 #define LEFT_VIS   0x0001
00077 #define RIGHT_VIS  0x0002
00078 #define TOP_VIS    0x0004
00079 #define BOTTOM_VIS 0x0008
00080 #define ALL_VIS    0x000F
00081 #define NONE_VIS   0x0000
00082 
00083 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
00084 
00085 /*******************************************************************************
00086  * nsFramesetDrag
00087  ******************************************************************************/
00088 nsFramesetDrag::nsFramesetDrag() 
00089 {
00090   UnSet();
00091 }
00092 
00093 nsFramesetDrag::nsFramesetDrag(PRBool               aVertical, 
00094                                PRInt32              aIndex, 
00095                                PRInt32              aChange, 
00096                                nsHTMLFramesetFrame* aSource) 
00097 {
00098   mVertical = aVertical;
00099   mIndex    = aIndex;
00100   mChange   = aChange; 
00101   mSource   = aSource;
00102 }
00103 void nsFramesetDrag::Reset(PRBool               aVertical, 
00104                            PRInt32              aIndex, 
00105                            PRInt32              aChange, 
00106                            nsHTMLFramesetFrame* aSource) 
00107 {
00108   mVertical = aVertical;
00109   mIndex    = aIndex;
00110   mChange   = aChange;
00111   mSource   = aSource;
00112   mActive   = PR_TRUE;
00113 }
00114 
00115 void nsFramesetDrag::UnSet()
00116 {
00117   mVertical = PR_TRUE;
00118   mIndex    = -1;
00119   mChange   = 0;
00120   mSource   = nsnull;
00121   mActive   = PR_FALSE;
00122 }
00123 
00124 /*******************************************************************************
00125  * nsHTMLFramesetBorderFrame
00126  ******************************************************************************/
00127 class nsHTMLFramesetBorderFrame : public nsLeafFrame {
00128 
00129 public:
00130 #ifdef DEBUG
00131   NS_IMETHOD GetFrameName(nsAString& aResult) const;
00132 #endif
00133 
00134   NS_IMETHOD HandleEvent(nsPresContext* aPresContext, 
00135                          nsGUIEvent* aEvent,
00136                          nsEventStatus* aEventStatus);
00137 
00138   NS_IMETHOD GetFrameForPoint(const nsPoint& aPoint, 
00139                               nsFramePaintLayer aWhichLayer,
00140                               nsIFrame**     aFrame);
00141 
00142   NS_IMETHOD GetCursor(const nsPoint&    aPoint,
00143                        nsIFrame::Cursor& aCursor);
00144   
00145   NS_IMETHOD Paint(nsPresContext*      aPresContext,
00146                    nsIRenderingContext& aRenderingContext,
00147                    const nsRect&        aDirtyRect,
00148                    nsFramePaintLayer    aWhichLayer,
00149                    PRUint32             aFlags);
00150 
00151   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
00152                     nsHTMLReflowMetrics&     aDesiredSize,
00153                     const nsHTMLReflowState& aReflowState,
00154                     nsReflowStatus&          aStatus);
00155 
00156   PRBool GetVisibility() { return mVisibility || mVisibilityOverride; }
00157   void SetVisibility(PRBool aVisibility);
00158   void SetColor(nscolor aColor);
00159 
00160 protected:
00161   nsHTMLFramesetBorderFrame(PRInt32 aWidth, PRBool aVertical, PRBool aVisible);
00162   virtual ~nsHTMLFramesetBorderFrame();
00163   virtual void GetDesiredSize(nsPresContext* aPresContext,
00164                               const nsHTMLReflowState& aReflowState,
00165                               nsHTMLReflowMetrics& aDesiredSize);
00166   PRInt32 mWidth;
00167   PRPackedBool mVertical;
00168   PRPackedBool mVisibility;
00169   PRPackedBool mVisibilityOverride;
00170   nscolor mColor;
00171   // the prev and next neighbors are indexes into the row (for a horizontal border) or col (for
00172   // a vertical border) of nsHTMLFramesetFrames or nsHTMLFrames
00173   PRInt32 mPrevNeighbor; 
00174   PRInt32 mNextNeighbor;
00175   PRBool mCanResize;
00176   friend class nsHTMLFramesetFrame;
00177 };
00178 /*******************************************************************************
00179  * nsHTMLFramesetBlankFrame
00180  ******************************************************************************/
00181 class nsHTMLFramesetBlankFrame : public nsLeafFrame {
00182 
00183 public:
00184 #ifdef DEBUG
00185   NS_IMETHOD List(nsPresContext* aPresContext, FILE* out = stdout, PRInt32 aIndent = 0) const;
00186 #endif
00187 
00188   NS_IMETHOD Paint(nsPresContext*      aPresContext,
00189                    nsIRenderingContext& aRenderingContext,
00190                    const nsRect&        aDirtyRect,
00191                    nsFramePaintLayer    aWhichLayer,
00192                    PRUint32             aFlags);
00193 
00194   NS_IMETHOD Reflow(nsPresContext*          aPresContext,
00195                     nsHTMLReflowMetrics&     aDesiredSize,
00196                     const nsHTMLReflowState& aReflowState,
00197                     nsReflowStatus&          aStatus);
00198 
00199 protected:
00200   virtual ~nsHTMLFramesetBlankFrame();
00201   virtual void GetDesiredSize(nsPresContext*          aPresContext,
00202                               const nsHTMLReflowState& aReflowState,
00203                               nsHTMLReflowMetrics&     aDesiredSize);
00204   friend class nsHTMLFramesetFrame;
00205   friend class nsHTMLFrameset;
00206 };
00207 
00208 /*******************************************************************************
00209  * nsHTMLFramesetFrame
00210  ******************************************************************************/
00211 PRBool  nsHTMLFramesetFrame::gDragInProgress = PR_FALSE;
00212 #define kFrameResizePref "layout.frames.force_resizability"
00213 #define DEFAULT_BORDER_WIDTH_PX 6
00214 
00215 nsHTMLFramesetFrame::nsHTMLFramesetFrame()
00216   : nsHTMLContainerFrame()
00217 {
00218   mNumRows             = 0;
00219   mRowSizes            = nsnull;
00220   mNumCols             = 0;
00221   mColSizes            = nsnull;
00222   mEdgeVisibility      = 0;
00223   mParentFrameborder   = eFrameborder_Yes; // default
00224   mParentBorderWidth   = -1; // default not set
00225   mParentBorderColor   = NO_COLOR; // default not set
00226   mFirstDragPoint.x     = mFirstDragPoint.y = 0;
00227   mMinDrag             = 0;
00228   mNonBorderChildCount = 0;
00229   mNonBlankChildCount  = 0;
00230   mDragger             = nsnull;
00231   mChildCount          = 0;
00232   mTopLevelFrameset    = nsnull;
00233   mEdgeColors.Set(NO_COLOR);
00234   mVerBorders          = nsnull;
00235   mHorBorders          = nsnull;
00236   mChildTypes          = nsnull;
00237   mChildFrameborder    = nsnull;
00238   mChildBorderColors   = nsnull;
00239   mForceFrameResizability = PR_FALSE;
00240 }
00241 
00242 nsHTMLFramesetFrame::~nsHTMLFramesetFrame()
00243 {
00244   delete[] mRowSizes;
00245   delete[] mColSizes;
00246   delete[] mVerBorders;
00247   delete[] mHorBorders;
00248   delete[] mChildTypes;
00249   delete[] mChildFrameborder;
00250   delete[] mChildBorderColors;
00251 
00252   nsContentUtils::UnregisterPrefCallback(kFrameResizePref,
00253                                          FrameResizePrefCallback, this);
00254 }
00255 
00256 nsresult nsHTMLFramesetFrame::QueryInterface(const nsIID& aIID, 
00257                                              void**       aInstancePtr)
00258 {
00259   if (NULL == aInstancePtr) {
00260     return NS_ERROR_NULL_POINTER;
00261   }
00262 
00263   if (aIID.Equals(NS_GET_IID(nsHTMLFramesetFrame))) {
00264     *aInstancePtr = (void*)this;
00265     return NS_OK;
00266   } 
00267 
00268   return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr);
00269 }
00270 
00271 // static
00272 int
00273 nsHTMLFramesetFrame::FrameResizePrefCallback(const char* aPref, void* aClosure)
00274 {
00275   nsHTMLFramesetFrame *frame =
00276     NS_REINTERPRET_CAST(nsHTMLFramesetFrame *, aClosure);
00277 
00278   nsIDocument* doc = frame->mContent->GetDocument();
00279   mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, PR_TRUE);
00280   if (doc) {
00281     doc->AttributeWillChange(frame->mContent,
00282                              kNameSpaceID_None,
00283                              nsHTMLAtoms::frameborder);
00284   }
00285 
00286   frame->mForceFrameResizability =
00287     nsContentUtils::GetBoolPref(kFrameResizePref,
00288                                 frame->mForceFrameResizability);
00289 
00290   frame->RecalculateBorderResize();
00291   if (doc) {
00292     doc->AttributeChanged(frame->mContent,
00293                           kNameSpaceID_None,
00294                           nsHTMLAtoms::frameborder,
00295                           nsIDOMMutationEvent::MODIFICATION);
00296   }
00297 
00298   return 0;
00299 }
00300 
00301 #define FRAMESET 0
00302 #define FRAME 1
00303 #define BLANK 2
00304 
00305 NS_IMETHODIMP
00306 nsHTMLFramesetFrame::Init(nsPresContext*  aPresContext,
00307                           nsIContent*      aContent,
00308                           nsIFrame*        aParent,
00309                           nsStyleContext*  aContext,
00310                           nsIFrame*        aPrevInFlow)
00311 {
00312   nsHTMLContainerFrame::Init(aPresContext, aContent, aParent,
00313                              aContext, aPrevInFlow);
00314   // find the highest ancestor that is a frameset
00315   nsresult rv = NS_OK;
00316   nsIFrame* parentFrame = GetParent();
00317   mTopLevelFrameset = (nsHTMLFramesetFrame*)this;
00318   while (parentFrame) {
00319     nsHTMLFramesetFrame* frameset = nsnull;
00320     CallQueryInterface(parentFrame, &frameset);
00321     
00322     if (frameset) {
00323       mTopLevelFrameset = frameset;
00324       parentFrame = parentFrame->GetParent();
00325     } else {
00326       break;
00327     }
00328   }
00329 
00330   // create the view. a view is needed since it needs to be a mouse grabber
00331   nsIViewManager* viewMan = aPresContext->GetViewManager();
00332 
00333   nsIView *parView = GetAncestorWithView()->GetView();
00334   nsRect boundBox(0, 0, 0, 0); 
00335   nsIView* view = viewMan->CreateView(boundBox, parView);
00336   if (!view)
00337     return NS_ERROR_OUT_OF_MEMORY;
00338 
00339   // XXX Put it last in document order until we can do better
00340   viewMan->InsertChild(parView, view, nsnull, PR_TRUE);
00341   SetView(view);
00342 
00343   nsIPresShell *shell = aPresContext->PresShell();
00344   
00345   nsFrameborder  frameborder = GetFrameBorder();
00346   PRInt32 borderWidth = GetBorderWidth(aPresContext, PR_FALSE);
00347   nscolor borderColor = GetBorderColor();
00348  
00349   // Get the rows= cols= data
00350   nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
00351   NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
00352   const nsFramesetSpec* rowSpecs = nsnull;
00353   const nsFramesetSpec* colSpecs = nsnull;
00354   nsresult result = ourContent->GetRowSpec(&mNumRows, &rowSpecs);
00355   NS_ENSURE_SUCCESS(result, result);
00356   result = ourContent->GetColSpec(&mNumCols, &colSpecs);
00357   NS_ENSURE_SUCCESS(result, result);
00358   mRowSizes  = new nscoord[mNumRows];
00359   mColSizes  = new nscoord[mNumCols];
00360   if (!mRowSizes || !mColSizes)
00361     return NS_ERROR_OUT_OF_MEMORY; 
00362 
00363   PRInt32 numCells = mNumRows*mNumCols;
00364 
00365   mVerBorders    = new nsHTMLFramesetBorderFrame*[mNumCols];  // 1 more than number of ver borders
00366   if (!mVerBorders)
00367     return NS_ERROR_OUT_OF_MEMORY;
00368 
00369   for (int verX  = 0; verX < mNumCols; verX++)
00370     mVerBorders[verX]    = nsnull;
00371 
00372   mHorBorders    = new nsHTMLFramesetBorderFrame*[mNumRows];  // 1 more than number of hor borders
00373   if (!mHorBorders)
00374     return NS_ERROR_OUT_OF_MEMORY;
00375 
00376   for (int horX = 0; horX < mNumRows; horX++)
00377     mHorBorders[horX]    = nsnull;
00378      
00379   mChildTypes = new PRInt32[numCells]; 
00380   mChildFrameborder  = new nsFrameborder[numCells]; 
00381   mChildBorderColors  = new nsBorderColor[numCells]; 
00382   if (!mChildTypes || !mChildFrameborder || !mChildBorderColors)
00383     return NS_ERROR_OUT_OF_MEMORY;
00384 
00385   // create the children frames; skip content which isn't <frameset> or <frame>
00386   nsIFrame* lastChild = nsnull;
00387   mChildCount = 0; // number of <frame> or <frameset> children
00388   nsIFrame* frame;
00389 
00390   // number of any type of children
00391   PRUint32 numChildren = mContent->GetChildCount();
00392 
00393   for (PRUint32 childX = 0; childX < numChildren; childX++) {
00394     if (mChildCount == numCells) { // we have more <frame> or <frameset> than cells
00395       break;
00396     }
00397     nsIContent *child = mContent->GetChildAt(childX);
00398 
00399     if (!child->IsContentOfType(nsIContent::eHTML))
00400       continue;
00401 
00402     nsIAtom *tag = child->Tag();
00403     if (tag == nsHTMLAtoms::frameset || tag == nsHTMLAtoms::frame) {
00404       nsRefPtr<nsStyleContext> kidSC;
00405       nsresult result;
00406 
00407       kidSC = shell->StyleSet()->ResolveStyleFor(child, mStyleContext);
00408       if (tag == nsHTMLAtoms::frameset) {
00409         result = NS_NewHTMLFramesetFrame(shell, &frame);
00410         if (NS_FAILED(result))
00411           return result;
00412 
00413         mChildTypes[mChildCount] = FRAMESET;
00414         nsHTMLFramesetFrame* childFrame = (nsHTMLFramesetFrame*)frame;
00415         childFrame->SetParentFrameborder(frameborder);
00416         childFrame->SetParentBorderWidth(borderWidth);
00417         childFrame->SetParentBorderColor(borderColor);
00418         result = frame->Init(aPresContext, child, this, kidSC, nsnull);
00419         if (NS_FAILED(result)) {
00420           frame->Destroy(aPresContext);
00421           return result;
00422         }
00423 
00424         mChildBorderColors[mChildCount].Set(childFrame->GetBorderColor());
00425       } else { // frame
00426         result = NS_NewSubDocumentFrame(shell, &frame);
00427         if (NS_FAILED(result))
00428           return NS_ERROR_OUT_OF_MEMORY;
00429 
00430         result = frame->Init(aPresContext, child, this, kidSC, nsnull);
00431         if (NS_FAILED(result)) {
00432           frame->Destroy(aPresContext);
00433           return result;
00434         }
00435 
00436         mChildTypes[mChildCount] = FRAME;
00437         
00438         mChildFrameborder[mChildCount] = GetFrameBorder(child);
00439         mChildBorderColors[mChildCount].Set(GetBorderColor(child));
00440       }
00441       
00442       if (NS_FAILED(result))
00443         return result;
00444 
00445       if (lastChild)
00446         lastChild->SetNextSibling(frame);
00447       else
00448         mFrames.SetFrames(frame);
00449       
00450       lastChild = frame;
00451       mChildCount++;
00452     }
00453   }
00454 
00455   mNonBlankChildCount = mChildCount;
00456   // add blank frames for frameset cells that had no content provided
00457   for (int blankX = mChildCount; blankX < numCells; blankX++) {
00458     // XXX the blank frame is using the content of its parent - at some point it 
00459     // should just have null content, if we support that
00460     nsHTMLFramesetBlankFrame* blankFrame = new (shell) nsHTMLFramesetBlankFrame;
00461     if (!blankFrame)
00462       return NS_ERROR_OUT_OF_MEMORY;
00463 
00464     nsRefPtr<nsStyleContext> pseudoStyleContext;
00465     pseudoStyleContext = shell->StyleSet()->ResolvePseudoStyleFor(nsnull,
00466                                                                   nsCSSAnonBoxes::framesetBlank,
00467                                                                   mStyleContext);
00468     if (!pseudoStyleContext) {
00469       blankFrame->Destroy(aPresContext);
00470       return NS_ERROR_OUT_OF_MEMORY;
00471     }
00472 
00473     result = blankFrame->Init(aPresContext, mContent, this, pseudoStyleContext, nsnull);
00474     if (NS_FAILED(result)) {
00475       blankFrame->Destroy(aPresContext);
00476       return result;
00477     }
00478    
00479     if (lastChild)
00480       lastChild->SetNextSibling(blankFrame);
00481     else
00482       mFrames.SetFrames(blankFrame);
00483     
00484     lastChild = blankFrame;
00485     mChildTypes[mChildCount] = BLANK;
00486     mChildBorderColors[mChildCount].Set(NO_COLOR);
00487     mChildCount++;
00488   }
00489 
00490   mNonBorderChildCount = mChildCount;
00491   return rv;
00492 }
00493 
00494 // XXX should this try to allocate twips based on an even pixel boundary?
00495 void nsHTMLFramesetFrame::Scale(nscoord  aDesired, 
00496                                 PRInt32  aNumIndicies, 
00497                                 PRInt32* aIndicies, 
00498                                 PRInt32  aNumItems,
00499                                 PRInt32* aItems)
00500 {
00501   PRInt32 actual = 0;
00502   PRInt32 i, j;
00503   // get the actual total
00504   for (i = 0; i < aNumIndicies; i++) {
00505     j = aIndicies[i];
00506     actual += aItems[j];
00507   }
00508 
00509   if (actual > 0) {
00510     float factor = (float)aDesired / (float)actual;
00511     actual = 0;
00512     // scale the items up or down
00513     for (i = 0; i < aNumIndicies; i++) {
00514       j = aIndicies[i];
00515       aItems[j] = NSToCoordRound((float)aItems[j] * factor);
00516       actual += aItems[j];
00517     }
00518   } else if (aNumIndicies != 0) {
00519     // All the specs say zero width, but we have to fill up space
00520     // somehow.  Distribute it equally.
00521     nscoord width = NSToCoordRound((float)aDesired / (float)aNumIndicies);
00522     actual = width * aNumIndicies;
00523     for (i = 0; i < aNumIndicies; i++) {
00524       aItems[aIndicies[i]] = width;
00525     }
00526   }
00527 
00528   if (aNumIndicies > 0 && aDesired != actual) {
00529     PRInt32 unit = (aDesired > actual) ? 1 : -1;
00530     for (i=0; (i < aNumIndicies) && (aDesired != actual); i++) {
00531       j = aIndicies[i];
00532       if (j < aNumItems) {
00533         aItems[j] += unit;
00534         actual += unit;
00535       }
00536     }
00537   }
00538 }
00539   
00540 
00547 void nsHTMLFramesetFrame::CalculateRowCol(nsPresContext*       aPresContext, 
00548                                           nscoord               aSize, 
00549                                           PRInt32               aNumSpecs, 
00550                                           const nsFramesetSpec* aSpecs, 
00551                                           nscoord*              aValues)
00552 {
00553   PRInt32  fixedTotal = 0;
00554   PRInt32  numFixed = 0;
00555   PRInt32* fixed = new PRInt32[aNumSpecs];
00556   PRInt32  numPercent = 0;
00557   PRInt32* percent = new PRInt32[aNumSpecs];
00558   PRInt32  relativeSums = 0;
00559   PRInt32  numRelative = 0;
00560   PRInt32* relative= new PRInt32[aNumSpecs];
00561 
00562   float p2t = aPresContext->ScaledPixelsToTwips();
00563   PRInt32 i, j;
00564  
00565   // initialize the fixed, percent, relative indices, allocate the fixed sizes and zero the others
00566   for (i = 0; i < aNumSpecs; i++) {   
00567     aValues[i] = 0;
00568     switch (aSpecs[i].mUnit) {
00569       case eFramesetUnit_Fixed:
00570         aValues[i] = NSToCoordRound(p2t * aSpecs[i].mValue);
00571         fixedTotal += aValues[i];
00572         fixed[numFixed] = i;
00573         numFixed++;
00574         break;
00575       case eFramesetUnit_Percent:
00576         percent[numPercent] = i;
00577         numPercent++;
00578         break;
00579       case eFramesetUnit_Relative:
00580         relative[numRelative] = i;
00581         numRelative++;
00582         relativeSums += aSpecs[i].mValue;
00583         break;
00584     }
00585   }
00586 
00587   // scale the fixed sizes if they total too much (or too little and there aren't any percent or relative)
00588   if ((fixedTotal > aSize) || ((fixedTotal < aSize) && (0 == numPercent) && (0 == numRelative))) { 
00589     Scale(aSize, numFixed, fixed, aNumSpecs, aValues);
00590     delete [] fixed; delete [] percent; delete [] relative;
00591     return;
00592   }
00593 
00594   PRInt32 percentMax = aSize - fixedTotal;
00595   PRInt32 percentTotal = 0;
00596   // allocate the percentage sizes from what is left over from the fixed allocation
00597   for (i = 0; i < numPercent; i++) {
00598     j = percent[i];
00599     aValues[j] = NSToCoordRound((float)aSpecs[j].mValue * (float)aSize / 100.0f);
00600     percentTotal += aValues[j];
00601   }
00602 
00603   // scale the percent sizes if they total too much (or too little and there aren't any relative)
00604   if ((percentTotal > percentMax) || ((percentTotal < percentMax) && (0 == numRelative))) { 
00605     Scale(percentMax, numPercent, percent, aNumSpecs, aValues);
00606     delete [] fixed; delete [] percent; delete [] relative;
00607     return;
00608   }
00609 
00610   PRInt32 relativeMax = percentMax - percentTotal;
00611   PRInt32 relativeTotal = 0;
00612   // allocate the relative sizes from what is left over from the percent allocation
00613   for (i = 0; i < numRelative; i++) {
00614     j = relative[i];
00615     aValues[j] = NSToCoordRound((float)aSpecs[j].mValue * (float)relativeMax / (float)relativeSums);
00616     relativeTotal += aValues[j];
00617   }
00618 
00619   // scale the relative sizes if they take up too much or too little
00620   if (relativeTotal != relativeMax) { 
00621     Scale(relativeMax, numRelative, relative, aNumSpecs, aValues);
00622   }
00623   
00624   delete [] fixed; delete [] percent; delete [] relative;
00625 }
00626 
00627 
00633 void nsHTMLFramesetFrame::GenerateRowCol(nsPresContext*       aPresContext, 
00634                                          nscoord               aSize, 
00635                                          PRInt32               aNumSpecs, 
00636                                          const nsFramesetSpec* aSpecs,
00637                                          nscoord*              aValues,
00638                                          nsString&             aNewAttr)
00639 {
00640   float t2p;
00641   t2p = aPresContext->TwipsToPixels();
00642   PRInt32 i;
00643  
00644   for (i = 0; i < aNumSpecs; i++) {
00645     if (!aNewAttr.IsEmpty())
00646       aNewAttr.Append(PRUnichar(','));
00647     
00648     switch (aSpecs[i].mUnit) {
00649       case eFramesetUnit_Fixed:
00650         aNewAttr.AppendInt(NSToCoordRound(t2p * aValues[i]));
00651         break;
00652       case eFramesetUnit_Percent: // XXX Only accurate to 1%, need 1 pixel
00653       case eFramesetUnit_Relative:
00654         // Add 0.5 to the percentage to make rounding work right.
00655         aNewAttr.AppendInt(PRUint32((100.0*aValues[i])/aSize + 0.5)); 
00656         aNewAttr.Append(PRUnichar('%'));
00657         break;
00658     }
00659   }
00660 }
00661 
00662 PRInt32 nsHTMLFramesetFrame::GetBorderWidth(nsPresContext* aPresContext,
00663                                             PRBool aTakeForcingIntoAccount)
00664 {
00665   PRBool forcing = mForceFrameResizability && aTakeForcingIntoAccount;
00666   
00667   if (!forcing) {
00668     nsFrameborder frameborder = GetFrameBorder();
00669     if (frameborder == eFrameborder_No) {
00670       return 0;
00671     }
00672   }
00673   float p2t = aPresContext->ScaledPixelsToTwips();
00674   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
00675 
00676   if (content) {
00677     const nsAttrValue* attr = content->GetParsedAttr(nsHTMLAtoms::border);
00678     if (attr) {
00679       PRInt32 intVal = 0;
00680       if (attr->Type() == nsAttrValue::eInteger) {
00681         intVal = attr->GetIntegerValue();
00682         if (intVal < 0) {
00683           intVal = 0;
00684         }
00685       }
00686 
00687       if (forcing && intVal == 0) {
00688         intVal = DEFAULT_BORDER_WIDTH_PX;
00689       }
00690       return NSIntPixelsToTwips(intVal, p2t);
00691     }
00692   }
00693 
00694   if (mParentBorderWidth > 0 ||
00695       (mParentBorderWidth == 0 && !forcing)) {
00696     return mParentBorderWidth;
00697   }
00698 
00699   return NSIntPixelsToTwips(DEFAULT_BORDER_WIDTH_PX, p2t);
00700 }
00701 
00702 
00703 PRIntn
00704 nsHTMLFramesetFrame::GetSkipSides() const
00705 {
00706   return 0;
00707 }
00708 
00709 void 
00710 nsHTMLFramesetFrame::GetDesiredSize(nsPresContext*          aPresContext,
00711                                     const nsHTMLReflowState& aReflowState,
00712                                     nsHTMLReflowMetrics&     aDesiredSize)
00713 {
00714   nsHTMLFramesetFrame* framesetParent = GetFramesetParent(this);
00715   if (nsnull == framesetParent) {
00716     nsRect area = aPresContext->GetVisibleArea();
00717 
00718     aDesiredSize.width = area.width;
00719     aDesiredSize.height= area.height;
00720   } else {
00721     nsSize size;
00722     framesetParent->GetSizeOfChild(this, size);
00723     aDesiredSize.width  = size.width;
00724     aDesiredSize.height = size.height;
00725   } 
00726   aDesiredSize.ascent = aDesiredSize.height;
00727   aDesiredSize.descent = 0;
00728 }
00729 
00730 
00731 nsHTMLFramesetFrame* nsHTMLFramesetFrame::GetFramesetParent(nsIFrame* aChild)
00732 {
00733   nsHTMLFramesetFrame* parent = nsnull;
00734   nsIContent* content = aChild->GetContent();
00735 
00736   if (content) { 
00737     nsCOMPtr<nsIContent> contentParent = content->GetParent();
00738 
00739     if (contentParent && contentParent->IsContentOfType(nsIContent::eHTML) &&
00740         contentParent->Tag() == nsHTMLAtoms::frameset) {
00741       nsIFrame* fptr = aChild->GetParent();
00742       parent = (nsHTMLFramesetFrame*) fptr;
00743     }
00744   }
00745 
00746   return parent;
00747 }
00748 
00749 // only valid for non border children
00750 void nsHTMLFramesetFrame::GetSizeOfChildAt(PRInt32  aIndexInParent, 
00751                                            nsSize&  aSize, 
00752                                            nsPoint& aCellIndex)
00753 {
00754   PRInt32 row = aIndexInParent / mNumCols;
00755   PRInt32 col = aIndexInParent - (row * mNumCols); // remainder from dividing index by mNumCols
00756   if ((row < mNumRows) && (col < mNumCols)) {
00757     aSize.width  = mColSizes[col];
00758     aSize.height = mRowSizes[row];
00759     aCellIndex.x = col;
00760     aCellIndex.y = row;
00761   } else {
00762     aSize.width = aSize.height = aCellIndex.x = aCellIndex.y = 0;
00763   }
00764 }
00765 
00766 // only valid for non border children
00767 void nsHTMLFramesetFrame::GetSizeOfChild(nsIFrame* aChild, 
00768                                          nsSize&   aSize)
00769 {
00770   // Reflow only creates children frames for <frameset> and <frame> content.
00771   // this assumption is used here
00772   int i = 0;
00773   for (nsIFrame* child = mFrames.FirstChild(); child;
00774        child = child->GetNextSibling()) {
00775     if (aChild == child) {
00776       nsPoint ignore;
00777       GetSizeOfChildAt(i, aSize, ignore);
00778       return;
00779     }
00780     i++;
00781   }
00782   aSize.width  = 0;
00783   aSize.height = 0;
00784 }  
00785 
00786   
00787 NS_METHOD nsHTMLFramesetFrame::HandleEvent(nsPresContext* aPresContext, 
00788                                            nsGUIEvent*     aEvent,
00789                                            nsEventStatus*  aEventStatus)
00790 {
00791   NS_ENSURE_ARG_POINTER(aEventStatus);
00792   if (mDragger) {
00793     // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
00794     switch (aEvent->message) {
00795       case NS_MOUSE_MOVE:
00796         MouseDrag(aPresContext, aEvent);
00797              break;
00798       case NS_MOUSE_LEFT_BUTTON_UP:
00799         EndMouseDrag(aPresContext);
00800              break;
00801     }
00802     *aEventStatus = nsEventStatus_eConsumeNoDefault;
00803   } else {
00804     *aEventStatus = nsEventStatus_eIgnore;
00805   }
00806   return NS_OK;
00807 }
00808 
00809 #if 0
00810 PRBool 
00811 nsHTMLFramesetFrame::IsGrabbingMouse()
00812 {
00813   PRBool result = PR_FALSE;
00814   nsIView* view = GetView();
00815   if (view) {
00816     nsIViewManager* viewMan = view->GetViewManager();
00817     if (viewMan) {
00818       nsIView* grabber;
00819       viewMan->GetMouseEventGrabber(grabber);
00820       if (grabber == view) {
00821         // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
00822         result = PR_TRUE;
00823       }
00824       NS_RELEASE(viewMan);
00825     }
00826   }
00827   return result;
00828 }
00829 #endif
00830 
00831 NS_IMETHODIMP
00832 nsHTMLFramesetFrame::GetCursor(const nsPoint&    aPoint,
00833                                nsIFrame::Cursor& aCursor)
00834 {
00835   if (mDragger) {
00836     aCursor.mCursor = (mDragger->mVertical) ? NS_STYLE_CURSOR_W_RESIZE : NS_STYLE_CURSOR_N_RESIZE;
00837   } else {
00838     aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
00839   }
00840   return NS_OK;
00841 }
00842 
00843 NS_IMETHODIMP 
00844 nsHTMLFramesetFrame::GetFrameForPoint(const nsPoint& aPoint, 
00845                                       nsFramePaintLayer aWhichLayer,
00846                                       nsIFrame**     aFrame)
00847 {
00848   //XXX Temporary to deal with event handling in both this and FramsetBorderFrame
00849   if (mDragger) { 
00850     *aFrame = this;
00851     return NS_OK;
00852   } else {
00853     return nsContainerFrame::GetFrameForPoint(aPoint, aWhichLayer, aFrame);
00854   }
00855 }
00856 
00857 NS_IMETHODIMP
00858 nsHTMLFramesetFrame::Paint(nsPresContext*      aPresContext,
00859                            nsIRenderingContext& aRenderingContext,
00860                            const nsRect&        aDirtyRect,
00861                            nsFramePaintLayer    aWhichLayer,
00862                            PRUint32             aFlags)
00863 {
00864   //printf("frameset paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
00865   return nsHTMLContainerFrame::Paint(aPresContext, aRenderingContext,
00866                                      aDirtyRect, aWhichLayer);
00867 }
00868 
00869 void 
00870 nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame*                aChild,
00871                                       nsPresContext*          aPresContext,
00872                                       const nsHTMLReflowState& aReflowState,
00873                                       nsPoint&                 aOffset,
00874                                       nsSize&                  aSize,
00875                                       nsPoint*                 aCellIndex)
00876 {
00877   // reflow the child
00878   nsHTMLReflowState  reflowState(aPresContext, aReflowState, aChild, aSize);
00879   nsHTMLReflowMetrics metrics(nsnull);
00880   metrics.width = aSize.width;
00881   metrics.height= aSize.height;
00882   nsReflowStatus status;
00883   
00884   ReflowChild(aChild, aPresContext, metrics, reflowState, aOffset.x,
00885               aOffset.y, 0, status);
00886   NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status");
00887   
00888   // Place and size the child
00889   metrics.width = aSize.width;
00890   metrics.height = aSize.height;
00891   FinishReflowChild(aChild, aPresContext, nsnull, metrics, aOffset.x, aOffset.y, 0);
00892 }
00893 
00894 static
00895 nsFrameborder GetFrameBorderHelper(nsGenericHTMLElement* aContent)
00896 {
00897   if (nsnull != aContent) {
00898     const nsAttrValue* attr = aContent->GetParsedAttr(nsHTMLAtoms::frameborder);
00899     if (attr && attr->Type() == nsAttrValue::eEnum) {
00900       switch (attr->GetEnumValue())
00901       {
00902         case NS_STYLE_FRAME_YES:
00903         case NS_STYLE_FRAME_1:
00904           return eFrameborder_Yes;
00905           break;
00906 
00907         case NS_STYLE_FRAME_NO:
00908         case NS_STYLE_FRAME_0:
00909           return eFrameborder_No;
00910           break;
00911       }
00912     }
00913   }
00914   return eFrameborder_Notset;
00915 }
00916 
00917 nsFrameborder nsHTMLFramesetFrame::GetFrameBorder() 
00918 {
00919   nsFrameborder result = eFrameborder_Notset;
00920   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
00921 
00922   if (content) {
00923     result = GetFrameBorderHelper(content);
00924   }
00925   if (eFrameborder_Notset == result) {
00926     return mParentFrameborder;
00927   }
00928   return result;
00929 }
00930 
00931 nsFrameborder nsHTMLFramesetFrame::GetFrameBorder(nsIContent* aContent)
00932 {
00933   nsFrameborder result = eFrameborder_Notset;
00934 
00935   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(aContent);
00936 
00937   if (content) {
00938     result = GetFrameBorderHelper(content);
00939   }
00940   if (eFrameborder_Notset == result) {
00941     return GetFrameBorder();
00942   }
00943   return result;
00944 }
00945 
00946 nscolor nsHTMLFramesetFrame::GetBorderColor() 
00947 {
00948   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
00949 
00950   if (content) {
00951     const nsAttrValue* attr = content->GetParsedAttr(nsHTMLAtoms::bordercolor);
00952     if (attr) {
00953       nscolor color;
00954       if (attr->GetColorValue(color)) {
00955         return color;
00956       }
00957     }
00958   }
00959 
00960   return mParentBorderColor;
00961 }
00962 
00963 nscolor nsHTMLFramesetFrame::GetBorderColor(nsIContent* aContent) 
00964 {
00965   nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(aContent);
00966 
00967   if (content) {
00968     const nsAttrValue* attr = content->GetParsedAttr(nsHTMLAtoms::bordercolor);
00969     if (attr) {
00970       nscolor color;
00971       if (attr->GetColorValue(color)) {
00972         return color;
00973       }
00974     }
00975   }
00976   return GetBorderColor();
00977 }
00978 
00979 NS_IMETHODIMP
00980 nsHTMLFramesetFrame::Reflow(nsPresContext*          aPresContext,
00981                             nsHTMLReflowMetrics&     aDesiredSize,
00982                             const nsHTMLReflowState& aReflowState,
00983                             nsReflowStatus&          aStatus)
00984 {
00985   DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame", aReflowState.reason);
00986   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
00987   nsIPresShell *shell = aPresContext->PresShell();
00988   nsStyleSet *styleSet = shell->StyleSet();
00989 
00990   //printf("FramesetFrame2::Reflow %X (%d,%d) \n", this, aReflowState.availableWidth, aReflowState.availableHeight); 
00991   // Always get the size so that the caller knows how big we are
00992   GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
00993   
00994   nscoord width  = (aDesiredSize.width <= aReflowState.availableWidth)
00995     ? aDesiredSize.width : aReflowState.availableWidth;
00996   nscoord height = (aDesiredSize.height <= aReflowState.availableHeight)
00997     ? aDesiredSize.height : aReflowState.availableHeight;
00998 
00999   PRBool firstTime = (eReflowReason_Initial == aReflowState.reason);
01000   if (firstTime) {
01001     nsContentUtils::RegisterPrefCallback(kFrameResizePref,
01002                                          FrameResizePrefCallback, this);
01003     mForceFrameResizability =
01004       nsContentUtils::GetBoolPref(kFrameResizePref);
01005   }
01006   
01007   // subtract out the width of all of the potential borders. There are
01008   // only borders between <frame>s. There are none on the edges (e.g the
01009   // leftmost <frame> has no left border).
01010   PRInt32 borderWidth = GetBorderWidth(aPresContext, PR_TRUE);
01011 
01012   width  -= (mNumCols - 1) * borderWidth;
01013   if (width < 0) width = 0;
01014 
01015   height -= (mNumRows - 1) * borderWidth;
01016   if (height < 0) height = 0;
01017 
01018   nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
01019   NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
01020   const nsFramesetSpec* rowSpecs = nsnull;
01021   const nsFramesetSpec* colSpecs = nsnull;
01022   PRInt32 rows = 0;
01023   PRInt32 cols = 0;
01024   ourContent->GetRowSpec(&rows, &rowSpecs);
01025   ourContent->GetColSpec(&cols, &colSpecs);
01026   // If the number of cols or rows has changed, the frame for the frameset
01027   // will be re-created.
01028   if (mNumRows != rows || mNumCols != cols) {
01029     aStatus = NS_FRAME_COMPLETE;
01030     mDrag.UnSet();
01031     NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
01032     return NS_OK;
01033   }
01034 
01035   if (!mDrag.mActive) {
01036     CalculateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes);
01037     CalculateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes);
01038   }
01039 
01040   PRBool*        verBordersVis     = nsnull; // vertical borders visibility
01041   nscolor*       verBorderColors   = nsnull;
01042   PRBool*        horBordersVis     = nsnull; // horizontal borders visibility
01043   nscolor*       horBorderColors   = nsnull;
01044   nscolor        borderColor       = GetBorderColor();
01045   nsFrameborder  frameborder       = GetFrameBorder();
01046 
01047   if (firstTime) {
01048     verBordersVis = new PRBool[mNumCols];
01049     verBorderColors = new nscolor[mNumCols];
01050     for (int verX  = 0; verX < mNumCols; verX++) {
01051       verBordersVis[verX] = PR_FALSE;
01052       verBorderColors[verX] = NO_COLOR;
01053     }
01054 
01055     horBordersVis = new PRBool[mNumRows];
01056     horBorderColors = new nscolor[mNumRows];
01057     for (int horX = 0; horX < mNumRows; horX++) {
01058       horBordersVis[horX] = PR_FALSE;
01059       horBorderColors[horX] = NO_COLOR;
01060     }
01061   }
01062 
01063   // reflow the children
01064   PRInt32 lastRow = 0;
01065   PRInt32 lastCol = 0;
01066   PRInt32 borderChildX = mNonBorderChildCount; // index of border children
01067   nsHTMLFramesetBorderFrame* borderFrame = nsnull;
01068   nsPoint offset(0,0);
01069   nsSize size, lastSize;
01070   nsIFrame* child = mFrames.FirstChild();
01071   nsIFrame* lastChild = mFrames.LastChild();
01072 
01073   for (PRInt32 childX = 0; childX < mNonBorderChildCount; childX++) {
01074     nsPoint cellIndex;
01075     GetSizeOfChildAt(childX, size, cellIndex);
01076 
01077     if (lastRow != cellIndex.y) {  // changed to next row
01078       offset.x = 0;
01079       offset.y += lastSize.height;
01080       if (firstTime) { // create horizontal border
01081         borderFrame = new (shell) nsHTMLFramesetBorderFrame(borderWidth,
01082                                                             PR_FALSE,
01083                                                             PR_FALSE);
01084         nsRefPtr<nsStyleContext> pseudoStyleContext;
01085         pseudoStyleContext = styleSet->ResolvePseudoStyleFor(mContent,
01086                                                              nsCSSPseudoElements::horizontalFramesetBorder,
01087                                                              mStyleContext);
01088         borderFrame->Init(aPresContext, mContent, this, pseudoStyleContext, nsnull);
01089 
01090         mChildCount++;
01091         lastChild->SetNextSibling(borderFrame);
01092         lastChild = borderFrame;
01093         mHorBorders[cellIndex.y-1] = borderFrame;
01094         // set the neighbors for determining drag boundaries
01095         borderFrame->mPrevNeighbor = lastRow; 
01096         borderFrame->mNextNeighbor = cellIndex.y;  
01097       } else {
01098         borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
01099         borderFrame->mWidth = borderWidth;
01100         borderChildX++;
01101       }
01102       nsSize borderSize(aDesiredSize.width, borderWidth);
01103       ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize);
01104       offset.y += borderWidth;
01105       borderFrame = nsnull;
01106     } else {
01107       if (cellIndex.x > 0) {  // moved to next col in same row
01108         if (0 == cellIndex.y) { // in 1st row
01109           if (firstTime) { // create vertical border
01110             borderFrame = new (shell) nsHTMLFramesetBorderFrame(borderWidth,
01111                                                                 PR_TRUE,
01112                                                                 PR_FALSE);
01113             nsRefPtr<nsStyleContext> pseudoStyleContext;
01114             pseudoStyleContext = styleSet->ResolvePseudoStyleFor(mContent,
01115                                                                  nsCSSPseudoElements::verticalFramesetBorder,
01116                                                                  mStyleContext);
01117             borderFrame->Init(aPresContext, mContent, this, pseudoStyleContext, nsnull);
01118 
01119             mChildCount++;
01120             lastChild->SetNextSibling(borderFrame);
01121             lastChild = borderFrame;
01122             mVerBorders[cellIndex.x-1] = borderFrame;
01123             // set the neighbors for determining drag boundaries
01124             borderFrame->mPrevNeighbor = lastCol; 
01125             borderFrame->mNextNeighbor = cellIndex.x;  
01126           } else {         
01127             borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
01128             borderFrame->mWidth = borderWidth;
01129             borderChildX++;
01130           }
01131           nsSize borderSize(borderWidth, aDesiredSize.height);
01132           ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize);
01133           borderFrame = nsnull;
01134         }
01135         offset.x += borderWidth;
01136       }
01137     }
01138 
01139     ReflowPlaceChild(child, aPresContext, aReflowState, offset, size, &cellIndex);
01140 
01141     if (firstTime) {
01142       PRInt32 childVis; 
01143       if (FRAMESET == mChildTypes[childX]) {
01144         nsHTMLFramesetFrame* childFS = (nsHTMLFramesetFrame*)child; 
01145         childVis = childFS->mEdgeVisibility;
01146         mChildBorderColors[childX] = childFS->mEdgeColors;
01147       } else if (FRAME == mChildTypes[childX]) {
01148         if (eFrameborder_Yes == mChildFrameborder[childX]) {
01149           childVis = ALL_VIS;
01150         } else if (eFrameborder_No == mChildFrameborder[childX]) {
01151           childVis = NONE_VIS;
01152         } else {  // notset
01153           childVis = (eFrameborder_No == frameborder) ? NONE_VIS : ALL_VIS;
01154         }
01155       } else {  // blank 
01156         childVis = NONE_VIS;
01157       }
01158       nsBorderColor childColors = mChildBorderColors[childX];
01159       // set the visibility, color of our edge borders based on children
01160       if (0 == cellIndex.x) {
01161         if (!(mEdgeVisibility & LEFT_VIS)) {
01162           mEdgeVisibility |= (LEFT_VIS & childVis);
01163         }
01164         if (NO_COLOR == mEdgeColors.mLeft) {
01165           mEdgeColors.mLeft = childColors.mLeft;
01166         }
01167       }
01168       if (0 == cellIndex.y) {
01169         if (!(mEdgeVisibility & TOP_VIS)) {
01170           mEdgeVisibility |= (TOP_VIS & childVis);
01171         }
01172         if (NO_COLOR == mEdgeColors.mTop) {
01173           mEdgeColors.mTop = childColors.mTop;
01174         }
01175       }
01176       if (mNumCols-1 == cellIndex.x) {
01177         if (!(mEdgeVisibility & RIGHT_VIS)) {
01178           mEdgeVisibility |= (RIGHT_VIS & childVis);
01179         }
01180         if (NO_COLOR == mEdgeColors.mRight) {
01181           mEdgeColors.mRight = childColors.mRight;
01182         }
01183       }
01184       if (mNumRows-1 == cellIndex.y) {
01185         if (!(mEdgeVisibility & BOTTOM_VIS)) {
01186           mEdgeVisibility |= (BOTTOM_VIS & childVis);
01187         }
01188         if (NO_COLOR == mEdgeColors.mBottom) {
01189           mEdgeColors.mBottom = childColors.mBottom;
01190         }
01191       }
01192       // set the visibility of borders that the child may affect
01193       if (childVis & RIGHT_VIS) {
01194         verBordersVis[cellIndex.x] = PR_TRUE;
01195       }
01196       if (childVis & BOTTOM_VIS) {
01197         horBordersVis[cellIndex.y] = PR_TRUE;
01198       }
01199       if ((cellIndex.x > 0) && (childVis & LEFT_VIS)) {
01200         verBordersVis[cellIndex.x-1] = PR_TRUE;
01201       }
01202       if ((cellIndex.y > 0) && (childVis & TOP_VIS)) {
01203         horBordersVis[cellIndex.y-1] = PR_TRUE;
01204       }
01205       // set the colors of borders that the child may affect
01206       if (NO_COLOR == verBorderColors[cellIndex.x]) {
01207         verBorderColors[cellIndex.x] = mChildBorderColors[childX].mRight;
01208       }
01209       if (NO_COLOR == horBorderColors[cellIndex.y]) {
01210         horBorderColors[cellIndex.y] = mChildBorderColors[childX].mBottom;
01211       }
01212       if ((cellIndex.x > 0) && (NO_COLOR == verBorderColors[cellIndex.x-1])) {
01213         verBorderColors[cellIndex.x-1] = mChildBorderColors[childX].mLeft;
01214       }
01215       if ((cellIndex.y > 0) && (NO_COLOR == horBorderColors[cellIndex.y-1])) {
01216         horBorderColors[cellIndex.y-1] = mChildBorderColors[childX].mTop;
01217       }
01218     }
01219     lastRow  = cellIndex.y;
01220     lastCol  = cellIndex.x;
01221     lastSize = size;
01222     offset.x += size.width;
01223     child = child->GetNextSibling();
01224   }
01225 
01226   if (firstTime) {
01227     nscolor childColor;
01228     // set the visibility, color, mouse sensitivity of borders
01229     for (int verX = 0; verX < mNumCols-1; verX++) {
01230       if (mVerBorders[verX]) {
01231         mVerBorders[verX]->SetVisibility(verBordersVis[verX]);
01232         if (mForceFrameResizability) {
01233           mVerBorders[verX]->mVisibilityOverride = PR_TRUE;
01234         } else {
01235           SetBorderResize(mChildTypes, mVerBorders[verX]);
01236         }
01237         childColor = (NO_COLOR == verBorderColors[verX]) ? borderColor : verBorderColors[verX];
01238         mVerBorders[verX]->SetColor(childColor);
01239       }
01240     }
01241     for (int horX = 0; horX < mNumRows-1; horX++) {
01242       if (mHorBorders[horX]) {
01243         mHorBorders[horX]->SetVisibility(horBordersVis[horX]);
01244         if (mForceFrameResizability) {
01245           mHorBorders[horX]->mVisibilityOverride = PR_TRUE;
01246         } else {
01247           SetBorderResize(mChildTypes, mHorBorders[horX]);
01248         }
01249         childColor = (NO_COLOR == horBorderColors[horX]) ? borderColor : horBorderColors[horX]; 
01250         mHorBorders[horX]->SetColor(childColor);
01251       }
01252     }
01253 
01254     delete[] verBordersVis;    
01255     delete[] verBorderColors;
01256     delete[] horBordersVis; 
01257     delete[] horBorderColors;
01258     delete[] mChildTypes; 
01259     delete[] mChildFrameborder;
01260     delete[] mChildBorderColors;
01261 
01262     mChildTypes = nsnull;
01263     mChildFrameborder = nsnull;
01264     mChildBorderColors = nsnull;
01265   }
01266 
01267   if (aDesiredSize.mComputeMEW) {
01268     aDesiredSize.mMaxElementWidth = aDesiredSize.width;
01269   }
01270 
01271   aStatus = NS_FRAME_COMPLETE;
01272   mDrag.UnSet();
01273 
01274   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
01275   return NS_OK;
01276 }
01277 
01278 nsIAtom*
01279 nsHTMLFramesetFrame::GetType() const
01280 {
01281   return nsLayoutAtoms::frameSetFrame;
01282 }
01283 
01284 PRBool
01285 nsHTMLFramesetFrame::IsLeaf() const
01286 {
01287   // We handle constructing our kids manually
01288   return PR_TRUE;
01289 }
01290 
01291 PRBool 
01292 nsHTMLFramesetFrame::ChildIsFrameset(nsIFrame* aChild) 
01293 {
01294   nsIFrame* childFrame = nsnull;
01295   aChild->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame), (void**)&childFrame);
01296   if (childFrame) {
01297     return PR_TRUE;
01298   }
01299   return PR_FALSE;
01300 }
01301 
01302 
01303 PRBool 
01304 nsHTMLFramesetFrame::CanResize(PRBool aVertical, 
01305                                PRBool aLeft) 
01306 {
01307   nsIFrame* child;
01308   PRInt32 childX;
01309   PRInt32 startX;
01310   if (aVertical) {
01311     startX = (aLeft) ? 0 : mNumCols-1;
01312     for (childX = startX; childX < mNonBorderChildCount; childX += mNumCols) {
01313       child = mFrames.FrameAt(childX);
01314       if (!CanChildResize(aVertical, aLeft, childX, ChildIsFrameset(child))) {
01315         return PR_FALSE;
01316       }
01317     } 
01318   } else {
01319     startX = (aLeft) ? 0 : (mNumRows - 1) * mNumCols;
01320     PRInt32 endX = startX + mNumCols;
01321     for (childX = startX; childX < endX; childX++) {
01322       child = mFrames.FrameAt(childX);
01323       if (!CanChildResize(aVertical, aLeft, childX, ChildIsFrameset(child))) {
01324         return PR_FALSE;
01325       }
01326     }
01327   }
01328   return PR_TRUE;
01329 }
01330 
01331 PRBool
01332 nsHTMLFramesetFrame::GetNoResize(nsIFrame* aChildFrame) 
01333 {
01334   PRBool result = PR_FALSE;
01335   nsIContent* content = aChildFrame->GetContent();
01336 
01337   return content && content->HasAttr(kNameSpaceID_None, nsHTMLAtoms::noresize);
01338 }
01339 
01340 PRBool 
01341 nsHTMLFramesetFrame::CanChildResize(PRBool  aVertical, 
01342                                     PRBool  aLeft, 
01343                                     PRInt32 aChildX, 
01344                                     PRBool  aFrameset) 
01345 {
01346   nsIFrame* child = mFrames.FrameAt(aChildX);
01347   if (aFrameset) {
01348     return ((nsHTMLFramesetFrame*)child)->CanResize(aVertical, aLeft);
01349   } else {
01350     return !GetNoResize(child);
01351   }
01352 }
01353 
01354 // This calculates and sets the resizability of all border frames
01355 
01356 void
01357 nsHTMLFramesetFrame::RecalculateBorderResize()
01358 {
01359   if (!mContent) {
01360     return;
01361   }
01362 
01363   PRInt32 numCells = mNumRows * mNumCols; // max number of cells
01364   PRInt32* childTypes = new PRInt32[numCells];
01365   PRUint32 childIndex, frameOrFramesetChildIndex = 0;
01366 
01367   // number of any type of children
01368   PRUint32 numChildren = mContent->GetChildCount();
01369   for (childIndex = 0; childIndex < numChildren; childIndex++) {
01370     nsIContent *child = mContent->GetChildAt(childIndex);
01371 
01372     if (child->IsContentOfType(nsIContent::eHTML)) {
01373       nsINodeInfo *ni = child->GetNodeInfo();
01374 
01375       if (ni->Equals(nsHTMLAtoms::frameset)) {
01376         childTypes[frameOrFramesetChildIndex++] = FRAMESET;
01377       } else if (ni->Equals(nsHTMLAtoms::frame)) {
01378         childTypes[frameOrFramesetChildIndex++] = FRAME;
01379       }
01380       // Don't overflow childTypes array
01381       if (((PRInt32)frameOrFramesetChildIndex) >= numCells) {
01382         break;
01383       }
01384     }
01385   }
01386 
01387   // set the visibility and mouse sensitivity of borders
01388   PRInt32 verX;
01389   for (verX = 0; verX < mNumCols-1; verX++) {
01390     if (mVerBorders[verX]) {
01391       mVerBorders[verX]->mCanResize = PR_TRUE;
01392       if (mForceFrameResizability) {
01393         mVerBorders[verX]->mVisibilityOverride = PR_TRUE;
01394       } else {
01395         mVerBorders[verX]->mVisibilityOverride = PR_FALSE;
01396         SetBorderResize(childTypes, mVerBorders[verX]);
01397       }
01398     }
01399   }
01400   PRInt32 horX;
01401   for (horX = 0; horX < mNumRows-1; horX++) {
01402     if (mHorBorders[horX]) {
01403       mHorBorders[horX]->mCanResize = PR_TRUE;
01404       if (mForceFrameResizability) {
01405         mHorBorders[horX]->mVisibilityOverride = PR_TRUE;
01406       } else {
01407         mHorBorders[horX]->mVisibilityOverride = PR_FALSE;
01408         SetBorderResize(childTypes, mHorBorders[horX]);
01409       }
01410     }
01411   }
01412   delete[] childTypes;
01413 }
01414 
01415 void 
01416 nsHTMLFramesetFrame::SetBorderResize(PRInt32*                   aChildTypes, 
01417                                      nsHTMLFramesetBorderFrame* aBorderFrame)
01418 {
01419   if (aBorderFrame->mVertical) {
01420     for (int rowX = 0; rowX < mNumRows; rowX++) {
01421       PRInt32 childX = aBorderFrame->mPrevNeighbor + (rowX * mNumCols);
01422       if (!CanChildResize(PR_TRUE, PR_FALSE, childX, (FRAMESET == aChildTypes[childX])) ||
01423           !CanChildResize(PR_TRUE, PR_TRUE, childX+1,(FRAMESET == aChildTypes[childX+1]))) {
01424         aBorderFrame->mCanResize = PR_FALSE;
01425       }
01426     }
01427   } else {
01428     PRInt32 childX = aBorderFrame->mPrevNeighbor * mNumCols;
01429     PRInt32 endX   = childX + mNumCols;
01430     for (; childX < endX; childX++) {
01431       if (!CanChildResize(PR_FALSE, PR_FALSE, childX, (FRAMESET == aChildTypes[childX]))) {
01432         aBorderFrame->mCanResize = PR_FALSE;
01433       }
01434     }
01435     endX = endX + mNumCols;
01436     for (; childX < endX; childX++) {
01437       if (!CanChildResize(PR_FALSE, PR_TRUE, childX, (FRAMESET == aChildTypes[childX]))) {
01438         aBorderFrame->mCanResize = PR_FALSE;
01439       }
01440     }
01441   }
01442 }
01443   
01444         
01445 NS_IMETHODIMP
01446 nsHTMLFramesetFrame::VerifyTree() const
01447 {
01448   // XXX Completely disabled for now; once pseud-frames are reworked
01449   // then we can turn it back on.
01450   return NS_OK;
01451 }
01452 
01453 void
01454 nsHTMLFramesetFrame::StartMouseDrag(nsPresContext*            aPresContext, 
01455                                     nsHTMLFramesetBorderFrame* aBorder, 
01456                                     nsGUIEvent*                aEvent)
01457 {
01458   if (mMinDrag == 0) {
01459     float p2t;
01460     p2t = aPresContext->PixelsToTwips();
01461     mMinDrag = NSIntPixelsToTwips(2, p2t);  // set min drag and min frame size to 2 pixels
01462   }
01463 
01464 #if 0
01465   PRInt32 index;
01466   IndexOf(aBorder, index);
01467   NS_ASSERTION((nsnull != aBorder) && (index >= 0), "invalid dragger");
01468 #endif
01469   nsIView* view = GetView();
01470   if (view) {
01471     nsIViewManager* viewMan = view->GetViewManager();
01472     if (viewMan) {
01473       PRBool ignore;
01474       viewMan->GrabMouseEvents(view, ignore);
01475       mDragger = aBorder;
01476 
01477       //XXX This should go away!  Border should have own view instead
01478       viewMan->SetViewCheckChildEvents(view, PR_FALSE);
01479 
01480       // The point isn't in frameset coords, but we're using it to compute
01481       // moves relative to the start position.
01482       mFirstDragPoint.MoveTo(aEvent->point.x, aEvent->point.y);
01483 
01484       // Store the original frame sizes
01485       if (mDragger->mVertical) {
01486         mPrevNeighborOrigSize = mColSizes[mDragger->mPrevNeighbor];
01487        mNextNeighborOrigSize = mColSizes[mDragger->mNextNeighbor];
01488       } else {
01489         mPrevNeighborOrigSize = mRowSizes[mDragger->mPrevNeighbor];
01490        mNextNeighborOrigSize = mRowSizes[mDragger->mNextNeighbor];
01491       }
01492 
01493       gDragInProgress = PR_TRUE;
01494     }
01495   }
01496 }
01497   
01498 
01499 void
01500 nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext, 
01501                                nsGUIEvent*     aEvent)
01502 {
01503   PRInt32 change; // measured positive from left-to-right or top-to-bottom
01504   nsWeakFrame weakFrame(this);
01505   if (mDragger->mVertical) {
01506     change = aEvent->point.x - mFirstDragPoint.x;
01507     if (change > mNextNeighborOrigSize - mMinDrag) {
01508       change = mNextNeighborOrigSize - mMinDrag;
01509     } else if (change <= mMinDrag - mPrevNeighborOrigSize) {
01510       change = mMinDrag - mPrevNeighborOrigSize;
01511     }
01512     mColSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change;
01513     mColSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change;
01514 
01515     if (change != 0) {
01516       // Recompute the specs from the new sizes.
01517       nscoord width = mRect.width - (mNumCols - 1) * GetBorderWidth(aPresContext, PR_TRUE);
01518       nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
01519       NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
01520       const nsFramesetSpec* colSpecs = nsnull;
01521       ourContent->GetColSpec(&mNumCols, &colSpecs);
01522       nsAutoString newColAttr;
01523       GenerateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes,
01524                      newColAttr);
01525       // Setting the attr will trigger a reflow
01526       mContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::cols, newColAttr, PR_TRUE);
01527     }
01528   } else {
01529     change = aEvent->point.y - mFirstDragPoint.y;
01530     if (change > mNextNeighborOrigSize - mMinDrag) {
01531       change = mNextNeighborOrigSize - mMinDrag;
01532     } else if (change <= mMinDrag - mPrevNeighborOrigSize) {
01533       change = mMinDrag - mPrevNeighborOrigSize;
01534     }
01535     mRowSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change;
01536     mRowSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change;
01537 
01538     if (change != 0) {
01539       // Recompute the specs from the new sizes.
01540       nscoord height = mRect.height - (mNumRows - 1) * GetBorderWidth(aPresContext, PR_TRUE);
01541       nsCOMPtr<nsIFrameSetElement> ourContent(do_QueryInterface(mContent));
01542       NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
01543       const nsFramesetSpec* rowSpecs = nsnull;
01544       ourContent->GetRowSpec(&mNumRows, &rowSpecs);
01545       nsAutoString newRowAttr;
01546       GenerateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes,
01547                      newRowAttr);
01548       // Setting the attr will trigger a reflow
01549       mContent->SetAttr(kNameSpaceID_None, nsHTMLAtoms::rows, newRowAttr, PR_TRUE);
01550     }
01551   }
01552 
01553   ENSURE_TRUE(weakFrame.IsAlive());
01554   if (change != 0) {
01555     mDrag.Reset(mDragger->mVertical, mDragger->mPrevNeighbor, change, this);
01556     nsIFrame* parentFrame = GetParent();
01557     if (!parentFrame) {
01558       return;
01559     }
01560 
01561     // Update the view immediately (make drag appear snappier)
01562     nsIViewManager* vm = aPresContext->GetViewManager();
01563     if (vm) {
01564       nsIView* root;
01565       vm->GetRootView(root);
01566       if (root) {
01567         vm->UpdateView(root, NS_VMREFRESH_IMMEDIATE);
01568       }
01569     }
01570   }
01571 }  
01572 
01573 void
01574 nsHTMLFramesetFrame::EndMouseDrag(nsPresContext* aPresContext)
01575 {
01576   nsIView* view = GetView();
01577   if (view) {
01578     nsIViewManager* viewMan = view->GetViewManager();
01579     if (viewMan) {
01580       mDragger = nsnull;
01581       PRBool ignore;
01582       viewMan->GrabMouseEvents(nsnull, ignore);
01583       //XXX This should go away!  Border should have own view instead
01584       viewMan->SetViewCheckChildEvents(view, PR_TRUE);
01585     }
01586   }
01587   gDragInProgress = PR_FALSE;
01588 }  
01589 
01590 nsresult
01591 NS_NewHTMLFramesetFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
01592 {
01593   NS_PRECONDITION(aNewFrame, "null OUT ptr");
01594   if (nsnull == aNewFrame) {
01595     return NS_ERROR_NULL_POINTER;
01596   }
01597   nsHTMLFramesetFrame* it = new (aPresShell) nsHTMLFramesetFrame;
01598   if (!it) {
01599     return NS_ERROR_OUT_OF_MEMORY;
01600   }
01601   *aNewFrame = it;
01602   return NS_OK;
01603 }
01604 
01605 /*******************************************************************************
01606  * nsHTMLFramesetBorderFrame
01607  ******************************************************************************/
01608 nsHTMLFramesetBorderFrame::nsHTMLFramesetBorderFrame(PRInt32 aWidth, 
01609                                                      PRBool  aVertical, 
01610                                                      PRBool  aVisibility)
01611   : nsLeafFrame(), mWidth(aWidth), mVertical(aVertical), mVisibility(aVisibility)
01612 {
01613    mVisibilityOverride = PR_FALSE;
01614    mCanResize    = PR_TRUE;
01615    mColor        = NO_COLOR;
01616    mPrevNeighbor = 0;
01617    mNextNeighbor = 0;
01618 }
01619 
01620 nsHTMLFramesetBorderFrame::~nsHTMLFramesetBorderFrame()
01621 {
01622   //printf("nsHTMLFramesetBorderFrame destructor %p \n", this);
01623 }
01624 
01625 void nsHTMLFramesetBorderFrame::GetDesiredSize(nsPresContext*          aPresContext,
01626                                                const nsHTMLReflowState& aReflowState,
01627                                                nsHTMLReflowMetrics&     aDesiredSize)
01628 {
01629   aDesiredSize.width   = aReflowState.availableWidth;
01630   aDesiredSize.height  = aReflowState.availableHeight;
01631   aDesiredSize.ascent  = aDesiredSize.width;
01632   aDesiredSize.descent = 0;
01633 }
01634 
01635 void nsHTMLFramesetBorderFrame::SetVisibility(PRBool aVisibility)
01636 { 
01637   mVisibility = aVisibility; 
01638 }
01639 
01640 void nsHTMLFramesetBorderFrame::SetColor(nscolor aColor)
01641 { 
01642   mColor = aColor;
01643 }
01644 
01645 
01646 NS_IMETHODIMP
01647 nsHTMLFramesetBorderFrame::Reflow(nsPresContext*          aPresContext,
01648                                   nsHTMLReflowMetrics&     aDesiredSize,
01649                                   const nsHTMLReflowState& aReflowState,
01650                                   nsReflowStatus&          aStatus)
01651 {
01652   DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame", aReflowState.reason);
01653   GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
01654   aStatus = NS_FRAME_COMPLETE;
01655   return NS_OK;
01656 }
01657 
01658 NS_METHOD
01659 nsHTMLFramesetBorderFrame::Paint(nsPresContext*      aPresContext,
01660                                  nsIRenderingContext& aRenderingContext,
01661                                  const nsRect&        aDirtyRect,
01662                                  nsFramePaintLayer    aWhichLayer,
01663                                  PRUint32             aFlags)
01664 {
01665   if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) {
01666     return NS_OK;
01667   }
01668   //printf("border frame paint %X (%d,%d,%d,%d) \n", this, aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
01669   nscolor WHITE    = NS_RGB(255, 255, 255);
01670   nscolor bgColor  = NS_RGB(200,200,200);
01671   nscolor fgColor  = NS_RGB(0,0,0);
01672   nscolor hltColor = NS_RGB(255,255,255);
01673   nscolor sdwColor = NS_RGB(128,128,128);
01674 
01675   {
01676     nsCOMPtr<nsILookAndFeel> lookAndFeel = do_GetService(kLookAndFeelCID);
01677     if (lookAndFeel) {
01678       lookAndFeel->GetColor(nsILookAndFeel::eColor_WidgetBackground,  bgColor);
01679       lookAndFeel->GetColor(nsILookAndFeel::eColor_WidgetForeground,  fgColor);
01680       lookAndFeel->GetColor(nsILookAndFeel::eColor_Widget3DShadow,    sdwColor);
01681       lookAndFeel->GetColor(nsILookAndFeel::eColor_Widget3DHighlight, hltColor);
01682     }
01683   }
01684 
01685   float t2p;
01686   t2p = aPresContext->TwipsToPixels();
01687   nscoord widthInPixels = NSTwipsToIntPixels(mWidth, t2p);
01688   float p2t;
01689   p2t = aPresContext->PixelsToTwips();
01690   nscoord pixelWidth    = NSIntPixelsToTwips(1, p2t);
01691 
01692   if (widthInPixels <= 0) {
01693     return NS_OK;
01694   }
01695 
01696   nscoord x0 = 0;
01697   nscoord y0 = 0;
01698   nscoord x1 = (mVertical) ? x0 : mRect.width;
01699   nscoord y1 = (mVertical) ? mRect.height : x0;
01700 
01701   nscolor color = WHITE;
01702   if (mVisibility || mVisibilityOverride) {
01703     color = (NO_COLOR == mColor) ? bgColor : mColor;
01704   }
01705   aRenderingContext.SetColor(color);
01706   // draw grey or white first
01707   for (int i = 0; i < widthInPixels; i++) {
01708     aRenderingContext.DrawLine (x0, y0, x1, y1);
01709     if (mVertical) {
01710       x0 += pixelWidth;
01711       x1 =  x0;
01712     } else {
01713       y0 += pixelWidth;
01714       y1 =  y0;
01715     }
01716   }
01717 
01718   if (!mVisibility && !mVisibilityOverride) {
01719     return NS_OK;
01720   }
01721 
01722   if (widthInPixels >= 5) {
01723     aRenderingContext.SetColor(hltColor);
01724     x0 = (mVertical) ? pixelWidth : 0;
01725     y0 = (mVertical) ? 0 : pixelWidth;
01726     x1 = (mVertical) ? x0 : mRect.width;
01727     y1 = (mVertical) ? mRect.height : y0;
01728     aRenderingContext.DrawLine(x0, y0, x1, y1);
01729   }
01730 
01731   if (widthInPixels >= 2) {
01732     aRenderingContext.SetColor(sdwColor);
01733     x0 = (mVertical) ? mRect.width - (2 * pixelWidth) : 0;
01734     y0 = (mVertical) ? 0 : mRect.height - (2 * pixelWidth);
01735     x1 = (mVertical) ? x0 : mRect.width;
01736     y1 = (mVertical) ? mRect.height : y0;
01737     aRenderingContext.DrawLine(x0, y0, x1, y1);
01738   }
01739 
01740   if (widthInPixels >= 1) {
01741     aRenderingContext.SetColor(fgColor);
01742     x0 = (mVertical) ? mRect.width - pixelWidth : 0;
01743     y0 = (mVertical) ? 0 : mRect.height - pixelWidth;
01744     x1 = (mVertical) ? x0 : mRect.width;
01745     y1 = (mVertical) ? mRect.height : y0;
01746     aRenderingContext.DrawLine(x0, y0, x1, y1);
01747   }
01748 
01749   return NS_OK;
01750 }
01751 
01752 
01753 NS_IMETHODIMP
01754 nsHTMLFramesetBorderFrame::HandleEvent(nsPresContext* aPresContext, 
01755                                        nsGUIEvent*     aEvent,
01756                                        nsEventStatus*  aEventStatus)
01757 {
01758   NS_ENSURE_ARG_POINTER(aEventStatus);
01759   *aEventStatus = nsEventStatus_eIgnore;
01760 
01761   //XXX Mouse setting logic removed.  The remaining logic should also move.
01762   if (!mCanResize) {
01763     return NS_OK;
01764   }
01765 
01766   switch (aEvent->message) {
01767     case NS_MOUSE_LEFT_BUTTON_DOWN:
01768       nsHTMLFramesetFrame* parentFrame;
01769       nsIFrame* fptr = GetParent();
01770       parentFrame = (nsHTMLFramesetFrame*) fptr;
01771       parentFrame->StartMouseDrag(aPresContext, this, aEvent);
01772       *aEventStatus = nsEventStatus_eConsumeNoDefault;
01773            break;
01774   }
01775   return NS_OK;
01776 }
01777 
01778 NS_IMETHODIMP 
01779 nsHTMLFramesetBorderFrame::GetFrameForPoint(const nsPoint& aPoint, 
01780                                             nsFramePaintLayer aWhichLayer,
01781                                             nsIFrame**     aFrame)
01782 {
01783   if ( (aWhichLayer != NS_FRAME_PAINT_LAYER_FOREGROUND) ||
01784        (!((mState & NS_FRAME_OUTSIDE_CHILDREN) || mRect.Contains(aPoint) )))
01785   {
01786     return NS_ERROR_FAILURE;
01787   }
01788 
01789   *aFrame = this;
01790   return NS_OK;
01791 }
01792 
01793 NS_IMETHODIMP
01794 nsHTMLFramesetBorderFrame::GetCursor(const nsPoint&    aPoint,
01795                                      nsIFrame::Cursor& aCursor)
01796 {
01797   if (!mCanResize) {
01798     aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
01799   } else {   
01800     aCursor.mCursor = (mVertical) ? NS_STYLE_CURSOR_W_RESIZE : NS_STYLE_CURSOR_N_RESIZE;
01801   }
01802   return NS_OK;
01803 }
01804 
01805 #ifdef DEBUG
01806 NS_IMETHODIMP nsHTMLFramesetBorderFrame::GetFrameName(nsAString& aResult) const
01807 {
01808   return MakeFrameName(NS_LITERAL_STRING("FramesetBorder"), aResult);
01809 }
01810 #endif
01811 
01812 /*******************************************************************************
01813  * nsHTMLFramesetBlankFrame
01814  ******************************************************************************/
01815 
01816 nsHTMLFramesetBlankFrame::~nsHTMLFramesetBlankFrame()
01817 {
01818   //printf("nsHTMLFramesetBlankFrame destructor %p \n", this);
01819 }
01820 
01821 void nsHTMLFramesetBlankFrame::GetDesiredSize(nsPresContext*          aPresContext,
01822                                               const nsHTMLReflowState& aReflowState,
01823                                               nsHTMLReflowMetrics&     aDesiredSize)
01824 {
01825   aDesiredSize.width   = aReflowState.availableWidth;
01826   aDesiredSize.height  = aReflowState.availableHeight;
01827   aDesiredSize.ascent  = aDesiredSize.width;
01828   aDesiredSize.descent = 0;
01829 }
01830 
01831 NS_IMETHODIMP
01832 nsHTMLFramesetBlankFrame::Reflow(nsPresContext*          aPresContext,
01833                                  nsHTMLReflowMetrics&     aDesiredSize,
01834                                  const nsHTMLReflowState& aReflowState,
01835                                  nsReflowStatus&          aStatus)
01836 {
01837   DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame", aReflowState.reason);
01838   GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
01839   aStatus = NS_FRAME_COMPLETE;
01840   return NS_OK;
01841 }
01842 
01843 NS_METHOD
01844 nsHTMLFramesetBlankFrame::Paint(nsPresContext*      aPresContext,
01845                                 nsIRenderingContext& aRenderingContext,
01846                                 const nsRect&        aDirtyRect,
01847                                 nsFramePaintLayer    aWhichLayer,
01848                                 PRUint32             aFlags)
01849 {
01850   if (NS_FRAME_PAINT_LAYER_FOREGROUND != aWhichLayer) {
01851     return NS_OK;
01852   }
01853   nscolor white = NS_RGB(255,255,255);
01854   aRenderingContext.SetColor (white);
01855   // XXX FillRect doesn't seem to work
01856   //aRenderingContext.FillRect (mRect);
01857 
01858   float p2t;
01859   p2t = aPresContext->PixelsToTwips();
01860   nscoord x0 = 0;
01861   nscoord y0 = 0;
01862   nscoord x1 = x0;
01863   nscoord y1 = mRect.height;
01864   nscoord pixel = NSIntPixelsToTwips(1, p2t);
01865 
01866   aRenderingContext.SetColor(white);
01867   for (int i = 0; i < mRect.width; i += pixel) {
01868     aRenderingContext.DrawLine (x0, y0, x1, y1);
01869     x0 += NSIntPixelsToTwips(1, p2t);
01870     x1 =  x0;
01871   }
01872 
01873   return NS_OK;
01874 }
01875 
01876 #ifdef DEBUG
01877 NS_IMETHODIMP nsHTMLFramesetBlankFrame::List(nsPresContext* aPresContext,
01878                                              FILE*   out, 
01879                                              PRInt32 aIndent) const
01880 {
01881   for (PRInt32 i = aIndent; --i >= 0; ) fputs("  ", out);   // Indent
01882   fprintf(out, "%p BLANK \n", this);
01883   return nsLeafFrame::List(aPresContext, out, aIndent);
01884 }
01885 #endif