void
nsScrollbarButtonFrame::DoButtonAction(PRBool aSmoothScroll) 
{
  // get the scrollbar control
  nsIFrame* scrollbar;
  GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);

  if (scrollbar == nsnull)
    return;

  // get the scrollbars content node
  nsCOMPtr<nsIContent> content = scrollbar->GetContent();

  // get the current pos
  PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
  PRInt32 oldpos = curpos;

  // get the max pos
  PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);

  // increment the given amount
  if (mIncrement)
    curpos += mIncrement;

  // make sure the current position is between the current and max positions
  if (curpos < 0)
    curpos = 0;
  else if (curpos > maxpos)
    curpos = maxpos;

  nsIScrollbarFrame* sb;
  CallQueryInterface(scrollbar, &sb);
  if (sb) {
    nsIScrollbarMediator* m = sb->GetScrollbarMediator();
    if (m) {
      m->ScrollbarButtonPressed(sb, oldpos, curpos);
      return;
    }
  }

  // set the current position of the slider.
  nsAutoString curposStr;
  curposStr.AppendInt(curpos);

  if (aSmoothScroll)
    content->SetAttr(kNameSpaceID_None, nsGkAtoms::smooth, NS_LITERAL_STRING("true"), PR_FALSE);
  content->SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, curposStr, PR_TRUE);
  if (aSmoothScroll)
    content->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, PR_FALSE);
}
PRBool
nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext, 
                                          nsGUIEvent*     aEvent,
                                          nsEventStatus*  aEventStatus)
{
  // Get the desired action for the scrollbar button.
  nsILookAndFeel::nsMetricID tmpAction;
  if (aEvent->eventStructType == NS_MOUSE_EVENT &&
      aEvent->message == NS_MOUSE_BUTTON_DOWN) {
    PRUint16 button = static_cast<nsMouseEvent*>(aEvent)->button;
    if (button == nsMouseEvent::eLeftButton) {
      tmpAction = nsILookAndFeel::eMetric_ScrollButtonLeftMouseButtonAction;
    } else if (button == nsMouseEvent::eMiddleButton) {
      tmpAction = nsILookAndFeel::eMetric_ScrollButtonMiddleMouseButtonAction;
    } else if (button == nsMouseEvent::eRightButton) {
      tmpAction = nsILookAndFeel::eMetric_ScrollButtonRightMouseButtonAction;
    } else {
      return PR_FALSE;
    }
  } else {
    return PR_FALSE;
  }

  // Get the button action metric from the pres. shell.
  PRInt32 pressedButtonAction;
  if (NS_FAILED(aPresContext->LookAndFeel()->GetMetric(tmpAction,
                                                       pressedButtonAction)))
    return PR_FALSE;

  // get the scrollbar control
  nsIFrame* scrollbar;
  GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);

  if (scrollbar == nsnull)
    return PR_FALSE;

  // get the scrollbars content node
  nsIContent* content = scrollbar->GetContent();

  static nsIContent::AttrValuesArray strings[] = { &nsGkAtoms::increment,
                                                   &nsGkAtoms::decrement,
                                                   nsnull };
  PRInt32 index = mContent->FindAttrValueIn(kNameSpaceID_None,
                                            nsGkAtoms::type,
                                            strings, eCaseMatters);
  PRInt32 direction;
  if (index == 0) 
    direction = 1;
  else if (index == 1)
    direction = -1;
  else
    return PR_FALSE;

  // Whether or not to repeat the click action.
  PRBool repeat = PR_TRUE;
  // Use smooth scrolling by default.
  PRBool smoothScroll = PR_TRUE;
  switch (pressedButtonAction) {
    case 0:
      mIncrement = direction * nsSliderFrame::GetIncrement(content);
      break;
    case 1:
      mIncrement = direction * nsSliderFrame::GetPageIncrement(content);
      break;
    case 2:
      if (direction == -1)
        mIncrement = -nsSliderFrame::GetCurrentPosition(content);
      else
        mIncrement = nsSliderFrame::GetMaxPosition(content) - 
                     nsSliderFrame::GetCurrentPosition(content);
      // Don't repeat or use smooth scrolling if scrolling to beginning or end
      // of a page.
      repeat = smoothScroll = PR_FALSE;
      break;
    case 3:
    default:
      // We were told to ignore this click, or someone assigned a non-standard
      // value to the button's action.
      return PR_FALSE;
  }
  // set this attribute so we can style it later
  nsWeakFrame weakFrame(this);
  mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), PR_TRUE);

  if (weakFrame.IsAlive()) {
    DoButtonAction(smoothScroll);
  }
  if (repeat)
    StartRepeat();
  return PR_TRUE;
}
void
nsScrollbarButtonFrame::MouseClicked() 
{
   // when we are clicked either increment or decrement the slider position.

   // get the scrollbar control
   nsIFrame* scrollbar;
   GetParentWithTag(nsXULAtoms::scrollbar, this, scrollbar);

   if (scrollbar == nsnull)
       return;

   // get the scrollbars content node
   nsCOMPtr<nsIContent> content = scrollbar->GetContent();

   // get the current pos
   PRInt32 curpos = nsSliderFrame::GetCurrentPosition(content);
   PRInt32 oldpos = curpos;

   // get the max pos
   PRInt32 maxpos = nsSliderFrame::GetMaxPosition(content);

   // get the increment amount
   PRInt32 increment = nsSliderFrame::GetIncrement(content);
#ifdef MOZ_WIDGET_COCOA
   // Emulate the Mac IE behavior of scrolling 2 lines instead of 1
   // on a button press.  This makes scrolling appear smoother and
   // keeps us competitive with IE.
   increment *= 2;
#endif

   nsString value;
   if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type, value))
   {
     // if our class is DecrementButton subtract the current pos by increment amount
     // if our class is IncrementButton increment the current pos by the decrement amount
     if (value.EqualsLiteral("decrement"))
         curpos -= increment;
     else if (value.EqualsLiteral("increment"))
         curpos += increment;

      // make sure the current positon is between the current and max positions
    if (curpos < 0)
       curpos = 0;
    else if (curpos > maxpos)
       curpos = maxpos;

    nsCOMPtr<nsIScrollbarFrame> sb(do_QueryInterface(scrollbar));
    if (sb) {
      nsCOMPtr<nsIScrollbarMediator> m;
      sb->GetScrollbarMediator(getter_AddRefs(m));
      if (m) {
        m->ScrollbarButtonPressed(sb, oldpos, curpos);
        return;
      }
    }

    // set the current position of the slider.
    nsAutoString curposStr;
    curposStr.AppendInt(curpos);

    content->SetAttr(kNameSpaceID_None, nsXULAtoms::smooth, NS_LITERAL_STRING("true"), PR_FALSE);
    content->SetAttr(kNameSpaceID_None, nsXULAtoms::curpos, curposStr, PR_TRUE);
    content->UnsetAttr(kNameSpaceID_None, nsXULAtoms::smooth, PR_FALSE);
  }
}