layout/generic/nsFrameSetFrame.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/generic/nsFrameSetFrame.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1698 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/* rendering object for HTML <frameset> elements */
    1.10 +
    1.11 +#include "nsFrameSetFrame.h"
    1.12 +
    1.13 +#include "mozilla/DebugOnly.h"
    1.14 +#include "mozilla/Likely.h"
    1.15 +
    1.16 +#include "nsGenericHTMLElement.h"
    1.17 +#include "nsAttrValueInlines.h"
    1.18 +#include "nsLeafFrame.h"
    1.19 +#include "nsContainerFrame.h"
    1.20 +#include "nsPresContext.h"
    1.21 +#include "nsIPresShell.h"
    1.22 +#include "nsGkAtoms.h"
    1.23 +#include "nsStyleConsts.h"
    1.24 +#include "nsStyleContext.h"
    1.25 +#include "nsHTMLParts.h"
    1.26 +#include "nsRenderingContext.h"
    1.27 +#include "nsIDOMMutationEvent.h"
    1.28 +#include "nsNameSpaceManager.h"
    1.29 +#include "nsCSSAnonBoxes.h"
    1.30 +#include "nsAutoPtr.h"
    1.31 +#include "nsStyleSet.h"
    1.32 +#include "mozilla/dom/Element.h"
    1.33 +#include "nsDisplayList.h"
    1.34 +#include "nsNodeUtils.h"
    1.35 +#include "mozAutoDocUpdate.h"
    1.36 +#include "mozilla/Preferences.h"
    1.37 +#include "mozilla/dom/HTMLFrameSetElement.h"
    1.38 +#include "mozilla/LookAndFeel.h"
    1.39 +#include "mozilla/MouseEvents.h"
    1.40 +#include "nsSubDocumentFrame.h"
    1.41 +
    1.42 +using namespace mozilla;
    1.43 +using namespace mozilla::dom;
    1.44 +
    1.45 +// masks for mEdgeVisibility
    1.46 +#define LEFT_VIS   0x0001
    1.47 +#define RIGHT_VIS  0x0002
    1.48 +#define TOP_VIS    0x0004
    1.49 +#define BOTTOM_VIS 0x0008
    1.50 +#define ALL_VIS    0x000F
    1.51 +#define NONE_VIS   0x0000
    1.52 +
    1.53 +/*******************************************************************************
    1.54 + * nsFramesetDrag
    1.55 + ******************************************************************************/
    1.56 +nsFramesetDrag::nsFramesetDrag()
    1.57 +{
    1.58 +  UnSet();
    1.59 +}
    1.60 +
    1.61 +void nsFramesetDrag::Reset(bool                 aVertical,
    1.62 +                           int32_t              aIndex,
    1.63 +                           int32_t              aChange,
    1.64 +                           nsHTMLFramesetFrame* aSource)
    1.65 +{
    1.66 +  mVertical = aVertical;
    1.67 +  mIndex    = aIndex;
    1.68 +  mChange   = aChange;
    1.69 +  mSource   = aSource;
    1.70 +}
    1.71 +
    1.72 +void nsFramesetDrag::UnSet()
    1.73 +{
    1.74 +  mVertical = true;
    1.75 +  mIndex    = -1;
    1.76 +  mChange   = 0;
    1.77 +  mSource   = nullptr;
    1.78 +}
    1.79 +
    1.80 +/*******************************************************************************
    1.81 + * nsHTMLFramesetBorderFrame
    1.82 + ******************************************************************************/
    1.83 +class nsHTMLFramesetBorderFrame : public nsLeafFrame
    1.84 +{
    1.85 +public:
    1.86 +  NS_DECL_FRAMEARENA_HELPERS
    1.87 +
    1.88 +#ifdef DEBUG_FRAME_DUMP
    1.89 +  virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
    1.90 +#endif
    1.91 +
    1.92 +  virtual nsresult HandleEvent(nsPresContext* aPresContext,
    1.93 +                               WidgetGUIEvent* aEvent,
    1.94 +                               nsEventStatus* aEventStatus) MOZ_OVERRIDE;
    1.95 +
    1.96 +  virtual nsresult GetCursor(const nsPoint&    aPoint,
    1.97 +                             nsIFrame::Cursor& aCursor) MOZ_OVERRIDE;
    1.98 +
    1.99 +  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   1.100 +                                const nsRect&           aDirtyRect,
   1.101 +                                const nsDisplayListSet& aLists) MOZ_OVERRIDE;
   1.102 +
   1.103 +  virtual nsresult Reflow(nsPresContext*           aPresContext,
   1.104 +                          nsHTMLReflowMetrics&     aDesiredSize,
   1.105 +                          const nsHTMLReflowState& aReflowState,
   1.106 +                          nsReflowStatus&          aStatus) MOZ_OVERRIDE;
   1.107 +
   1.108 +  bool GetVisibility() { return mVisibility || mVisibilityOverride; }
   1.109 +  void SetVisibility(bool aVisibility);
   1.110 +  void SetColor(nscolor aColor);
   1.111 +
   1.112 +  void PaintBorder(nsRenderingContext& aRenderingContext, nsPoint aPt);
   1.113 +
   1.114 +protected:
   1.115 +  nsHTMLFramesetBorderFrame(nsStyleContext* aContext, int32_t aWidth, bool aVertical, bool aVisible);
   1.116 +  virtual ~nsHTMLFramesetBorderFrame();
   1.117 +  virtual nscoord GetIntrinsicWidth() MOZ_OVERRIDE;
   1.118 +  virtual nscoord GetIntrinsicHeight() MOZ_OVERRIDE;
   1.119 +
   1.120 +  // the prev and next neighbors are indexes into the row (for a horizontal border) or col (for
   1.121 +  // a vertical border) of nsHTMLFramesetFrames or nsHTMLFrames
   1.122 +  int32_t mPrevNeighbor;
   1.123 +  int32_t mNextNeighbor;
   1.124 +  nscolor mColor;
   1.125 +  int32_t mWidth;
   1.126 +  bool mVertical;
   1.127 +  bool mVisibility;
   1.128 +  bool mVisibilityOverride;
   1.129 +  bool mCanResize;
   1.130 +  friend class nsHTMLFramesetFrame;
   1.131 +};
   1.132 +/*******************************************************************************
   1.133 + * nsHTMLFramesetBlankFrame
   1.134 + ******************************************************************************/
   1.135 +class nsHTMLFramesetBlankFrame : public nsLeafFrame
   1.136 +{
   1.137 +public:
   1.138 +  NS_DECL_QUERYFRAME_TARGET(nsHTMLFramesetBlankFrame)
   1.139 +  NS_DECL_QUERYFRAME
   1.140 +  NS_DECL_FRAMEARENA_HELPERS
   1.141 +
   1.142 +#ifdef DEBUG_FRAME_DUMP
   1.143 +  virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE
   1.144 +  {
   1.145 +    return MakeFrameName(NS_LITERAL_STRING("FramesetBlank"), aResult);
   1.146 +  }
   1.147 +#endif
   1.148 +
   1.149 +  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   1.150 +                                const nsRect&           aDirtyRect,
   1.151 +                                const nsDisplayListSet& aLists) MOZ_OVERRIDE;
   1.152 +
   1.153 +  virtual nsresult Reflow(nsPresContext*           aPresContext,
   1.154 +                          nsHTMLReflowMetrics&     aDesiredSize,
   1.155 +                          const nsHTMLReflowState& aReflowState,
   1.156 +                          nsReflowStatus&          aStatus) MOZ_OVERRIDE;
   1.157 +
   1.158 +protected:
   1.159 +  nsHTMLFramesetBlankFrame(nsStyleContext* aContext) : nsLeafFrame(aContext) {}
   1.160 +  virtual ~nsHTMLFramesetBlankFrame();
   1.161 +  virtual nscoord GetIntrinsicWidth() MOZ_OVERRIDE;
   1.162 +  virtual nscoord GetIntrinsicHeight() MOZ_OVERRIDE;
   1.163 +
   1.164 +  friend class nsHTMLFramesetFrame;
   1.165 +  friend class nsHTMLFrameset;
   1.166 +};
   1.167 +
   1.168 +/*******************************************************************************
   1.169 + * nsHTMLFramesetFrame
   1.170 + ******************************************************************************/
   1.171 +bool    nsHTMLFramesetFrame::gDragInProgress = false;
   1.172 +#define kFrameResizePref "layout.frames.force_resizability"
   1.173 +#define DEFAULT_BORDER_WIDTH_PX 6
   1.174 +
   1.175 +nsHTMLFramesetFrame::nsHTMLFramesetFrame(nsStyleContext* aContext)
   1.176 +  : nsContainerFrame(aContext)
   1.177 +{
   1.178 +  mNumRows             = 0;
   1.179 +  mRowSizes            = nullptr;
   1.180 +  mNumCols             = 0;
   1.181 +  mColSizes            = nullptr;
   1.182 +  mEdgeVisibility      = 0;
   1.183 +  mParentFrameborder   = eFrameborder_Yes; // default
   1.184 +  mParentBorderWidth   = -1; // default not set
   1.185 +  mParentBorderColor   = NO_COLOR; // default not set
   1.186 +  mFirstDragPoint.x     = mFirstDragPoint.y = 0;
   1.187 +  mMinDrag             = nsPresContext::CSSPixelsToAppUnits(2);
   1.188 +  mNonBorderChildCount = 0;
   1.189 +  mNonBlankChildCount  = 0;
   1.190 +  mDragger             = nullptr;
   1.191 +  mChildCount          = 0;
   1.192 +  mTopLevelFrameset    = nullptr;
   1.193 +  mEdgeColors.Set(NO_COLOR);
   1.194 +  mVerBorders          = nullptr;
   1.195 +  mHorBorders          = nullptr;
   1.196 +  mChildFrameborder    = nullptr;
   1.197 +  mChildBorderColors   = nullptr;
   1.198 +  mForceFrameResizability = false;
   1.199 +}
   1.200 +
   1.201 +nsHTMLFramesetFrame::~nsHTMLFramesetFrame()
   1.202 +{
   1.203 +  delete[] mRowSizes;
   1.204 +  delete[] mColSizes;
   1.205 +  delete[] mVerBorders;
   1.206 +  delete[] mHorBorders;
   1.207 +  delete[] mChildFrameborder;
   1.208 +  delete[] mChildBorderColors;
   1.209 +
   1.210 +  Preferences::UnregisterCallback(FrameResizePrefCallback,
   1.211 +                                  kFrameResizePref, this);
   1.212 +}
   1.213 +
   1.214 +NS_QUERYFRAME_HEAD(nsHTMLFramesetFrame)
   1.215 +  NS_QUERYFRAME_ENTRY(nsHTMLFramesetFrame)
   1.216 +NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
   1.217 +
   1.218 +// static
   1.219 +void
   1.220 +nsHTMLFramesetFrame::FrameResizePrefCallback(const char* aPref, void* aClosure)
   1.221 +{
   1.222 +  nsHTMLFramesetFrame *frame =
   1.223 +    reinterpret_cast<nsHTMLFramesetFrame *>(aClosure);
   1.224 +
   1.225 +  nsIDocument* doc = frame->mContent->GetDocument();
   1.226 +  mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true);
   1.227 +  if (doc) {
   1.228 +    nsNodeUtils::AttributeWillChange(frame->GetContent()->AsElement(),
   1.229 +                                     kNameSpaceID_None,
   1.230 +                                     nsGkAtoms::frameborder,
   1.231 +                                     nsIDOMMutationEvent::MODIFICATION);
   1.232 +  }
   1.233 +
   1.234 +  frame->mForceFrameResizability =
   1.235 +    Preferences::GetBool(kFrameResizePref, frame->mForceFrameResizability);
   1.236 +
   1.237 +  frame->RecalculateBorderResize();
   1.238 +  if (doc) {
   1.239 +    nsNodeUtils::AttributeChanged(frame->GetContent()->AsElement(),
   1.240 +                                  kNameSpaceID_None,
   1.241 +                                  nsGkAtoms::frameborder,
   1.242 +                                  nsIDOMMutationEvent::MODIFICATION);
   1.243 +  }
   1.244 +}
   1.245 +
   1.246 +void
   1.247 +nsHTMLFramesetFrame::Init(nsIContent*      aContent,
   1.248 +                          nsIFrame*        aParent,
   1.249 +                          nsIFrame*        aPrevInFlow)
   1.250 +{
   1.251 +  nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
   1.252 +  // find the highest ancestor that is a frameset
   1.253 +  nsIFrame* parentFrame = GetParent();
   1.254 +  mTopLevelFrameset = this;
   1.255 +  while (parentFrame) {
   1.256 +    nsHTMLFramesetFrame* frameset = do_QueryFrame(parentFrame);
   1.257 +    if (frameset) {
   1.258 +      mTopLevelFrameset = frameset;
   1.259 +      parentFrame = parentFrame->GetParent();
   1.260 +    } else {
   1.261 +      break;
   1.262 +    }
   1.263 +  }
   1.264 +
   1.265 +  nsPresContext* presContext = PresContext();
   1.266 +  nsIPresShell* shell = presContext->PresShell();
   1.267 +
   1.268 +  nsFrameborder  frameborder = GetFrameBorder();
   1.269 +  int32_t borderWidth = GetBorderWidth(presContext, false);
   1.270 +  nscolor borderColor = GetBorderColor();
   1.271 +
   1.272 +  // Get the rows= cols= data
   1.273 +  HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent);
   1.274 +  NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
   1.275 +  const nsFramesetSpec* rowSpecs = nullptr;
   1.276 +  const nsFramesetSpec* colSpecs = nullptr;
   1.277 +  // GetRowSpec and GetColSpec can fail, but when they do they set
   1.278 +  // mNumRows and mNumCols respectively to 0, so we deal with it fine.
   1.279 +  ourContent->GetRowSpec(&mNumRows, &rowSpecs);
   1.280 +  ourContent->GetColSpec(&mNumCols, &colSpecs);
   1.281 +
   1.282 +  // Maximum value of mNumRows and mNumCols is NS_MAX_FRAMESET_SPEC_COUNT
   1.283 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscoord));
   1.284 +  mRowSizes  = new nscoord[mNumRows];
   1.285 +  mColSizes  = new nscoord[mNumCols];
   1.286 +
   1.287 +  // Ensure we can't overflow numCells
   1.288 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT);
   1.289 +  int32_t numCells = mNumRows*mNumCols;
   1.290 +
   1.291 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nsHTMLFramesetBorderFrame*));
   1.292 +  mVerBorders    = new nsHTMLFramesetBorderFrame*[mNumCols];  // 1 more than number of ver borders
   1.293 +
   1.294 +  for (int verX  = 0; verX < mNumCols; verX++)
   1.295 +    mVerBorders[verX]    = nullptr;
   1.296 +
   1.297 +  mHorBorders    = new nsHTMLFramesetBorderFrame*[mNumRows];  // 1 more than number of hor borders
   1.298 +
   1.299 +  for (int horX = 0; horX < mNumRows; horX++)
   1.300 +    mHorBorders[horX]    = nullptr;
   1.301 +
   1.302 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
   1.303 +                   < UINT_MAX / sizeof(int32_t) / NS_MAX_FRAMESET_SPEC_COUNT);
   1.304 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
   1.305 +                   < UINT_MAX / sizeof(nsFrameborder) / NS_MAX_FRAMESET_SPEC_COUNT);
   1.306 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
   1.307 +                   < UINT_MAX / sizeof(nsBorderColor) / NS_MAX_FRAMESET_SPEC_COUNT);
   1.308 +  mChildFrameborder  = new nsFrameborder[numCells];
   1.309 +  mChildBorderColors  = new nsBorderColor[numCells];
   1.310 +
   1.311 +  // create the children frames; skip content which isn't <frameset> or <frame>
   1.312 +  mChildCount = 0; // number of <frame> or <frameset> children
   1.313 +  nsIFrame* frame;
   1.314 +
   1.315 +  // number of any type of children
   1.316 +  uint32_t numChildren = mContent->GetChildCount();
   1.317 +
   1.318 +  for (uint32_t childX = 0; childX < numChildren; childX++) {
   1.319 +    if (mChildCount == numCells) { // we have more <frame> or <frameset> than cells
   1.320 +      // Clear the lazy bits in the remaining children.  Also clear
   1.321 +      // the restyle flags, like nsCSSFrameConstructor::ProcessChildren does.
   1.322 +      for (uint32_t i = childX; i < numChildren; i++) {
   1.323 +        nsIContent *child = mContent->GetChildAt(i);
   1.324 +        child->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
   1.325 +        if (child->IsElement()) {
   1.326 +          child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
   1.327 +        }
   1.328 +      }
   1.329 +      break;
   1.330 +    }
   1.331 +    nsIContent *child = mContent->GetChildAt(childX);
   1.332 +    child->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME);
   1.333 +    // Also clear the restyle flags in the child like
   1.334 +    // nsCSSFrameConstructor::ProcessChildren does.
   1.335 +    if (child->IsElement()) {
   1.336 +      child->UnsetFlags(ELEMENT_ALL_RESTYLE_FLAGS);
   1.337 +    }
   1.338 +
   1.339 +    // IMPORTANT: This must match the conditions in
   1.340 +    // nsCSSFrameConstructor::ContentAppended/Inserted/Removed
   1.341 +    if (!child->IsHTML())
   1.342 +      continue;
   1.343 +
   1.344 +    nsIAtom *tag = child->Tag();
   1.345 +    if (tag == nsGkAtoms::frameset || tag == nsGkAtoms::frame) {
   1.346 +      nsRefPtr<nsStyleContext> kidSC;
   1.347 +
   1.348 +      kidSC = shell->StyleSet()->ResolveStyleFor(child->AsElement(),
   1.349 +                                                 mStyleContext);
   1.350 +      if (tag == nsGkAtoms::frameset) {
   1.351 +        frame = NS_NewHTMLFramesetFrame(shell, kidSC);
   1.352 +
   1.353 +        nsHTMLFramesetFrame* childFrame = (nsHTMLFramesetFrame*)frame;
   1.354 +        childFrame->SetParentFrameborder(frameborder);
   1.355 +        childFrame->SetParentBorderWidth(borderWidth);
   1.356 +        childFrame->SetParentBorderColor(borderColor);
   1.357 +        frame->Init(child, this, nullptr);
   1.358 +
   1.359 +        mChildBorderColors[mChildCount].Set(childFrame->GetBorderColor());
   1.360 +      } else { // frame
   1.361 +        frame = NS_NewSubDocumentFrame(shell, kidSC);
   1.362 +
   1.363 +        frame->Init(child, this, nullptr);
   1.364 +
   1.365 +        mChildFrameborder[mChildCount] = GetFrameBorder(child);
   1.366 +        mChildBorderColors[mChildCount].Set(GetBorderColor(child));
   1.367 +      }
   1.368 +      child->SetPrimaryFrame(frame);
   1.369 +
   1.370 +      mFrames.AppendFrame(nullptr, frame);
   1.371 +
   1.372 +      mChildCount++;
   1.373 +    }
   1.374 +  }
   1.375 +
   1.376 +  mNonBlankChildCount = mChildCount;
   1.377 +  // add blank frames for frameset cells that had no content provided
   1.378 +  for (int blankX = mChildCount; blankX < numCells; blankX++) {
   1.379 +    nsRefPtr<nsStyleContext> pseudoStyleContext;
   1.380 +    pseudoStyleContext = shell->StyleSet()->
   1.381 +      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::framesetBlank, mStyleContext);
   1.382 +
   1.383 +    // XXX the blank frame is using the content of its parent - at some point it
   1.384 +    // should just have null content, if we support that
   1.385 +    nsHTMLFramesetBlankFrame* blankFrame = new (shell) nsHTMLFramesetBlankFrame(pseudoStyleContext);
   1.386 +
   1.387 +    blankFrame->Init(mContent, this, nullptr);
   1.388 +
   1.389 +    mFrames.AppendFrame(nullptr, blankFrame);
   1.390 +
   1.391 +    mChildBorderColors[mChildCount].Set(NO_COLOR);
   1.392 +    mChildCount++;
   1.393 +  }
   1.394 +
   1.395 +  mNonBorderChildCount = mChildCount;
   1.396 +}
   1.397 +
   1.398 +nsresult
   1.399 +nsHTMLFramesetFrame::SetInitialChildList(ChildListID  aListID,
   1.400 +                                         nsFrameList& aChildList)
   1.401 +{
   1.402 +  // We do this weirdness where we create our child frames in Init().  On the
   1.403 +  // other hand, we're going to get a SetInitialChildList() with an empty list
   1.404 +  // and null list name after the frame constructor is done creating us.  So
   1.405 +  // just ignore that call.
   1.406 +  if (aListID == kPrincipalList && aChildList.IsEmpty()) {
   1.407 +    return NS_OK;
   1.408 +  }
   1.409 +
   1.410 +  return nsContainerFrame::SetInitialChildList(aListID, aChildList);
   1.411 +}
   1.412 +
   1.413 +// XXX should this try to allocate twips based on an even pixel boundary?
   1.414 +void nsHTMLFramesetFrame::Scale(nscoord  aDesired,
   1.415 +                                int32_t  aNumIndicies,
   1.416 +                                int32_t* aIndicies,
   1.417 +                                int32_t  aNumItems,
   1.418 +                                int32_t* aItems)
   1.419 +{
   1.420 +  int32_t actual = 0;
   1.421 +  int32_t i, j;
   1.422 +  // get the actual total
   1.423 +  for (i = 0; i < aNumIndicies; i++) {
   1.424 +    j = aIndicies[i];
   1.425 +    actual += aItems[j];
   1.426 +  }
   1.427 +
   1.428 +  if (actual > 0) {
   1.429 +    float factor = (float)aDesired / (float)actual;
   1.430 +    actual = 0;
   1.431 +    // scale the items up or down
   1.432 +    for (i = 0; i < aNumIndicies; i++) {
   1.433 +      j = aIndicies[i];
   1.434 +      aItems[j] = NSToCoordRound((float)aItems[j] * factor);
   1.435 +      actual += aItems[j];
   1.436 +    }
   1.437 +  } else if (aNumIndicies != 0) {
   1.438 +    // All the specs say zero width, but we have to fill up space
   1.439 +    // somehow.  Distribute it equally.
   1.440 +    nscoord width = NSToCoordRound((float)aDesired / (float)aNumIndicies);
   1.441 +    actual = width * aNumIndicies;
   1.442 +    for (i = 0; i < aNumIndicies; i++) {
   1.443 +      aItems[aIndicies[i]] = width;
   1.444 +    }
   1.445 +  }
   1.446 +
   1.447 +  if (aNumIndicies > 0 && aDesired != actual) {
   1.448 +    int32_t unit = (aDesired > actual) ? 1 : -1;
   1.449 +    for (i=0; (i < aNumIndicies) && (aDesired != actual); i++) {
   1.450 +      j = aIndicies[i];
   1.451 +      if (j < aNumItems) {
   1.452 +        aItems[j] += unit;
   1.453 +        actual += unit;
   1.454 +      }
   1.455 +    }
   1.456 +  }
   1.457 +}
   1.458 +
   1.459 +
   1.460 +/**
   1.461 +  * Translate the rows/cols specs into an array of integer sizes for
   1.462 +  * each cell in the frameset. Sizes are allocated based on the priorities of the
   1.463 +  * specifier - fixed sizes have the highest priority, percentage sizes have the next
   1.464 +  * highest priority and relative sizes have the lowest.
   1.465 +  */
   1.466 +void nsHTMLFramesetFrame::CalculateRowCol(nsPresContext*        aPresContext,
   1.467 +                                          nscoord               aSize,
   1.468 +                                          int32_t               aNumSpecs,
   1.469 +                                          const nsFramesetSpec* aSpecs,
   1.470 +                                          nscoord*              aValues)
   1.471 +{
   1.472 +  // aNumSpecs maximum value is NS_MAX_FRAMESET_SPEC_COUNT
   1.473 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(int32_t));
   1.474 +
   1.475 +  int32_t  fixedTotal = 0;
   1.476 +  int32_t  numFixed = 0;
   1.477 +  nsAutoArrayPtr<int32_t> fixed(new int32_t[aNumSpecs]);
   1.478 +  int32_t  numPercent = 0;
   1.479 +  nsAutoArrayPtr<int32_t> percent(new int32_t[aNumSpecs]);
   1.480 +  int32_t  relativeSums = 0;
   1.481 +  int32_t  numRelative = 0;
   1.482 +  nsAutoArrayPtr<int32_t> relative(new int32_t[aNumSpecs]);
   1.483 +
   1.484 +  if (MOZ_UNLIKELY(!fixed || !percent || !relative)) {
   1.485 +    return; // NS_ERROR_OUT_OF_MEMORY
   1.486 +  }
   1.487 +
   1.488 +  int32_t i, j;
   1.489 +
   1.490 +  // initialize the fixed, percent, relative indices, allocate the fixed sizes and zero the others
   1.491 +  for (i = 0; i < aNumSpecs; i++) {
   1.492 +    aValues[i] = 0;
   1.493 +    switch (aSpecs[i].mUnit) {
   1.494 +      case eFramesetUnit_Fixed:
   1.495 +        aValues[i] = nsPresContext::CSSPixelsToAppUnits(aSpecs[i].mValue);
   1.496 +        fixedTotal += aValues[i];
   1.497 +        fixed[numFixed] = i;
   1.498 +        numFixed++;
   1.499 +        break;
   1.500 +      case eFramesetUnit_Percent:
   1.501 +        percent[numPercent] = i;
   1.502 +        numPercent++;
   1.503 +        break;
   1.504 +      case eFramesetUnit_Relative:
   1.505 +        relative[numRelative] = i;
   1.506 +        numRelative++;
   1.507 +        relativeSums += aSpecs[i].mValue;
   1.508 +        break;
   1.509 +    }
   1.510 +  }
   1.511 +
   1.512 +  // scale the fixed sizes if they total too much (or too little and there aren't any percent or relative)
   1.513 +  if ((fixedTotal > aSize) || ((fixedTotal < aSize) && (0 == numPercent) && (0 == numRelative))) {
   1.514 +    Scale(aSize, numFixed, fixed, aNumSpecs, aValues);
   1.515 +    return;
   1.516 +  }
   1.517 +
   1.518 +  int32_t percentMax = aSize - fixedTotal;
   1.519 +  int32_t percentTotal = 0;
   1.520 +  // allocate the percentage sizes from what is left over from the fixed allocation
   1.521 +  for (i = 0; i < numPercent; i++) {
   1.522 +    j = percent[i];
   1.523 +    aValues[j] = NSToCoordRound((float)aSpecs[j].mValue * (float)aSize / 100.0f);
   1.524 +    percentTotal += aValues[j];
   1.525 +  }
   1.526 +
   1.527 +  // scale the percent sizes if they total too much (or too little and there aren't any relative)
   1.528 +  if ((percentTotal > percentMax) || ((percentTotal < percentMax) && (0 == numRelative))) {
   1.529 +    Scale(percentMax, numPercent, percent, aNumSpecs, aValues);
   1.530 +    return;
   1.531 +  }
   1.532 +
   1.533 +  int32_t relativeMax = percentMax - percentTotal;
   1.534 +  int32_t relativeTotal = 0;
   1.535 +  // allocate the relative sizes from what is left over from the percent allocation
   1.536 +  for (i = 0; i < numRelative; i++) {
   1.537 +    j = relative[i];
   1.538 +    aValues[j] = NSToCoordRound((float)aSpecs[j].mValue * (float)relativeMax / (float)relativeSums);
   1.539 +    relativeTotal += aValues[j];
   1.540 +  }
   1.541 +
   1.542 +  // scale the relative sizes if they take up too much or too little
   1.543 +  if (relativeTotal != relativeMax) {
   1.544 +    Scale(relativeMax, numRelative, relative, aNumSpecs, aValues);
   1.545 +  }
   1.546 +}
   1.547 +
   1.548 +
   1.549 +/**
   1.550 +  * Translate the rows/cols integer sizes into an array of specs for
   1.551 +  * each cell in the frameset.  Reverse of CalculateRowCol() behaviour.
   1.552 +  * This allows us to maintain the user size info through reflows.
   1.553 +  */
   1.554 +void nsHTMLFramesetFrame::GenerateRowCol(nsPresContext*        aPresContext,
   1.555 +                                         nscoord               aSize,
   1.556 +                                         int32_t               aNumSpecs,
   1.557 +                                         const nsFramesetSpec* aSpecs,
   1.558 +                                         nscoord*              aValues,
   1.559 +                                         nsString&             aNewAttr)
   1.560 +{
   1.561 +  int32_t i;
   1.562 +
   1.563 +  for (i = 0; i < aNumSpecs; i++) {
   1.564 +    if (!aNewAttr.IsEmpty())
   1.565 +      aNewAttr.Append(char16_t(','));
   1.566 +
   1.567 +    switch (aSpecs[i].mUnit) {
   1.568 +      case eFramesetUnit_Fixed:
   1.569 +        aNewAttr.AppendInt(nsPresContext::AppUnitsToIntCSSPixels(aValues[i]));
   1.570 +        break;
   1.571 +      case eFramesetUnit_Percent: // XXX Only accurate to 1%, need 1 pixel
   1.572 +      case eFramesetUnit_Relative:
   1.573 +        // Add 0.5 to the percentage to make rounding work right.
   1.574 +        aNewAttr.AppendInt(uint32_t((100.0*aValues[i])/aSize + 0.5));
   1.575 +        aNewAttr.Append(char16_t('%'));
   1.576 +        break;
   1.577 +    }
   1.578 +  }
   1.579 +}
   1.580 +
   1.581 +int32_t nsHTMLFramesetFrame::GetBorderWidth(nsPresContext* aPresContext,
   1.582 +                                            bool aTakeForcingIntoAccount)
   1.583 +{
   1.584 +  bool forcing = mForceFrameResizability && aTakeForcingIntoAccount;
   1.585 +
   1.586 +  if (!forcing) {
   1.587 +    nsFrameborder frameborder = GetFrameBorder();
   1.588 +    if (frameborder == eFrameborder_No) {
   1.589 +      return 0;
   1.590 +    }
   1.591 +  }
   1.592 +  nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
   1.593 +
   1.594 +  if (content) {
   1.595 +    const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::border);
   1.596 +    if (attr) {
   1.597 +      int32_t intVal = 0;
   1.598 +      if (attr->Type() == nsAttrValue::eInteger) {
   1.599 +        intVal = attr->GetIntegerValue();
   1.600 +        if (intVal < 0) {
   1.601 +          intVal = 0;
   1.602 +        }
   1.603 +      }
   1.604 +
   1.605 +      if (forcing && intVal == 0) {
   1.606 +        intVal = DEFAULT_BORDER_WIDTH_PX;
   1.607 +      }
   1.608 +      return nsPresContext::CSSPixelsToAppUnits(intVal);
   1.609 +    }
   1.610 +  }
   1.611 +
   1.612 +  if (mParentBorderWidth > 0 ||
   1.613 +      (mParentBorderWidth == 0 && !forcing)) {
   1.614 +    return mParentBorderWidth;
   1.615 +  }
   1.616 +
   1.617 +  return nsPresContext::CSSPixelsToAppUnits(DEFAULT_BORDER_WIDTH_PX);
   1.618 +}
   1.619 +
   1.620 +void
   1.621 +nsHTMLFramesetFrame::GetDesiredSize(nsPresContext*           aPresContext,
   1.622 +                                    const nsHTMLReflowState& aReflowState,
   1.623 +                                    nsHTMLReflowMetrics&     aDesiredSize)
   1.624 +{
   1.625 +  nsHTMLFramesetFrame* framesetParent = do_QueryFrame(GetParent());
   1.626 +  if (nullptr == framesetParent) {
   1.627 +    if (aPresContext->IsPaginated()) {
   1.628 +      // XXX This needs to be changed when framesets paginate properly
   1.629 +      aDesiredSize.Width() = aReflowState.AvailableWidth();
   1.630 +      aDesiredSize.Height() = aReflowState.AvailableHeight();
   1.631 +    } else {
   1.632 +      nsRect area = aPresContext->GetVisibleArea();
   1.633 +
   1.634 +      aDesiredSize.Width() = area.width;
   1.635 +      aDesiredSize.Height() = area.height;
   1.636 +    }
   1.637 +  } else {
   1.638 +    nsSize size;
   1.639 +    framesetParent->GetSizeOfChild(this, size);
   1.640 +    aDesiredSize.Width() = size.width;
   1.641 +    aDesiredSize.Height() = size.height;
   1.642 +  }
   1.643 +}
   1.644 +
   1.645 +// only valid for non border children
   1.646 +void nsHTMLFramesetFrame::GetSizeOfChildAt(int32_t  aIndexInParent,
   1.647 +                                           nsSize&  aSize,
   1.648 +                                           nsIntPoint& aCellIndex)
   1.649 +{
   1.650 +  int32_t row = aIndexInParent / mNumCols;
   1.651 +  int32_t col = aIndexInParent - (row * mNumCols); // remainder from dividing index by mNumCols
   1.652 +  if ((row < mNumRows) && (col < mNumCols)) {
   1.653 +    aSize.width  = mColSizes[col];
   1.654 +    aSize.height = mRowSizes[row];
   1.655 +    aCellIndex.x = col;
   1.656 +    aCellIndex.y = row;
   1.657 +  } else {
   1.658 +    aSize.width = aSize.height = 0;
   1.659 +    aCellIndex.x = aCellIndex.y = 0;
   1.660 +  }
   1.661 +}
   1.662 +
   1.663 +// only valid for non border children
   1.664 +void nsHTMLFramesetFrame::GetSizeOfChild(nsIFrame* aChild,
   1.665 +                                         nsSize&   aSize)
   1.666 +{
   1.667 +  // Reflow only creates children frames for <frameset> and <frame> content.
   1.668 +  // this assumption is used here
   1.669 +  int i = 0;
   1.670 +  for (nsIFrame* child = mFrames.FirstChild(); child;
   1.671 +       child = child->GetNextSibling()) {
   1.672 +    if (aChild == child) {
   1.673 +      nsIntPoint ignore;
   1.674 +      GetSizeOfChildAt(i, aSize, ignore);
   1.675 +      return;
   1.676 +    }
   1.677 +    i++;
   1.678 +  }
   1.679 +  aSize.width  = 0;
   1.680 +  aSize.height = 0;
   1.681 +}
   1.682 +
   1.683 +
   1.684 +nsresult nsHTMLFramesetFrame::HandleEvent(nsPresContext* aPresContext,
   1.685 +                                           WidgetGUIEvent* aEvent,
   1.686 +                                           nsEventStatus* aEventStatus)
   1.687 +{
   1.688 +  NS_ENSURE_ARG_POINTER(aEventStatus);
   1.689 +  if (mDragger) {
   1.690 +    // the nsFramesetBorderFrame has captured NS_MOUSE_DOWN
   1.691 +    switch (aEvent->message) {
   1.692 +      case NS_MOUSE_MOVE:
   1.693 +        MouseDrag(aPresContext, aEvent);
   1.694 +	      break;
   1.695 +      case NS_MOUSE_BUTTON_UP:
   1.696 +        if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
   1.697 +          EndMouseDrag(aPresContext);
   1.698 +        }
   1.699 +	      break;
   1.700 +    }
   1.701 +    *aEventStatus = nsEventStatus_eConsumeNoDefault;
   1.702 +  } else {
   1.703 +    *aEventStatus = nsEventStatus_eIgnore;
   1.704 +  }
   1.705 +  return NS_OK;
   1.706 +}
   1.707 +
   1.708 +nsresult
   1.709 +nsHTMLFramesetFrame::GetCursor(const nsPoint&    aPoint,
   1.710 +                               nsIFrame::Cursor& aCursor)
   1.711 +{
   1.712 +  if (mDragger) {
   1.713 +    aCursor.mCursor = (mDragger->mVertical) ? NS_STYLE_CURSOR_EW_RESIZE : NS_STYLE_CURSOR_NS_RESIZE;
   1.714 +  } else {
   1.715 +    aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
   1.716 +  }
   1.717 +  return NS_OK;
   1.718 +}
   1.719 +
   1.720 +void
   1.721 +nsHTMLFramesetFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   1.722 +                                      const nsRect&           aDirtyRect,
   1.723 +                                      const nsDisplayListSet& aLists)
   1.724 +{
   1.725 +  BuildDisplayListForInline(aBuilder, aDirtyRect, aLists);
   1.726 +
   1.727 +  if (mDragger && aBuilder->IsForEventDelivery()) {
   1.728 +    aLists.Content()->AppendNewToTop(
   1.729 +      new (aBuilder) nsDisplayEventReceiver(aBuilder, this));
   1.730 +  }
   1.731 +}
   1.732 +
   1.733 +void
   1.734 +nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame*                aChild,
   1.735 +                                      nsPresContext*           aPresContext,
   1.736 +                                      const nsHTMLReflowState& aReflowState,
   1.737 +                                      nsPoint&                 aOffset,
   1.738 +                                      nsSize&                  aSize,
   1.739 +                                      nsIntPoint*              aCellIndex)
   1.740 +{
   1.741 +  // reflow the child
   1.742 +  nsHTMLReflowState reflowState(aPresContext, aReflowState, aChild, aSize);
   1.743 +  reflowState.SetComputedWidth(std::max(0, aSize.width - reflowState.ComputedPhysicalBorderPadding().LeftRight()));
   1.744 +  reflowState.SetComputedHeight(std::max(0, aSize.height - reflowState.ComputedPhysicalBorderPadding().TopBottom()));
   1.745 +  nsHTMLReflowMetrics metrics(aReflowState);
   1.746 +  metrics.Width() = aSize.width;
   1.747 +  metrics.Height() = aSize.height;
   1.748 +  nsReflowStatus status;
   1.749 +
   1.750 +  ReflowChild(aChild, aPresContext, metrics, reflowState, aOffset.x,
   1.751 +              aOffset.y, 0, status);
   1.752 +  NS_ASSERTION(NS_FRAME_IS_COMPLETE(status), "bad status");
   1.753 +
   1.754 +  // Place and size the child
   1.755 +  metrics.Width() = aSize.width;
   1.756 +  metrics.Height() = aSize.height;
   1.757 +  FinishReflowChild(aChild, aPresContext, metrics, nullptr, aOffset.x, aOffset.y, 0);
   1.758 +}
   1.759 +
   1.760 +static
   1.761 +nsFrameborder GetFrameBorderHelper(nsGenericHTMLElement* aContent)
   1.762 +{
   1.763 +  if (nullptr != aContent) {
   1.764 +    const nsAttrValue* attr = aContent->GetParsedAttr(nsGkAtoms::frameborder);
   1.765 +    if (attr && attr->Type() == nsAttrValue::eEnum) {
   1.766 +      switch (attr->GetEnumValue())
   1.767 +      {
   1.768 +        case NS_STYLE_FRAME_YES:
   1.769 +        case NS_STYLE_FRAME_1:
   1.770 +          return eFrameborder_Yes;
   1.771 +          break;
   1.772 +
   1.773 +        case NS_STYLE_FRAME_NO:
   1.774 +        case NS_STYLE_FRAME_0:
   1.775 +          return eFrameborder_No;
   1.776 +          break;
   1.777 +      }
   1.778 +    }
   1.779 +  }
   1.780 +  return eFrameborder_Notset;
   1.781 +}
   1.782 +
   1.783 +nsFrameborder nsHTMLFramesetFrame::GetFrameBorder()
   1.784 +{
   1.785 +  nsFrameborder result = eFrameborder_Notset;
   1.786 +  nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
   1.787 +
   1.788 +  if (content) {
   1.789 +    result = GetFrameBorderHelper(content);
   1.790 +  }
   1.791 +  if (eFrameborder_Notset == result) {
   1.792 +    return mParentFrameborder;
   1.793 +  }
   1.794 +  return result;
   1.795 +}
   1.796 +
   1.797 +nsFrameborder nsHTMLFramesetFrame::GetFrameBorder(nsIContent* aContent)
   1.798 +{
   1.799 +  nsFrameborder result = eFrameborder_Notset;
   1.800 +
   1.801 +  nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(aContent);
   1.802 +
   1.803 +  if (content) {
   1.804 +    result = GetFrameBorderHelper(content);
   1.805 +  }
   1.806 +  if (eFrameborder_Notset == result) {
   1.807 +    return GetFrameBorder();
   1.808 +  }
   1.809 +  return result;
   1.810 +}
   1.811 +
   1.812 +nscolor nsHTMLFramesetFrame::GetBorderColor()
   1.813 +{
   1.814 +  nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(mContent);
   1.815 +
   1.816 +  if (content) {
   1.817 +    const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::bordercolor);
   1.818 +    if (attr) {
   1.819 +      nscolor color;
   1.820 +      if (attr->GetColorValue(color)) {
   1.821 +        return color;
   1.822 +      }
   1.823 +    }
   1.824 +  }
   1.825 +
   1.826 +  return mParentBorderColor;
   1.827 +}
   1.828 +
   1.829 +nscolor nsHTMLFramesetFrame::GetBorderColor(nsIContent* aContent)
   1.830 +{
   1.831 +  nsGenericHTMLElement *content = nsGenericHTMLElement::FromContent(aContent);
   1.832 +
   1.833 +  if (content) {
   1.834 +    const nsAttrValue* attr = content->GetParsedAttr(nsGkAtoms::bordercolor);
   1.835 +    if (attr) {
   1.836 +      nscolor color;
   1.837 +      if (attr->GetColorValue(color)) {
   1.838 +        return color;
   1.839 +      }
   1.840 +    }
   1.841 +  }
   1.842 +  return GetBorderColor();
   1.843 +}
   1.844 +
   1.845 +nsresult
   1.846 +nsHTMLFramesetFrame::Reflow(nsPresContext*           aPresContext,
   1.847 +                            nsHTMLReflowMetrics&     aDesiredSize,
   1.848 +                            const nsHTMLReflowState& aReflowState,
   1.849 +                            nsReflowStatus&          aStatus)
   1.850 +{
   1.851 +  DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame");
   1.852 +  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   1.853 +  nsIPresShell *shell = aPresContext->PresShell();
   1.854 +  nsStyleSet *styleSet = shell->StyleSet();
   1.855 +
   1.856 +  mParent->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
   1.857 +
   1.858 +  //printf("FramesetFrame2::Reflow %X (%d,%d) \n", this, aReflowState.AvailableWidth(), aReflowState.AvailableHeight());
   1.859 +  // Always get the size so that the caller knows how big we are
   1.860 +  GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
   1.861 +
   1.862 +  nscoord width  = (aDesiredSize.Width() <= aReflowState.AvailableWidth())
   1.863 +    ? aDesiredSize.Width() : aReflowState.AvailableWidth();
   1.864 +  nscoord height = (aDesiredSize.Height() <= aReflowState.AvailableHeight())
   1.865 +    ? aDesiredSize.Height() : aReflowState.AvailableHeight();
   1.866 +
   1.867 +  bool firstTime = (GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
   1.868 +  if (firstTime) {
   1.869 +    Preferences::RegisterCallback(FrameResizePrefCallback,
   1.870 +                                  kFrameResizePref, this);
   1.871 +    mForceFrameResizability = Preferences::GetBool(kFrameResizePref);
   1.872 +  }
   1.873 +
   1.874 +  // subtract out the width of all of the potential borders. There are
   1.875 +  // only borders between <frame>s. There are none on the edges (e.g the
   1.876 +  // leftmost <frame> has no left border).
   1.877 +  int32_t borderWidth = GetBorderWidth(aPresContext, true);
   1.878 +
   1.879 +  width  -= (mNumCols - 1) * borderWidth;
   1.880 +  if (width < 0) width = 0;
   1.881 +
   1.882 +  height -= (mNumRows - 1) * borderWidth;
   1.883 +  if (height < 0) height = 0;
   1.884 +
   1.885 +  HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent);
   1.886 +  NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
   1.887 +  const nsFramesetSpec* rowSpecs = nullptr;
   1.888 +  const nsFramesetSpec* colSpecs = nullptr;
   1.889 +  int32_t rows = 0;
   1.890 +  int32_t cols = 0;
   1.891 +  ourContent->GetRowSpec(&rows, &rowSpecs);
   1.892 +  ourContent->GetColSpec(&cols, &colSpecs);
   1.893 +  // If the number of cols or rows has changed, the frame for the frameset
   1.894 +  // will be re-created.
   1.895 +  if (mNumRows != rows || mNumCols != cols) {
   1.896 +    aStatus = NS_FRAME_COMPLETE;
   1.897 +    mDrag.UnSet();
   1.898 +    NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   1.899 +    return NS_OK;
   1.900 +  }
   1.901 +
   1.902 +  CalculateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes);
   1.903 +  CalculateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes);
   1.904 +
   1.905 +  nsAutoArrayPtr<bool>  verBordersVis; // vertical borders visibility
   1.906 +  nsAutoArrayPtr<nscolor> verBorderColors;
   1.907 +  nsAutoArrayPtr<bool>  horBordersVis; // horizontal borders visibility
   1.908 +  nsAutoArrayPtr<nscolor> horBorderColors;
   1.909 +  nscolor                 borderColor = GetBorderColor();
   1.910 +  nsFrameborder           frameborder = GetFrameBorder();
   1.911 +
   1.912 +  if (firstTime) {
   1.913 +    // Check for overflow in memory allocations using mNumCols and mNumRows
   1.914 +    // which have a maxium value of NS_MAX_FRAMESET_SPEC_COUNT.
   1.915 +    PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(bool));
   1.916 +    PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < UINT_MAX / sizeof(nscolor));
   1.917 +
   1.918 +    verBordersVis = new bool[mNumCols];
   1.919 +    NS_ENSURE_TRUE(verBordersVis, NS_ERROR_OUT_OF_MEMORY);
   1.920 +    verBorderColors = new nscolor[mNumCols];
   1.921 +    NS_ENSURE_TRUE(verBorderColors, NS_ERROR_OUT_OF_MEMORY);
   1.922 +    for (int verX  = 0; verX < mNumCols; verX++) {
   1.923 +      verBordersVis[verX] = false;
   1.924 +      verBorderColors[verX] = NO_COLOR;
   1.925 +    }
   1.926 +
   1.927 +    horBordersVis = new bool[mNumRows];
   1.928 +    NS_ENSURE_TRUE(horBordersVis, NS_ERROR_OUT_OF_MEMORY);
   1.929 +    horBorderColors = new nscolor[mNumRows];
   1.930 +    NS_ENSURE_TRUE(horBorderColors, NS_ERROR_OUT_OF_MEMORY);
   1.931 +    for (int horX = 0; horX < mNumRows; horX++) {
   1.932 +      horBordersVis[horX] = false;
   1.933 +      horBorderColors[horX] = NO_COLOR;
   1.934 +    }
   1.935 +  }
   1.936 +
   1.937 +  // reflow the children
   1.938 +  int32_t lastRow = 0;
   1.939 +  int32_t lastCol = 0;
   1.940 +  int32_t borderChildX = mNonBorderChildCount; // index of border children
   1.941 +  nsHTMLFramesetBorderFrame* borderFrame = nullptr;
   1.942 +  nsPoint offset(0,0);
   1.943 +  nsSize size, lastSize;
   1.944 +  nsIFrame* child = mFrames.FirstChild();
   1.945 +
   1.946 +  for (int32_t childX = 0; childX < mNonBorderChildCount; childX++) {
   1.947 +    nsIntPoint cellIndex;
   1.948 +    GetSizeOfChildAt(childX, size, cellIndex);
   1.949 +
   1.950 +    if (lastRow != cellIndex.y) {  // changed to next row
   1.951 +      offset.x = 0;
   1.952 +      offset.y += lastSize.height;
   1.953 +      if (firstTime) { // create horizontal border
   1.954 +
   1.955 +        nsRefPtr<nsStyleContext> pseudoStyleContext;
   1.956 +        pseudoStyleContext = styleSet->
   1.957 +          ResolveAnonymousBoxStyle(nsCSSAnonBoxes::horizontalFramesetBorder,
   1.958 +                                   mStyleContext);
   1.959 +
   1.960 +        borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext,
   1.961 +                                                            borderWidth,
   1.962 +                                                            false,
   1.963 +                                                            false);
   1.964 +        borderFrame->Init(mContent, this, nullptr);
   1.965 +        mChildCount++;
   1.966 +        mFrames.AppendFrame(nullptr, borderFrame);
   1.967 +        mHorBorders[cellIndex.y-1] = borderFrame;
   1.968 +        // set the neighbors for determining drag boundaries
   1.969 +        borderFrame->mPrevNeighbor = lastRow;
   1.970 +        borderFrame->mNextNeighbor = cellIndex.y;
   1.971 +      } else {
   1.972 +        borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
   1.973 +        borderFrame->mWidth = borderWidth;
   1.974 +        borderChildX++;
   1.975 +      }
   1.976 +      nsSize borderSize(aDesiredSize.Width(), borderWidth);
   1.977 +      ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize);
   1.978 +      borderFrame = nullptr;
   1.979 +      offset.y += borderWidth;
   1.980 +    } else {
   1.981 +      if (cellIndex.x > 0) {  // moved to next col in same row
   1.982 +        if (0 == cellIndex.y) { // in 1st row
   1.983 +          if (firstTime) { // create vertical border
   1.984 +
   1.985 +            nsRefPtr<nsStyleContext> pseudoStyleContext;
   1.986 +            pseudoStyleContext = styleSet->
   1.987 +              ResolveAnonymousBoxStyle(nsCSSAnonBoxes::verticalFramesetBorder,
   1.988 +                                       mStyleContext);
   1.989 +
   1.990 +            borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext,
   1.991 +                                                                borderWidth,
   1.992 +                                                                true,
   1.993 +                                                                false);
   1.994 +            borderFrame->Init(mContent, this, nullptr);
   1.995 +            mChildCount++;
   1.996 +            mFrames.AppendFrame(nullptr, borderFrame);
   1.997 +            mVerBorders[cellIndex.x-1] = borderFrame;
   1.998 +            // set the neighbors for determining drag boundaries
   1.999 +            borderFrame->mPrevNeighbor = lastCol;
  1.1000 +            borderFrame->mNextNeighbor = cellIndex.x;
  1.1001 +          } else {
  1.1002 +            borderFrame = (nsHTMLFramesetBorderFrame*)mFrames.FrameAt(borderChildX);
  1.1003 +            borderFrame->mWidth = borderWidth;
  1.1004 +            borderChildX++;
  1.1005 +          }
  1.1006 +          nsSize borderSize(borderWidth, aDesiredSize.Height());
  1.1007 +          ReflowPlaceChild(borderFrame, aPresContext, aReflowState, offset, borderSize);
  1.1008 +          borderFrame = nullptr;
  1.1009 +        }
  1.1010 +        offset.x += borderWidth;
  1.1011 +      }
  1.1012 +    }
  1.1013 +
  1.1014 +    ReflowPlaceChild(child, aPresContext, aReflowState, offset, size, &cellIndex);
  1.1015 +
  1.1016 +    if (firstTime) {
  1.1017 +      int32_t childVis;
  1.1018 +      nsHTMLFramesetFrame* framesetFrame = do_QueryFrame(child);
  1.1019 +      nsSubDocumentFrame* subdocFrame;
  1.1020 +      if (framesetFrame) {
  1.1021 +        childVis = framesetFrame->mEdgeVisibility;
  1.1022 +        mChildBorderColors[childX] = framesetFrame->mEdgeColors;
  1.1023 +      } else if ((subdocFrame = do_QueryFrame(child))) {
  1.1024 +        if (eFrameborder_Yes == mChildFrameborder[childX]) {
  1.1025 +          childVis = ALL_VIS;
  1.1026 +        } else if (eFrameborder_No == mChildFrameborder[childX]) {
  1.1027 +          childVis = NONE_VIS;
  1.1028 +        } else {  // notset
  1.1029 +          childVis = (eFrameborder_No == frameborder) ? NONE_VIS : ALL_VIS;
  1.1030 +        }
  1.1031 +      } else {  // blank
  1.1032 +        DebugOnly<nsHTMLFramesetBlankFrame*> blank;
  1.1033 +        MOZ_ASSERT(blank = do_QueryFrame(child), "unexpected child frame type");
  1.1034 +        childVis = NONE_VIS;
  1.1035 +      }
  1.1036 +      nsBorderColor childColors = mChildBorderColors[childX];
  1.1037 +      // set the visibility, color of our edge borders based on children
  1.1038 +      if (0 == cellIndex.x) {
  1.1039 +        if (!(mEdgeVisibility & LEFT_VIS)) {
  1.1040 +          mEdgeVisibility |= (LEFT_VIS & childVis);
  1.1041 +        }
  1.1042 +        if (NO_COLOR == mEdgeColors.mLeft) {
  1.1043 +          mEdgeColors.mLeft = childColors.mLeft;
  1.1044 +        }
  1.1045 +      }
  1.1046 +      if (0 == cellIndex.y) {
  1.1047 +        if (!(mEdgeVisibility & TOP_VIS)) {
  1.1048 +          mEdgeVisibility |= (TOP_VIS & childVis);
  1.1049 +        }
  1.1050 +        if (NO_COLOR == mEdgeColors.mTop) {
  1.1051 +          mEdgeColors.mTop = childColors.mTop;
  1.1052 +        }
  1.1053 +      }
  1.1054 +      if (mNumCols-1 == cellIndex.x) {
  1.1055 +        if (!(mEdgeVisibility & RIGHT_VIS)) {
  1.1056 +          mEdgeVisibility |= (RIGHT_VIS & childVis);
  1.1057 +        }
  1.1058 +        if (NO_COLOR == mEdgeColors.mRight) {
  1.1059 +          mEdgeColors.mRight = childColors.mRight;
  1.1060 +        }
  1.1061 +      }
  1.1062 +      if (mNumRows-1 == cellIndex.y) {
  1.1063 +        if (!(mEdgeVisibility & BOTTOM_VIS)) {
  1.1064 +          mEdgeVisibility |= (BOTTOM_VIS & childVis);
  1.1065 +        }
  1.1066 +        if (NO_COLOR == mEdgeColors.mBottom) {
  1.1067 +          mEdgeColors.mBottom = childColors.mBottom;
  1.1068 +        }
  1.1069 +      }
  1.1070 +      // set the visibility of borders that the child may affect
  1.1071 +      if (childVis & RIGHT_VIS) {
  1.1072 +        verBordersVis[cellIndex.x] = true;
  1.1073 +      }
  1.1074 +      if (childVis & BOTTOM_VIS) {
  1.1075 +        horBordersVis[cellIndex.y] = true;
  1.1076 +      }
  1.1077 +      if ((cellIndex.x > 0) && (childVis & LEFT_VIS)) {
  1.1078 +        verBordersVis[cellIndex.x-1] = true;
  1.1079 +      }
  1.1080 +      if ((cellIndex.y > 0) && (childVis & TOP_VIS)) {
  1.1081 +        horBordersVis[cellIndex.y-1] = true;
  1.1082 +      }
  1.1083 +      // set the colors of borders that the child may affect
  1.1084 +      if (NO_COLOR == verBorderColors[cellIndex.x]) {
  1.1085 +        verBorderColors[cellIndex.x] = mChildBorderColors[childX].mRight;
  1.1086 +      }
  1.1087 +      if (NO_COLOR == horBorderColors[cellIndex.y]) {
  1.1088 +        horBorderColors[cellIndex.y] = mChildBorderColors[childX].mBottom;
  1.1089 +      }
  1.1090 +      if ((cellIndex.x > 0) && (NO_COLOR == verBorderColors[cellIndex.x-1])) {
  1.1091 +        verBorderColors[cellIndex.x-1] = mChildBorderColors[childX].mLeft;
  1.1092 +      }
  1.1093 +      if ((cellIndex.y > 0) && (NO_COLOR == horBorderColors[cellIndex.y-1])) {
  1.1094 +        horBorderColors[cellIndex.y-1] = mChildBorderColors[childX].mTop;
  1.1095 +      }
  1.1096 +    }
  1.1097 +    lastRow  = cellIndex.y;
  1.1098 +    lastCol  = cellIndex.x;
  1.1099 +    lastSize = size;
  1.1100 +    offset.x += size.width;
  1.1101 +    child = child->GetNextSibling();
  1.1102 +  }
  1.1103 +
  1.1104 +  if (firstTime) {
  1.1105 +    nscolor childColor;
  1.1106 +    // set the visibility, color, mouse sensitivity of borders
  1.1107 +    for (int verX = 0; verX < mNumCols-1; verX++) {
  1.1108 +      if (mVerBorders[verX]) {
  1.1109 +        mVerBorders[verX]->SetVisibility(verBordersVis[verX]);
  1.1110 +        if (mForceFrameResizability) {
  1.1111 +          mVerBorders[verX]->mVisibilityOverride = true;
  1.1112 +        } else {
  1.1113 +          SetBorderResize(mVerBorders[verX]);
  1.1114 +        }
  1.1115 +        childColor = (NO_COLOR == verBorderColors[verX]) ? borderColor : verBorderColors[verX];
  1.1116 +        mVerBorders[verX]->SetColor(childColor);
  1.1117 +      }
  1.1118 +    }
  1.1119 +    for (int horX = 0; horX < mNumRows-1; horX++) {
  1.1120 +      if (mHorBorders[horX]) {
  1.1121 +        mHorBorders[horX]->SetVisibility(horBordersVis[horX]);
  1.1122 +        if (mForceFrameResizability) {
  1.1123 +          mHorBorders[horX]->mVisibilityOverride = true;
  1.1124 +        } else {
  1.1125 +          SetBorderResize(mHorBorders[horX]);
  1.1126 +        }
  1.1127 +        childColor = (NO_COLOR == horBorderColors[horX]) ? borderColor : horBorderColors[horX];
  1.1128 +        mHorBorders[horX]->SetColor(childColor);
  1.1129 +      }
  1.1130 +    }
  1.1131 +
  1.1132 +    delete[] mChildFrameborder;
  1.1133 +    delete[] mChildBorderColors;
  1.1134 +
  1.1135 +    mChildFrameborder = nullptr;
  1.1136 +    mChildBorderColors = nullptr;
  1.1137 +  }
  1.1138 +
  1.1139 +  aStatus = NS_FRAME_COMPLETE;
  1.1140 +  mDrag.UnSet();
  1.1141 +
  1.1142 +  aDesiredSize.SetOverflowAreasToDesiredBounds();
  1.1143 +  FinishAndStoreOverflow(&aDesiredSize);
  1.1144 +
  1.1145 +  NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
  1.1146 +  return NS_OK;
  1.1147 +}
  1.1148 +
  1.1149 +nsIAtom*
  1.1150 +nsHTMLFramesetFrame::GetType() const
  1.1151 +{
  1.1152 +  return nsGkAtoms::frameSetFrame;
  1.1153 +}
  1.1154 +
  1.1155 +#ifdef DEBUG_FRAME_DUMP
  1.1156 +nsresult
  1.1157 +nsHTMLFramesetFrame::GetFrameName(nsAString& aResult) const
  1.1158 +{
  1.1159 +  return MakeFrameName(NS_LITERAL_STRING("Frameset"), aResult);
  1.1160 +}
  1.1161 +#endif
  1.1162 +
  1.1163 +bool
  1.1164 +nsHTMLFramesetFrame::IsLeaf() const
  1.1165 +{
  1.1166 +  // We handle constructing our kids manually
  1.1167 +  return true;
  1.1168 +}
  1.1169 +
  1.1170 +bool
  1.1171 +nsHTMLFramesetFrame::CanResize(bool aVertical,
  1.1172 +                               bool aLeft)
  1.1173 +{
  1.1174 +  int32_t childX;
  1.1175 +  int32_t startX;
  1.1176 +  if (aVertical) {
  1.1177 +    startX = (aLeft) ? 0 : mNumCols-1;
  1.1178 +    for (childX = startX; childX < mNonBorderChildCount; childX += mNumCols) {
  1.1179 +      if (!CanChildResize(aVertical, aLeft, childX)) {
  1.1180 +        return false;
  1.1181 +      }
  1.1182 +    }
  1.1183 +  } else {
  1.1184 +    startX = (aLeft) ? 0 : (mNumRows - 1) * mNumCols;
  1.1185 +    int32_t endX = startX + mNumCols;
  1.1186 +    for (childX = startX; childX < endX; childX++) {
  1.1187 +      if (!CanChildResize(aVertical, aLeft, childX)) {
  1.1188 +        return false;
  1.1189 +      }
  1.1190 +    }
  1.1191 +  }
  1.1192 +  return true;
  1.1193 +}
  1.1194 +
  1.1195 +bool
  1.1196 +nsHTMLFramesetFrame::GetNoResize(nsIFrame* aChildFrame)
  1.1197 +{
  1.1198 +  nsIContent* content = aChildFrame->GetContent();
  1.1199 +
  1.1200 +  return content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::noresize);
  1.1201 +}
  1.1202 +
  1.1203 +bool
  1.1204 +nsHTMLFramesetFrame::CanChildResize(bool aVertical, bool aLeft, int32_t aChildX)
  1.1205 +{
  1.1206 +  nsIFrame* child = mFrames.FrameAt(aChildX);
  1.1207 +  nsHTMLFramesetFrame* frameset = do_QueryFrame(child);
  1.1208 +  return frameset ? frameset->CanResize(aVertical, aLeft) : !GetNoResize(child);
  1.1209 +}
  1.1210 +
  1.1211 +// This calculates and sets the resizability of all border frames
  1.1212 +
  1.1213 +void
  1.1214 +nsHTMLFramesetFrame::RecalculateBorderResize()
  1.1215 +{
  1.1216 +  if (!mContent) {
  1.1217 +    return;
  1.1218 +  }
  1.1219 +
  1.1220 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT < INT32_MAX / NS_MAX_FRAMESET_SPEC_COUNT);
  1.1221 +  PR_STATIC_ASSERT(NS_MAX_FRAMESET_SPEC_COUNT
  1.1222 +                   < UINT_MAX / sizeof(int32_t) / NS_MAX_FRAMESET_SPEC_COUNT);
  1.1223 +  // set the visibility and mouse sensitivity of borders
  1.1224 +  int32_t verX;
  1.1225 +  for (verX = 0; verX < mNumCols-1; verX++) {
  1.1226 +    if (mVerBorders[verX]) {
  1.1227 +      mVerBorders[verX]->mCanResize = true;
  1.1228 +      if (mForceFrameResizability) {
  1.1229 +        mVerBorders[verX]->mVisibilityOverride = true;
  1.1230 +      } else {
  1.1231 +        mVerBorders[verX]->mVisibilityOverride = false;
  1.1232 +        SetBorderResize(mVerBorders[verX]);
  1.1233 +      }
  1.1234 +    }
  1.1235 +  }
  1.1236 +  int32_t horX;
  1.1237 +  for (horX = 0; horX < mNumRows-1; horX++) {
  1.1238 +    if (mHorBorders[horX]) {
  1.1239 +      mHorBorders[horX]->mCanResize = true;
  1.1240 +      if (mForceFrameResizability) {
  1.1241 +        mHorBorders[horX]->mVisibilityOverride = true;
  1.1242 +      } else {
  1.1243 +        mHorBorders[horX]->mVisibilityOverride = false;
  1.1244 +        SetBorderResize(mHorBorders[horX]);
  1.1245 +      }
  1.1246 +    }
  1.1247 +  }
  1.1248 +}
  1.1249 +
  1.1250 +void
  1.1251 +nsHTMLFramesetFrame::SetBorderResize(nsHTMLFramesetBorderFrame* aBorderFrame)
  1.1252 +{
  1.1253 +  if (aBorderFrame->mVertical) {
  1.1254 +    for (int rowX = 0; rowX < mNumRows; rowX++) {
  1.1255 +      int32_t childX = aBorderFrame->mPrevNeighbor + (rowX * mNumCols);
  1.1256 +      if (!CanChildResize(true, false, childX) ||
  1.1257 +          !CanChildResize(true, true, childX+1)) {
  1.1258 +        aBorderFrame->mCanResize = false;
  1.1259 +      }
  1.1260 +    }
  1.1261 +  } else {
  1.1262 +    int32_t childX = aBorderFrame->mPrevNeighbor * mNumCols;
  1.1263 +    int32_t endX   = childX + mNumCols;
  1.1264 +    for (; childX < endX; childX++) {
  1.1265 +      if (!CanChildResize(false, false, childX)) {
  1.1266 +        aBorderFrame->mCanResize = false;
  1.1267 +      }
  1.1268 +    }
  1.1269 +    endX = endX + mNumCols;
  1.1270 +    for (; childX < endX; childX++) {
  1.1271 +      if (!CanChildResize(false, true, childX)) {
  1.1272 +        aBorderFrame->mCanResize = false;
  1.1273 +      }
  1.1274 +    }
  1.1275 +  }
  1.1276 +}
  1.1277 +
  1.1278 +void
  1.1279 +nsHTMLFramesetFrame::StartMouseDrag(nsPresContext*             aPresContext,
  1.1280 +                                    nsHTMLFramesetBorderFrame* aBorder,
  1.1281 +                                    WidgetGUIEvent*            aEvent)
  1.1282 +{
  1.1283 +#if 0
  1.1284 +  int32_t index;
  1.1285 +  IndexOf(aBorder, index);
  1.1286 +  NS_ASSERTION((nullptr != aBorder) && (index >= 0), "invalid dragger");
  1.1287 +#endif
  1.1288 +
  1.1289 +  nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
  1.1290 +
  1.1291 +  mDragger = aBorder;
  1.1292 +
  1.1293 +  mFirstDragPoint = LayoutDeviceIntPoint::ToUntyped(aEvent->refPoint);
  1.1294 +
  1.1295 +  // Store the original frame sizes
  1.1296 +  if (mDragger->mVertical) {
  1.1297 +    mPrevNeighborOrigSize = mColSizes[mDragger->mPrevNeighbor];
  1.1298 +    mNextNeighborOrigSize = mColSizes[mDragger->mNextNeighbor];
  1.1299 +  } else {
  1.1300 +    mPrevNeighborOrigSize = mRowSizes[mDragger->mPrevNeighbor];
  1.1301 +    mNextNeighborOrigSize = mRowSizes[mDragger->mNextNeighbor];
  1.1302 +  }
  1.1303 +
  1.1304 +  gDragInProgress = true;
  1.1305 +}
  1.1306 +
  1.1307 +
  1.1308 +void
  1.1309 +nsHTMLFramesetFrame::MouseDrag(nsPresContext* aPresContext,
  1.1310 +                               WidgetGUIEvent* aEvent)
  1.1311 +{
  1.1312 +  // if the capture ended, reset the drag state
  1.1313 +  if (nsIPresShell::GetCapturingContent() != GetContent()) {
  1.1314 +    mDragger = nullptr;
  1.1315 +    gDragInProgress = false;
  1.1316 +    return;
  1.1317 +  }
  1.1318 +
  1.1319 +  int32_t change; // measured positive from left-to-right or top-to-bottom
  1.1320 +  nsWeakFrame weakFrame(this);
  1.1321 +  if (mDragger->mVertical) {
  1.1322 +    change = aPresContext->DevPixelsToAppUnits(aEvent->refPoint.x - mFirstDragPoint.x);
  1.1323 +    if (change > mNextNeighborOrigSize - mMinDrag) {
  1.1324 +      change = mNextNeighborOrigSize - mMinDrag;
  1.1325 +    } else if (change <= mMinDrag - mPrevNeighborOrigSize) {
  1.1326 +      change = mMinDrag - mPrevNeighborOrigSize;
  1.1327 +    }
  1.1328 +    mColSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change;
  1.1329 +    mColSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change;
  1.1330 +
  1.1331 +    if (change != 0) {
  1.1332 +      // Recompute the specs from the new sizes.
  1.1333 +      nscoord width = mRect.width - (mNumCols - 1) * GetBorderWidth(aPresContext, true);
  1.1334 +      HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent);
  1.1335 +      NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
  1.1336 +      const nsFramesetSpec* colSpecs = nullptr;
  1.1337 +      ourContent->GetColSpec(&mNumCols, &colSpecs);
  1.1338 +      nsAutoString newColAttr;
  1.1339 +      GenerateRowCol(aPresContext, width, mNumCols, colSpecs, mColSizes,
  1.1340 +                     newColAttr);
  1.1341 +      // Setting the attr will trigger a reflow
  1.1342 +      mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::cols, newColAttr, true);
  1.1343 +    }
  1.1344 +  } else {
  1.1345 +    change = aPresContext->DevPixelsToAppUnits(aEvent->refPoint.y - mFirstDragPoint.y);
  1.1346 +    if (change > mNextNeighborOrigSize - mMinDrag) {
  1.1347 +      change = mNextNeighborOrigSize - mMinDrag;
  1.1348 +    } else if (change <= mMinDrag - mPrevNeighborOrigSize) {
  1.1349 +      change = mMinDrag - mPrevNeighborOrigSize;
  1.1350 +    }
  1.1351 +    mRowSizes[mDragger->mPrevNeighbor] = mPrevNeighborOrigSize + change;
  1.1352 +    mRowSizes[mDragger->mNextNeighbor] = mNextNeighborOrigSize - change;
  1.1353 +
  1.1354 +    if (change != 0) {
  1.1355 +      // Recompute the specs from the new sizes.
  1.1356 +      nscoord height = mRect.height - (mNumRows - 1) * GetBorderWidth(aPresContext, true);
  1.1357 +      HTMLFrameSetElement* ourContent = HTMLFrameSetElement::FromContent(mContent);
  1.1358 +      NS_ASSERTION(ourContent, "Someone gave us a broken frameset element!");
  1.1359 +      const nsFramesetSpec* rowSpecs = nullptr;
  1.1360 +      ourContent->GetRowSpec(&mNumRows, &rowSpecs);
  1.1361 +      nsAutoString newRowAttr;
  1.1362 +      GenerateRowCol(aPresContext, height, mNumRows, rowSpecs, mRowSizes,
  1.1363 +                     newRowAttr);
  1.1364 +      // Setting the attr will trigger a reflow
  1.1365 +      mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::rows, newRowAttr, true);
  1.1366 +    }
  1.1367 +  }
  1.1368 +
  1.1369 +  ENSURE_TRUE(weakFrame.IsAlive());
  1.1370 +  if (change != 0) {
  1.1371 +    mDrag.Reset(mDragger->mVertical, mDragger->mPrevNeighbor, change, this);
  1.1372 +  }
  1.1373 +}
  1.1374 +
  1.1375 +void
  1.1376 +nsHTMLFramesetFrame::EndMouseDrag(nsPresContext* aPresContext)
  1.1377 +{
  1.1378 +  nsIPresShell::SetCapturingContent(nullptr, 0);
  1.1379 +  mDragger = nullptr;
  1.1380 +  gDragInProgress = false;
  1.1381 +}
  1.1382 +
  1.1383 +nsIFrame*
  1.1384 +NS_NewHTMLFramesetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  1.1385 +{
  1.1386 +#ifdef DEBUG
  1.1387 +  const nsStyleDisplay* disp = aContext->StyleDisplay();
  1.1388 +  NS_ASSERTION(!disp->IsAbsolutelyPositionedStyle() && !disp->IsFloatingStyle(),
  1.1389 +               "Framesets should not be positioned and should not float");
  1.1390 +#endif
  1.1391 +
  1.1392 +  return new (aPresShell) nsHTMLFramesetFrame(aContext);
  1.1393 +}
  1.1394 +
  1.1395 +NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetFrame)
  1.1396 +
  1.1397 +/*******************************************************************************
  1.1398 + * nsHTMLFramesetBorderFrame
  1.1399 + ******************************************************************************/
  1.1400 +nsHTMLFramesetBorderFrame::nsHTMLFramesetBorderFrame(nsStyleContext* aContext,
  1.1401 +                                                     int32_t aWidth,
  1.1402 +                                                     bool    aVertical,
  1.1403 +                                                     bool    aVisibility)
  1.1404 +  : nsLeafFrame(aContext), mWidth(aWidth), mVertical(aVertical), mVisibility(aVisibility)
  1.1405 +{
  1.1406 +   mVisibilityOverride = false;
  1.1407 +   mCanResize    = true;
  1.1408 +   mColor        = NO_COLOR;
  1.1409 +   mPrevNeighbor = 0;
  1.1410 +   mNextNeighbor = 0;
  1.1411 +}
  1.1412 +
  1.1413 +nsHTMLFramesetBorderFrame::~nsHTMLFramesetBorderFrame()
  1.1414 +{
  1.1415 +  //printf("nsHTMLFramesetBorderFrame destructor %p \n", this);
  1.1416 +}
  1.1417 +
  1.1418 +NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetBorderFrame)
  1.1419 +
  1.1420 +nscoord nsHTMLFramesetBorderFrame::GetIntrinsicWidth()
  1.1421 +{
  1.1422 +  // No intrinsic width
  1.1423 +  return 0;
  1.1424 +}
  1.1425 +
  1.1426 +nscoord nsHTMLFramesetBorderFrame::GetIntrinsicHeight()
  1.1427 +{
  1.1428 +  // No intrinsic height
  1.1429 +  return 0;
  1.1430 +}
  1.1431 +
  1.1432 +void nsHTMLFramesetBorderFrame::SetVisibility(bool aVisibility)
  1.1433 +{
  1.1434 +  mVisibility = aVisibility;
  1.1435 +}
  1.1436 +
  1.1437 +void nsHTMLFramesetBorderFrame::SetColor(nscolor aColor)
  1.1438 +{
  1.1439 +  mColor = aColor;
  1.1440 +}
  1.1441 +
  1.1442 +
  1.1443 +nsresult
  1.1444 +nsHTMLFramesetBorderFrame::Reflow(nsPresContext*           aPresContext,
  1.1445 +                                  nsHTMLReflowMetrics&     aDesiredSize,
  1.1446 +                                  const nsHTMLReflowState& aReflowState,
  1.1447 +                                  nsReflowStatus&          aStatus)
  1.1448 +{
  1.1449 +  DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame");
  1.1450 +  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
  1.1451 +
  1.1452 +  // Override Reflow(), since we don't want to deal with what our
  1.1453 +  // computed values are.
  1.1454 +  SizeToAvailSize(aReflowState, aDesiredSize);
  1.1455 +
  1.1456 +  aDesiredSize.SetOverflowAreasToDesiredBounds();
  1.1457 +  aStatus = NS_FRAME_COMPLETE;
  1.1458 +  return NS_OK;
  1.1459 +}
  1.1460 +
  1.1461 +class nsDisplayFramesetBorder : public nsDisplayItem {
  1.1462 +public:
  1.1463 +  nsDisplayFramesetBorder(nsDisplayListBuilder* aBuilder,
  1.1464 +                          nsHTMLFramesetBorderFrame* aFrame)
  1.1465 +    : nsDisplayItem(aBuilder, aFrame) {
  1.1466 +    MOZ_COUNT_CTOR(nsDisplayFramesetBorder);
  1.1467 +  }
  1.1468 +#ifdef NS_BUILD_REFCNT_LOGGING
  1.1469 +  virtual ~nsDisplayFramesetBorder() {
  1.1470 +    MOZ_COUNT_DTOR(nsDisplayFramesetBorder);
  1.1471 +  }
  1.1472 +#endif
  1.1473 +
  1.1474 +  // REVIEW: see old GetFrameForPoint
  1.1475 +  // Receives events in its bounds
  1.1476 +  virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
  1.1477 +                       HitTestState* aState,
  1.1478 +                       nsTArray<nsIFrame*> *aOutFrames) MOZ_OVERRIDE {
  1.1479 +    aOutFrames->AppendElement(mFrame);
  1.1480 +  }
  1.1481 +  virtual void Paint(nsDisplayListBuilder* aBuilder,
  1.1482 +                     nsRenderingContext* aCtx) MOZ_OVERRIDE;
  1.1483 +  NS_DISPLAY_DECL_NAME("FramesetBorder", TYPE_FRAMESET_BORDER)
  1.1484 +};
  1.1485 +
  1.1486 +void nsDisplayFramesetBorder::Paint(nsDisplayListBuilder* aBuilder,
  1.1487 +                                    nsRenderingContext* aCtx)
  1.1488 +{
  1.1489 +  static_cast<nsHTMLFramesetBorderFrame*>(mFrame)->
  1.1490 +    PaintBorder(*aCtx, ToReferenceFrame());
  1.1491 +}
  1.1492 +
  1.1493 +void
  1.1494 +nsHTMLFramesetBorderFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
  1.1495 +                                            const nsRect&           aDirtyRect,
  1.1496 +                                            const nsDisplayListSet& aLists)
  1.1497 +{
  1.1498 +  aLists.Content()->AppendNewToTop(
  1.1499 +    new (aBuilder) nsDisplayFramesetBorder(aBuilder, this));
  1.1500 +}
  1.1501 +
  1.1502 +void nsHTMLFramesetBorderFrame::PaintBorder(nsRenderingContext& aRenderingContext,
  1.1503 +                                            nsPoint aPt)
  1.1504 +{
  1.1505 +  nscolor WHITE    = NS_RGB(255, 255, 255);
  1.1506 +
  1.1507 +  nscolor bgColor =
  1.1508 +    LookAndFeel::GetColor(LookAndFeel::eColorID_WidgetBackground,
  1.1509 +                          NS_RGB(200,200,200));
  1.1510 +  nscolor fgColor =
  1.1511 +    LookAndFeel::GetColor(LookAndFeel::eColorID_WidgetForeground,
  1.1512 +                          NS_RGB(0,0,0));
  1.1513 +  nscolor hltColor =
  1.1514 +    LookAndFeel::GetColor(LookAndFeel::eColorID_Widget3DHighlight,
  1.1515 +                          NS_RGB(255,255,255));
  1.1516 +  nscolor sdwColor =
  1.1517 +    LookAndFeel::GetColor(LookAndFeel::eColorID_Widget3DShadow,
  1.1518 +                          NS_RGB(128,128,128));
  1.1519 +
  1.1520 +  nsRenderingContext::AutoPushTranslation
  1.1521 +    translate(&aRenderingContext, aPt);
  1.1522 +
  1.1523 +  nscoord widthInPixels = nsPresContext::AppUnitsToIntCSSPixels(mWidth);
  1.1524 +  nscoord pixelWidth    = nsPresContext::CSSPixelsToAppUnits(1);
  1.1525 +
  1.1526 +  if (widthInPixels <= 0)
  1.1527 +    return;
  1.1528 +
  1.1529 +  nsPoint start(0,0);
  1.1530 +  nsPoint end((mVertical) ? 0 : mRect.width, (mVertical) ? mRect.height : 0);
  1.1531 +
  1.1532 +  nscolor color = WHITE;
  1.1533 +  if (mVisibility || mVisibilityOverride) {
  1.1534 +    color = (NO_COLOR == mColor) ? bgColor : mColor;
  1.1535 +  }
  1.1536 +  aRenderingContext.SetColor(color);
  1.1537 +  // draw grey or white first
  1.1538 +  for (int i = 0; i < widthInPixels; i++) {
  1.1539 +    aRenderingContext.DrawLine (start, end);
  1.1540 +    if (mVertical) {
  1.1541 +      start.x += pixelWidth;
  1.1542 +      end.x =  start.x;
  1.1543 +    } else {
  1.1544 +      start.y += pixelWidth;
  1.1545 +      end.y =  start.y;
  1.1546 +    }
  1.1547 +  }
  1.1548 +
  1.1549 +  if (!mVisibility && !mVisibilityOverride)
  1.1550 +    return;
  1.1551 +
  1.1552 +  if (widthInPixels >= 5) {
  1.1553 +    aRenderingContext.SetColor(hltColor);
  1.1554 +    start.x = (mVertical) ? pixelWidth : 0;
  1.1555 +    start.y = (mVertical) ? 0 : pixelWidth;
  1.1556 +    end.x   = (mVertical) ? start.x : mRect.width;
  1.1557 +    end.y   = (mVertical) ? mRect.height : start.y;
  1.1558 +    aRenderingContext.DrawLine(start, end);
  1.1559 +  }
  1.1560 +
  1.1561 +  if (widthInPixels >= 2) {
  1.1562 +    aRenderingContext.SetColor(sdwColor);
  1.1563 +    start.x = (mVertical) ? mRect.width - (2 * pixelWidth) : 0;
  1.1564 +    start.y = (mVertical) ? 0 : mRect.height - (2 * pixelWidth);
  1.1565 +    end.x   = (mVertical) ? start.x : mRect.width;
  1.1566 +    end.y   = (mVertical) ? mRect.height : start.y;
  1.1567 +    aRenderingContext.DrawLine(start, end);
  1.1568 +  }
  1.1569 +
  1.1570 +  if (widthInPixels >= 1) {
  1.1571 +    aRenderingContext.SetColor(fgColor);
  1.1572 +    start.x = (mVertical) ? mRect.width - pixelWidth : 0;
  1.1573 +    start.y = (mVertical) ? 0 : mRect.height - pixelWidth;
  1.1574 +    end.x   = (mVertical) ? start.x : mRect.width;
  1.1575 +    end.y   = (mVertical) ? mRect.height : start.y;
  1.1576 +    aRenderingContext.DrawLine(start, end);
  1.1577 +  }
  1.1578 +}
  1.1579 +
  1.1580 +
  1.1581 +nsresult
  1.1582 +nsHTMLFramesetBorderFrame::HandleEvent(nsPresContext* aPresContext,
  1.1583 +                                       WidgetGUIEvent* aEvent,
  1.1584 +                                       nsEventStatus* aEventStatus)
  1.1585 +{
  1.1586 +  NS_ENSURE_ARG_POINTER(aEventStatus);
  1.1587 +  *aEventStatus = nsEventStatus_eIgnore;
  1.1588 +
  1.1589 +  //XXX Mouse setting logic removed.  The remaining logic should also move.
  1.1590 +  if (!mCanResize) {
  1.1591 +    return NS_OK;
  1.1592 +  }
  1.1593 +
  1.1594 +  if (aEvent->message == NS_MOUSE_BUTTON_DOWN &&
  1.1595 +      aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
  1.1596 +    nsHTMLFramesetFrame* parentFrame = do_QueryFrame(GetParent());
  1.1597 +    if (parentFrame) {
  1.1598 +      parentFrame->StartMouseDrag(aPresContext, this, aEvent);
  1.1599 +      *aEventStatus = nsEventStatus_eConsumeNoDefault;
  1.1600 +    }
  1.1601 +  }
  1.1602 +  return NS_OK;
  1.1603 +}
  1.1604 +
  1.1605 +nsresult
  1.1606 +nsHTMLFramesetBorderFrame::GetCursor(const nsPoint&    aPoint,
  1.1607 +                                     nsIFrame::Cursor& aCursor)
  1.1608 +{
  1.1609 +  if (!mCanResize) {
  1.1610 +    aCursor.mCursor = NS_STYLE_CURSOR_DEFAULT;
  1.1611 +  } else {
  1.1612 +    aCursor.mCursor = (mVertical) ? NS_STYLE_CURSOR_EW_RESIZE : NS_STYLE_CURSOR_NS_RESIZE;
  1.1613 +  }
  1.1614 +  return NS_OK;
  1.1615 +}
  1.1616 +
  1.1617 +#ifdef DEBUG_FRAME_DUMP
  1.1618 +nsresult nsHTMLFramesetBorderFrame::GetFrameName(nsAString& aResult) const
  1.1619 +{
  1.1620 +  return MakeFrameName(NS_LITERAL_STRING("FramesetBorder"), aResult);
  1.1621 +}
  1.1622 +#endif
  1.1623 +
  1.1624 +/*******************************************************************************
  1.1625 + * nsHTMLFramesetBlankFrame
  1.1626 + ******************************************************************************/
  1.1627 +
  1.1628 +NS_QUERYFRAME_HEAD(nsHTMLFramesetBlankFrame)
  1.1629 +  NS_QUERYFRAME_ENTRY(nsHTMLFramesetBlankFrame)
  1.1630 +NS_QUERYFRAME_TAIL_INHERITING(nsLeafFrame)
  1.1631 +
  1.1632 +NS_IMPL_FRAMEARENA_HELPERS(nsHTMLFramesetBlankFrame)
  1.1633 +
  1.1634 +nsHTMLFramesetBlankFrame::~nsHTMLFramesetBlankFrame()
  1.1635 +{
  1.1636 +  //printf("nsHTMLFramesetBlankFrame destructor %p \n", this);
  1.1637 +}
  1.1638 +
  1.1639 +nscoord nsHTMLFramesetBlankFrame::GetIntrinsicWidth()
  1.1640 +{
  1.1641 +  // No intrinsic width
  1.1642 +  return 0;
  1.1643 +}
  1.1644 +
  1.1645 +nscoord nsHTMLFramesetBlankFrame::GetIntrinsicHeight()
  1.1646 +{
  1.1647 +  // No intrinsic height
  1.1648 +  return 0;
  1.1649 +}
  1.1650 +
  1.1651 +nsresult
  1.1652 +nsHTMLFramesetBlankFrame::Reflow(nsPresContext*           aPresContext,
  1.1653 +                                 nsHTMLReflowMetrics&     aDesiredSize,
  1.1654 +                                 const nsHTMLReflowState& aReflowState,
  1.1655 +                                 nsReflowStatus&          aStatus)
  1.1656 +{
  1.1657 +  DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame");
  1.1658 +
  1.1659 +  // Override Reflow(), since we don't want to deal with what our
  1.1660 +  // computed values are.
  1.1661 +  SizeToAvailSize(aReflowState, aDesiredSize);
  1.1662 +
  1.1663 +  aDesiredSize.SetOverflowAreasToDesiredBounds();
  1.1664 +  aStatus = NS_FRAME_COMPLETE;
  1.1665 +  return NS_OK;
  1.1666 +}
  1.1667 +
  1.1668 +class nsDisplayFramesetBlank : public nsDisplayItem {
  1.1669 +public:
  1.1670 +  nsDisplayFramesetBlank(nsDisplayListBuilder* aBuilder,
  1.1671 +                         nsIFrame* aFrame) :
  1.1672 +    nsDisplayItem(aBuilder, aFrame) {
  1.1673 +    MOZ_COUNT_CTOR(nsDisplayFramesetBlank);
  1.1674 +  }
  1.1675 +#ifdef NS_BUILD_REFCNT_LOGGING
  1.1676 +  virtual ~nsDisplayFramesetBlank() {
  1.1677 +    MOZ_COUNT_DTOR(nsDisplayFramesetBlank);
  1.1678 +  }
  1.1679 +#endif
  1.1680 +
  1.1681 +  virtual void Paint(nsDisplayListBuilder* aBuilder,
  1.1682 +                     nsRenderingContext* aCtx) MOZ_OVERRIDE;
  1.1683 +  NS_DISPLAY_DECL_NAME("FramesetBlank", TYPE_FRAMESET_BLANK)
  1.1684 +};
  1.1685 +
  1.1686 +void nsDisplayFramesetBlank::Paint(nsDisplayListBuilder* aBuilder,
  1.1687 +                                   nsRenderingContext* aCtx)
  1.1688 +{
  1.1689 +  nscolor white = NS_RGB(255,255,255);
  1.1690 +  aCtx->SetColor(white);
  1.1691 +  aCtx->FillRect(mVisibleRect);
  1.1692 +}
  1.1693 +
  1.1694 +void
  1.1695 +nsHTMLFramesetBlankFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
  1.1696 +                                           const nsRect&           aDirtyRect,
  1.1697 +                                           const nsDisplayListSet& aLists)
  1.1698 +{
  1.1699 +  aLists.Content()->AppendNewToTop(
  1.1700 +    new (aBuilder) nsDisplayFramesetBlank(aBuilder, this));
  1.1701 +}

mercurial