Bug 768748 part 1 - Clean up nsHTMLEditor::IsNext/PrevCharWhitespace; r=ehsan

This commit is contained in:
Aryeh Gregor 2012-07-01 14:07:16 +03:00
Родитель 4e1178db04
Коммит 37d4deed65
5 изменённых файлов: 70 добавлений и 210 удалений

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

@ -3906,24 +3906,6 @@ nsEditor::AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2)
}
// IsTextOrElementNode: true if node of dom type element or text
//
bool
nsEditor::IsTextOrElementNode(nsIDOMNode *aNode)
{
if (!aNode)
{
NS_NOTREACHED("null node passed to IsTextOrElementNode()");
return false;
}
PRUint16 nodeType;
aNode->GetNodeType(&nodeType);
return ((nodeType == nsIDOMNode::ELEMENT_NODE) || (nodeType == nsIDOMNode::TEXT_NODE));
}
///////////////////////////////////////////////////////////////////////////
// IsTextNode: true if node of dom type text
//

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

@ -590,7 +590,6 @@ public:
bool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
virtual bool AreNodesSameType(nsIContent* aNode1, nsIContent* aNode2);
static bool IsTextOrElementNode(nsIDOMNode *aNode);
static bool IsTextNode(nsIDOMNode *aNode);
static bool IsTextNode(nsINode *aNode);

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

