Bug 197974 [ATK Accessibility] rewrite nsAccessibleText code

r=bolian.yin
Not in the default build
This commit is contained in:
kyle.yuan%sun.com 2003-03-24 03:23:12 +00:00
Родитель 96da93ef2f
Коммит cb5f6c0bc2
7 изменённых файлов: 673 добавлений и 165 удалений

Просмотреть файл

@ -67,6 +67,11 @@ interface nsIAccessibleText : nsISupports
out long startOffset,
out long endOffset);
AString getTextBeforeOffset (in long offset,
in nsAccessibleTextBoundary boundaryType,
out long startOffset,
out long endOffset);
/**
* It would be better to return an unsigned long here,
* to allow unicode chars > 16 bits
@ -77,11 +82,6 @@ interface nsIAccessibleText : nsISupports
out long rangeStartOffset,
out long rangeEndOffset);
AString getTextBeforeOffset (in long offset,
in nsAccessibleTextBoundary boundaryType,
out long startOffset,
out long endOffset);
void getCharacterExtents (in long offset,
out long x,
out long y,
@ -109,23 +109,21 @@ interface nsIAccessibleText : nsISupports
Assumptions:
Using wstring (UCS2) instead of string encoded in UTF-8.
Multibyte encodings (or at least potentially multi-byte
encodings) would be preferred for the reasons cited above.
Multibyte encodings (or at least potentially multi-byte
encodings) would be preferred for the reasons cited above.
The following methods will throw an exception
on failure (since not every text component will allow
every operation):
setSelectionBounds, addSelection, removeSelection,
setCaretOffset.
The following methods will throw an exception on failure
(since not every text component will allow every operation):
setSelectionBounds, addSelection, removeSelection, setCaretOffset.
getRangeAttributes defined to return an nsISupports
interface instead of a pango specific data structure.
It may be that some other return type is more appropriate
for mozilla text attributes.
It may be that some other return type is more appropriate
for mozilla text attributes.
we assume that all text components support the idea of
a caret offset, whether visible or "virtual". If this
isn't the case, caretOffset can be made readonly and
a setCaretOffset method provided which throws an exception
on failure (as with *selection methods above).
we assume that all text components support the idea of
a caret offset, whether visible or "virtual". If this
isn't the case, caretOffset can be made readonly and
a setCaretOffset method provided which throws an exception
on failure (as with *selection methods above).
*/

Просмотреть файл

@ -42,6 +42,10 @@
#ifdef MOZ_ACCESSIBILITY_ATK
#include "nsCOMPtr.h"
class nsIAccessible;
struct AtkStateChange {
PRUint32 state;
PRBool enable;
@ -78,7 +82,7 @@ struct AtkChildrenChange {
};
struct AtkTextChange {
PRUint32 start;
PRInt32 start;
PRUint32 length;
PRBool add; // true for add, false for delete
};

Просмотреть файл

@ -39,6 +39,7 @@
#include "nsCaretAccessible.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsICaret.h"
@ -50,6 +51,7 @@
#include "nsIWidget.h"
#include "nsIPresShell.h"
#include "nsTextAccessible.h"
#include "nsRootAccessible.h"
NS_IMPL_ISUPPORTS_INHERITED2(nsCaretAccessible, nsLeafAccessible, nsIAccessibleCaret, nsISelectionListener)
@ -119,6 +121,11 @@ NS_IMETHODIMP nsCaretAccessible::AttachNewSelectionListener(nsIDOMNode *aCurrent
NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, nsISelection *aSel, short aReason)
{
#ifdef MOZ_ACCESSIBILITY_ATK
if (nsAccessibleText::gSuppressedNotifySelectionChanged)
return NS_OK;
#endif
nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
if (!doc)
return NS_OK;
@ -137,6 +144,7 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
nsRect caretRect;
PRBool isCollapsed;
caret->GetCaretCoordinates(nsICaret::eTopLevelWindowCoordinates, domSel, &caretRect, &isCollapsed, nsnull);
#ifndef MOZ_ACCESSIBILITY_ATK
PRBool visible = (caretRect.x >= 0 && caretRect.y >= 0 && caretRect.width >= 0 && caretRect.height >= 0);
if (visible) // Make sure it's visible both by looking at coordinates and visible flag
caret->GetCaretVisible(&visible);
@ -171,6 +179,7 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
nsRect caretScreenRect;
widget->WidgetToScreen(caretRect, mCaretRect);
#endif
#ifndef MOZ_ACCESSIBILITY_ATK
if (visible)
@ -179,10 +188,27 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
nsCOMPtr<nsIDOMNode> focusNode;
nsCOMPtr<nsIDOMHTMLInputElement> inputElement(do_QueryInterface(mCurrentDOMNode));
nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea(do_QueryInterface(mCurrentDOMNode));
if (inputElement || textArea)
if (inputElement || textArea) {
focusNode = mCurrentDOMNode;
else
}
else {
domSel->GetFocusNode(getter_AddRefs(focusNode));
nsCOMPtr<nsIDOMNode> blockNode;
nsAccessible::GetParentBlockNode(focusNode, getter_AddRefs(blockNode));
nsCOMPtr<nsIDOMHTMLBodyElement> body(do_QueryInterface(blockNode));
if (body) {
nsCOMPtr<nsIDocument> parentDoc;
doc->GetParentDocument(getter_AddRefs(parentDoc));
nsCOMPtr<nsIDOMDocument> xulDoc(do_QueryInterface(parentDoc));
nsCOMPtr<nsIDOMElement> domElement;
xulDoc->GetElementById(NS_LITERAL_STRING("content-frame"), getter_AddRefs(domElement));
focusNode = do_QueryInterface(domElement);
}
else {
focusNode = blockNode;
}
}
if (!focusNode)
return NS_OK;
@ -195,8 +221,10 @@ NS_IMETHODIMP nsCaretAccessible::NotifySelectionChanged(nsIDOMDocument *aDoc, ns
domSel->GetFocusOffset(&caretOffset);
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_ATK_TEXT_CARET_MOVE, accessible, &caretOffset);
}
else
mListener->HandleEvent(nsIAccessibleEventListener::EVENT_ATK_TEXT_SELECTION_CHANGE, accessible, nsnull);
else {
//Current text interface doesn't support this event yet
//mListener->HandleEvent(nsIAccessibleEventListener::EVENT_ATK_TEXT_SELECTION_CHANGE, accessible, nsnull);
}
}
#endif

