//
// IsEditor
//
// Determine if the document we're working with is Editor or Browser
//
PRBool
nsXBLWindowKeyHandler::IsEditor()
{
  nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(mTarget));
  NS_ENSURE_TRUE(windowRoot, PR_FALSE);
  nsCOMPtr<nsIFocusController> focusController;
  windowRoot->GetFocusController(getter_AddRefs(focusController));
  if (!focusController) {
    NS_WARNING("********* Something went wrong! No focus controller on the root!!!\n");
    return PR_FALSE;
  }

  nsCOMPtr<nsIDOMWindowInternal> focusedWindow;
  focusController->GetFocusedWindow(getter_AddRefs(focusedWindow));
  if (!focusedWindow)
    return PR_FALSE;
  
  nsCOMPtr<nsPIDOMWindow> piwin(do_QueryInterface(focusedWindow));
  nsIDocShell *docShell = piwin->GetDocShell();
  nsCOMPtr<nsIPresShell> presShell;
  if (docShell)
    docShell->GetPresShell(getter_AddRefs(presShell));

  if (presShell) {
    PRInt16 isEditor;
    presShell->GetSelectionFlags(&isEditor);
    return isEditor == nsISelectionDisplay::DISPLAY_ALL;
  }

  return PR_FALSE;
}
nsresult
nsXBLPrototypeHandler::DispatchXBLCommand(nsPIDOMEventTarget* aTarget, nsIDOMEvent* aEvent)
{
  // This is a special-case optimization to make command handling fast.
  // It isn't really a part of XBL, but it helps speed things up.

  // See if preventDefault has been set.  If so, don't execute.
  PRBool preventDefault = PR_FALSE;
  nsCOMPtr<nsIDOMNSUIEvent> nsUIEvent(do_QueryInterface(aEvent));
  if (nsUIEvent)
    nsUIEvent->GetPreventDefault(&preventDefault);

  if (preventDefault)
    return NS_OK;

  nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(aEvent);
  if (privateEvent) {
    PRBool dispatchStopped = privateEvent->IsDispatchStopped();
    if (dispatchStopped)
      return NS_OK;
  }

  // Instead of executing JS, let's get the controller for the bound
  // element and call doCommand on it.
  nsCOMPtr<nsIController> controller;
  nsCOMPtr<nsIFocusController> focusController;

  nsCOMPtr<nsPIDOMWindow> privateWindow;
  nsCOMPtr<nsPIWindowRoot> windowRoot(do_QueryInterface(aTarget));
  if (windowRoot) {
    windowRoot->GetFocusController(getter_AddRefs(focusController));
    if (windowRoot)
      privateWindow = do_QueryInterface(windowRoot->GetWindow());
  }
  else {
    privateWindow = do_QueryInterface(aTarget);
    if (!privateWindow) {
      nsCOMPtr<nsIContent> elt(do_QueryInterface(aTarget));
      nsCOMPtr<nsIDocument> doc;
      // XXXbz sXBL/XBL2 issue -- this should be the "scope doc" or
      // something... whatever we use when wrapping DOM nodes
      // normally.  It's not clear that the owner doc is the right
      // thing.
      if (elt)
        doc = elt->GetOwnerDoc();

      if (!doc)
        doc = do_QueryInterface(aTarget);

      if (!doc)
        return NS_ERROR_FAILURE;

      privateWindow = do_QueryInterface(doc->GetScriptGlobalObject());
      if (!privateWindow)
        return NS_ERROR_FAILURE;
    }

    focusController = privateWindow->GetRootFocusController();
  }

  NS_LossyConvertUTF16toASCII command(mHandlerText);
  if (focusController)
    focusController->GetControllerForCommand(privateWindow, command.get(), getter_AddRefs(controller));
  else
    controller = GetController(aTarget); // We're attached to the receiver possibly.

  nsAutoString type;
  mEventName->ToString(type);

  if (type.EqualsLiteral("keypress") &&
      mDetail == nsIDOMKeyEvent::DOM_VK_SPACE &&
      mMisc == 1) {
    // get the focused element so that we can pageDown only at
    // certain times.

    nsCOMPtr<nsPIDOMWindow> windowToCheck;
    if (windowRoot)
      windowToCheck = do_QueryInterface(windowRoot->GetWindow());
    else
      windowToCheck = privateWindow->GetPrivateRoot();

    nsCOMPtr<nsIContent> focusedContent;
    if (windowToCheck) {
      nsCOMPtr<nsPIDOMWindow> focusedWindow;
      focusedContent =
        nsFocusManager::GetFocusedDescendant(windowToCheck, PR_TRUE, getter_AddRefs(focusedWindow));
    }

    PRBool isLink = PR_FALSE;
    nsIContent *content = focusedContent;

    // if the focused element is a link then we do want space to 
    // scroll down. The focused element may be an element in a link,
    // we need to check the parent node too. Only do this check if an
    // element is focused and has a parent.
    if (focusedContent && focusedContent->GetParent()) {
      while (content) {
        if (content->Tag() == nsGkAtoms::a &&
            content->IsNodeOfType(nsINode::eHTML)) {
          isLink = PR_TRUE;
          break;
        }

        if (content->HasAttr(kNameSpaceID_XLink, nsGkAtoms::type)) {
          isLink = content->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
                                        nsGkAtoms::simple, eCaseMatters);

          if (isLink) {
            break;
          }
        }

        content = content->GetParent();
      }

      if (!isLink)
        return NS_OK;
    }
  }

  // We are the default action for this command.
  // Stop any other default action from executing.
  aEvent->PreventDefault();
  
  if (controller)
    controller->DoCommand(command.get());

  return NS_OK;
}