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 // IsTextNode: true if node of dom type text
// //

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

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

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

@ -5290,7 +5290,7 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode,
actionID == nsEditor::kOpDeleteText) actionID == nsEditor::kOpDeleteText)
{ {
bool isSpace, isNBSP; bool isSpace, isNBSP;
nsCOMPtr<nsIDOMNode> temp; nsCOMPtr<nsIContent> temp;
// for text actions, we want to look backwards (or forwards, as appropriate) // 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 // 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! // 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 do
{ {
PRInt32 prevOffset; PRInt32 prevOffset;
mHTMLEditor->IsPrevCharWhitespace(node, offset, &isSpace, &isNBSP, nsCOMPtr<nsIContent> content = do_QueryInterface(node);
address_of(temp), &prevOffset); mHTMLEditor->IsPrevCharInNodeWhitespace(content, offset, &isSpace,
&isNBSP, getter_AddRefs(temp),
&prevOffset);
if (isSpace || isNBSP) { if (isSpace || isNBSP) {
node = temp; node = temp->AsDOMNode();
offset = prevOffset; offset = prevOffset;
} else { } else {
break; break;
@ -5317,10 +5319,12 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode,
do do
{ {
PRInt32 nextOffset; PRInt32 nextOffset;
mHTMLEditor->IsNextCharWhitespace(node, offset, &isSpace, &isNBSP, nsCOMPtr<nsIContent> content = do_QueryInterface(node);
address_of(temp), &nextOffset); mHTMLEditor->IsNextCharInNodeWhitespace(content, offset, &isSpace,
&isNBSP, getter_AddRefs(temp),
&nextOffset);
if (isSpace || isNBSP) { if (isSpace || isNBSP) {
node = temp; node = temp->AsDOMNode();
offset = nextOffset; offset = nextOffset;
} else { } else {
break; break;

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

@ -64,6 +64,7 @@
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsIParserService.h" #include "nsIParserService.h"
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
#include "nsTextFragment.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::widget; using namespace mozilla::widget;
@ -847,195 +848,70 @@ nsHTMLEditor::GetBlockNodeParent(nsIDOMNode *aNode)
return p.forget(); 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; static const PRUnichar nbsp = 160;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// IsNextCharWhitespace: checks the adjacent content in the same block // IsNextCharInNodeWhitespace: checks the adjacent content in the same node to
// to see if following selection is whitespace or nbsp // see if following selection is whitespace or nbsp
void void
nsHTMLEditor::IsNextCharWhitespace(nsIDOMNode *aParentNode, nsHTMLEditor::IsNextCharInNodeWhitespace(nsIContent* aContent,
PRInt32 aOffset, PRInt32 aOffset,
bool *outIsSpace, bool* outIsSpace,
bool *outIsNBSP, bool* outIsNBSP,
nsCOMPtr<nsIDOMNode> *outNode, nsIContent** outNode,
PRInt32 *outOffset) PRInt32* outOffset)
{ {
MOZ_ASSERT(outIsSpace && outIsNBSP); MOZ_ASSERT(aContent && outIsSpace && outIsNBSP);
MOZ_ASSERT((outNode && outOffset) || (!outNode && !outOffset));
*outIsSpace = false; *outIsSpace = false;
*outIsNBSP = false; *outIsNBSP = false;
if (outNode) *outNode = nsnull; if (outNode && outOffset) {
if (outOffset) *outOffset = -1; *outNode = nsnull;
*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;
}
} }
// harder case: next char in next node. if (aContent->IsNodeOfType(nsINode::eTEXT) &&
nsCOMPtr<nsIDOMNode> node = NextNodeInBlock(aParentNode, kIterForward); (PRUint32)aOffset < aContent->Length()) {
nsCOMPtr<nsIDOMNode> tmp; PRUnichar ch = aContent->GetText()->CharAt(aOffset);
while (node) *outIsSpace = nsCRT::IsAsciiSpace(ch);
{ *outIsNBSP = (ch == nbsp);
bool isBlock (false); if (outNode && outOffset) {
NodeIsBlock(node, &isBlock); NS_IF_ADDREF(*outNode = aContent);
if (isBlock) // skip over bold, italic, link, ect nodes // yes, this is _past_ the character
{ *outOffset = aOffset + 1;
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;
}
} }
tmp = node;
node = NextNodeInBlock(tmp, kIterForward);
} }
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// IsPrevCharWhitespace: checks the adjacent content in the same block // IsPrevCharInNodeWhitespace: checks the adjacent content in the same node to
// to see if following selection is whitespace // see if following selection is whitespace
void void
nsHTMLEditor::IsPrevCharWhitespace(nsIDOMNode *aParentNode, nsHTMLEditor::IsPrevCharInNodeWhitespace(nsIContent* aContent,
PRInt32 aOffset, PRInt32 aOffset,
bool *outIsSpace, bool* outIsSpace,
bool *outIsNBSP, bool* outIsNBSP,
nsCOMPtr<nsIDOMNode> *outNode, nsIContent** outNode,
PRInt32 *outOffset) PRInt32* outOffset)
{ {
MOZ_ASSERT(outIsSpace && outIsNBSP); MOZ_ASSERT(aContent && outIsSpace && outIsNBSP);
MOZ_ASSERT((outNode && outOffset) || (!outNode && !outOffset));
*outIsSpace = false; *outIsSpace = false;
*outIsNBSP = false; *outIsNBSP = false;
if (outNode) *outNode = nsnull; if (outNode && outOffset) {
if (outOffset) *outOffset = -1; *outNode = nsnull;
*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;
}
} }
// harder case: prev char in next node if (aContent->IsNodeOfType(nsINode::eTEXT) && aOffset > 0) {
nsCOMPtr<nsIDOMNode> node = NextNodeInBlock(aParentNode, kIterBackward); PRUnichar ch = aContent->GetText()->CharAt(aOffset - 1);
nsCOMPtr<nsIDOMNode> tmp; *outIsSpace = nsCRT::IsAsciiSpace(ch);
while (node) *outIsNBSP = (ch == nbsp);
{ if (outNode && outOffset) {
bool isBlock (false); NS_IF_ADDREF(*outNode = aContent);
NodeIsBlock(node, &isBlock); *outOffset = aOffset - 1;
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;
}
} }
// 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 -------------- */ /* ------------ Block methods moved from nsEditor -------------- */
static already_AddRefed<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode); static already_AddRefed<nsIDOMNode> GetBlockNodeParent(nsIDOMNode *aNode);
static already_AddRefed<nsIDOMNode> NextNodeInBlock(nsIDOMNode *aNode, IterDirection aDir); void IsNextCharInNodeWhitespace(nsIContent* aContent,
void IsNextCharWhitespace(nsIDOMNode *aParentNode, PRInt32 aOffset,
PRInt32 aOffset, bool* outIsSpace,
bool *outIsSpace, bool* outIsNBSP,
bool *outIsNBSP, nsIContent** outNode = nsnull,
nsCOMPtr<nsIDOMNode> *outNode = 0, PRInt32* outOffset = 0);
PRInt32 *outOffset = 0); void IsPrevCharInNodeWhitespace(nsIContent* aContent,
void IsPrevCharWhitespace(nsIDOMNode *aParentNode, PRInt32 aOffset,
PRInt32 aOffset, bool* outIsSpace,
bool *outIsSpace, bool* outIsNBSP,
bool *outIsNBSP, nsIContent** outNode = nsnull,
nsCOMPtr<nsIDOMNode> *outNode = 0, PRInt32* outOffset = 0);
PRInt32 *outOffset = 0);
/* ------------ Overrides of nsEditor interface methods -------------- */ /* ------------ Overrides of nsEditor interface methods -------------- */