Accessible*
nsAccessiblePivot::AdjustStartPosition(Accessible* aAccessible,
                                       RuleCache& aCache,
                                       uint16_t* aFilterResult,
                                       nsresult* aResult)
{
  Accessible* matched = aAccessible;
  *aResult = aCache.ApplyFilter(aAccessible, aFilterResult);

  if (aAccessible != mRoot && aAccessible != mModalRoot) {
    for (Accessible* temp = aAccessible->Parent();
         temp && temp != mRoot && temp != mModalRoot; temp = temp->Parent()) {
      uint16_t filtered = nsIAccessibleTraversalRule::FILTER_IGNORE;
      *aResult = aCache.ApplyFilter(temp, &filtered);
      NS_ENSURE_SUCCESS(*aResult, nullptr);
      if (filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) {
        *aFilterResult = filtered;
        matched = temp;
      }
    }
  }

  if (aAccessible == mPosition && mStartOffset != -1 && mEndOffset != -1) {
    HyperTextAccessible* text = aAccessible->AsHyperText();
    if (text) {
      matched = text->GetChildAtOffset(mStartOffset);
    }
  }

  return matched;
}
static gchar*
getTextAtOffsetCB(AtkText *aText, gint aOffset,
                  AtkTextBoundary aBoundaryType,
                  gint *aStartOffset, gint *aEndOffset)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  if (!accWrap)
    return nullptr;

  HyperTextAccessible* text = accWrap->AsHyperText();
  if (!text || !text->IsTextRole())
    return nullptr;

    nsAutoString autoStr;
    int32_t startOffset = 0, endOffset = 0;
    nsresult rv =
        text->GetTextAtOffset(aOffset, aBoundaryType,
                              &startOffset, &endOffset, autoStr);
    *aStartOffset = startOffset;
    *aEndOffset = endOffset;

    NS_ENSURE_SUCCESS(rv, nullptr);

    ConvertTexttoAsterisks(accWrap, autoStr);
    NS_ConvertUTF16toUTF8 cautoStr(autoStr);
    return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
}
void
EventQueue::CreateTextChangeEventFor(AccMutationEvent* aEvent)
{
    Accessible* container = aEvent->mAccessible->Parent();
    if (!container)
        return;

    HyperTextAccessible* textAccessible = container->AsHyperText();
    if (!textAccessible)
        return;

    // Don't fire event for the first html:br in an editor.
    if (aEvent->mAccessible->Role() == roles::WHITESPACE) {
        nsCOMPtr<nsIEditor> editor = textAccessible->GetEditor();
        if (editor) {
            bool isEmpty = false;
            editor->GetDocumentIsEmpty(&isEmpty);
            if (isEmpty)
                return;
        }
    }

    int32_t offset = textAccessible->GetChildOffset(aEvent->mAccessible);

    nsAutoString text;
    aEvent->mAccessible->AppendTextTo(text);
    if (text.IsEmpty())
        return;

    aEvent->mTextChangeEvent =
        new AccTextChangeEvent(textAccessible, offset, text, aEvent->IsShow(),
                               aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
}
static void
getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
                  AtkCoordType aCoords, AtkTextRectangle *aRect)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  if(!accWrap || !aRect)
    return;

  HyperTextAccessible* text = accWrap->AsHyperText();
  if (!text || !text->IsTextRole())
    return;

    int32_t extY = 0, extX = 0;
    int32_t extWidth = 0, extHeight = 0;

    uint32_t geckoCoordType;
    if (aCoords == ATK_XY_SCREEN)
        geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
    else
        geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;

#ifdef DEBUG
    nsresult rv =
