зеркало из https://github.com/mozilla/gecko-dev.git
Bug 768748 part 1 - Clean up nsHTMLEditor::IsNext/PrevCharWhitespace; r=ehsan
This commit is contained in:
Родитель
4e1178db04
Коммит
37d4deed65
|
@ -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 -------------- */
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче