зеркало из https://github.com/mozilla/gecko-dev.git
Bug 619273 - Move the selection state bit from frames to content nodes. r=smaug
This commit is contained in:
Родитель
5fb4d8f356
Коммит
498185f3f0
|
@ -106,9 +106,7 @@ nsHTMLTableCellAccessible::NativeState()
|
|||
|
||||
if (frame) {
|
||||
state |= states::SELECTABLE;
|
||||
bool isSelected = false;
|
||||
frame->GetSelected(&isSelected);
|
||||
if (isSelected)
|
||||
if (frame->IsSelected())
|
||||
state |= states::SELECTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -916,6 +916,18 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if |this| node is the common ancestor of the start/end
|
||||
* nodes of a Range in a Selection or a descendant of such a common ancestor.
|
||||
* This node is definitely not selected when |false| is returned, but it may
|
||||
* or may not be selected when |true| is returned.
|
||||
*/
|
||||
bool IsSelectionDescendant() const
|
||||
{
|
||||
return IsDescendantOfCommonAncestorForRangeInSelection() ||
|
||||
IsCommonAncestorForRangeInSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root content of an editor. So, this node must be a descendant of
|
||||
* an editor. Note that this should be only used for getting input or textarea
|
||||
|
@ -1201,6 +1213,11 @@ private:
|
|||
ElementHasName,
|
||||
// Set if the element might have a contenteditable attribute set.
|
||||
ElementMayHaveContentEditableAttr,
|
||||
// Set if the node is the common ancestor of the start/end nodes of a Range
|
||||
// that is in a Selection.
|
||||
NodeIsCommonAncestorForRangeInSelection,
|
||||
// Set if the node is a descendant of a node with the above bit set.
|
||||
NodeIsDescendantOfCommonAncestorForRangeInSelection,
|
||||
// Guard value
|
||||
BooleanFlagCount
|
||||
};
|
||||
|
@ -1235,6 +1252,18 @@ public:
|
|||
bool HasName() const { return GetBoolFlag(ElementHasName); }
|
||||
bool MayHaveContentEditableAttr() const
|
||||
{ return GetBoolFlag(ElementMayHaveContentEditableAttr); }
|
||||
bool IsCommonAncestorForRangeInSelection() const
|
||||
{ return GetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
|
||||
void SetCommonAncestorForRangeInSelection()
|
||||
{ SetBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
|
||||
void ClearCommonAncestorForRangeInSelection()
|
||||
{ ClearBoolFlag(NodeIsCommonAncestorForRangeInSelection); }
|
||||
bool IsDescendantOfCommonAncestorForRangeInSelection() const
|
||||
{ return GetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
|
||||
void SetDescendantOfCommonAncestorForRangeInSelection()
|
||||
{ SetBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
|
||||
void ClearDescendantOfCommonAncestorForRangeInSelection()
|
||||
{ ClearBoolFlag(NodeIsDescendantOfCommonAncestorForRangeInSelection); }
|
||||
|
||||
protected:
|
||||
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
|
||||
|
|
|
@ -40,8 +40,10 @@
|
|||
|
||||
#include "nsISupports.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsTHashtable.h"
|
||||
|
||||
// IID for the nsIRange interface
|
||||
#define NS_IRANGE_IID \
|
||||
|
@ -60,7 +62,8 @@ public:
|
|||
mEndOffset(0),
|
||||
mIsPositioned(false),
|
||||
mIsDetached(false),
|
||||
mMaySpanAnonymousSubtrees(false)
|
||||
mMaySpanAnonymousSubtrees(false),
|
||||
mInSelection(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -110,6 +113,33 @@ public:
|
|||
mMaySpanAnonymousSubtrees = aMaySpanAnonymousSubtrees;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true iff this range is part of at least one Selection object
|
||||
* and isn't detached.
|
||||
*/
|
||||
bool IsInSelection() const
|
||||
{
|
||||
return mInSelection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the range is added/removed from a Selection.
|
||||
*/
|
||||
void SetInSelection(bool aInSelection)
|
||||
{
|
||||
if (mInSelection == aInSelection || mIsDetached) {
|
||||
return;
|
||||
}
|
||||
mInSelection = aInSelection;
|
||||
nsINode* commonAncestor = GetCommonAncestor();
|
||||
NS_ASSERTION(commonAncestor, "unexpected disconnected nodes");
|
||||
if (mInSelection) {
|
||||
RegisterCommonAncestor(commonAncestor);
|
||||
} else {
|
||||
UnregisterCommonAncestor(commonAncestor);
|
||||
}
|
||||
}
|
||||
|
||||
virtual nsINode* GetCommonAncestor() const = 0;
|
||||
|
||||
virtual void Reset() = 0;
|
||||
|
@ -128,7 +158,12 @@ public:
|
|||
// To support the font inspector API
|
||||
NS_IMETHOD GetUsedFontFaces(nsIDOMFontFaceList** aResult) = 0;
|
||||
|
||||
typedef nsTHashtable<nsPtrHashKey<nsIRange> > RangeHashTable;
|
||||
protected:
|
||||
void RegisterCommonAncestor(nsINode* aNode);
|
||||
void UnregisterCommonAncestor(nsINode* aNode);
|
||||
nsINode* IsValidBoundary(nsINode* aNode);
|
||||
|
||||
nsCOMPtr<nsINode> mRoot;
|
||||
nsCOMPtr<nsINode> mStartParent;
|
||||
nsCOMPtr<nsINode> mEndParent;
|
||||
|
@ -138,6 +173,7 @@ protected:
|
|||
bool mIsPositioned;
|
||||
bool mIsDetached;
|
||||
bool mMaySpanAnonymousSubtrees;
|
||||
bool mInSelection;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIRange, NS_IRANGE_IID)
|
||||
|
|
|
@ -63,11 +63,8 @@
|
|||
// whitespace, we may need to reframe it (or its ancestors).
|
||||
#define NS_REFRAME_IF_WHITESPACE (1 << (NODE_TYPE_SPECIFIC_BITS_OFFSET + 1))
|
||||
|
||||
// This bit is set to indicate that the text may be part of a selection.
|
||||
#define NS_TEXT_IN_SELECTION (1 << (NODE_TYPE_SPECIFIC_BITS_OFFSET + 2))
|
||||
|
||||
// Make sure we have enough space for those bits
|
||||
PR_STATIC_ASSERT(NODE_TYPE_SPECIFIC_BITS_OFFSET + 2 < 32);
|
||||
PR_STATIC_ASSERT(NODE_TYPE_SPECIFIC_BITS_OFFSET + 1 < 32);
|
||||
|
||||
class nsIDOMAttr;
|
||||
class nsIDOMEventListener;
|
||||
|
|
|
@ -91,6 +91,9 @@
|
|||
#endif /* MOZ_XUL */
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#ifdef DEBUG
|
||||
#include "nsIRange.h"
|
||||
#endif
|
||||
|
||||
#include "nsBindingManager.h"
|
||||
#include "nsXBLBinding.h"
|
||||
|
@ -4932,6 +4935,11 @@ nsGenericElement::List(FILE* out, PRInt32 aIndent,
|
|||
|
||||
fprintf(out, " state=[%llx]", State().GetInternalValue());
|
||||
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
|
||||
if (IsCommonAncestorForRangeInSelection()) {
|
||||
nsIRange::RangeHashTable* ranges =
|
||||
static_cast<nsIRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
|
||||
fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
|
||||
}
|
||||
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
|
||||
fprintf(out, " refcount=%d<", mRefCnt.get());
|
||||
|
||||
|
|
|
@ -836,6 +836,7 @@ GK_ATOM(queryset, "queryset")
|
|||
GK_ATOM(querytype, "querytype")
|
||||
GK_ATOM(radio, "radio")
|
||||
GK_ATOM(radiogroup, "radiogroup")
|
||||
GK_ATOM(range, "range")
|
||||
GK_ATOM(readonly, "readonly")
|
||||
GK_ATOM(rect, "rect")
|
||||
GK_ATOM(rectangle, "rectangle")
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mats Palmgren <matspal@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -156,6 +157,69 @@ nsRange::CompareNodeToRange(nsINode* aNode, nsIRange* aRange,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
struct FindSelectedRangeData
|
||||
{
|
||||
nsINode* mNode;
|
||||
nsIRange* mResult;
|
||||
PRUint32 mStartOffset;
|
||||
PRUint32 mEndOffset;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
FindSelectedRange(nsPtrHashKey<nsIRange>* aEntry, void* userArg)
|
||||
{
|
||||
nsIRange* range = aEntry->GetKey();
|
||||
if (range->IsInSelection() && !range->Collapsed()) {
|
||||
FindSelectedRangeData* data = static_cast<FindSelectedRangeData*>(userArg);
|
||||
PRInt32 cmp = nsContentUtils::ComparePoints(data->mNode, data->mEndOffset,
|
||||
range->GetStartParent(),
|
||||
range->StartOffset());
|
||||
if (cmp == 1) {
|
||||
cmp = nsContentUtils::ComparePoints(data->mNode, data->mStartOffset,
|
||||
range->GetEndParent(),
|
||||
range->EndOffset());
|
||||
if (cmp == -1) {
|
||||
data->mResult = range;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static nsINode*
|
||||
GetNextRangeCommonAncestor(nsINode* aNode)
|
||||
{
|
||||
while (aNode && !aNode->IsCommonAncestorForRangeInSelection()) {
|
||||
if (!aNode->IsDescendantOfCommonAncestorForRangeInSelection()) {
|
||||
return nsnull;
|
||||
}
|
||||
aNode = aNode->GetNodeParent();
|
||||
}
|
||||
return aNode;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsRange::IsNodeSelected(nsINode* aNode, PRUint32 aStartOffset,
|
||||
PRUint32 aEndOffset)
|
||||
{
|
||||
NS_PRECONDITION(aNode, "bad arg");
|
||||
|
||||
FindSelectedRangeData data = { aNode, nsnull, aStartOffset, aEndOffset };
|
||||
nsINode* n = GetNextRangeCommonAncestor(aNode);
|
||||
NS_ASSERTION(n || !aNode->IsSelectionDescendant(),
|
||||
"orphan selection descendant");
|
||||
for (; n; n = GetNextRangeCommonAncestor(n->GetNodeParent())) {
|
||||
RangeHashTable* ranges =
|
||||
static_cast<RangeHashTable*>(n->GetProperty(nsGkAtoms::range));
|
||||
ranges->EnumerateEntries(FindSelectedRange, &data);
|
||||
if (data.mResult) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* non members
|
||||
******************************************************/
|
||||
|
@ -225,8 +289,10 @@ NS_NewRange(nsIDOMRange** aResult)
|
|||
|
||||
nsRange::~nsRange()
|
||||
{
|
||||
DoSetRange(nsnull, 0, nsnull, 0, nsnull);
|
||||
NS_ASSERTION(!IsInSelection(), "deleting nsRange that is in use");
|
||||
|
||||
// we want the side effects (releases and list removals)
|
||||
DoSetRange(nsnull, 0, nsnull, 0, nsnull);
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
|
@ -260,6 +326,94 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsRange)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
static void
|
||||
RangeHashTableDtor(void* aObject, nsIAtom* aPropertyName, void* aPropertyValue,
|
||||
void* aData)
|
||||
{
|
||||
nsIRange::RangeHashTable* ranges =
|
||||
static_cast<nsIRange::RangeHashTable*>(aPropertyValue);
|
||||
delete ranges;
|
||||
}
|
||||
|
||||
static void MarkDescendants(nsINode* aNode)
|
||||
{
|
||||
// Set NodeIsDescendantOfCommonAncestorForRangeInSelection on aNode's
|
||||
// descendants unless aNode is already marked as a range common ancestor
|
||||
// or a descendant of one, in which case all of our descendants have the
|
||||
// bit set already.
|
||||
if (!aNode->IsSelectionDescendant()) {
|
||||
// don't set the Descendant bit on |aNode| itself
|
||||
nsINode* node = aNode->GetNextNode(aNode);
|
||||
while (node) {
|
||||
node->SetDescendantOfCommonAncestorForRangeInSelection();
|
||||
if (!node->IsCommonAncestorForRangeInSelection()) {
|
||||
node = node->GetNextNode(aNode);
|
||||
} else {
|
||||
// optimize: skip this sub-tree since it's marked already.
|
||||
node = node->GetNextNonChildNode(aNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void UnmarkDescendants(nsINode* aNode)
|
||||
{
|
||||
// Unset NodeIsDescendantOfCommonAncestorForRangeInSelection on aNode's
|
||||
// descendants unless aNode is a descendant of another range common ancestor.
|
||||
// Also, exclude descendants of range common ancestors (but not the common
|
||||
// ancestor itself).
|
||||
if (!aNode->IsDescendantOfCommonAncestorForRangeInSelection()) {
|
||||
// we know |aNode| doesn't have any bit set
|
||||
nsINode* node = aNode->GetNextNode(aNode);
|
||||
while (node) {
|
||||
node->ClearDescendantOfCommonAncestorForRangeInSelection();
|
||||
if (!node->IsCommonAncestorForRangeInSelection()) {
|
||||
node = node->GetNextNode(aNode);
|
||||
} else {
|
||||
// We found an ancestor of an overlapping range, skip its descendants.
|
||||
node = node->GetNextNonChildNode(aNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIRange::RegisterCommonAncestor(nsINode* aNode)
|
||||
{
|
||||
NS_PRECONDITION(aNode, "bad arg");
|
||||
NS_ASSERTION(IsInSelection(), "registering range not in selection");
|
||||
|
||||
MarkDescendants(aNode);
|
||||
|
||||
RangeHashTable* ranges =
|
||||
static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
|
||||
if (!ranges) {
|
||||
ranges = new RangeHashTable;
|
||||
ranges->Init();
|
||||
aNode->SetProperty(nsGkAtoms::range, ranges, RangeHashTableDtor);
|
||||
}
|
||||
ranges->PutEntry(this);
|
||||
aNode->SetCommonAncestorForRangeInSelection();
|
||||
}
|
||||
|
||||
void
|
||||
nsIRange::UnregisterCommonAncestor(nsINode* aNode)
|
||||
{
|
||||
NS_PRECONDITION(aNode, "bad arg");
|
||||
NS_ASSERTION(aNode->IsCommonAncestorForRangeInSelection(), "wrong node");
|
||||
RangeHashTable* ranges =
|
||||
static_cast<RangeHashTable*>(aNode->GetProperty(nsGkAtoms::range));
|
||||
NS_ASSERTION(ranges->GetEntry(this), "unknown range");
|
||||
|
||||
if (ranges->Count() == 1) {
|
||||
aNode->ClearCommonAncestorForRangeInSelection();
|
||||
aNode->DeleteProperty(nsGkAtoms::range);
|
||||
UnmarkDescendants(aNode);
|
||||
} else {
|
||||
ranges->RemoveEntry(this);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* nsIMutationObserver implementation
|
||||
******************************************************/
|
||||
|
@ -293,6 +447,15 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
|
|||
if (NS_UNLIKELY(aContent == mRoot)) {
|
||||
newRoot = IsValidBoundary(newStartNode);
|
||||
}
|
||||
|
||||
bool isCommonAncestor = IsInSelection() && mStartParent == mEndParent;
|
||||
if (isCommonAncestor) {
|
||||
UnregisterCommonAncestor(mStartParent);
|
||||
RegisterCommonAncestor(newStartNode);
|
||||
}
|
||||
if (mStartParent->IsDescendantOfCommonAncestorForRangeInSelection()) {
|
||||
newStartNode->SetDescendantOfCommonAncestorForRangeInSelection();
|
||||
}
|
||||
} else {
|
||||
// If boundary is inside changed text, position it before change
|
||||
// else adjust start offset for the change in length.
|
||||
|
@ -317,6 +480,16 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
|
|||
"mEndOffset is beyond the end of this node");
|
||||
newEndOffset = static_cast<PRUint32>(mEndOffset) - aInfo->mChangeStart;
|
||||
newEndNode = aInfo->mDetails->mNextSibling;
|
||||
|
||||
bool isCommonAncestor = IsInSelection() && mStartParent == mEndParent;
|
||||
if (isCommonAncestor && !newStartNode) {
|
||||
// The split occurs inside the range.
|
||||
UnregisterCommonAncestor(mStartParent);
|
||||
RegisterCommonAncestor(mStartParent->GetParent());
|
||||
newEndNode->SetDescendantOfCommonAncestorForRangeInSelection();
|
||||
} else if (mEndParent->IsDescendantOfCommonAncestorForRangeInSelection()) {
|
||||
newEndNode->SetDescendantOfCommonAncestorForRangeInSelection();
|
||||
}
|
||||
} else {
|
||||
mEndOffset = static_cast<PRUint32>(mEndOffset) <= aInfo->mChangeEnd ?
|
||||
aInfo->mChangeStart :
|
||||
|
@ -355,11 +528,29 @@ nsRange::CharacterDataChanged(nsIDocument* aDocument,
|
|||
newEndOffset = mEndOffset;
|
||||
}
|
||||
DoSetRange(newStartNode, newStartOffset, newEndNode, newEndOffset,
|
||||
newRoot ? newRoot : mRoot.get()
|
||||
#ifdef DEBUG
|
||||
, !newEndNode->GetParent() || !newStartNode->GetParent()
|
||||
#endif
|
||||
);
|
||||
newRoot ? newRoot : mRoot.get(),
|
||||
!newEndNode->GetParent() || !newStartNode->GetParent());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsRange::ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aFirstNewContent,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{
|
||||
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
|
||||
|
||||
nsINode* container = NODE_FROM(aContainer, aDocument);
|
||||
if (container->IsSelectionDescendant() && IsInSelection()) {
|
||||
nsINode* child = aFirstNewContent;
|
||||
while (child) {
|
||||
if (!child->IsDescendantOfCommonAncestorForRangeInSelection()) {
|
||||
MarkDescendants(child);
|
||||
child->SetDescendantOfCommonAncestorForRangeInSelection();
|
||||
}
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,6 +571,11 @@ nsRange::ContentInserted(nsIDocument* aDocument,
|
|||
if (container == mEndParent && aIndexInContainer < mEndOffset) {
|
||||
++mEndOffset;
|
||||
}
|
||||
if (container->IsSelectionDescendant() &&
|
||||
!aChild->IsDescendantOfCommonAncestorForRangeInSelection()) {
|
||||
MarkDescendants(aChild);
|
||||
aChild->SetDescendantOfCommonAncestorForRangeInSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -392,6 +588,8 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
|
|||
NS_ASSERTION(mIsPositioned, "shouldn't be notified if not positioned");
|
||||
|
||||
nsINode* container = NODE_FROM(aContainer, aDocument);
|
||||
bool gravitateStart = false;
|
||||
bool gravitateEnd = false;
|
||||
|
||||
// Adjust position if a sibling was removed...
|
||||
if (container == mStartParent) {
|
||||
|
@ -401,8 +599,7 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
|
|||
}
|
||||
// ...or gravitate if an ancestor was removed.
|
||||
else if (nsContentUtils::ContentIsDescendantOf(mStartParent, aChild)) {
|
||||
mStartParent = container;
|
||||
mStartOffset = aIndexInContainer;
|
||||
gravitateStart = true;
|
||||
}
|
||||
|
||||
// Do same thing for end boundry.
|
||||
|
@ -412,8 +609,20 @@ nsRange::ContentRemoved(nsIDocument* aDocument,
|
|||
}
|
||||
}
|
||||
else if (nsContentUtils::ContentIsDescendantOf(mEndParent, aChild)) {
|
||||
mEndParent = container;
|
||||
mEndOffset = aIndexInContainer;
|
||||
gravitateEnd = true;
|
||||
}
|
||||
|
||||
if (gravitateStart || gravitateEnd) {
|
||||
DoSetRange(gravitateStart ? container : mStartParent.get(),
|
||||
gravitateStart ? aIndexInContainer : mStartOffset,
|
||||
gravitateEnd ? container : mEndParent.get(),
|
||||
gravitateEnd ? aIndexInContainer : mEndOffset,
|
||||
mRoot);
|
||||
}
|
||||
if (container->IsSelectionDescendant() &&
|
||||
aChild->IsDescendantOfCommonAncestorForRangeInSelection()) {
|
||||
aChild->ClearDescendantOfCommonAncestorForRangeInSelection();
|
||||
UnmarkDescendants(aChild);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,11 +716,7 @@ static PRUint32 GetNodeLength(nsINode *aNode)
|
|||
void
|
||||
nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
|
||||
nsINode* aEndN, PRInt32 aEndOffset,
|
||||
nsINode* aRoot
|
||||
#ifdef DEBUG
|
||||
, bool aNotInsertedYet
|
||||
#endif
|
||||
)
|
||||
nsINode* aRoot, bool aNotInsertedYet)
|
||||
{
|
||||
NS_PRECONDITION((aStartN && aEndN && aRoot) ||
|
||||
(!aStartN && !aEndN && !aRoot),
|
||||
|
@ -545,12 +750,29 @@ nsRange::DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
|
|||
aRoot->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool checkCommonAncestor = (mStartParent != aStartN || mEndParent != aEndN) &&
|
||||
IsInSelection() && !aNotInsertedYet;
|
||||
nsINode* oldCommonAncestor = checkCommonAncestor ? GetCommonAncestor() : nsnull;
|
||||
mStartParent = aStartN;
|
||||
mStartOffset = aStartOffset;
|
||||
mEndParent = aEndN;
|
||||
mEndOffset = aEndOffset;
|
||||
mIsPositioned = !!mStartParent;
|
||||
if (checkCommonAncestor) {
|
||||
nsINode* newCommonAncestor = GetCommonAncestor();
|
||||
if (newCommonAncestor != oldCommonAncestor) {
|
||||
if (oldCommonAncestor) {
|
||||
UnregisterCommonAncestor(oldCommonAncestor);
|
||||
}
|
||||
if (newCommonAncestor) {
|
||||
RegisterCommonAncestor(newCommonAncestor);
|
||||
} else {
|
||||
NS_ASSERTION(mIsDetached, "unexpected disconnected nodes");
|
||||
mInSelection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This needs to be the last thing this function does. See comment
|
||||
// in ParentChainChanged.
|
||||
mRoot = aRoot;
|
||||
|
@ -664,7 +886,7 @@ nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent)
|
|||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsINode* nsRange::IsValidBoundary(nsINode* aNode)
|
||||
nsINode* nsIRange::IsValidBoundary(nsINode* aNode)
|
||||
{
|
||||
if (!aNode) {
|
||||
return nsnull;
|
||||
|
|
|
@ -77,9 +77,7 @@ class nsRange : public nsIRange,
|
|||
public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
nsRange()
|
||||
{
|
||||
}
|
||||
nsRange(){}
|
||||
virtual ~nsRange();
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -116,14 +114,13 @@ public:
|
|||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
|
||||
private:
|
||||
// no copy's or assigns
|
||||
nsRange(const nsRange&);
|
||||
nsRange& operator=(const nsRange&);
|
||||
|
||||
nsINode* IsValidBoundary(nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Cut or delete the range's contents.
|
||||
*
|
||||
|
@ -157,16 +154,17 @@ public:
|
|||
bool *outNodeBefore,
|
||||
bool *outNodeAfter);
|
||||
|
||||
static bool IsNodeSelected(nsINode* aNode, PRUint32 aStartOffset,
|
||||
PRUint32 aEndOffset);
|
||||
|
||||
protected:
|
||||
// CharacterDataChanged set aNotInsertedYet to true to disable an assertion
|
||||
// and suppress re-registering a range common ancestor node since
|
||||
// the new text node of a splitText hasn't been inserted yet.
|
||||
// CharacterDataChanged does the re-registering when needed.
|
||||
void DoSetRange(nsINode* aStartN, PRInt32 aStartOffset,
|
||||
nsINode* aEndN, PRInt32 aEndOffset,
|
||||
nsINode* aRoot
|
||||
#ifdef DEBUG
|
||||
// CharacterDataChanged use this to disable an assertion since
|
||||
// the new text node of a splitText hasn't been inserted yet.
|
||||
, bool aNotInsertedYet = false
|
||||
#endif
|
||||
);
|
||||
nsINode* aRoot, bool aNotInsertedYet = false);
|
||||
};
|
||||
|
||||
// Make a new nsIDOMRange object
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
#include "nsIAttribute.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#ifdef DEBUG
|
||||
#include "nsIRange.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
|
@ -224,6 +227,12 @@ nsTextNode::List(FILE* out, PRInt32 aIndent) const
|
|||
|
||||
fprintf(out, "Text@%p", static_cast<const void*>(this));
|
||||
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
|
||||
if (IsCommonAncestorForRangeInSelection()) {
|
||||
typedef nsTHashtable<nsPtrHashKey<nsIRange> > RangeHashTable;
|
||||
RangeHashTable* ranges =
|
||||
static_cast<RangeHashTable*>(GetProperty(nsGkAtoms::range));
|
||||
fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
|
||||
}
|
||||
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
|
||||
fprintf(out, " refcount=%d<", mRefCnt.get());
|
||||
|
||||
|
|
|
@ -217,8 +217,8 @@ public:
|
|||
void SetIncludeAllOutOfFlows() { mIncludeAllOutOfFlows = true; }
|
||||
bool GetIncludeAllOutOfFlows() const { return mIncludeAllOutOfFlows; }
|
||||
/**
|
||||
* Calling this setter makes us exclude all leaf frames that does
|
||||
* not have the NS_FRAME_SELECTED_CONTENT bit.
|
||||
* Calling this setter makes us exclude all leaf frames that aren't
|
||||
* selected.
|
||||
*/
|
||||
void SetSelectedFramesOnly() { mSelectedFramesOnly = true; }
|
||||
bool GetSelectedFramesOnly() { return mSelectedFramesOnly; }
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#include "nsFrameTraversal.h"
|
||||
#include "nsStyleChangeList.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsITableLayout.h" //selection necessity
|
||||
#include "nsITableCellLayout.h"// "
|
||||
#include "nsITextControlFrame.h"
|
||||
|
@ -444,8 +445,7 @@ nsFrame::Init(nsIContent* aContent,
|
|||
nsFrameState state = aPrevInFlow->GetStateBits();
|
||||
|
||||
// Make bits that are currently off (see constructor) the same:
|
||||
mState |= state & (NS_FRAME_SELECTED_CONTENT |
|
||||
NS_FRAME_INDEPENDENT_SELECTION |
|
||||
mState |= state & (NS_FRAME_INDEPENDENT_SELECTION |
|
||||
NS_FRAME_IS_SPECIAL |
|
||||
NS_FRAME_MAY_BE_TRANSFORMED);
|
||||
}
|
||||
|
@ -568,8 +568,7 @@ nsFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
|
||||
shell->NotifyDestroyingFrame(this);
|
||||
|
||||
if ((mState & NS_FRAME_EXTERNAL_REFERENCE) ||
|
||||
(mState & NS_FRAME_SELECTED_CONTENT)) {
|
||||
if (mState & NS_FRAME_EXTERNAL_REFERENCE) {
|
||||
shell->ClearFrameRefs(this);
|
||||
}
|
||||
|
||||
|
@ -1204,10 +1203,7 @@ nsFrame::DisplaySelectionOverlay(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayList* aList,
|
||||
PRUint16 aContentType)
|
||||
{
|
||||
//check frame selection state
|
||||
if ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) != NS_FRAME_SELECTED_CONTENT)
|
||||
return NS_OK;
|
||||
if (!IsVisibleForPainting(aBuilder))
|
||||
if (!IsSelected() || !IsVisibleForPainting(aBuilder))
|
||||
return NS_OK;
|
||||
|
||||
nsPresContext* presContext = PresContext();
|
||||
|
@ -1922,7 +1918,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
if (childType != nsGkAtoms::placeholderFrame &&
|
||||
aBuilder->GetSelectedFramesOnly() &&
|
||||
child->IsLeaf() &&
|
||||
!(child->GetStateBits() & NS_FRAME_SELECTED_CONTENT)) {
|
||||
!aChild->IsSelected()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2493,9 +2489,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext,
|
|||
// drag the selected region to some other app.
|
||||
|
||||
SelectionDetails *details = 0;
|
||||
bool isSelected = ((GetStateBits() & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT);
|
||||
|
||||
if (isSelected)
|
||||
if (GetContent()->IsSelectionDescendant())
|
||||
{
|
||||
bool inSelection = false;
|
||||
details = frameselection->LookUpSelection(offsets.content, 0,
|
||||
|
@ -5199,8 +5193,9 @@ nsIFrame::IsVisibleOrCollapsedForPainting(nsDisplayListBuilder* aBuilder) {
|
|||
bool
|
||||
nsIFrame::IsVisibleInSelection(nsISelection* aSelection)
|
||||
{
|
||||
if ((mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT)
|
||||
return true;
|
||||
if (!GetContent() || !GetContent()->IsSelectionDescendant()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent));
|
||||
bool vis;
|
||||
|
@ -5256,11 +5251,11 @@ nsIFrame::GetFrameSelection()
|
|||
}
|
||||
|
||||
const nsFrameSelection*
|
||||
nsIFrame::GetConstFrameSelection()
|
||||
nsIFrame::GetConstFrameSelection() const
|
||||
{
|
||||
nsIFrame *frame = this;
|
||||
nsIFrame* frame = const_cast<nsIFrame*>(this);
|
||||
while (frame && (frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION)) {
|
||||
nsITextControlFrame *tcf = do_QueryFrame(frame);
|
||||
nsITextControlFrame* tcf = do_QueryFrame(frame);
|
||||
if (tcf) {
|
||||
return tcf->GetOwnedFrameSelection();
|
||||
}
|
||||
|
@ -5338,39 +5333,13 @@ nsFrame::DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
nsIFrame::SetSelected(bool aSelected, SelectionType aType)
|
||||
bool
|
||||
nsIFrame::IsFrameSelected() const
|
||||
{
|
||||
NS_ASSERTION(!GetPrevContinuation(),
|
||||
"Should only be called on first in flow");
|
||||
if (aType != nsISelectionController::SELECTION_NORMAL)
|
||||
return;
|
||||
|
||||
// check whether style allows selection
|
||||
bool selectable;
|
||||
IsSelectable(&selectable, nsnull);
|
||||
if (!selectable)
|
||||
return;
|
||||
|
||||
for (nsIFrame* f = this; f; f = f->GetNextContinuation()) {
|
||||
if (aSelected) {
|
||||
AddStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
} else {
|
||||
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
|
||||
// Repaint this frame subtree's entire area
|
||||
InvalidateFrameSubtree();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrame::GetSelected(bool *aSelected) const
|
||||
{
|
||||
if (!aSelected )
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aSelected = !!(mState & NS_FRAME_SELECTED_CONTENT);
|
||||
return NS_OK;
|
||||
NS_ASSERTION(!GetContent() || GetContent()->IsSelectionDescendant(),
|
||||
"use the public IsSelected() instead");
|
||||
return nsRange::IsNodeSelected(GetContent(), 0,
|
||||
GetContent()->GetChildCount());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -232,7 +232,6 @@ public:
|
|||
NS_IMETHOD GetOffsetFromView(nsPoint& aOffset, nsIView** aView) const;
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
NS_IMETHOD GetSelected(bool *aSelected) const;
|
||||
NS_IMETHOD IsSelectable(bool* aIsSelectable, PRUint8* aSelectStyle) const;
|
||||
|
||||
NS_IMETHOD GetSelectionController(nsPresContext *aPresContext, nsISelectionController **aSelCon);
|
||||
|
|
|
@ -596,7 +596,6 @@ public:
|
|||
*/
|
||||
nsresult MaintainSelection(nsSelectionAmount aAmount = eSelectNoAmount);
|
||||
|
||||
|
||||
nsFrameSelection();
|
||||
|
||||
void StartBatchChanges();
|
||||
|
@ -606,7 +605,7 @@ public:
|
|||
|
||||
nsIPresShell *GetShell()const { return mShell; }
|
||||
|
||||
void DisconnectFromPresShell() { StopAutoScrollTimer(); mShell = nsnull; }
|
||||
void DisconnectFromPresShell();
|
||||
private:
|
||||
nsresult TakeFocus(nsIContent *aNewFocus,
|
||||
PRUint32 aContentOffset,
|
||||
|
|
|
@ -199,8 +199,8 @@ typedef PRUint64 nsFrameState;
|
|||
// e.g., it is absolutely positioned or floated
|
||||
#define NS_FRAME_OUT_OF_FLOW NS_FRAME_STATE_BIT(8)
|
||||
|
||||
// If this bit is set, then the frame reflects content that may be selected
|
||||
#define NS_FRAME_SELECTED_CONTENT NS_FRAME_STATE_BIT(9)
|
||||
// This bit is available for re-use.
|
||||
//#define NS_FRAME_SELECTED_CONTENT NS_FRAME_STATE_BIT(9)
|
||||
|
||||
// If this bit is set, then the frame is dirty and needs to be reflowed.
|
||||
// This bit is set when the frame is first created.
|
||||
|
@ -261,6 +261,7 @@ typedef PRUint64 nsFrameState;
|
|||
|
||||
// Bits 20-31 and 60-63 of the frame state are reserved for implementations.
|
||||
#define NS_FRAME_IMPL_RESERVED nsFrameState(0xF0000000FFF00000)
|
||||
#define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED
|
||||
|
||||
// This bit is set on floats whose parent does not contain their
|
||||
// placeholder. This can happen for two reasons: (1) the float was
|
||||
|
@ -297,9 +298,6 @@ typedef PRUint64 nsFrameState;
|
|||
// This is only set during painting
|
||||
#define NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO NS_FRAME_STATE_BIT(40)
|
||||
|
||||
// Bits 0-19 and bits 32-59 of the frame state are reserved by this API.
|
||||
#define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED
|
||||
|
||||
// Box layout bits
|
||||
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
|
||||
#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)
|
||||
|
@ -579,6 +577,12 @@ public:
|
|||
void Destroy() { DestroyFrom(this); }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Return true if the frame is part of a Selection.
|
||||
* Helper method to implement the public IsSelected() API.
|
||||
*/
|
||||
virtual bool IsFrameSelected() const;
|
||||
|
||||
/**
|
||||
* Implements Destroy(). Do not call this directly except from within a
|
||||
* DestroyFrom() implementation.
|
||||
|
@ -2305,25 +2309,13 @@ public:
|
|||
*/
|
||||
virtual PRIntn GetSkipSides() const { return 0; }
|
||||
|
||||
/** Selection related calls
|
||||
/**
|
||||
* @returns true if this frame is selected.
|
||||
*/
|
||||
/**
|
||||
* Called to set the selection status of the frame.
|
||||
*
|
||||
* This must be called on the primary frame, but all continuations
|
||||
* will be affected the same way.
|
||||
*
|
||||
* This sets or clears NS_FRAME_SELECTED_CONTENT for each frame in the
|
||||
* continuation chain, if the frames are currently selectable.
|
||||
* The frames are unconditionally invalidated, if this selection type
|
||||
* is supported at all.
|
||||
* @param aSelected is it selected?
|
||||
* @param aType the selection type of the selection that you are setting on the frame
|
||||
*/
|
||||
virtual void SetSelected(bool aSelected,
|
||||
SelectionType aType);
|
||||
|
||||
NS_IMETHOD GetSelected(bool *aSelected) const = 0;
|
||||
bool IsSelected() const {
|
||||
return (GetContent() && GetContent()->IsSelectionDescendant()) ?
|
||||
IsFrameSelected() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* called to discover where this frame, or a parent frame has user-select style
|
||||
|
@ -2352,10 +2344,7 @@ public:
|
|||
* GetConstFrameSelection returns an object which methods are safe to use for
|
||||
* example in nsIFrame code.
|
||||
*/
|
||||
const nsFrameSelection* GetConstFrameSelection();
|
||||
|
||||
/** EndSelection related calls
|
||||
*/
|
||||
const nsFrameSelection* GetConstFrameSelection() const;
|
||||
|
||||
/**
|
||||
* called to find the previous/next character, word, or line returns the actual
|
||||
|
|
|
@ -267,7 +267,6 @@ public:
|
|||
|
||||
nsresult StopAutoScrollTimer();
|
||||
|
||||
|
||||
private:
|
||||
friend class nsAutoScrollTimer;
|
||||
|
||||
|
@ -1702,8 +1701,8 @@ nsFrameSelection::HandleDrag(nsIFrame *aFrame, nsPoint aPoint)
|
|||
if (!offsets.content)
|
||||
return;
|
||||
|
||||
if ((newFrame->GetStateBits() & NS_FRAME_SELECTED_CONTENT) &&
|
||||
AdjustForMaintainedSelection(offsets.content, offsets.offset))
|
||||
if (newFrame->IsSelected() &&
|
||||
AdjustForMaintainedSelection(offsets.content, offsets.offset))
|
||||
return;
|
||||
|
||||
// Adjust offsets according to maintained amount
|
||||
|
@ -1911,7 +1910,6 @@ printf(" * TakeFocus - moving into new cell\n");
|
|||
}
|
||||
|
||||
|
||||
|
||||
SelectionDetails*
|
||||
nsFrameSelection::LookUpSelection(nsIContent *aContent,
|
||||
PRInt32 aContentOffset,
|
||||
|
@ -2478,8 +2476,7 @@ printf("HandleTableSelection: Mouse down event\n");
|
|||
// Check if new cell is already selected
|
||||
nsIFrame *cellFrame = childContent->GetPrimaryFrame();
|
||||
if (!cellFrame) return NS_ERROR_NULL_POINTER;
|
||||
result = cellFrame->GetSelected(&isSelected);
|
||||
if (NS_FAILED(result)) return result;
|
||||
isSelected = cellFrame->IsSelected();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3377,6 +3374,16 @@ nsFrameSelection::GetDelayedCaretData()
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameSelection::DisconnectFromPresShell()
|
||||
{
|
||||
StopAutoScrollTimer();
|
||||
for (PRInt32 i = 0; i < nsISelectionController::NUM_SELECTIONTYPES; i++) {
|
||||
mDomSelections[i]->Clear(nsnull);
|
||||
}
|
||||
mShell = nsnull;
|
||||
}
|
||||
|
||||
//END nsISelection interface implementations
|
||||
|
||||
#if 0
|
||||
|
@ -3406,6 +3413,11 @@ nsTypedSelection::~nsTypedSelection()
|
|||
{
|
||||
setAnchorFocusRange(-1);
|
||||
|
||||
PRUint32 count = mRanges.Length();
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
mRanges[i].mRange->SetInSelection(false);
|
||||
}
|
||||
|
||||
if (mAutoScrollTimer) {
|
||||
mAutoScrollTimer->Stop();
|
||||
mAutoScrollTimer = nsnull;
|
||||
|
@ -3730,6 +3742,8 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
|
|||
if (mRanges.Length() == 0) {
|
||||
if (!mRanges.AppendElement(RangeData(aItem)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
aItem->SetInSelection(true);
|
||||
|
||||
if (aOutIndex)
|
||||
*aOutIndex = 0;
|
||||
return NS_OK;
|
||||
|
@ -3767,6 +3781,7 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
|
|||
// The new range doesn't overlap any existing ranges
|
||||
if (!mRanges.InsertElementAt(startIndex, RangeData(aItem)))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
aItem->SetInSelection(true);
|
||||
if (aOutIndex)
|
||||
*aOutIndex = startIndex;
|
||||
return NS_OK;
|
||||
|
@ -3788,6 +3803,9 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
|
|||
}
|
||||
|
||||
// Remove all the overlapping ranges
|
||||
for (PRInt32 i = startIndex; i < endIndex; ++i) {
|
||||
mRanges[i].mRange->SetInSelection(false);
|
||||
}
|
||||
mRanges.RemoveElementsAt(startIndex, endIndex - startIndex);
|
||||
|
||||
nsTArray<RangeData> temp;
|
||||
|
@ -3811,6 +3829,10 @@ nsTypedSelection::AddItem(nsIRange *aItem, PRInt32 *aOutIndex)
|
|||
if (!mRanges.InsertElementsAt(startIndex, temp))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for (PRUint32 i = 0; i < temp.Length(); ++i) {
|
||||
temp[i].mRange->SetInSelection(true);
|
||||
}
|
||||
|
||||
*aOutIndex = startIndex + insertionPoint;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3837,6 +3859,7 @@ nsTypedSelection::RemoveItem(nsIRange *aItem)
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mRanges.RemoveElementAt(idx);
|
||||
aItem->SetInSelection(false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3860,8 +3883,9 @@ nsTypedSelection::Clear(nsPresContext* aPresContext)
|
|||
{
|
||||
setAnchorFocusRange(-1);
|
||||
|
||||
for (PRInt32 i = 0; i < (PRInt32)mRanges.Length(); i ++) {
|
||||
selectFrames(aPresContext, mRanges[i].mRange, 0);
|
||||
for (PRUint32 i = 0; i < mRanges.Length(); ++i) {
|
||||
mRanges[i].mRange->SetInSelection(false);
|
||||
selectFrames(aPresContext, mRanges[i].mRange, false);
|
||||
}
|
||||
mRanges.Clear();
|
||||
|
||||
|
@ -4274,42 +4298,29 @@ nsTypedSelection::SelectAllFramesForContent(nsIContentIterator *aInnerIter,
|
|||
nsIContent *aContent,
|
||||
bool aSelected)
|
||||
{
|
||||
if (!mFrameSelection)
|
||||
return NS_OK; // nothing to do
|
||||
nsIPresShell* shell = mFrameSelection->GetShell();
|
||||
if (!shell)
|
||||
return NS_OK;
|
||||
nsresult result;
|
||||
if (!aInnerIter)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
result = aInnerIter->Init(aContent);
|
||||
nsresult result = aInnerIter->Init(aContent);
|
||||
nsIFrame *frame;
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// First select frame of content passed in
|
||||
frame = aContent->GetPrimaryFrame();
|
||||
if (frame)
|
||||
{
|
||||
frame->SetSelected(aSelected, mType);
|
||||
if (mFrameSelection->GetTableCellSelection())
|
||||
{
|
||||
nsITableCellLayout *tcl = do_QueryFrame(frame);
|
||||
if (tcl)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
if (frame && frame->GetType() == nsGkAtoms::textFrame) {
|
||||
nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
|
||||
textFrame->SetSelectedRange(0, aContent->GetText()->GetLength(), aSelected, mType);
|
||||
}
|
||||
// Now iterated through the child frames and set them
|
||||
while (!aInnerIter->IsDone())
|
||||
{
|
||||
while (!aInnerIter->IsDone()) {
|
||||
nsCOMPtr<nsIContent> innercontent =
|
||||
do_QueryInterface(aInnerIter->GetCurrentNode());
|
||||
|
||||
frame = innercontent->GetPrimaryFrame();
|
||||
if (frame)
|
||||
{
|
||||
frame->SetSelected(aSelected, mType);
|
||||
if (frame) {
|
||||
if (frame->GetType() == nsGkAtoms::textFrame) {
|
||||
nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
|
||||
textFrame->SetSelectedRange(0, innercontent->GetText()->GetLength(), aSelected, mType);
|
||||
} else {
|
||||
frame->InvalidateFrameSubtree(); // frame continuations?
|
||||
}
|
||||
}
|
||||
|
||||
aInnerIter->Next();
|
||||
|
@ -4321,21 +4332,23 @@ nsTypedSelection::SelectAllFramesForContent(nsIContentIterator *aInnerIter,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//the idea of this helper method is to select, deselect "top to bottom" traversing through the frames
|
||||
nsresult
|
||||
nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bool aFlags)
|
||||
{
|
||||
if (!mFrameSelection || !aPresContext)
|
||||
if (!mFrameSelection || !aPresContext || !aPresContext->GetPresShell())
|
||||
return NS_OK; // nothing to do
|
||||
nsIPresShell *presShell = aPresContext->GetPresShell();
|
||||
if (!presShell)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMRange> domRange = do_QueryInterface(aRange);
|
||||
if (!domRange || !aPresContext)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (mFrameSelection->GetTableCellSelection()) {
|
||||
nsINode* node = aRange->GetCommonAncestor();
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||
nsIFrame* frame = content ? content->GetPrimaryFrame()
|
||||
: aPresContext->FrameManager()->GetRootFrame();
|
||||
if (frame) {
|
||||
frame->InvalidateFrameSubtree();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIContentIterator> iter = do_CreateInstance(
|
||||
|
@ -4348,8 +4361,7 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
|
|||
kCContentIteratorCID,
|
||||
&result);
|
||||
|
||||
if ((NS_SUCCEEDED(result)) && iter && inneriter)
|
||||
{
|
||||
if ((NS_SUCCEEDED(result)) && iter) {
|
||||
result = iter->Init(aRange);
|
||||
|
||||
// loop through the content iterator for each content node
|
||||
|
@ -4360,8 +4372,7 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
|
|||
if (!content)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (content->IsNodeOfType(nsINode::eTEXT))
|
||||
{
|
||||
if (content->IsNodeOfType(nsINode::eTEXT)) {
|
||||
nsIFrame* frame = content->GetPrimaryFrame();
|
||||
// The frame could be an SVG text frame, in which case we'll ignore
|
||||
// it.
|
||||
|
@ -4380,13 +4391,9 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
|
|||
}
|
||||
|
||||
iter->First();
|
||||
|
||||
while (!iter->IsDone())
|
||||
{
|
||||
while (!iter->IsDone()) {
|
||||
content = do_QueryInterface(iter->GetCurrentNode());
|
||||
|
||||
SelectAllFramesForContent(inneriter, content, aFlags);
|
||||
|
||||
iter->Next();
|
||||
}
|
||||
|
||||
|
@ -4413,6 +4420,7 @@ nsTypedSelection::selectFrames(nsPresContext* aPresContext, nsIRange *aRange, bo
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
// nsTypedSelection::LookUpSelection
|
||||
//
|
||||
// This function is called when a node wants to know where the selection is
|
||||
|
@ -4785,13 +4793,7 @@ nsTypedSelection::AddRange(nsIRange* aRange)
|
|||
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
GetPresContext(getter_AddRefs(presContext));
|
||||
|
||||
// Ensure all frames are properly constructed for selectFrames, bug 602331.
|
||||
nsIPresShell* presShell = presContext ? presContext->GetPresShell() : nsnull;
|
||||
if (presShell) {
|
||||
presShell->FlushPendingNotifications(Flush_Frames);
|
||||
}
|
||||
selectFrames(presContext, aRange, true);
|
||||
selectFrames(presContext, aRange, true);
|
||||
|
||||
if (!mFrameSelection)
|
||||
return NS_OK;//nothing to do
|
||||
|
@ -4926,27 +4928,21 @@ nsTypedSelection::Collapse(nsINode* aParentNode, PRInt32 aOffset)
|
|||
return result;
|
||||
|
||||
#ifdef DEBUG_SELECTION
|
||||
if (aParentNode)
|
||||
{
|
||||
nsCOMPtr<nsIContent>content;
|
||||
content = do_QueryInterface(aParentNode);
|
||||
if (!content)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
printf ("Sel. Collapse to %p %s %d\n", content.get(),
|
||||
nsAtomCString(content->Tag()).get(), aOffset);
|
||||
}
|
||||
else {
|
||||
printf ("Sel. Collapse set to null parent.\n");
|
||||
if (aParentNode) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aParentNode);
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aParentNode);
|
||||
printf ("Sel. Collapse to %p %s %d\n", aParentNode,
|
||||
content ? nsAtomCString(content->Tag()).get()
|
||||
: (doc ? "DOCUMENT" : "???"),
|
||||
aOffset);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
result = AddItem(range);
|
||||
setAnchorFocusRange(0);
|
||||
selectFrames(presContext, range, true);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
setAnchorFocusRange(0);
|
||||
selectFrames(presContext, range, true);
|
||||
return mFrameSelection->NotifySelectionListeners(GetType());
|
||||
}
|
||||
|
||||
|
|
|
@ -165,11 +165,7 @@ public:
|
|||
* false otherwise
|
||||
* @param aType the type of selection added or removed
|
||||
*/
|
||||
virtual void SetSelected(bool aSelected,
|
||||
SelectionType aType);
|
||||
void SetSelectedRange(PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
bool aSelected,
|
||||
void SetSelectedRange(PRUint32 aStart, PRUint32 aEnd, bool aSelected,
|
||||
SelectionType aType);
|
||||
|
||||
virtual bool PeekOffsetNoAmount(bool aForward, PRInt32* aOffset);
|
||||
|
@ -476,6 +472,12 @@ protected:
|
|||
nscoord mAscent;
|
||||
gfxTextRun* mTextRun;
|
||||
|
||||
/**
|
||||
* Return true if the frame is part of a Selection.
|
||||
* Helper method to implement the public IsSelected() API.
|
||||
*/
|
||||
virtual bool IsFrameSelected() const;
|
||||
|
||||
// The caller of this method must call DestroySelectionDetails() on the
|
||||
// return value, if that return value is not null. Calling
|
||||
// DestroySelectionDetails() on a null value is still OK, just not necessary.
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
#include "nsFrameSelection.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsRange.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsLineBreaker.h"
|
||||
|
@ -3689,6 +3690,7 @@ nsTextFrame::Init(nsIContent* aContent,
|
|||
|
||||
// Since our content has a frame now, this flag is no longer needed.
|
||||
aContent->UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE);
|
||||
|
||||
// We're not a continuing frame.
|
||||
// mContentOffset = 0; not necessary since we get zeroed out at init
|
||||
return nsFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
|
@ -4314,6 +4316,9 @@ SelectionDetails*
|
|||
nsTextFrame::GetSelectionDetails()
|
||||
{
|
||||
const nsFrameSelection* frameSelection = GetConstFrameSelection();
|
||||
if (frameSelection->GetTableCellSelection()) {
|
||||
return nsnull;
|
||||
}
|
||||
if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) {
|
||||
SelectionDetails* details =
|
||||
frameSelection->LookUpSelection(mContent, GetContentOffset(),
|
||||
|
@ -4575,7 +4580,7 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
|||
}
|
||||
// When this frame is not selected, the text-decoration area must be in
|
||||
// frame bounds.
|
||||
if (!(GetStateBits() & NS_FRAME_SELECTED_CONTENT) ||
|
||||
if (!IsSelected() ||
|
||||
!CombineSelectionUnderlineRect(aPresContext, *aVisualOverflowRect))
|
||||
return;
|
||||
AddStateBits(TEXT_SELECTION_UNDERLINE_OVERFLOWED);
|
||||
|
@ -5025,13 +5030,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
|||
*aAllTypes = allTypes;
|
||||
|
||||
if (!allTypes) {
|
||||
// Nothing is selected in the given text range.
|
||||
if (aContentLength == aProvider.GetOriginalLength()) {
|
||||
// It's the full text range so we can remove the FRAME_SELECTED_CONTENT
|
||||
// bit to avoid going through this slow path until something is selected
|
||||
// in this frame again.
|
||||
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
// Nothing is selected in the given text range. XXX can this still occur?
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5179,14 +5178,10 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
|
|||
nsTextPaintStyle& aTextPaintStyle,
|
||||
const nsCharClipDisplayItem::ClipEdges& aClipEdges)
|
||||
{
|
||||
NS_ASSERTION(GetContent()->IsSelectionDescendant(), "wrong paint path");
|
||||
|
||||
SelectionDetails* details = GetSelectionDetails();
|
||||
if (!details) {
|
||||
if (aContentLength == aProvider.GetOriginalLength()) {
|
||||
// It's the full text range so we can remove the FRAME_SELECTED_CONTENT
|
||||
// bit to avoid going through this slow path until something is selected
|
||||
// in this frame again.
|
||||
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -5194,8 +5189,7 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
|
|||
if (!PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
|
||||
aProvider, aContentOffset, aContentLength,
|
||||
aTextPaintStyle, details, &allTypes,
|
||||
aClipEdges))
|
||||
{
|
||||
aClipEdges)) {
|
||||
DestroySelectionDetails(details);
|
||||
return false;
|
||||
}
|
||||
|
@ -5412,15 +5406,16 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
|||
gfxRect dirtyRect(aDirtyRect.x, aDirtyRect.y,
|
||||
aDirtyRect.width, aDirtyRect.height);
|
||||
// Fork off to the (slower) paint-with-selection path if necessary.
|
||||
if (nsLayoutUtils::GetNonGeneratedAncestor(this)->GetStateBits() & NS_FRAME_SELECTED_CONTENT) {
|
||||
if (IsSelected()) {
|
||||
gfxSkipCharsIterator tmp(provider.GetStart());
|
||||
PRInt32 contentOffset = tmp.ConvertSkippedToOriginal(startOffset);
|
||||
PRInt32 contentLength =
|
||||
tmp.ConvertSkippedToOriginal(startOffset + maxLength) - contentOffset;
|
||||
if (PaintTextWithSelection(ctx, framePt, textBaselinePt, dirtyRect,
|
||||
provider, contentOffset, contentLength,
|
||||
textPaintStyle, clipEdges))
|
||||
textPaintStyle, clipEdges)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nscolor foregroundColor = textPaintStyle.GetTextColor();
|
||||
|
@ -5610,8 +5605,7 @@ bool
|
|||
nsTextFrame::IsVisibleInSelection(nsISelection* aSelection)
|
||||
{
|
||||
// Check the quick way first
|
||||
bool isSelected = (mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
||||
if (!isSelected)
|
||||
if (!GetContent()->IsSelectionDescendant())
|
||||
return false;
|
||||
|
||||
SelectionDetails* details = GetSelectionDetails();
|
||||
|
@ -5801,17 +5795,17 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
|
|||
return !aRect.IsEmpty() && !givenRect.Contains(aRect);
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::SetSelected(bool aSelected,
|
||||
SelectionType aType)
|
||||
bool
|
||||
nsTextFrame::IsFrameSelected() const
|
||||
{
|
||||
SetSelectedRange(0, mContent->GetText()->GetLength(), aSelected, aType);
|
||||
NS_ASSERTION(!GetContent() || GetContent()->IsSelectionDescendant(),
|
||||
"use the public IsSelected() instead");
|
||||
return nsRange::IsNodeSelected(GetContent(), GetContentOffset(),
|
||||
GetContentEnd());
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::SetSelectedRange(PRUint32 aStart,
|
||||
PRUint32 aEnd,
|
||||
bool aSelected,
|
||||
nsTextFrame::SetSelectedRange(PRUint32 aStart, PRUint32 aEnd, bool aSelected,
|
||||
SelectionType aType)
|
||||
{
|
||||
NS_ASSERTION(!GetPrevContinuation(), "Should only be called for primary frame");
|
||||
|
@ -5825,35 +5819,18 @@ nsTextFrame::SetSelectedRange(PRUint32 aStart,
|
|||
// check whether style allows selection
|
||||
bool selectable;
|
||||
IsSelectable(&selectable, nsnull);
|
||||
if (!selectable)
|
||||
if (!selectable) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool anySelected = false;
|
||||
|
||||
nsTextFrame* f = this;
|
||||
while (f && f->GetContentEnd() <= PRInt32(aStart)) {
|
||||
if (f->GetStateBits() & NS_FRAME_SELECTED_CONTENT) {
|
||||
anySelected = true;
|
||||
}
|
||||
f = static_cast<nsTextFrame*>(f->GetNextContinuation());
|
||||
}
|
||||
|
||||
nsPresContext* presContext = PresContext();
|
||||
while (f && f->GetContentOffset() < PRInt32(aEnd)) {
|
||||
if (aSelected) {
|
||||
f->AddStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
anySelected = true;
|
||||
} else { // we need to see if any other selection is available.
|
||||
SelectionDetails *details = f->GetSelectionDetails();
|
||||
if (details) {
|
||||
anySelected = true;
|
||||
DestroySelectionDetails(details);
|
||||
} else {
|
||||
f->RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
}
|
||||
|
||||
// We may need to reflow to recompute the overflow area for
|
||||
// spellchecking or IME underline if their underline is thicker than
|
||||
// the normal decoration line.
|
||||
|
@ -5874,22 +5851,6 @@ nsTextFrame::SetSelectedRange(PRUint32 aStart,
|
|||
|
||||
f = static_cast<nsTextFrame*>(f->GetNextContinuation());
|
||||
}
|
||||
|
||||
// Scan remaining continuations to see if any are selected
|
||||
while (f && !anySelected) {
|
||||
if (f->GetStateBits() & NS_FRAME_SELECTED_CONTENT) {
|
||||
anySelected = true;
|
||||
}
|
||||
f = static_cast<nsTextFrame*>(f->GetNextContinuation());
|
||||
}
|
||||
|
||||
if (anySelected) {
|
||||
mContent->SetFlags(NS_TEXT_IN_SELECTION);
|
||||
} else {
|
||||
// This is only legal because there is only one presentation for the
|
||||
// content with a selection
|
||||
mContent->UnsetFlags(NS_TEXT_IN_SELECTION);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -7623,16 +7584,6 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
|||
|
||||
SetLength(contentLength, &aLineLayout, ALLOW_FRAME_CREATION_AND_DESTRUCTION);
|
||||
|
||||
if (mContent->HasFlag(NS_TEXT_IN_SELECTION)) {
|
||||
SelectionDetails* details = GetSelectionDetails();
|
||||
if (details) {
|
||||
AddStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
DestroySelectionDetails(details);
|
||||
} else {
|
||||
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
}
|
||||
|
||||
Invalidate(aMetrics.VisualOverflow());
|
||||
|
||||
#ifdef NOISY_REFLOW
|
||||
|
@ -7996,12 +7947,9 @@ nsTextFrame::List(FILE* out, PRInt32 aIndent) const
|
|||
|
||||
// Output the rect and state
|
||||
fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height);
|
||||
if (0 != mState) {
|
||||
if (mState & NS_FRAME_SELECTED_CONTENT) {
|
||||
fprintf(out, " [state=%016llx] SELECTED", mState);
|
||||
} else {
|
||||
fprintf(out, " [state=%016llx]", mState);
|
||||
}
|
||||
fprintf(out, " [state=%016llx]", mState);
|
||||
if (IsSelected()) {
|
||||
fprintf(out, " SELECTED");
|
||||
}
|
||||
fprintf(out, " [content=%p]", static_cast<void*>(mContent));
|
||||
if (HasOverflowAreas()) {
|
||||
|
|
|
@ -89,12 +89,7 @@ bool
|
|||
nsMathMLmoFrame::IsFrameInSelection(nsIFrame* aFrame)
|
||||
{
|
||||
NS_ASSERTION(aFrame, "null arg");
|
||||
if (!aFrame)
|
||||
return false;
|
||||
|
||||
bool isSelected = false;
|
||||
aFrame->GetSelected(&isSelected);
|
||||
if (!isSelected)
|
||||
if (!aFrame || !aFrame->IsSelected())
|
||||
return false;
|
||||
|
||||
const nsFrameSelection* frameSelection = aFrame->GetConstFrameSelection();
|
||||
|
|
|
@ -2546,15 +2546,7 @@ nsPrintEngine::FindSelectionBoundsWithList(nsPresContext* aPresContext,
|
|||
aRect += aParentFrame->GetPosition();
|
||||
for (; !aChildFrames.AtEnd(); aChildFrames.Next()) {
|
||||
nsIFrame* child = aChildFrames.get();
|
||||
// only leaf frames have this bit flipped
|
||||
// then check the hard way
|
||||
bool isSelected = (child->GetStateBits() & NS_FRAME_SELECTED_CONTENT)
|
||||
== NS_FRAME_SELECTED_CONTENT;
|
||||
if (isSelected) {
|
||||
isSelected = child->IsVisibleForPainting();
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
if (child->IsSelected() && child->IsVisibleForPainting()) {
|
||||
nsRect r = child->GetRect();
|
||||
if (aStartFrame == nsnull) {
|
||||
aStartFrame = child;
|
||||
|
|
|
@ -271,42 +271,6 @@ nsSVGGlyphFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGGlyphFrame::SetSelected(bool aSelected,
|
||||
SelectionType aType)
|
||||
{
|
||||
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
|
||||
printf("nsSVGGlyphFrame(%p)::SetSelected()\n", this);
|
||||
#endif
|
||||
|
||||
if (aType != nsISelectionController::SELECTION_NORMAL)
|
||||
return;
|
||||
|
||||
// check whether style allows selection
|
||||
bool selectable;
|
||||
IsSelectable(&selectable, nsnull);
|
||||
if (!selectable)
|
||||
return;
|
||||
|
||||
if (aSelected) {
|
||||
AddStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
} else {
|
||||
RemoveStateBits(NS_FRAME_SELECTED_CONTENT);
|
||||
}
|
||||
|
||||
nsSVGUtils::UpdateGraphic(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGlyphFrame::GetSelected(bool *aSelected) const
|
||||
{
|
||||
nsresult rv = nsSVGGlyphFrameBase::GetSelected(aSelected);
|
||||
#if defined(DEBUG) && defined(SVG_DEBUG_SELECTION)
|
||||
printf("nsSVGGlyphFrame(%p)::GetSelected()=%d\n", this, *aSelected);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSVGGlyphFrame::IsSelectable(bool* aIsSelectable,
|
||||
PRUint8* aSelectStyle) const
|
||||
|
@ -984,9 +948,7 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
|
|||
*charnum=0;
|
||||
*nchars=0;
|
||||
|
||||
bool hasHighlight =
|
||||
(mState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
||||
|
||||
bool hasHighlight = IsSelected();
|
||||
if (!hasHighlight) {
|
||||
NS_ERROR("nsSVGGlyphFrame::GetHighlight() called by renderer when there is no highlight");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -135,9 +135,6 @@ public:
|
|||
|
||||
virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);
|
||||
|
||||
virtual void SetSelected(bool aSelected,
|
||||
SelectionType aType);
|
||||
NS_IMETHOD GetSelected(bool *aSelected) const;
|
||||
NS_IMETHOD IsSelectable(bool* aIsSelectable, PRUint8* aSelectStyle) const;
|
||||
|
||||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
|
|
|
@ -318,8 +318,7 @@ void
|
|||
nsTableCellFrame::DecorateForSelection(nsRenderingContext& aRenderingContext,
|
||||
nsPoint aPt)
|
||||
{
|
||||
NS_ASSERTION(GetStateBits() & NS_FRAME_SELECTED_CONTENT,
|
||||
"Should only be called for selected cells");
|
||||
NS_ASSERTION(IsSelected(), "Should only be called for selected cells");
|
||||
PRInt16 displaySelection;
|
||||
nsPresContext* presContext = PresContext();
|
||||
displaySelection = DisplaySelection(presContext);
|
||||
|
@ -499,9 +498,7 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
}
|
||||
|
||||
// and display the selection border if we need to
|
||||
bool isSelected =
|
||||
(GetStateBits() & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
||||
if (isSelected) {
|
||||
if (IsSelected()) {
|
||||
nsresult rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
||||
nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
|
||||
"TableCellSelection",
|
||||
|
|
|
@ -3667,7 +3667,7 @@ nsTableFrame::GetCellDataAt(PRInt32 aRowIndex,
|
|||
PRInt32& aColSpan,
|
||||
PRInt32& aActualRowSpan,
|
||||
PRInt32& aActualColSpan,
|
||||
bool& aIsSelected)
|
||||
bool& aIsSelected)
|
||||
{
|
||||
// Initialize out params
|
||||
aCell = nsnull;
|
||||
|
@ -3700,8 +3700,7 @@ nsTableFrame::GetCellDataAt(PRInt32 aRowIndex,
|
|||
if (aActualRowSpan == 0 || aActualColSpan == 0)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
result = cellFrame->GetSelected(&aIsSelected);
|
||||
if (NS_FAILED(result)) return result;
|
||||
aIsSelected = cellFrame->IsSelected();
|
||||
|
||||
// do this last, because it addrefs,
|
||||
// and we don't want the caller leaking it on error
|
||||
|
|
|
@ -371,14 +371,6 @@ nsTableOuterFrame::BuildDisplayListForInnerTable(nsDisplayListBuilder* aBuilde
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsTableOuterFrame::SetSelected(bool aSelected,
|
||||
SelectionType aType)
|
||||
{
|
||||
nsFrame::SetSelected(aSelected, aType);
|
||||
InnerTableFrame()->SetSelected(aSelected, aType);
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsTableOuterFrame::GetParentStyleContextFrame()
|
||||
{
|
||||
|
|
|
@ -159,11 +159,6 @@ public:
|
|||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
#endif
|
||||
|
||||
/** SetSelected needs to be overridden to talk to inner tableframe
|
||||
*/
|
||||
void SetSelected(bool aSelected,
|
||||
SelectionType aType);
|
||||
|
||||
virtual nsIFrame* GetParentStyleContextFrame();
|
||||
|
||||
/*---------------- nsITableLayout methods ------------------------*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче