зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1213589 part.2 Clean up GenerateFlatTextContent(), GelerateFlatFontRanges() and GetFlatTextOffsetOfRange() of ContentEventHandler r=smaug
This commit is contained in:
Родитель
1b1d719d0f
Коммит
18395c1495
|
@ -407,37 +407,41 @@ static uint32_t ConvertToXPOffset(nsIContent* aContent, uint32_t aNativeOffset)
|
|||
#endif
|
||||
}
|
||||
|
||||
static nsresult GenerateFlatTextContent(nsRange* aRange,
|
||||
nsAFlatString& aString,
|
||||
LineBreakType aLineBreakType)
|
||||
nsresult
|
||||
ContentEventHandler::GenerateFlatTextContent(nsRange* aRange,
|
||||
nsAFlatString& aString,
|
||||
LineBreakType aLineBreakType)
|
||||
{
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
iter->Init(aRange);
|
||||
|
||||
NS_ASSERTION(aString.IsEmpty(), "aString must be empty string");
|
||||
|
||||
nsINode* startNode = aRange->GetStartParent();
|
||||
NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
|
||||
nsINode* endNode = aRange->GetEndParent();
|
||||
NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
|
||||
if (NS_WARN_IF(!startNode) || NS_WARN_IF(!endNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (startNode == endNode && startNode->IsNodeOfType(nsINode::eTEXT)) {
|
||||
nsIContent* content = static_cast<nsIContent*>(startNode);
|
||||
nsIContent* content = startNode->AsContent();
|
||||
AppendSubString(aString, content, aRange->StartOffset(),
|
||||
aRange->EndOffset() - aRange->StartOffset());
|
||||
ConvertToNativeNewlines(aString);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
nsresult rv = iter->Init(aRange);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
for (; !iter->IsDone(); iter->Next()) {
|
||||
nsINode* node = iter->GetCurrentNode();
|
||||
if (!node) {
|
||||
if (NS_WARN_IF(!node)) {
|
||||
break;
|
||||
}
|
||||
if (!node->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
if (!node->IsContent()) {
|
||||
continue;
|
||||
}
|
||||
nsIContent* content = static_cast<nsIContent*>(node);
|
||||
nsIContent* content = node->AsContent();
|
||||
|
||||
if (content->IsNodeOfType(nsINode::eTEXT)) {
|
||||
if (content == startNode) {
|
||||
|
@ -578,14 +582,18 @@ ContentEventHandler::GenerateFlatFontRanges(nsRange* aRange,
|
|||
|
||||
nsINode* startNode = aRange->GetStartParent();
|
||||
nsINode* endNode = aRange->GetEndParent();
|
||||
if (NS_WARN_IF(!startNode || !endNode)) {
|
||||
if (NS_WARN_IF(!startNode) || NS_WARN_IF(!endNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// baseOffset is the flattened offset of each content node.
|
||||
int32_t baseOffset = 0;
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
for (iter->Init(aRange); !iter->IsDone(); iter->Next()) {
|
||||
nsresult rv = iter->Init(aRange);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
for (; !iter->IsDone(); iter->Next()) {
|
||||
nsINode* node = iter->GetCurrentNode();
|
||||
if (NS_WARN_IF(!node)) {
|
||||
break;
|
||||
|
@ -690,20 +698,22 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
|
|||
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewPreContentIterator();
|
||||
nsresult rv = iter->Init(mRootContent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint32_t offset = 0;
|
||||
uint32_t endOffset = aOffset + aLength;
|
||||
bool startSet = false;
|
||||
for (; !iter->IsDone(); iter->Next()) {
|
||||
nsINode* node = iter->GetCurrentNode();
|
||||
if (!node) {
|
||||
if (NS_WARN_IF(!node)) {
|
||||
break;
|
||||
}
|
||||
if (!node->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
if (!node->IsContent()) {
|
||||
continue;
|
||||
}
|
||||
nsIContent* content = static_cast<nsIContent*>(node);
|
||||
nsIContent* content = node->AsContent();
|
||||
|
||||
uint32_t textLength =
|
||||
content->IsNodeOfType(nsINode::eTEXT) ?
|
||||
|
@ -722,25 +732,31 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
|
|||
if (aLineBreakType == LINE_BREAK_TYPE_NATIVE) {
|
||||
xpOffset = ConvertToXPOffset(content, xpOffset);
|
||||
}
|
||||
}
|
||||
|
||||
if (aExpandToClusterBoundaries) {
|
||||
uint32_t oldXPOffset = xpOffset;
|
||||
rv = ExpandToClusterBoundary(content, false, &xpOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aNewOffset) {
|
||||
// This is correct since a cluster shouldn't include line break.
|
||||
*aNewOffset -= (oldXPOffset - xpOffset);
|
||||
if (aExpandToClusterBoundaries) {
|
||||
uint32_t oldXPOffset = xpOffset;
|
||||
rv = ExpandToClusterBoundary(content, false, &xpOffset);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (aNewOffset) {
|
||||
// This is correct since a cluster shouldn't include line break.
|
||||
*aNewOffset -= (oldXPOffset - xpOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = aRange->SetStart(content, int32_t(xpOffset));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
startSet = true;
|
||||
if (aLength == 0) {
|
||||
// Ensure that the end offset and the start offset are same.
|
||||
rv = aRange->SetEnd(content, int32_t(xpOffset));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
@ -754,7 +770,9 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
|
|||
}
|
||||
if (aExpandToClusterBoundaries) {
|
||||
rv = ExpandToClusterBoundary(content, true, &xpOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Use first position of next node, because the end node is ignored
|
||||
|
@ -768,7 +786,9 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
|
|||
}
|
||||
|
||||
rv = aRange->SetEnd(endNode, int32_t(xpOffset));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -782,14 +802,18 @@ ContentEventHandler::SetRangeFromFlatTextOffset(nsRange* aRange,
|
|||
if (!startSet) {
|
||||
MOZ_ASSERT(!mRootContent->IsNodeOfType(nsINode::eTEXT));
|
||||
rv = aRange->SetStart(mRootContent, int32_t(mRootContent->GetChildCount()));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (aNewOffset) {
|
||||
*aNewOffset = offset;
|
||||
}
|
||||
}
|
||||
rv = aRange->SetEnd(mRootContent, int32_t(mRootContent->GetChildCount()));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "nsRange::SetEnd failed");
|
||||
return rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ LineBreakType
|
||||
|
@ -868,8 +892,8 @@ ContentEventHandler::OnQuerySelectedText(WidgetQueryContentEvent* aEvent)
|
|||
"The reply string must be empty");
|
||||
|
||||
LineBreakType lineBreakType = GetLineBreakType(aEvent);
|
||||
rv = GetFlatTextOffsetOfRange(mRootContent, mFirstSelectedRange,
|
||||
&aEvent->mReply.mOffset, lineBreakType);
|
||||
rv = GetFlatTextLengthBefore(mFirstSelectedRange,
|
||||
&aEvent->mReply.mOffset, lineBreakType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsINode> anchorNode, focusNode;
|
||||
|
@ -1140,8 +1164,8 @@ ContentEventHandler::OnQueryCaretRect(WidgetQueryContentEvent* aEvent)
|
|||
nsIFrame* caretFrame = nsCaret::GetGeometry(mSelection, &caretRect);
|
||||
if (caretFrame) {
|
||||
uint32_t offset;
|
||||
rv = GetFlatTextOffsetOfRange(mRootContent, mFirstSelectedRange, &offset,
|
||||
lineBreakType);
|
||||
rv = GetFlatTextLengthBefore(mFirstSelectedRange,
|
||||
&offset, lineBreakType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (offset == aEvent->mInput.mOffset) {
|
||||
rv = ConvertToRootRelativeOffset(caretFrame, caretRect);
|
||||
|
@ -1320,8 +1344,9 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = GetFlatTextOffsetOfRange(mRootContent, tentativeCaretOffsets.content,
|
||||
tentativeCaretOffsets.offset,
|
||||
rv = GetFlatTextLengthInRange(NodePosition(mRootContent, 0),
|
||||
NodePosition(tentativeCaretOffsets),
|
||||
mRootContent,
|
||||
&aEvent->mReply.mTentativeCaretOffset,
|
||||
GetLineBreakType(aEvent));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
@ -1344,10 +1369,13 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
|
|||
textframe->GetCharacterOffsetAtFramePoint(ptInTarget);
|
||||
NS_ENSURE_TRUE(contentOffsets.content, NS_ERROR_FAILURE);
|
||||
uint32_t offset;
|
||||
rv = GetFlatTextOffsetOfRange(mRootContent, contentOffsets.content,
|
||||
contentOffsets.offset, &offset,
|
||||
rv = GetFlatTextLengthInRange(NodePosition(mRootContent, 0),
|
||||
NodePosition(contentOffsets),
|
||||
mRootContent, &offset,
|
||||
GetLineBreakType(aEvent));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
WidgetQueryContentEvent textRect(true, eQueryTextRect, aEvent->widget);
|
||||
textRect.InitForQueryTextRect(offset, 1, aEvent->mUseNativeLineBreak);
|
||||
|
@ -1409,76 +1437,89 @@ ContentEventHandler::OnQueryDOMWidgetHittest(WidgetQueryContentEvent* aEvent)
|
|||
}
|
||||
|
||||
/* static */ nsresult
|
||||
ContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
|
||||
nsINode* aNode,
|
||||
int32_t aNodeOffset,
|
||||
uint32_t* aOffset,
|
||||
LineBreakType aLineBreakType)
|
||||
ContentEventHandler::GetFlatTextLengthInRange(
|
||||
const NodePosition& aStartPosition,
|
||||
const NodePosition& aEndPosition,
|
||||
nsIContent* aRootContent,
|
||||
uint32_t* aLength,
|
||||
LineBreakType aLineBreakType)
|
||||
{
|
||||
NS_ENSURE_STATE(aRootContent);
|
||||
NS_ASSERTION(aOffset, "param is invalid");
|
||||
|
||||
RefPtr<nsRange> prev = new nsRange(aRootContent);
|
||||
nsCOMPtr<nsIDOMNode> rootDOMNode(do_QueryInterface(aRootContent));
|
||||
prev->SetStart(rootDOMNode, 0);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startDOMNode(do_QueryInterface(aNode));
|
||||
NS_ASSERTION(startDOMNode, "startNode doesn't have nsIDOMNode");
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
|
||||
if (aNode->Length() >= static_cast<uint32_t>(aNodeOffset)) {
|
||||
// Offset is within node's length; set end of range to that offset
|
||||
prev->SetEnd(startDOMNode, aNodeOffset);
|
||||
iter->Init(prev);
|
||||
} else if (aNode != static_cast<nsINode*>(aRootContent)) {
|
||||
// Offset is past node's length; set end of range to end of node
|
||||
prev->SetEndAfter(startDOMNode);
|
||||
iter->Init(prev);
|
||||
} else {
|
||||
// Offset is past the root node; set end of range to end of root node
|
||||
iter->Init(aRootContent);
|
||||
if (NS_WARN_IF(!aRootContent) || NS_WARN_IF(!aStartPosition.IsValid()) ||
|
||||
NS_WARN_IF(!aEndPosition.IsValid()) || NS_WARN_IF(!aLength)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> startNode = do_QueryInterface(startDOMNode);
|
||||
nsINode* endNode = aNode;
|
||||
RefPtr<nsRange> prev = new nsRange(aRootContent);
|
||||
nsresult rv = aStartPosition.SetToRangeStart(prev);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*aOffset = 0;
|
||||
nsCOMPtr<nsIContentIterator> iter = NS_NewContentIterator();
|
||||
if (aEndPosition.OffsetIsValid()) {
|
||||
// Offset is within node's length; set end of range to that offset
|
||||
rv = aEndPosition.SetToRangeEnd(prev);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = iter->Init(prev);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else if (aEndPosition.mNode != aRootContent) {
|
||||
// Offset is past node's length; set end of range to end of node
|
||||
rv = aEndPosition.SetToRangeEndAfter(prev);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = iter->Init(prev);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
// Offset is past the root node; set end of range to end of root node
|
||||
rv = iter->Init(aRootContent);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
*aLength = 0;
|
||||
for (; !iter->IsDone(); iter->Next()) {
|
||||
nsINode* node = iter->GetCurrentNode();
|
||||
if (!node) {
|
||||
if (NS_WARN_IF(!node)) {
|
||||
break;
|
||||
}
|
||||
if (!node->IsNodeOfType(nsINode::eCONTENT)) {
|
||||
if (!node->IsContent()) {
|
||||
continue;
|
||||
}
|
||||
nsIContent* content = static_cast<nsIContent*>(node);
|
||||
nsIContent* content = node->AsContent();
|
||||
|
||||
if (node->IsNodeOfType(nsINode::eTEXT)) {
|
||||
// Note: our range always starts from offset 0
|
||||
if (node == endNode) {
|
||||
*aOffset += GetTextLength(content, aLineBreakType, aNodeOffset);
|
||||
if (node == aEndPosition.mNode) {
|
||||
*aLength += GetTextLength(content, aLineBreakType,
|
||||
aEndPosition.mOffset);
|
||||
} else {
|
||||
*aOffset += GetTextLength(content, aLineBreakType);
|
||||
*aLength += GetTextLength(content, aLineBreakType);
|
||||
}
|
||||
} else if (IsContentBR(content)) {
|
||||
*aOffset += GetBRLength(aLineBreakType);
|
||||
*aLength += GetBRLength(aLineBreakType);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
ContentEventHandler::GetFlatTextOffsetOfRange(nsIContent* aRootContent,
|
||||
nsRange* aRange,
|
||||
uint32_t* aOffset,
|
||||
LineBreakType aLineBreakType)
|
||||
nsresult
|
||||
ContentEventHandler::GetFlatTextLengthBefore(nsRange* aRange,
|
||||
uint32_t* aOffset,
|
||||
LineBreakType aLineBreakType)
|
||||
{
|
||||
nsINode* startNode = aRange->GetStartParent();
|
||||
NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
|
||||
int32_t startOffset = aRange->StartOffset();
|
||||
return GetFlatTextOffsetOfRange(aRootContent, startNode, startOffset,
|
||||
aOffset, aLineBreakType);
|
||||
MOZ_ASSERT(aRange);
|
||||
return GetFlatTextLengthInRange(
|
||||
NodePosition(mRootContent, 0),
|
||||
NodePosition(aRange->GetStartParent(), aRange->StartOffset()),
|
||||
mRootContent, aOffset, aLineBreakType);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsRange.h"
|
||||
|
||||
class nsPresContext;
|
||||
|
@ -81,15 +83,60 @@ public:
|
|||
// FlatText means the text that is generated from DOM tree. The BR elements
|
||||
// are replaced to native linefeeds. Other elements are ignored.
|
||||
|
||||
// Get the offset in FlatText of the range. (also used by IMEContentObserver)
|
||||
static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
|
||||
nsINode* aNode,
|
||||
int32_t aNodeOffset,
|
||||
uint32_t* aOffset,
|
||||
LineBreakType aLineBreakType);
|
||||
static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
|
||||
nsRange* aRange,
|
||||
uint32_t* aOffset,
|
||||
// NodePosition stores a pair of node and offset in the node.
|
||||
// This is useful to receive one or more sets of them instead of nsRange.
|
||||
struct NodePosition final
|
||||
{
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
int32_t mOffset;
|
||||
|
||||
NodePosition()
|
||||
: mOffset(-1)
|
||||
{
|
||||
}
|
||||
|
||||
NodePosition(nsINode* aNode, int32_t aOffset)
|
||||
: mNode(aNode)
|
||||
, mOffset(aOffset)
|
||||
{
|
||||
}
|
||||
|
||||
explicit NodePosition(const nsIFrame::ContentOffsets& aContentOffsets)
|
||||
: mNode(aContentOffsets.content)
|
||||
, mOffset(aContentOffsets.offset)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return mNode && mOffset >= 0;
|
||||
}
|
||||
bool OffsetIsValid() const
|
||||
{
|
||||
return IsValid() && static_cast<uint32_t>(mOffset) <= mNode->Length();
|
||||
}
|
||||
nsresult SetToRangeStart(nsRange* aRange) const
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mNode));
|
||||
return aRange->SetStart(domNode, mOffset);
|
||||
}
|
||||
nsresult SetToRangeEnd(nsRange* aRange) const
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mNode));
|
||||
return aRange->SetEnd(domNode, mOffset);
|
||||
}
|
||||
nsresult SetToRangeEndAfter(nsRange* aRange) const
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mNode));
|
||||
return aRange->SetEndAfter(domNode);
|
||||
}
|
||||
};
|
||||
|
||||
// Get the flatten text length in the range.
|
||||
static nsresult GetFlatTextLengthInRange(const NodePosition& aStartPosition,
|
||||
const NodePosition& aEndPosition,
|
||||
nsIContent* aRootContent,
|
||||
uint32_t* aLength,
|
||||
LineBreakType aLineBreakType);
|
||||
// Computes the native text length between aStartOffset and aEndOffset of
|
||||
// aContent. aContent must be a text node.
|
||||
|
@ -114,6 +161,14 @@ protected:
|
|||
uint32_t aXPStartOffset,
|
||||
uint32_t aXPEndOffset,
|
||||
LineBreakType aLineBreakType);
|
||||
// Get the contents of aRange as plain text.
|
||||
nsresult GenerateFlatTextContent(nsRange* aRange,
|
||||
nsAFlatString& aString,
|
||||
LineBreakType aLineBreakType);
|
||||
// Get the text length before the start position of aRange.
|
||||
nsresult GetFlatTextLengthBefore(nsRange* aRange,
|
||||
uint32_t* aOffset,
|
||||
LineBreakType aLineBreakType);
|
||||
// Get the line breaker length.
|
||||
static inline uint32_t GetBRLength(LineBreakType aLineBreakType);
|
||||
static LineBreakType GetLineBreakType(WidgetQueryContentEvent* aEvent);
|
||||
|
|
|
@ -876,11 +876,15 @@ IMEContentObserver::CharacterDataChanged(nsIDocument* aDocument,
|
|||
uint32_t offset = 0;
|
||||
// get offsets of change and fire notification
|
||||
nsresult rv =
|
||||
ContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aContent,
|
||||
aInfo->mChangeStart,
|
||||
&offset,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
ContentEventHandler::GetFlatTextLengthInRange(
|
||||
NodePosition(mRootContent, 0),
|
||||
NodePosition(aContent, aInfo->mChangeStart),
|
||||
mRootContent,
|
||||
&offset,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t newLength =
|
||||
ContentEventHandler::GetNativeTextLength(aContent, aInfo->mChangeStart,
|
||||
|
@ -912,9 +916,11 @@ IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
|
|||
nsresult rv = NS_OK;
|
||||
if (!mEndOfAddedTextCache.Match(aContainer, aStartIndex)) {
|
||||
mEndOfAddedTextCache.Clear();
|
||||
rv = ContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aContainer,
|
||||
aStartIndex, &offset,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
rv = ContentEventHandler::GetFlatTextLengthInRange(
|
||||
NodePosition(mRootContent, 0),
|
||||
NodePosition(aContainer, aStartIndex),
|
||||
mRootContent, &offset,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
if (NS_WARN_IF(NS_FAILED((rv)))) {
|
||||
return;
|
||||
}
|
||||
|
@ -923,11 +929,12 @@ IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
|
|||
}
|
||||
|
||||
// get offset at the end of the last added node
|
||||
nsIContent* childAtStart = aContainer->GetChildAt(aStartIndex);
|
||||
uint32_t addingLength = 0;
|
||||
rv = ContentEventHandler::GetFlatTextOffsetOfRange(childAtStart, aContainer,
|
||||
aEndIndex, &addingLength,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
rv = ContentEventHandler::GetFlatTextLengthInRange(
|
||||
NodePosition(aContainer, aStartIndex),
|
||||
NodePosition(aContainer, aEndIndex),
|
||||
mRootContent, &addingLength,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
if (NS_WARN_IF(NS_FAILED((rv)))) {
|
||||
mEndOfAddedTextCache.Clear();
|
||||
return;
|
||||
|
@ -988,10 +995,12 @@ IMEContentObserver::ContentRemoved(nsIDocument* aDocument,
|
|||
uint32_t offset = 0;
|
||||
nsresult rv = NS_OK;
|
||||
if (!mStartOfRemovingTextRangeCache.Match(containerNode, aIndexInContainer)) {
|
||||
rv =
|
||||
ContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, containerNode,
|
||||
aIndexInContainer, &offset,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
rv = ContentEventHandler::GetFlatTextLengthInRange(
|
||||
NodePosition(mRootContent, 0),
|
||||
NodePosition(containerNode, aIndexInContainer),
|
||||
mRootContent,
|
||||
&offset,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mStartOfRemovingTextRangeCache.Clear();
|
||||
return;
|
||||
|
@ -1003,18 +1012,21 @@ IMEContentObserver::ContentRemoved(nsIDocument* aDocument,
|
|||
}
|
||||
|
||||
// get offset at the end of the deleted node
|
||||
int32_t nodeLength =
|
||||
aChild->IsNodeOfType(nsINode::eTEXT) ?
|
||||
static_cast<int32_t>(aChild->TextLength()) :
|
||||
std::max(static_cast<int32_t>(aChild->GetChildCount()), 1);
|
||||
MOZ_ASSERT(nodeLength >= 0, "The node length is out of range");
|
||||
uint32_t textLength = 0;
|
||||
rv = ContentEventHandler::GetFlatTextOffsetOfRange(aChild, aChild,
|
||||
nodeLength, &textLength,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mStartOfRemovingTextRangeCache.Clear();
|
||||
return;
|
||||
if (aChild->IsNodeOfType(nsINode::eTEXT)) {
|
||||
textLength = ContentEventHandler::GetNativeTextLength(aChild);
|
||||
} else {
|
||||
uint32_t nodeLength =
|
||||
std::max(static_cast<int32_t>(aChild->GetChildCount()), 1);
|
||||
rv = ContentEventHandler::GetFlatTextLengthInRange(
|
||||
NodePosition(aChild, 0),
|
||||
NodePosition(aChild, nodeLength),
|
||||
mRootContent, &textLength,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mStartOfRemovingTextRangeCache.Clear();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!textLength) {
|
||||
|
@ -1062,10 +1074,14 @@ IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
|
|||
}
|
||||
uint32_t start;
|
||||
nsresult rv =
|
||||
ContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aElement,
|
||||
0, &start,
|
||||
ContentEventHandler::GetFlatTextLengthInRange(NodePosition(mRootContent, 0),
|
||||
NodePosition(aElement, 0),
|
||||
mRootContent,
|
||||
&start,
|
||||
LINE_BREAK_TYPE_NATIVE);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
TextChangeData data(start, start + mPreAttrChangeLength,
|
||||
start + postAttrChangeLength, causedByComposition,
|
||||
|
|
|
@ -40,6 +40,7 @@ class IMEContentObserver final : public nsISelectionListener
|
|||
, public nsIEditorObserver
|
||||
{
|
||||
public:
|
||||
typedef ContentEventHandler::NodePosition NodePosition;
|
||||
typedef widget::IMENotification::SelectionChangeData SelectionChangeData;
|
||||
typedef widget::IMENotification::TextChangeData TextChangeData;
|
||||
typedef widget::IMENotification::TextChangeDataBase TextChangeDataBase;
|
||||
|
|
Загрузка…
Ссылка в новой задаче