bool
nsCSSCompressedDataBlock::HasDefaultBorderImageOutset() const
{
  const nsCSSRect &outset =
    ValueFor(eCSSProperty_border_image_outset)->GetRectValue();
  return outset.AllSidesEqualTo(nsCSSValue(0.0f, eCSSUnit_Number));
}
bool
nsCSSCompressedDataBlock::HasDefaultBorderImageWidth() const
{
  const nsCSSRect &width =
    ValueFor(eCSSProperty_border_image_width)->GetRectValue();
  return width.AllSidesEqualTo(nsCSSValue(1.0f, eCSSUnit_Number));
}
bool
nsCSSCompressedDataBlock::HasDefaultBorderImageRepeat() const
{
  const nsCSSValuePair &repeat =
    ValueFor(eCSSProperty_border_image_repeat)->GetPairValue();
  return repeat.BothValuesEqualTo(
    nsCSSValue(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH, eCSSUnit_Enumerated));
}
bool
nsCSSCompressedDataBlock::HasDefaultBorderImageSlice() const
{
  const nsCSSValueList *slice =
    ValueFor(eCSSProperty_border_image_slice)->GetListValue();
  return !slice->mNext &&
         slice->mValue.GetRectValue().AllSidesEqualTo(
           nsCSSValue(1.0f, eCSSUnit_Percent));
}
bool
nsCSSCompressedDataBlock::TryReplaceValue(nsCSSProperty aProperty,
                                          nsCSSExpandedDataBlock& aFromBlock,
                                          bool *aChanged)
{
    nsCSSValue* newValue = aFromBlock.PropertyAt(aProperty);
    NS_ABORT_IF_FALSE(newValue && newValue->GetUnit() != eCSSUnit_Null,
                      "cannot replace with empty value");

    const nsCSSValue* oldValue = ValueFor(aProperty);
    if (!oldValue) {
        *aChanged = false;
        return false;
    }

    *aChanged = MoveValue(newValue, const_cast<nsCSSValue*>(oldValue));
    aFromBlock.ClearPropertyBit(aProperty);
    return true;
}
void
BChannelSlider::_DrawThumbs()
{
	if (fBacking == NULL) {
		// This is the idea: we build a bitmap by taking the coordinates
		// of the first and last thumb frames (top/left and bottom/right)
		BRect first = ThumbFrameFor(0);
		BRect last = ThumbFrameFor(CountChannels() - 1);
		BRect rect(first.LeftTop(), last.RightBottom());

		if (fIsVertical)
			rect.top -= ThumbRangeFor(0);
		else
			rect.right += ThumbRangeFor(0);

		rect.OffsetTo(B_ORIGIN);
		fBacking = new (std::nothrow) BBitmap(rect, B_RGB32, true);
		if (fBacking) {
			fBackingView = new (std::nothrow) BView(rect, "", 0, B_WILL_DRAW);
			if (fBackingView) {
				if (fBacking->Lock()) {
					fBacking->AddChild(fBackingView);
					fBackingView->SetFontSize(10.0);
					fBackingView->SetLowColor(
						ui_color(B_PANEL_BACKGROUND_COLOR));
					fBackingView->SetViewColor(
						ui_color(B_PANEL_BACKGROUND_COLOR));
					fBacking->Unlock();
				}
			} else {
				delete fBacking;
				fBacking = NULL;
			}
		}
	}

	if (fBacking && fBackingView) {
		BPoint drawHere;

		BRect bounds(fBacking->Bounds());
		drawHere.x = (Bounds().Width() - bounds.Width()) / 2.0;
		drawHere.y = (Bounds().Height() - bounds.Height()) - kPadding
			- fLineFeed;

		if (fBacking->Lock()) {
			// Clear the view's background
			fBackingView->FillRect(fBackingView->Bounds(), B_SOLID_LOW);

			BRect channelArea;
			// draw the entire control
			for (int32 channel = 0; channel < CountChannels(); channel++) {
				channelArea = ThumbFrameFor(channel);
				bool pressed = IsTracking()
					&& (channel == fCurrentChannel || fAllChannels);
				DrawChannel(fBackingView, channel, channelArea, pressed);
			}

			// draw some kind of current value tool tip
			if (fCurrentChannel != -1 && fMinPoint != 0) {
				char valueString[32];
				snprintf(valueString, 32, "%ld", ValueFor(fCurrentChannel));
				float stringWidth = fBackingView->StringWidth(valueString);
				float width = max_c(10.0, stringWidth);
				BRect valueRect(0.0, 0.0, width, 10.0);

				BRect thumbFrame(ThumbFrameFor(fCurrentChannel));
				float thumbDelta(ThumbDeltaFor(fCurrentChannel));

				if (fIsVertical) {
					valueRect.OffsetTo((thumbFrame.Width() - width) / 2.0
						+ fCurrentChannel * thumbFrame.Width(),
						thumbDelta + thumbFrame.Height() + 2.0);
					if (valueRect.bottom > fBackingView->Frame().bottom)
						valueRect.OffsetBy(0.0, -(thumbFrame.Height() + 12.0));
				} else {
					valueRect.OffsetTo((thumbDelta - (width + 2.0)),
						thumbFrame.top);
					if (valueRect.left < fBackingView->Frame().left) {
						valueRect.OffsetBy(thumbFrame.Width() + width + 2.0,
							0.0);
					}
				}

				rgb_color oldColor = fBackingView->HighColor();
				fBackingView->SetHighColor(255, 255, 172);
				fBackingView->FillRect(valueRect);
				fBackingView->SetHighColor(0, 0, 0);
				fBackingView->DrawString(valueString, BPoint(valueRect.left
					+ (valueRect.Width() - stringWidth) / 2.0, valueRect.bottom
					- 1.0));
				fBackingView->StrokeRect(valueRect.InsetByCopy(-0.5, -0.5));
				fBackingView->SetHighColor(oldColor);
			}

			fBackingView->Sync();
			fBacking->Unlock();
		}

		DrawBitmapAsync(fBacking, drawHere);

		// fClickDelta is used in MouseMoved()
		fClickDelta = drawHere;
	}
}
void
BChannelSlider::MouseDown(BPoint where)
{
	if (!IsEnabled())
		BControl::MouseDown(where);
	else {
		fCurrentChannel = -1;
		fMinPoint = 0;

		// Search the channel on which the mouse was over
		int32 numChannels = CountChannels();
		for (int32 channel = 0; channel < numChannels; channel++) {
			BRect frame = ThumbFrameFor(channel);
			frame.OffsetBy(fClickDelta);

			float range = ThumbRangeFor(channel);
			if (fIsVertical) {
				fMinPoint = frame.top + frame.Height() / 2;
				frame.bottom += range;
			} else {
				// TODO: Fix this, the clickzone isn't perfect
				frame.right += range;
				fMinPoint = frame.Width();
			}

			// Click was on a slider.
			if (frame.Contains(where)) {
				fCurrentChannel = channel;
				SetCurrentChannel(channel);
				break;
			}
		}

		// Click wasn't on a slider. Bail out.
		if (fCurrentChannel == -1)
			return;

		uint32 buttons = 0;
		BMessage* currentMessage = Window()->CurrentMessage();
		if (currentMessage != NULL)
			currentMessage->FindInt32("buttons", (int32*)&buttons);

		fAllChannels = (buttons & B_SECONDARY_MOUSE_BUTTON) == 0;

		if (fInitialValues != NULL && fAllChannels) {
			delete[] fInitialValues;
			fInitialValues = NULL;
		}

		if (fInitialValues == NULL)
			fInitialValues = new (std::nothrow) int32[numChannels];

		if (fInitialValues) {
			if (fAllChannels) {
				for (int32 i = 0; i < numChannels; i++)
					fInitialValues[i] = ValueFor(i);
			} else {
				fInitialValues[fCurrentChannel] = ValueFor(fCurrentChannel);
			}
		}

		if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
			if (!IsTracking()) {
				SetTracking(true);
				_DrawThumbs();
				Flush();
			}

			_MouseMovedCommon(where, B_ORIGIN);
			SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS |
				B_NO_POINTER_HISTORY);
		} else {
			do {
				snooze(30000);
				GetMouse(&where, &buttons);
				_MouseMovedCommon(where, B_ORIGIN);
			} while (buttons != 0);
			_FinishChange();
			fCurrentChannel = -1;
			fAllChannels = false;
		}
	}
}