@ -5290,7 +5290,7 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode,
actionID == nsEditor::kOpDeleteText)
{
bool isSpace, isNBSP;
nsCOMPtr<nsIDOMNode> temp;
nsCOMPtr<nsIContent> temp;
// for text actions, we want to look backwards (or forwards, as appropriate)
// for additional whitespace or nbsp's. We may have to act on these later even though
// they are outside of the initial selection. Even if they are in another node!
@ -5299,10 +5299,12 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode,
do
{
PRInt32 prevOffset;
mHTMLEditor->IsPrevCharWhitespace(node, offset, &isSpace, &isNBSP,
address_of(temp), &prevOffset);
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
mHTMLEditor->IsPrevCharInNodeWhitespace(content, offset, &isSpace,
&isNBSP, getter_AddRefs(temp),
&prevOffset);
if (isSpace || isNBSP) {
node = temp;
node = temp->AsDOMNode();
offset = prevOffset;
} else {
break;
@ -5317,10 +5319,12 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode,
do
{
PRInt32 nextOffset;
mHTMLEditor->IsNextCharWhitespace(node, offset, &isSpace, &isNBSP,
address_of(temp), &nextOffset);
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
mHTMLEditor->IsNextCharInNodeWhitespace(content, offset, &isSpace,
&isNBSP, getter_AddRefs(temp),
&nextOffset);
if (isSpace || isNBSP) {
node = temp;
node = temp->AsDOMNode();
offset = nextOffset;
} else {
break;

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

@ -64,6 +64,7 @@
#include "nsIFrame.h"
#include "nsIParserService.h"
#include "mozilla/dom/Element.h"
#include "nsTextFragment.h"
using namespace mozilla;
using namespace mozilla::widget;
@ -847,195 +848,70 @@ nsHTMLEditor::GetBlockNodeParent(nsIDOMNode *aNode)
return p.forget();
}
///////////////////////////////////////////////////////////////////////////
// NextNodeInBlock: gets the next/prev node in the block, if any. Next node
// must be an element or text node, others are ignored
already_AddRefed<nsIDOMNode>
nsHTMLEditor::NextNodeInBlock(nsIDOMNode *aNode, IterDirection aDir)
{
NS_ENSURE_TRUE(aNode, nsnull);
nsresult rv;
nsCOMPtr<nsIContentIterator> iter =
do_CreateInstance("@mozilla.org/content/post-content-iterator;1", &rv);
NS_ENSURE_SUCCESS(rv, nsnull);
// much gnashing of teeth as we twit back and forth between content and domnode types
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
nsCOMPtr<nsIDOMNode> blockParent;
bool isBlock;
if (NS_SUCCEEDED(NodeIsBlockStatic(aNode, &isBlock)) && isBlock) {
blockParent = aNode;
} else {
blockParent = GetBlockNodeParent(aNode);
}
NS_ENSURE_TRUE(blockParent, nsnull);
nsCOMPtr<nsIContent> blockContent = do_QueryInterface(blockParent);
NS_ENSURE_TRUE(blockContent, nsnull);
if (NS_FAILED(iter->Init(blockContent))) {
return nsnull;
}
if (NS_FAILED(iter->PositionAt(content))) {
return nsnull;
}
while (!iter->IsDone()) {
// ignore nodes that aren't elements or text, or that are the
// block parent
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(iter->GetCurrentNode());
if (node && IsTextOrElementNode(node) && node != blockParent &&
node != aNode)
return node.forget();
if (aDir == kIterForward)
iter->Next();
else
iter->Prev();
}
return nsnull;
}
static const PRUnichar nbsp = 160;
///////////////////////////////////////////////////////////////////////////
// IsNextCharWhitespace: checks the adjacent content in the same block
// to see if following selection is whitespace or nbsp
///////////////////////////////////////////////////////////////////////////////
// IsNextCharInNodeWhitespace: checks the adjacent content in the same node to
// see if following selection is whitespace or nbsp
void
nsHTMLEditor::IsNextCharWhitespace(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool *outIsSpace,
bool *outIsNBSP,
nsCOMPtr<nsIDOMNode> *outNode,
PRInt32 *outOffset)
nsHTMLEditor::IsNextCharInNodeWhitespace(nsIContent* aContent,
PRInt32 aOffset,
bool* outIsSpace,
bool* outIsNBSP,
nsIContent** outNode,
PRInt32* outOffset)
{
MOZ_ASSERT(outIsSpace && outIsNBSP);
MOZ_ASSERT(aContent && outIsSpace && outIsNBSP);
MOZ_ASSERT((outNode && outOffset) || (!outNode && !outOffset));
*outIsSpace = false;
*outIsNBSP = false;
if (outNode) *outNode = nsnull;
if (outOffset) *outOffset = -1;
nsAutoString tempString;
PRUint32 strLength;
nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(aParentNode);
if (textNode)
{
textNode->GetLength(&strLength);
if ((PRUint32)aOffset < strLength)
{
// easy case: next char is in same node
textNode->SubstringData(aOffset,aOffset+1,tempString);
*outIsSpace = nsCRT::IsAsciiSpace(tempString.First());
*outIsNBSP = (tempString.First() == nbsp);
if (outNode) *outNode = do_QueryInterface(aParentNode);
if (outOffset) *outOffset = aOffset+1; // yes, this is _past_ the character;
return;
}
if (outNode && outOffset) {
*outNode = nsnull;
*outOffset = -1;
}
// harder case: next char in next node.
nsCOMPtr<nsIDOMNode> node = NextNodeInBlock(aParentNode, kIterForward);
nsCOMPtr<nsIDOMNode> tmp;
while (node)
{
bool isBlock (false);
NodeIsBlock(node, &isBlock);
if (isBlock) // skip over bold, italic, link, ect nodes
{
if (IsTextNode(node) && IsEditable(node))
{
textNode = do_QueryInterface(node);
textNode->GetLength(&strLength);
if (strLength)
{
textNode->SubstringData(0,1,tempString);
*outIsSpace = nsCRT::IsAsciiSpace(tempString.First());
*outIsNBSP = (tempString.First() == nbsp);
if (outNode) *outNode = do_QueryInterface(node);
if (outOffset) *outOffset = 1; // yes, this is _past_ the character;
return;
}
// else it's an empty text node, or not editable; skip it.
}
else // node is an image or some other thingy that doesn't count as whitespace
{
break;
}
if (aContent->IsNodeOfType(nsINode::eTEXT) &&
(PRUint32)aOffset < aContent->Length()) {
PRUnichar ch = aContent->GetText()->CharAt(aOffset);
*outIsSpace = nsCRT::IsAsciiSpace(ch);
*outIsNBSP = (ch == nbsp);
if (outNode && outOffset) {
NS_IF_ADDREF(*outNode = aContent);
// yes, this is _past_ the character
*outOffset = aOffset + 1;
}
tmp = node;
node = NextNodeInBlock(tmp, kIterForward);
}
}
///////////////////////////////////////////////////////////////////////////
// IsPrevCharWhitespace: checks the adjacent content in the same block
// to see if following selection is whitespace
///////////////////////////////////////////////////////////////////////////////
// IsPrevCharInNodeWhitespace: checks the adjacent content in the same node to
// see if following selection is whitespace
void
nsHTMLEditor::IsPrevCharWhitespace(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool *outIsSpace,
bool *outIsNBSP,
nsCOMPtr<nsIDOMNode> *outNode,
PRInt32 *outOffset)
nsHTMLEditor::IsPrevCharInNodeWhitespace(nsIContent* aContent,
PRInt32 aOffset,
bool* outIsSpace,
bool* outIsNBSP,
nsIContent** outNode,
PRInt32* outOffset)
{
MOZ_ASSERT(outIsSpace && outIsNBSP);
MOZ_ASSERT(aContent && outIsSpace && outIsNBSP);
MOZ_ASSERT((outNode && outOffset) || (!outNode && !outOffset));
*outIsSpace = false;
*outIsNBSP = false;
if (outNode) *outNode = nsnull;
if (outOffset) *outOffset = -1;
nsAutoString tempString;
PRUint32 strLength;
nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(aParentNode);
if (textNode)
{
if (aOffset > 0)
{
// easy case: prev char is in same node
textNode->SubstringData(aOffset-1,aOffset,tempString);
*outIsSpace = nsCRT::IsAsciiSpace(tempString.First());
*outIsNBSP = (tempString.First() == nbsp);
if (outNode) *outNode = do_QueryInterface(aParentNode);
if (outOffset) *outOffset = aOffset-1;
return;
}
if (outNode && outOffset) {
*outNode = nsnull;
*outOffset = -1;
}
// harder case: prev char in next node
nsCOMPtr<nsIDOMNode> node = NextNodeInBlock(aParentNode, kIterBackward);
nsCOMPtr<nsIDOMNode> tmp;
while (node)
{
bool isBlock (false);
NodeIsBlock(node, &isBlock);
if (isBlock) // skip over bold, italic, link, ect nodes
{
if (IsTextNode(node) && IsEditable(node))
{
textNode = do_QueryInterface(node);
textNode->GetLength(&strLength);
if (strLength)
{
// you could use nsIContent::TextIsOnlyWhitespace here
textNode->SubstringData(strLength-1,strLength,tempString);
*outIsSpace = nsCRT::IsAsciiSpace(tempString.First());
*outIsNBSP = (tempString.First() == nbsp);
if (outNode) *outNode = do_QueryInterface(aParentNode);
if (outOffset) *outOffset = strLength-1;
return;
}
// else it's an empty text node, or not editable; skip it.
}
else // node is an image or some other thingy that doesn't count as whitespace
{
break;
}
if (aContent->IsNodeOfType(nsINode::eTEXT) && aOffset > 0) {
PRUnichar ch = aContent->GetText()->CharAt(aOffset - 1);
*outIsSpace = nsCRT::IsAsciiSpace(ch);
*outIsNBSP = (ch == nbsp);
if (outNode && outOffset) {
NS_IF_ADDREF(*outNode = aContent);
*outOffset = aOffset - 1;
}
// otherwise we found a node we want to skip, keep going
tmp = node;
node = NextNodeInBlock(tmp, kIterBackward);
}
}

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

@ -229,19 +229,18 @@ public:
/* ------------ Block methods moved from nsEditor -------------- */
static already_AddRefed<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
static already_AddRefed<nsIDOMNode> NextNodeInBlock(nsIDOMNode *aNode, IterDirection aDir);
void IsNextCharWhitespace(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool *outIsSpace,
bool *outIsNBSP,
nsCOMPtr<nsIDOMNode> *outNode = 0,
PRInt32 *outOffset = 0);
void IsPrevCharWhitespace(nsIDOMNode *aParentNode,
PRInt32 aOffset,
bool *outIsSpace,
bool *outIsNBSP,
nsCOMPtr<nsIDOMNode> *outNode = 0,
PRInt32 *outOffset = 0);
void IsNextCharInNodeWhitespace(nsIContent* aContent,
PRInt32 aOffset,
bool* outIsSpace,
bool* outIsNBSP,
nsIContent** outNode = nsnull,
PRInt32* outOffset = 0);
void IsPrevCharInNodeWhitespace(nsIContent* aContent,
PRInt32 aOffset,
bool* outIsSpace,
bool* outIsNBSP,
nsIContent** outNode = nsnull,
PRInt32* outOffset = 0);
/* ------------ Overrides of nsEditor interface methods -------------- */