#endif
    text->GetRangeExtents(aStartOffset, aEndOffset,
                          &extX, &extY,
                          &extWidth, &extHeight,
                          geckoCoordType);
    aRect->x = extX;
    aRect->y = extY;
    aRect->width = extWidth;
    aRect->height = extHeight;
    NS_ASSERTION(NS_SUCCEEDED(rv),
                 "MaiInterfaceText::GetRangeExtents, failed\n");
}
static gchar*
getTextSelectionCB(AtkText *aText, gint aSelectionNum,
                   gint *aStartOffset, gint *aEndOffset)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  int32_t startOffset = 0, endOffset = 0;
  if (accWrap) {
    HyperTextAccessible* text = accWrap->AsHyperText();
    if (!text || !text->IsTextRole()) {
      return nullptr;
    }

    text->SelectionBoundsAt(aSelectionNum, &startOffset, &endOffset);
    *aStartOffset = startOffset;
    *aEndOffset = endOffset;

    return getTextCB(aText, *aStartOffset, *aEndOffset);
  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
    nsString data;
    proxy->SelectionBoundsAt(aSelectionNum, data, &startOffset, &endOffset);
    *aStartOffset = startOffset;
    *aEndOffset = endOffset;

    NS_ConvertUTF16toUTF8 dataAsUTF8(data);
    return (dataAsUTF8.get()) ? g_strdup(dataAsUTF8.get()) : nullptr;
  }
  return nullptr;
}
static AtkAttributeSet*
getRunAttributesCB(AtkText *aText, gint aOffset,
                   gint *aStartOffset,
                   gint *aEndOffset)
{
  *aStartOffset = -1;
  *aEndOffset = -1;

  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  if (!accWrap)
    return nullptr;

  HyperTextAccessible* text = accWrap->AsHyperText();
  if (!text || !text->IsTextRole())
    return nullptr;

    nsCOMPtr<nsIPersistentProperties> attributes;
    int32_t startOffset = 0, endOffset = 0;
    nsresult rv = text->GetTextAttributes(false, aOffset,
                                          &startOffset, &endOffset,
                                          getter_AddRefs(attributes));
    NS_ENSURE_SUCCESS(rv, nullptr);

    *aStartOffset = startOffset;
    *aEndOffset = endOffset;

    return ConvertToAtkAttributeSet(attributes);
}
static void
getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
                  AtkCoordType aCoords, AtkTextRectangle *aRect)
{
  if (!aRect) {
    return;
  }

  nsIntRect rect;
  uint32_t geckoCoordType;
  if (aCoords == ATK_XY_SCREEN) {
    geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
  } else {
    geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
  }

  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  if(accWrap) {
    HyperTextAccessible* text = accWrap->AsHyperText();
    if (!text || !text->IsTextRole()) {
      return;
    }

    rect = text->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
    rect = proxy->TextBounds(aStartOffset, aEndOffset, geckoCoordType);
  } else {
    return;
  }

  aRect->x = rect.x;
  aRect->y = rect.y;
  aRect->width = rect.width;
  aRect->height = rect.height;
}
static gint
getOffsetAtPointCB(AtkText *aText,
                   gint aX, gint aY,
                   AtkCoordType aCoords)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  if (accWrap) {
    HyperTextAccessible* text = accWrap->AsHyperText();
    if (!text || !text->IsTextRole()) {
      return -1;
    }

    return static_cast<gint>(
      text->OffsetAtPoint(aX, aY,
                          (aCoords == ATK_XY_SCREEN ?
                           nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
                           nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
  }

  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
    return static_cast<gint>(
      proxy->OffsetAtPoint(aX, aY,
                           (aCoords == ATK_XY_SCREEN ?
                            nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE :
                            nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE)));
  }

  return -1;
}
static gchar*
getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
                      AtkTextBoundary aBoundaryType,
                      gint *aStartOffset, gint *aEndOffset)
{
  nsAutoString autoStr;
  int32_t startOffset = 0, endOffset = 0;
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  if (accWrap) {
    HyperTextAccessible* text = accWrap->AsHyperText();
    if (!text || !text->IsTextRole())
      return nullptr;

    text->TextBeforeOffset(aOffset, aBoundaryType,
                           &startOffset, &endOffset, autoStr);
    ConvertTexttoAsterisks(accWrap, autoStr);
  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
    proxy->GetTextBeforeOffset(aOffset, aBoundaryType, autoStr, &startOffset,
                               &endOffset);
  }

  *aStartOffset = startOffset;
  *aEndOffset = endOffset;

  NS_ConvertUTF16toUTF8 cautoStr(autoStr);
  return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr;
}
void
SelectionManager::NormalSelectionChanged(nsISelection* aSelection)
{
  mLastUsedSelection = do_GetWeakReference(aSelection);

  int32_t rangeCount = 0;
  aSelection->GetRangeCount(&rangeCount);
  if (rangeCount == 0) {
    mLastTextAccessible = nullptr;
    return; // No selection
  }

  HyperTextAccessible* textAcc =
    nsAccUtils::GetTextAccessibleFromSelection(aSelection);
  if (!textAcc)
    return;

  int32_t caretOffset = -1;
  nsresult rv = textAcc->GetCaretOffset(&caretOffset);
  if (NS_FAILED(rv))
    return;

  if (textAcc == mLastTextAccessible && caretOffset == mLastCaretOffset) {
    int32_t selectionCount = 0;
    textAcc->GetSelectionCount(&selectionCount);   // Don't swallow similar events when selecting text
    if (!selectionCount)
      return;  // Swallow duplicate caret event
  }

  mLastCaretOffset = caretOffset;
  mLastTextAccessible = textAcc;

  nsRefPtr<AccEvent> event = new AccCaretMoveEvent(mLastTextAccessible);
  mLastTextAccessible->Document()->FireDelayedEvent(event);
}
void
SelectionManager::ProcessSelectionChanged(nsISelection* aSelection)
{
  Selection* selection = static_cast<Selection*>(aSelection);
  const nsRange* range = selection->GetAnchorFocusRange();
  nsINode* cntrNode = nullptr;
  if (range)
    cntrNode = range->GetCommonAncestor();
  if (!cntrNode) {
    cntrNode = selection->GetFrameSelection()->GetAncestorLimiter();
    if (!cntrNode) {
      cntrNode = selection->GetPresShell()->GetDocument();
      NS_ASSERTION(selection->GetPresShell()->ConstFrameSelection() == selection->GetFrameSelection(),
                   "Wrong selection container was used!");
    }
  }

  HyperTextAccessible* text = nsAccUtils::GetTextContainer(cntrNode);
  if (!text) {
    NS_NOTREACHED("We must reach document accessible implementing text interface!");
    return;
  }

  if (selection->GetType() == nsISelectionController::SELECTION_NORMAL) {
    nsRefPtr<AccEvent> event = new AccTextSelChangeEvent(text, aSelection);
    text->Document()->FireDelayedEvent(event);

  } else if (selection->GetType() == nsISelectionController::SELECTION_SPELLCHECK) {
    // XXX: fire an event for container accessible of the focus/anchor range
    // of the spelcheck selection.
    text->Document()->FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
                                       text);
  }
}
void
SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent)
{
  AccTextSelChangeEvent* event = downcast_accEvent(aEvent);
  Selection* sel = static_cast<Selection*>(event->mSel.get());

  // Fire selection change event if it's not pure caret-move selection change.
  if (sel->GetRangeCount() != 1 || !sel->IsCollapsed())
    nsEventShell::FireEvent(aEvent);

  // Fire caret move event if there's a caret in the selection.
  nsINode* caretCntrNode =
    nsCoreUtils::GetDOMNodeFromDOMPoint(sel->GetFocusNode(),
                                        sel->GetFocusOffset());
  if (!caretCntrNode)
    return;

  HyperTextAccessible* caretCntr = nsAccUtils::GetTextContainer(caretCntrNode);
  NS_ASSERTION(caretCntr,
               "No text container for focus while there's one for common ancestor?!");
  if (!caretCntr)
    return;

  int32_t caretOffset = -1;
  if (NS_SUCCEEDED(caretCntr->GetCaretOffset(&caretOffset)) && caretOffset != -1) {
    nsRefPtr<AccCaretMoveEvent> caretMoveEvent =
      new AccCaretMoveEvent(caretCntr, caretOffset, aEvent->FromUserInput());
    nsEventShell::FireEvent(caretMoveEvent);
  }
}
Exemple #13
0
void SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent) {
  // Fire selection change event if it's not pure caret-move selection change,
  // i.e. the accessible has or had not collapsed selection.
  AccTextSelChangeEvent* event = downcast_accEvent(aEvent);
  if (!event->IsCaretMoveOnly()) nsEventShell::FireEvent(aEvent);

  // Fire caret move event if there's a caret in the selection.
  nsINode* caretCntrNode = nsCoreUtils::GetDOMNodeFromDOMPoint(
      event->mSel->GetFocusNode(), event->mSel->FocusOffset());
  if (!caretCntrNode) return;

  HyperTextAccessible* caretCntr = nsAccUtils::GetTextContainer(caretCntrNode);
  NS_ASSERTION(
      caretCntr,
      "No text container for focus while there's one for common ancestor?!");
  if (!caretCntr) return;

  Selection* selection = caretCntr->DOMSelection();

  // XXX Sometimes we can't get a selection for caretCntr, in that case assume
  // event->mSel is correct.
  if (!selection) selection = event->mSel;

  mCaretOffset = caretCntr->DOMPointToOffset(selection->GetFocusNode(),
                                             selection->FocusOffset());
  mAccWithCaret = caretCntr;
  if (mCaretOffset != -1) {
    RefPtr<AccCaretMoveEvent> caretMoveEvent =
        new AccCaretMoveEvent(caretCntr, mCaretOffset, aEvent->FromUserInput());
    nsEventShell::FireEvent(caretMoveEvent);
  }
}
/* private */
PRUint16
AccessibleWrap::CreateMaiInterfaces(void)
{
  PRUint16 interfacesBits = 0;
    
  // The Component interface is supported by all accessibles.
  interfacesBits |= 1 << MAI_INTERFACE_COMPONENT;

  // Add Action interface if the action count is more than zero.
  if (ActionCount() > 0)
    interfacesBits |= 1 << MAI_INTERFACE_ACTION;

  // Text, Editabletext, and Hypertext interface.
  HyperTextAccessible* hyperText = AsHyperText();
  if (hyperText && hyperText->IsTextRole()) {
    interfacesBits |= 1 << MAI_INTERFACE_TEXT;
    interfacesBits |= 1 << MAI_INTERFACE_EDITABLE_TEXT;
    if (!nsAccUtils::MustPrune(this))
      interfacesBits |= 1 << MAI_INTERFACE_HYPERTEXT;
  }

  // Value interface.
  nsCOMPtr<nsIAccessibleValue> accessInterfaceValue;
  QueryInterface(NS_GET_IID(nsIAccessibleValue),
                 getter_AddRefs(accessInterfaceValue));
  if (accessInterfaceValue) {
    interfacesBits |= 1 << MAI_INTERFACE_VALUE; 
  }

  // Document interface.
  if (IsDoc())
    interfacesBits |= 1 << MAI_INTERFACE_DOCUMENT;

  if (IsImage())
    interfacesBits |= 1 << MAI_INTERFACE_IMAGE;

  // HyperLink interface.
  if (IsLink())
    interfacesBits |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;

  if (!nsAccUtils::MustPrune(this)) {  // These interfaces require children
    // Table interface.
    nsCOMPtr<nsIAccessibleTable> accessInterfaceTable;
    QueryInterface(NS_GET_IID(nsIAccessibleTable),
                   getter_AddRefs(accessInterfaceTable));
    if (accessInterfaceTable) {
      interfacesBits |= 1 << MAI_INTERFACE_TABLE;
    }
      
    // Selection interface.
    if (IsSelect()) {
      interfacesBits |= 1 << MAI_INTERFACE_SELECTION;
    }
  }

  return interfacesBits;
}
NS_IMETHODIMP
xpcAccessibleHyperText::AddSelection(int32_t aStartOffset, int32_t aEndOffset)
{
  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->AddToSelection(aStartOffset, aEndOffset);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::SetTextContents(const nsAString& aText)
{
  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->ReplaceText(aText);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::ScriptablePasteText(int32_t aOffset)
{
  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->PasteText(aOffset);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::RemoveSelection(int32_t aSelectionNum)
{
  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->RemoveFromSelection(aSelectionNum);
  return NS_OK;
}
NS_IMETHODIMP
nsAccessiblePivot::MovePreviousByText(TextBoundaryType aBoundary, bool* aResult)
{
  NS_ENSURE_ARG(aResult);

  *aResult = false;

  int32_t oldStart = mStartOffset, oldEnd = mEndOffset;
  HyperTextAccessible* text = mPosition->AsHyperText();
  Accessible* oldPosition = mPosition;
  while (!text) {
    oldPosition = mPosition;
    mPosition = mPosition->Parent();
    text = mPosition->AsHyperText();
  }

  if (mStartOffset == -1)
    mStartOffset = text != oldPosition ? text->GetChildOffset(oldPosition) : 0;

  if (mStartOffset == 0)
    return NS_OK;

  AccessibleTextBoundary startBoundary, endBoundary;
  switch (aBoundary) {
    case CHAR_BOUNDARY:
      startBoundary = nsIAccessibleText::BOUNDARY_CHAR;
      endBoundary = nsIAccessibleText::BOUNDARY_CHAR;
      break;
    case WORD_BOUNDARY:
      startBoundary = nsIAccessibleText::BOUNDARY_WORD_START;
      endBoundary = nsIAccessibleText::BOUNDARY_WORD_END;
      break;
    default:
      return NS_ERROR_INVALID_ARG;
  }

  nsAutoString unusedText;
  int32_t newStart = 0, newEnd = 0;
  text->GetTextBeforeOffset(mStartOffset, startBoundary, &newStart, &newEnd,
                            unusedText);
  if (newStart < mStartOffset)
    mStartOffset = newEnd == mStartOffset ? newStart : newEnd;
  else // XXX: In certain odd cases newStart is equal to mStartOffset
    text->GetTextBeforeOffset(mStartOffset - 1, startBoundary, &newStart,
                              &mStartOffset, unusedText);
  text->GetTextAtOffset(mStartOffset, endBoundary, &newStart, &mEndOffset,
                        unusedText);

  *aResult = true;

  NotifyOfPivotChange(mPosition, oldStart, oldEnd,
                      nsIAccessiblePivot::REASON_TEXT);
  return NS_OK;
}
static gint
getCharacterCountCB(AtkText *aText)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
  if (!accWrap)
    return 0;

  HyperTextAccessible* textAcc = accWrap->AsHyperText();
  return textAcc->IsDefunct() ?
    0 : static_cast<gint>(textAcc->CharacterCount());
}
NS_IMETHODIMP
xpcAccessibleHyperText::ScriptableCutText(int32_t aStartOffset,
                                          int32_t aEndOffset)
{
  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->CutText(aStartOffset, aEndOffset);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::ScriptableInsertText(const nsAString& aText,
                                             int32_t aOffset)
{
  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->InsertText(aText, aOffset);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::ScriptableScrollSubstringTo(int32_t aStartOffset,
                                                    int32_t aEndOffset,
                                                    uint32_t aScrollType)
{
  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::GetText(int32_t aStartOffset, int32_t aEndOffset,
                                nsAString& aText)
{
  aText.Truncate();

  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  text->TextSubstring(aStartOffset, aEndOffset, aText);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::GetLinkCount(int32_t* aLinkCount)
{
  NS_ENSURE_ARG_POINTER(aLinkCount);
  *aLinkCount = 0;

  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  *aLinkCount = text->LinkCount();
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::GetScriptableCaretOffset(int32_t* aCaretOffset)
{
  NS_ENSURE_ARG_POINTER(aCaretOffset);
  *aCaretOffset = -1;

  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  *aCaretOffset = text->CaretOffset();
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::GetDefaultTextAttributes(nsIPersistentProperties** aAttributes)
{
  NS_ENSURE_ARG_POINTER(aAttributes);
  *aAttributes = nullptr;

  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIPersistentProperties> attrs = text->DefaultTextAttributes();
  attrs.swap(*aAttributes);
  return NS_OK;
}
NS_IMETHODIMP
xpcAccessibleHyperText::GetOffsetAtPoint(int32_t aX, int32_t aY,
                                         uint32_t aCoordType, int32_t* aOffset)
{
  NS_ENSURE_ARG_POINTER(aOffset);
  *aOffset = -1;

  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  *aOffset = text->OffsetAtPoint(aX, aY, aCoordType);
  return NS_OK;
}
STDMETHODIMP
ia2AccessibleText::addSelection(long aStartOffset, long aEndOffset)
{
  A11Y_TRYBLOCK_BEGIN

  HyperTextAccessible* textAcc = static_cast<HyperTextAccessibleWrap*>(this);
  if (textAcc->IsDefunct())
    return CO_E_OBJNOTCONNECTED;

  return textAcc->AddToSelection(aStartOffset, aEndOffset) ?
    S_OK : E_INVALIDARG;

  A11Y_TRYBLOCK_END
}
NS_IMETHODIMP
xpcAccessibleHyperText::GetLinkIndexAtOffset(int32_t aOffset,
                                             int32_t* aLinkIndex)
{
  NS_ENSURE_ARG_POINTER(aLinkIndex);
  *aLinkIndex = -1; // API says this magic value means 'not found'

  HyperTextAccessible* text = static_cast<HyperTextAccessible*>(this);
  if (text->IsDefunct())
    return NS_ERROR_FAILURE;

  *aLinkIndex = text->LinkIndexAtOffset(aOffset);
  return NS_OK;
}