Bug 790475 - Part 1: Allow inline spellcheck to operate through adjacent text nodes. r=ehsan. a=lsblakk

--HG--
extra : transplant_source : r%E6%FDZ%03X%DDp%C6%26z%10%BF%89%D5S%8D4%AD%B2
This commit is contained in:
Mike Conley 2012-10-25 18:32:12 -04:00
Родитель 485e18c9bb
Коммит 0d7ec6b6e0
1 изменённых файлов: 58 добавлений и 22 удалений

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

@ -367,25 +367,23 @@ IsBRElement(nsINode* aNode)
} }
/** /**
* Check if there's a DOM word separator before aBeforeOffset in this node. * Given a TextNode, checks to see if there's a DOM word separator before
* Always returns true if it's a BR element. * aBeforeOffset within it. This function does not modify aSeparatorOffset when
* aSeparatorOffset is set to the index of the first character in the last * it returns false.
* separator if any is found (0 for BR elements).
* *
* This function does not modify aSeparatorOffset when it returns false. * @param aNode the TextNode to check.
* @param aBeforeOffset the offset in the TextNode before which we will search
* for the DOM separator. You can pass INT32_MAX to search the entire
* length of the string.
* @param aSeparatorOffset will be set to the offset of the first separator it
* encounters. Will not be written to if no separator is found.
* @returns True if it found a separator.
*/ */
static bool static bool
ContainsDOMWordSeparator(nsINode* aNode, int32_t aBeforeOffset, TextNodeContainsDOMWordSeparator(nsINode* aNode,
int32_t aBeforeOffset,
int32_t* aSeparatorOffset) int32_t* aSeparatorOffset)
{ {
if (IsBRElement(aNode)) {
*aSeparatorOffset = 0;
return true;
}
if (!IsTextNode(aNode))
return false;
// aNode is actually an nsIContent, since it's eTEXT // aNode is actually an nsIContent, since it's eTEXT
nsIContent* content = static_cast<nsIContent*>(aNode); nsIContent* content = static_cast<nsIContent*>(aNode);
const nsTextFragment* textFragment = content->GetText(); const nsTextFragment* textFragment = content->GetText();
@ -407,6 +405,30 @@ ContainsDOMWordSeparator(nsINode* aNode, int32_t aBeforeOffset,
return false; return false;
} }
/**
* Check if there's a DOM word separator before aBeforeOffset in this node.
* Always returns true if it's a BR element.
* aSeparatorOffset is set to the index of the first character in the last
* separator if any is found (0 for BR elements).
*
* This function does not modify aSeparatorOffset when it returns false.
*/
static bool
ContainsDOMWordSeparator(nsINode* aNode, int32_t aBeforeOffset,
int32_t* aSeparatorOffset)
{
if (IsBRElement(aNode)) {
*aSeparatorOffset = 0;
return true;
}
if (!IsTextNode(aNode))
return false;
return TextNodeContainsDOMWordSeparator(aNode, aBeforeOffset,
aSeparatorOffset);
}
static bool static bool
IsBreakElement(nsINode* aNode) IsBreakElement(nsINode* aNode)
{ {
@ -469,13 +491,27 @@ mozInlineSpellWordUtil::BuildSoftText()
// word on the text node as well. // word on the text node as well.
int32_t newOffset = 0; int32_t newOffset = 0;
if (firstOffsetInNode > 0) { if (firstOffsetInNode > 0) {
// Try to find the previous word boundary. We ignore the return value // Try to find the previous word boundary in the current node. If
// of ContainsDOMWordSeparator here because there might be no preceding // we can't find one, start checking previous sibling nodes (if any
// word separator (such as when we're at the end of the first word in // adjacent ones exist) to see if we can find any text nodes with
// the text node), in which case we just set the found offsets to 0. // DOM word separators. We bail out as soon as we see a node that is
// Otherwise, ContainsDOMWordSeparator finds us the correct word // not a text node, or we run out of previous sibling nodes. In the
// boundary so that we can avoid looking at too many words. // event that we simply cannot find any preceding word separator, the
ContainsDOMWordSeparator(node, firstOffsetInNode - 1, &newOffset); // offset is set to 0, and the soft text beginning node is set to the
// "most previous" text node before the original starting node, or
// kept at the original starting node if no previous text nodes exist.
if (!ContainsDOMWordSeparator(node, firstOffsetInNode - 1,
&newOffset)) {
nsINode* prevNode = node->GetPreviousSibling();
while (prevNode && IsTextNode(prevNode)) {
mSoftBegin.mNode = prevNode;
if (TextNodeContainsDOMWordSeparator(prevNode, INT32_MAX,
&newOffset)) {
break;
}
prevNode = prevNode->GetPreviousSibling();
}
}
} }
firstOffsetInNode = newOffset; firstOffsetInNode = newOffset;
mSoftBegin.mOffset = newOffset; mSoftBegin.mOffset = newOffset;