Просмотреть файл

@ -14,7 +14,7 @@
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
@ -40,16 +40,27 @@
// NOTE: alphabetically ordered
#include "nsContentCID.h"
#include "nsIDeviceContext.h"
#include "nsIDocument.h"
#include "nsIAccessibleEditableText.h"
#include "nsIAccessibleEventListener.h"
#include "nsIClipboard.h"
#include "nsIDOMAbstractView.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentView.h"
#include "nsIDOMHTMLBRElement.h"
#include "nsIDOMHTMLDivElement.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsIDOMRange.h"
#include "nsIDOMText.h"
#include "nsIDOMWindow.h"
#include "nsIDOMWindowInternal.h"
#include "nsIDeviceContext.h"
#include "nsIDocument.h"
#include "nsIEditor.h"
#include "nsIFontMetrics.h"
#include "nsIFrame.h"
#include "nsIPlaintextEditor.h"
#include "nsIRenderingContext.h"
#include "nsITextContent.h"
#include "nsIWidget.h"
@ -61,8 +72,14 @@
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
PRBool nsAccessibleText::gSuppressedNotifySelectionChanged = PR_FALSE;
NS_IMPL_ISUPPORTS1(nsAccessibleText, nsIAccessibleText)
/**
* nsAccessibleText implements the nsIAccessibleText interface for static text which mTextNode
* has nsITextContent interface
*/
nsAccessibleText::nsAccessibleText()
{
}
@ -77,84 +94,293 @@ void nsAccessibleText::SetTextNode(nsIDOMNode *aNode)
}
/**
* nsIAccessibleText impl.
* nsIAccessibleText helpers
*/
nsresult nsAccessibleText::GetSelections(nsISelectionController **aSelCon, nsISelection **aDomSel)
{
nsCOMPtr<nsIDOMDocument> domDoc;
mTextNode->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
if (!doc)
return NS_ERROR_FAILURE;
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
nsCOMPtr<nsIPresShell> shell;
doc->GetShellAt(0, getter_AddRefs(shell));
if (!shell)
return NS_ERROR_FAILURE;
NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
nsCOMPtr<nsIContent> content(do_QueryInterface(mTextNode));
nsIFrame *frame = nsnull;
if (content && NS_SUCCEEDED(shell->GetPrimaryFrameFor(content, &frame)) && frame) {
frame->GetSelectionController(context, aSelCon);
if (*aSelCon)
(*aSelCon)->GetSelection(nsISelectionController::SELECTION_NORMAL, aDomSel);
shell->GetPrimaryFrameFor(content, &frame);
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
// Get the selection and selection controller
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
nsCOMPtr<nsIPresContext> context;
shell->GetPresContext(getter_AddRefs(context));
frame->GetSelectionController(context, getter_AddRefs(selCon));
if (selCon)
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
NS_ENSURE_TRUE(selCon && domSel, NS_ERROR_FAILURE);
PRBool isSelectionCollapsed;
domSel->GetIsCollapsed(&isSelectionCollapsed);
// Don't perform any actions when the selection is not collapsed
NS_ENSURE_TRUE(isSelectionCollapsed, NS_ERROR_FAILURE);
if (aSelCon) {
*aSelCon = selCon;
NS_ADDREF(*aSelCon);
}
if (*aSelCon && *aDomSel)
if (aDomSel) {
*aDomSel = domSel;
NS_ADDREF(*aDomSel);
}
return NS_OK;
}
nsresult nsAccessibleText::DOMPointToOffset(nsISupports *aClosure, nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32* aResult)
{
NS_ENSURE_ARG_POINTER(aNode && aResult);
*aResult = aNodeOffset;
nsCOMPtr<nsISupportsArray> domNodeArray(do_QueryInterface(aClosure));
if (domNodeArray) {
// Static text, calculate the offset from a given set of (text) node
PRUint32 textLength, totalLength = 0;
PRUint32 index, count;
domNodeArray->Count(&count);
for (index = 0; index < count; index++) {
nsIDOMNode* domNode = (nsIDOMNode *)domNodeArray->ElementAt(index);
if (aNode == domNode) {
*aResult = aNodeOffset + totalLength;
break;
}
nsCOMPtr<nsIDOMText> domText(do_QueryInterface(domNode));
if (domText) {
domText->GetLength(&textLength);
totalLength += textLength;
}
}
return NS_OK;
}
nsCOMPtr<nsIEditor> editor(do_QueryInterface(aClosure));
if (editor) { // revised according to nsTextControlFrame::DOMPointToOffset
// Editable text, calculate the offset from the editor
nsCOMPtr<nsIDOMElement> rootElement;
editor->GetRootElement(getter_AddRefs(rootElement));
nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootElement));
NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNodeList> nodeList;
nsresult rv = rootNode->GetChildNodes(getter_AddRefs(nodeList));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
PRUint32 length = 0;
rv = nodeList->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
if (!length || aNodeOffset < 0)
return NS_OK;
PRInt32 i, textOffset = 0;
PRInt32 lastIndex = (PRInt32)length - 1;
for (i = 0; i < (PRInt32)length; i++) {
if (rootNode == aNode && i == aNodeOffset) {
*aResult = textOffset;
return NS_OK;
}
nsCOMPtr<nsIDOMNode> item;
rv = nodeList->Item(i, getter_AddRefs(item));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
if (item == aNode) {
*aResult = textOffset + aNodeOffset;
return NS_OK;
}
nsCOMPtr<nsIDOMText> domText(do_QueryInterface(item));
if (domText) {
PRUint32 textLength = 0;
rv = domText->GetLength(&textLength);
NS_ENSURE_SUCCESS(rv, rv);
textOffset += textLength;
}
else {
// Must be a BR node. If it's not the last BR node
// under the root, count it as a newline.
if (i != lastIndex)
++textOffset;
}
}
NS_ASSERTION((aNode == rootNode && aNodeOffset == (PRInt32)length),
"Invalide node offset!");
*aResult = textOffset;
}
return NS_OK;
}
nsresult nsAccessibleText::OffsetToDOMPoint(nsISupports *aClosure, PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition)
{
NS_ENSURE_ARG_POINTER(aResult && aPosition);
*aResult = nsnull;
*aPosition = 0;
nsCOMPtr<nsIEditor> editor(do_QueryInterface(aClosure));
if (editor) { // revised according to nsTextControlFrame::OffsetToDOMPoint
nsCOMPtr<nsIDOMElement> rootElement;
editor->GetRootElement(getter_AddRefs(rootElement));
nsCOMPtr<nsIDOMNode> rootNode(do_QueryInterface(rootElement));
NS_ENSURE_TRUE(rootNode, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNodeList> nodeList;
nsresult rv = rootNode->GetChildNodes(getter_AddRefs(nodeList));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
PRUint32 length = 0;
rv = nodeList->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
if (!length || aOffset < 0) {
*aPosition = 0;
*aResult = rootNode;
NS_ADDREF(*aResult);
return NS_OK;
}
PRInt32 textOffset = 0;
PRUint32 lastIndex = length - 1;
for (PRUint32 i=0; i<length; i++) {
nsCOMPtr<nsIDOMNode> item;
rv = nodeList->Item(i, getter_AddRefs(item));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(item, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMText> domText(do_QueryInterface(item));
if (domText) {
PRUint32 textLength = 0;
rv = domText->GetLength(&textLength);
NS_ENSURE_SUCCESS(rv, rv);
// Check if aOffset falls within this range.
if (aOffset >= textOffset && aOffset <= textOffset+(PRInt32)textLength) {
*aPosition = aOffset - textOffset;
*aResult = item;
NS_ADDREF(*aResult);
return NS_OK;
}
textOffset += textLength;
// If there aren't any more siblings after this text node,
// return the point at the end of this text node!
if (i == lastIndex) {
*aPosition = textLength;
*aResult = item;
NS_ADDREF(*aResult);
return NS_OK;
}
}
else {
// Must be a BR node, count it as a newline.
if (aOffset == textOffset || i == lastIndex) {
// We've found the correct position, or aOffset takes us
// beyond the last child under rootNode, just return the point
// under rootNode that is in front of this br.
*aPosition = i;
*aResult = rootNode;
NS_ADDREF(*aResult);
return NS_OK;
}
++textOffset;
}
}
}
return NS_ERROR_FAILURE;
}
nsresult nsAccessibleText::GetCurrectOffset(nsISupports *aClosure, nsISelection *aDomSel, PRInt32 *aOffset)
{
nsCOMPtr<nsIDOMNode> focusNode;
aDomSel->GetFocusNode(getter_AddRefs(focusNode));
aDomSel->GetFocusOffset(aOffset);
return DOMPointToOffset(aClosure, focusNode, *aOffset, aOffset);
}
/*
Gets the specified text.
aBoundaryType means:
ATK_TEXT_BOUNDARY_CHAR
ATK_TEXT_BOUNDARY_CHAR
The character before/at/after the offset is returned.
ATK_TEXT_BOUNDARY_WORD_START
ATK_TEXT_BOUNDARY_WORD_START
The returned string is from the word start before/at/after the offset to the next word start.
ATK_TEXT_BOUNDARY_WORD_END
ATK_TEXT_BOUNDARY_WORD_END
The returned string is from the word end before/at/after the offset to the next work end.
ATK_TEXT_BOUNDARY_SENTENCE_START
ATK_TEXT_BOUNDARY_SENTENCE_START
The returned string is from the sentence start before/at/after the offset to the next sentence start.
ATK_TEXT_BOUNDARY_SENTENCE_END
ATK_TEXT_BOUNDARY_SENTENCE_END
The returned string is from the sentence end before/at/after the offset to the next sentence end.
ATK_TEXT_BOUNDARY_LINE_START
ATK_TEXT_BOUNDARY_LINE_START
The returned string is from the line start before/at/after the offset to the next line start.
ATK_TEXT_BOUNDARY_LINE_END
ATK_TEXT_BOUNDARY_LINE_END
The returned string is from the line end before/at/after the offset to the next line start.
*/
nsresult nsAccessibleText::GetTextHelper(EGetTextType aType, nsAccessibleTextBoundary aBoundaryType,
nsresult nsAccessibleText::GetTextHelperCore(EGetTextType aType, nsAccessibleTextBoundary aBoundaryType,
PRInt32 aOffset, PRInt32 *aStartOffset, PRInt32 *aEndOffset,
nsISupportsArray *aDomNodeArray, nsAString & _retval)
nsISelectionController *aSelCon, nsISelection *aDomSel,
nsISupports *aClosure, nsAString &aText)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
PRInt32 rangeCount;
nsCOMPtr<nsIDOMRange> range, oldRange;
aDomSel->GetRangeCount(&rangeCount);
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
return NS_ERROR_FAILURE;
if (rangeCount == 0) { // ever happen?
SetCaretOffset(aOffset); // a new range will be added here
rangeCount++;
}
aDomSel->GetRangeAt(rangeCount - 1, getter_AddRefs(range));
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMRange> range(do_CreateInstance(kRangeCID));
if (!range)
return NS_ERROR_OUT_OF_MEMORY;
*aStartOffset = *aEndOffset = aOffset;
// Move caret position to offset
range->SetStart(mTextNode, aOffset);
range->SetEnd(mTextNode, aOffset);
domSel->RemoveAllRanges();
domSel->AddRange(range);
// backup the original selection range to restore the selection status later
range->CloneRange(getter_AddRefs(oldRange));
// Step1: move caret to an appropriate start position
// Step2: move caret to end postion and select the text
@ -183,34 +409,30 @@ nsresult nsAccessibleText::GetTextHelper(EGetTextType aType, nsAccessibleTextBou
{
case BOUNDARY_CHAR:
if (aType == eGetAfter) { // We need the character next to current position
selCon->CharacterMove(isStep1Forward, PR_FALSE);
domSel->GetFocusNode(getter_AddRefs(startFocusNode));
domSel->GetFocusOffset(aStartOffset);
aSelCon->CharacterMove(isStep1Forward, PR_FALSE);
GetCurrectOffset(aClosure, aDomSel, aStartOffset);
}
selCon->CharacterMove(isStep2Forward, PR_TRUE);
domSel->GetFocusNode(getter_AddRefs(endFocusNode));
domSel->GetFocusOffset(aEndOffset);
aSelCon->CharacterMove(isStep2Forward, PR_TRUE);
GetCurrectOffset(aClosure, aDomSel, aEndOffset);
break;
case BOUNDARY_WORD_START:
{
PRBool dontMove = PR_FALSE;
// If we are at the word boundary, don't move the caret in the first step
if (*aStartOffset == 0)
if (aOffset == 0)
dontMove = PR_TRUE;
else {
PRUnichar prevChar;
GetCharacterAtOffset(aOffset - 1, &prevChar);
if (prevChar == ' ' || prevChar == '\t')
if (prevChar == ' ' || prevChar == '\t' || prevChar == '\n')
dontMove = PR_TRUE;
}
if (!dontMove) {
selCon->WordMove(isStep1Forward, PR_FALSE); // Move caret to previous/next word start boundary
domSel->GetFocusNode(getter_AddRefs(startFocusNode));
domSel->GetFocusOffset(aStartOffset);
aSelCon->WordMove(isStep1Forward, PR_FALSE); // Move caret to previous/next word start boundary
GetCurrectOffset(aClosure, aDomSel, aStartOffset);
}
selCon->WordMove(isStep2Forward, PR_TRUE); // Select previous/next word
domSel->GetFocusNode(getter_AddRefs(endFocusNode));
domSel->GetFocusOffset(aEndOffset);
aSelCon->WordMove(isStep2Forward, PR_TRUE); // Select previous/next word
GetCurrectOffset(aClosure, aDomSel, aEndOffset);
}
break;
case BOUNDARY_LINE_START:
@ -218,12 +440,10 @@ nsresult nsAccessibleText::GetTextHelper(EGetTextType aType, nsAccessibleTextBou
// XXX, don't support yet
return NS_ERROR_NOT_IMPLEMENTED;
}
selCon->IntraLineMove(PR_FALSE, PR_FALSE); // Move caret to the line start
domSel->GetFocusNode(getter_AddRefs(startFocusNode));
domSel->GetFocusOffset(aStartOffset);
selCon->IntraLineMove(PR_TRUE, PR_TRUE); // Move caret to the line end and select the whole line
domSel->GetFocusNode(getter_AddRefs(endFocusNode));
domSel->GetFocusOffset(aEndOffset);
aSelCon->IntraLineMove(PR_FALSE, PR_FALSE); // Move caret to the line start
GetCurrectOffset(aClosure, aDomSel, aStartOffset);
aSelCon->IntraLineMove(PR_TRUE, PR_TRUE); // Move caret to the line end and select the whole line
GetCurrectOffset(aClosure, aDomSel, aEndOffset);
break;
case BOUNDARY_WORD_END:
case BOUNDARY_LINE_END:
@ -237,37 +457,13 @@ nsresult nsAccessibleText::GetTextHelper(EGetTextType aType, nsAccessibleTextBou
nsXPIDLString text;
// Get text from selection
domSel->ToString(getter_Copies(text));
domSel->RemoveAllRanges();
_retval = text;
nsresult rv = aDomSel->ToString(getter_Copies(text));
aDomSel->RemoveAllRanges();
// restore the original selection range
aDomSel->AddRange(oldRange);
NS_ENSURE_SUCCESS(rv, rv);
if (aDomNodeArray) {
PRInt32 charCount, totalCount = 0;
PRBool isStartFinished = PR_FALSE, isEndFinished = PR_FALSE;
PRUint32 index, count;
aDomNodeArray->Count(&count);
for (index = 0; index < count; index++) {
nsIDOMNode* domNode = (nsIDOMNode *)aDomNodeArray->ElementAt(index);
if (startFocusNode == domNode && !isStartFinished) {
*aStartOffset += totalCount;
isStartFinished = PR_TRUE;
if (isEndFinished)
break;
}
if (endFocusNode == domNode && !isEndFinished) {
*aEndOffset += totalCount;
isEndFinished = PR_TRUE;
if (isStartFinished)
break;
}
nsCOMPtr<nsITextContent> textContent(do_QueryInterface(domNode));
if (!textContent)
continue;
textContent->GetTextLength(&charCount);
totalCount += charCount;
}
}
// XXX, startFocusNode and endFocusNode may be not in the aDomNodeArray
aText = text;
// Ensure aStartOffset <= aEndOffset
if (*aStartOffset > *aEndOffset) {
@ -279,15 +475,63 @@ nsresult nsAccessibleText::GetTextHelper(EGetTextType aType, nsAccessibleTextBou
return NS_OK;
}
nsresult nsAccessibleText::GetTextHelper(EGetTextType aType, nsAccessibleTextBoundary aBoundaryType,
PRInt32 aOffset, PRInt32 *aStartOffset, PRInt32 *aEndOffset,
nsISupports *aClosure, nsAString &aText)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
//backup old settings
PRInt16 displaySelection;
selCon->GetDisplaySelection(&displaySelection);
PRBool caretEnable;
selCon->GetCaretEnabled(&caretEnable);
//turn off display and caret
selCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
selCon->SetCaretEnabled(PR_FALSE);
//turn off nsCaretAccessible::NotifySelectionChanged
gSuppressedNotifySelectionChanged = PR_TRUE;
PRInt32 caretOffset;
if (NS_SUCCEEDED(GetCaretOffset(&caretOffset))) {
if (caretOffset != aOffset)
SetCaretOffset(aOffset);
}
*aStartOffset = *aEndOffset = aOffset;
rv = GetTextHelperCore(aType, aBoundaryType, aOffset, aStartOffset, aEndOffset, selCon, domSel, aClosure, aText);
//turn on nsCaretAccessible::NotifySelectionChanged
gSuppressedNotifySelectionChanged = PR_FALSE;
//restore old settings
selCon->SetDisplaySelection(displaySelection);
selCon->SetCaretEnabled(caretEnable);
return rv;
}
/**
* nsIAccessibleText impl.
*/
/*
* Gets the offset position of the caret (cursor).
*/
NS_IMETHODIMP nsAccessibleText::GetCaretOffset(PRInt32 *aCaretOffset)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
nsCOMPtr<nsIDOMNode> focusNode;
domSel->GetFocusNode(getter_AddRefs(focusNode));
if (focusNode != mTextNode)
return NS_ERROR_FAILURE;
return domSel->GetFocusOffset(aCaretOffset);
@ -298,18 +542,16 @@ NS_IMETHODIMP nsAccessibleText::GetCaretOffset(PRInt32 *aCaretOffset)
*/
NS_IMETHODIMP nsAccessibleText::SetCaretOffset(PRInt32 aCaretOffset)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
return NS_ERROR_FAILURE;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMRange> range(do_CreateInstance(kRangeCID));
if (! range)
return NS_ERROR_OUT_OF_MEMORY;
NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
range->SetStart(mTextNode, aCaretOffset);
range->SetEnd(mTextNode, aCaretOffset);
domSel->RemoveAllRanges();
return domSel->AddRange(range);
}
@ -330,63 +572,72 @@ NS_IMETHODIMP nsAccessibleText::GetCharacterCount(PRInt32 *aCharacterCount)
*/
NS_IMETHODIMP nsAccessibleText::GetSelectionCount(PRInt32 *aSelectionCount)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
return NS_ERROR_FAILURE;
PRBool isSelectionCollapsed;
rv = domSel->GetIsCollapsed(&isSelectionCollapsed);
NS_ENSURE_SUCCESS(rv, rv);
return domSel->GetRangeCount(aSelectionCount);
if (isSelectionCollapsed)
*aSelectionCount = 0;
rv = domSel->GetRangeCount(aSelectionCount);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
/*
* Gets the specified text.
*/
NS_IMETHODIMP nsAccessibleText::GetText(PRInt32 aStartOffset, PRInt32 aEndOffset, nsAString & _retval)
NS_IMETHODIMP nsAccessibleText::GetText(PRInt32 aStartOffset, PRInt32 aEndOffset, nsAString &aText)
{
nsAutoString text;
mTextNode->GetNodeValue(text);
_retval = Substring(text, aStartOffset, aEndOffset - aStartOffset);
aText = Substring(text, aStartOffset, aEndOffset - aStartOffset);
return NS_OK;
}
NS_IMETHODIMP nsAccessibleText::GetTextBeforeOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & _retval)
NS_IMETHODIMP nsAccessibleText::GetTextBeforeOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
{
return GetTextHelper(eGetBefore, aBoundaryType, aOffset, aStartOffset, aEndOffset, nsnull, _retval);
return GetTextHelper(eGetBefore, aBoundaryType, aOffset, aStartOffset, aEndOffset, nsnull, aText);
}
NS_IMETHODIMP nsAccessibleText::GetTextAtOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & _retval)
NS_IMETHODIMP nsAccessibleText::GetTextAtOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
{
return GetTextHelper(eGetAt, aBoundaryType, aOffset, aStartOffset, aEndOffset, nsnull, _retval);
return GetTextHelper(eGetAt, aBoundaryType, aOffset, aStartOffset, aEndOffset, nsnull, aText);
}
NS_IMETHODIMP nsAccessibleText::GetTextAfterOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & _retval)
NS_IMETHODIMP nsAccessibleText::GetTextAfterOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
{
return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, nsnull, _retval);
return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, nsnull, aText);
}
/*
* Gets the specified text.
*/
NS_IMETHODIMP nsAccessibleText::GetCharacterAtOffset(PRInt32 aOffset, PRUnichar *_retval)
NS_IMETHODIMP nsAccessibleText::GetCharacterAtOffset(PRInt32 aOffset, PRUnichar *aCharacter)
{
nsCOMPtr<nsITextContent> textContent(do_QueryInterface(mTextNode));
if (!textContent)
return NS_ERROR_FAILURE;
const nsTextFragment *textFrag;
textContent->GetText(&textFrag);
*_retval = textFrag->CharAt(aOffset);
nsAutoString text;
nsresult rv = GetText(aOffset, aOffset + 1, text);
NS_ENSURE_SUCCESS(rv, rv);
*aCharacter = text.First();
return NS_OK;
}
NS_IMETHODIMP nsAccessibleText::GetAttributeRange(PRInt32 aOffset, PRInt32 *aRangeStartOffset, PRInt32 *aRangeEndOffset, nsISupports **_retval)
NS_IMETHODIMP nsAccessibleText::GetAttributeRange(PRInt32 aOffset, PRInt32 *aRangeStartOffset,
PRInt32 *aRangeEndOffset, nsISupports **aAttribute)
{
// will do better job later
return NS_ERROR_NOT_IMPLEMENTED;
*aRangeStartOffset = aOffset;
GetCharacterCount(aRangeEndOffset);
*aAttribute = nsnull;
return NS_OK;
}
/*
@ -537,12 +788,13 @@ NS_IMETHODIMP nsAccessibleText::GetCharacterExtents(PRInt32 aOffset,
}
/*
* Gets the offset of the character located at coordinates x and y. x and y are interpreted as being relative to
* Gets the offset of the character located at coordinates x and y. x and y are interpreted as being relative to
* the screen or this widget's window depending on coords.
*/
NS_IMETHODIMP nsAccessibleText::GetOffsetAtPoint(PRInt32 aX, PRInt32 aY, nsAccessibleCoordType aCoordType, PRInt32 *_retval)
NS_IMETHODIMP nsAccessibleText::GetOffsetAtPoint(PRInt32 aX, PRInt32 aY, nsAccessibleCoordType aCoordType, PRInt32 *aOffset)
{
// will do better job later
*aOffset = 0;
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -551,11 +803,9 @@ NS_IMETHODIMP nsAccessibleText::GetOffsetAtPoint(PRInt32 aX, PRInt32 aY, nsAcces
*/
NS_IMETHODIMP nsAccessibleText::GetSelectionBounds(PRInt32 aSelectionNum, PRInt32 *aStartOffset, PRInt32 *aEndOffset)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
return NS_ERROR_FAILURE;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rangeCount;
domSel->GetRangeCount(&rangeCount);
@ -574,11 +824,9 @@ NS_IMETHODIMP nsAccessibleText::GetSelectionBounds(PRInt32 aSelectionNum, PRInt3
*/
NS_IMETHODIMP nsAccessibleText::SetSelectionBounds(PRInt32 aSelectionNum, PRInt32 aStartOffset, PRInt32 aEndOffset)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
return NS_ERROR_FAILURE;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rangeCount;
domSel->GetRangeCount(&rangeCount);
@ -592,8 +840,17 @@ NS_IMETHODIMP nsAccessibleText::SetSelectionBounds(PRInt32 aSelectionNum, PRInt3
nsCOMPtr<nsIDOMNode> endParent;
range->GetStartContainer(getter_AddRefs(startParent));
range->GetEndContainer(getter_AddRefs(endParent));
range->SetStart(startParent, aStartOffset);
range->SetEnd(endParent, aEndOffset);
PRInt32 oldEndOffset;
range->GetEndOffset(&oldEndOffset);
// to avoid set start point after the current end point
if (aStartOffset < oldEndOffset) {
range->SetStart(startParent, aStartOffset);
range->SetEnd(endParent, aEndOffset);
}
else {
range->SetEnd(endParent, aEndOffset);
range->SetStart(startParent, aStartOffset);
}
return NS_OK;
}
@ -607,7 +864,7 @@ NS_IMETHODIMP nsAccessibleText::AddSelection(PRInt32 aStartOffset, PRInt32 aEndO
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMRange> range(do_CreateInstance(kRangeCID));
if (! range)
return NS_ERROR_OUT_OF_MEMORY;
@ -622,11 +879,9 @@ NS_IMETHODIMP nsAccessibleText::AddSelection(PRInt32 aStartOffset, PRInt32 aEndO
*/
NS_IMETHODIMP nsAccessibleText::RemoveSelection(PRInt32 aSelectionNum)
{
nsCOMPtr<nsISelectionController> selCon;
nsCOMPtr<nsISelection> domSel;
if (NS_FAILED(GetSelections(getter_AddRefs(selCon), getter_AddRefs(domSel))))
return NS_ERROR_FAILURE;
nsresult rv = GetSelections(nsnull, getter_AddRefs(domSel));
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 rangeCount;
domSel->GetRangeCount(&rangeCount);
@ -638,6 +893,183 @@ NS_IMETHODIMP nsAccessibleText::RemoveSelection(PRInt32 aSelectionNum)
return domSel->RemoveRange(range);
}
/**
* nsAccessibleEditableText implements the nsIAccessibleText interface for editable text, such as HTML
* <input>, <textarea> and XUL <editor>
*/
NS_IMPL_ISUPPORTS1(nsAccessibleEditableText, nsIAccessibleText)
nsAccessibleEditableText::nsAccessibleEditableText()
{
}
nsAccessibleEditableText::~nsAccessibleEditableText()
{
}
/**
* nsIAccessibleText helpers
*/
void nsAccessibleEditableText::SetEditor(nsIEditor* aEditor)
{
mEditor = aEditor;
}
PRBool nsAccessibleEditableText::IsSingleLineTextControl(nsIDOMNode *aDomNode)
{
nsCOMPtr<nsIDOMHTMLInputElement> input(do_QueryInterface(aDomNode));
return input ? PR_TRUE : PR_FALSE;
}
nsresult nsAccessibleEditableText::FireTextChangeEvent(AtkTextChange *aTextData)
{
nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(NS_STATIC_CAST(nsIAccessibleText*, this)));
if (accessible) {
printf(" [start=%d, length=%d, add=%d]\n", aTextData->start, aTextData->length, aTextData->add);
accessible->HandleEvent(nsIAccessibleEventListener::EVENT_ATK_TEXT_CHANGE, accessible, aTextData);
}
return NS_OK;
}
nsITextControlFrame* nsAccessibleEditableText::GetTextFrame()
{
nsCOMPtr<nsIDOMDocument> domDoc;
mTextNode->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
NS_ENSURE_TRUE(doc, nsnull);
nsCOMPtr<nsIPresShell> shell;
doc->GetShellAt(0, getter_AddRefs(shell));
NS_ENSURE_TRUE(shell, nsnull);
nsCOMPtr<nsIContent> content(do_QueryInterface(mTextNode));
nsIFrame *frame = nsnull;
shell->GetPrimaryFrameFor(content, &frame);
NS_ENSURE_TRUE(frame, nsnull);
nsITextControlFrame *textFrame;
frame->QueryInterface(NS_GET_IID(nsITextControlFrame), (void**)&textFrame);
return textFrame;
}
nsresult nsAccessibleEditableText::GetSelectionRange(PRInt32 *aStartPos, PRInt32 *aEndPos)
{
*aStartPos = 0;
*aEndPos = 0;
nsITextControlFrame *textFrame = GetTextFrame();
if (textFrame) {
return textFrame->GetSelectionRange(aStartPos, aEndPos);
}
else {
}
return NS_OK;
}
nsresult nsAccessibleEditableText::SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos)
{
nsITextControlFrame *textFrame = GetTextFrame();
if (textFrame) {
return textFrame->SetSelectionRange(aStartPos, aEndPos);
}
else {
}
return NS_OK;
}
/**
* nsIAccessibleText impl.
*/
/*
* Gets the offset position of the caret (cursor).
*/
NS_IMETHODIMP nsAccessibleEditableText::GetCaretOffset(PRInt32 *aCaretOffset)
{
*aCaretOffset = 0;
PRInt32 startPos, endPos;
nsresult rv = GetSelectionRange(&startPos, &endPos);
NS_ENSURE_SUCCESS(rv, rv);
if (startPos == endPos) { // selection must be collapsed
*aCaretOffset = startPos;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
/*
* Sets the caret (cursor) position to the specified offset.
*/
NS_IMETHODIMP nsAccessibleEditableText::SetCaretOffset(PRInt32 aCaretOffset)
{
return SetSelectionRange(aCaretOffset, aCaretOffset);
}
/*
* Gets the character count.
*/
NS_IMETHODIMP nsAccessibleEditableText::GetCharacterCount(PRInt32 *aCharacterCount)
{
*aCharacterCount = 0;
nsITextControlFrame *textFrame = GetTextFrame();
if (textFrame) {
textFrame->GetTextLength(aCharacterCount);
return NS_OK;
}
else {
}
return NS_ERROR_FAILURE;
}
/*
* Gets the specified text.
*/
NS_IMETHODIMP nsAccessibleEditableText::GetText(PRInt32 aStartOffset, PRInt32 aEndOffset, nsAString & aText)
{
nsITextControlFrame *textFrame = GetTextFrame();
if (textFrame) {
nsAutoString text;
textFrame->GetValue(text, PR_TRUE);
if (aEndOffset == -1) // get all text from aStartOffset
aEndOffset = text.Length();
aText = Substring(text, aStartOffset, aEndOffset - aStartOffset);
return NS_OK;
}
else {
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsAccessibleEditableText::GetTextBeforeOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
{
return GetTextHelper(eGetBefore, aBoundaryType, aOffset, aStartOffset, aEndOffset, mEditor, aText);
}
NS_IMETHODIMP nsAccessibleEditableText::GetTextAtOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
{
return GetTextHelper(eGetAt, aBoundaryType, aOffset, aStartOffset, aEndOffset, mEditor, aText);
}
NS_IMETHODIMP nsAccessibleEditableText::GetTextAfterOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText)
{
return GetTextHelper(eGetAfter, aBoundaryType, aOffset, aStartOffset, aEndOffset, mEditor, aText);
}
#endif //MOZ_ACCESSIBILITY_ATK
// ------------

Просмотреть файл

@ -40,9 +40,14 @@
#ifndef _nsTextAccessible_H_
#define _nsTextAccessible_H_
#include "nsAccessibleEventData.h"
#include "nsBaseWidgetAccessible.h"
#include "nsIAccessibleEditableText.h"
#include "nsIAccessibleText.h"
#include "nsIEditActionListener.h"
#include "nsIEditor.h"
#include "nsISelectionController.h"
#include "nsITextControlFrame.h"
#ifdef MOZ_ACCESSIBILITY_ATK
@ -59,17 +64,58 @@ public:
void SetTextNode(nsIDOMNode *aNode);
static PRBool gSuppressedNotifySelectionChanged;
protected:
nsCOMPtr<nsIDOMNode> mTextNode;
nsresult GetSelections(nsISelectionController **aSelCon, nsISelection **aDomSel);
nsresult GetTextHelperCore(EGetTextType aType, nsAccessibleTextBoundary aBoundaryType,
PRInt32 aOffset, PRInt32 *aStartOffset, PRInt32 *aEndOffset,
nsISelectionController *aSelCon, nsISelection *aDomSel,
nsISupports *aClosure, nsAString & aText);
nsresult GetTextHelper(EGetTextType aType, nsAccessibleTextBoundary aBoundaryType,
PRInt32 aOffset, PRInt32 *aStartOffset, PRInt32 *aEndOffset,
nsISupportsArray *aDomNodeArray, nsAString & _retval);
nsISupports *aClosure, nsAString & aText);
static nsresult DOMPointToOffset(nsISupports *aClosure, nsIDOMNode* aNode, PRInt32 aNodeOffset, PRInt32 *aResult);
static nsresult OffsetToDOMPoint(nsISupports *aClosure, PRInt32 aOffset, nsIDOMNode** aResult, PRInt32* aPosition);
static nsresult GetCurrectOffset(nsISupports *aClosure, nsISelection *aDomSel, PRInt32 *aOffset);
friend class nsAccessibleHyperText;
};
class nsAccessibleEditableText : public nsAccessibleText
{
public:
NS_DECL_ISUPPORTS
nsAccessibleEditableText();
virtual ~nsAccessibleEditableText();
NS_IMETHOD GetCaretOffset(PRInt32 *aCaretOffset);
NS_IMETHOD SetCaretOffset(PRInt32 aCaretOffset);
NS_IMETHOD GetCharacterCount(PRInt32 *aCharacterCount);
NS_IMETHOD GetText(PRInt32 startOffset, PRInt32 endOffset, nsAString & aText);
NS_IMETHOD GetTextBeforeOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText);
NS_IMETHOD GetTextAtOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText);
NS_IMETHOD GetTextAfterOffset(PRInt32 aOffset, nsAccessibleTextBoundary aBoundaryType,
PRInt32 *aStartOffset, PRInt32 *aEndOffset, nsAString & aText);
static PRBool IsSingleLineTextControl(nsIDOMNode *aDomNode);
protected:
void SetEditor(nsIEditor *aEditor);
nsITextControlFrame* GetTextFrame();
nsresult GetSelectionRange(PRInt32 *aStartPos, PRInt32 *aEndPos);
nsresult SetSelectionRange(PRInt32 aStartPos, PRInt32 aEndPos);
nsresult FireTextChangeEvent(AtkTextChange *aTextData);
nsCOMPtr<nsIEditor> mEditor;
};
#endif //MOZ_ACCESSIBILITY_ATK
/**

Просмотреть файл

@ -56,7 +56,6 @@
#include "nsIEditor.h"
#include "nsIEventStateManager.h"
#include "nsIFrame.h"
#include "nsITextControlFrame.h"
#include "nsIPlaintextEditor.h"
#include "nsISelectionController.h"
#include "nsReadableUtils.h"

Просмотреть файл

@ -33,6 +33,7 @@ REQUIRES = \
content \
docshell \
dom \
editor \
gfx \
htmlparser \
intl \