mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-18 13:17:29 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
357
editor/libeditor/SelectionState.h
Normal file
357
editor/libeditor/SelectionState.h
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_SelectionState_h
|
||||
#define mozilla_SelectionState_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nscore.h"
|
||||
|
||||
class nsCycleCollectionTraversalCallback;
|
||||
class nsIDOMCharacterData;
|
||||
class nsRange;
|
||||
namespace mozilla {
|
||||
class RangeUpdater;
|
||||
namespace dom {
|
||||
class Selection;
|
||||
class Text;
|
||||
} // namespace dom
|
||||
|
||||
/**
|
||||
* A helper struct for saving/setting ranges.
|
||||
*/
|
||||
struct RangeItem final
|
||||
{
|
||||
RangeItem();
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~RangeItem();
|
||||
|
||||
public:
|
||||
void StoreRange(nsRange* aRange);
|
||||
already_AddRefed<nsRange> GetRange();
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(RangeItem)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(RangeItem)
|
||||
|
||||
nsCOMPtr<nsINode> startNode;
|
||||
int32_t startOffset;
|
||||
nsCOMPtr<nsINode> endNode;
|
||||
int32_t endOffset;
|
||||
};
|
||||
|
||||
/**
|
||||
* mozilla::SelectionState
|
||||
*
|
||||
* Class for recording selection info. Stores selection as collection of
|
||||
* { {startnode, startoffset} , {endnode, endoffset} } tuples. Can't store
|
||||
* ranges since dom gravity will possibly change the ranges.
|
||||
*/
|
||||
|
||||
class SelectionState final
|
||||
{
|
||||
public:
|
||||
SelectionState();
|
||||
~SelectionState();
|
||||
|
||||
void SaveSelection(dom::Selection *aSel);
|
||||
nsresult RestoreSelection(dom::Selection* aSel);
|
||||
bool IsCollapsed();
|
||||
bool IsEqual(SelectionState *aSelState);
|
||||
void MakeEmpty();
|
||||
bool IsEmpty();
|
||||
private:
|
||||
nsTArray<RefPtr<RangeItem>> mArray;
|
||||
|
||||
friend class RangeUpdater;
|
||||
friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
|
||||
SelectionState&,
|
||||
const char*,
|
||||
uint32_t);
|
||||
friend void ImplCycleCollectionUnlink(SelectionState&);
|
||||
};
|
||||
|
||||
inline void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
SelectionState& aField,
|
||||
const char* aName,
|
||||
uint32_t aFlags = 0)
|
||||
{
|
||||
ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
|
||||
}
|
||||
|
||||
inline void
|
||||
ImplCycleCollectionUnlink(SelectionState& aField)
|
||||
{
|
||||
ImplCycleCollectionUnlink(aField.mArray);
|
||||
}
|
||||
|
||||
class RangeUpdater final
|
||||
{
|
||||
public:
|
||||
RangeUpdater();
|
||||
~RangeUpdater();
|
||||
|
||||
void RegisterRangeItem(RangeItem* aRangeItem);
|
||||
void DropRangeItem(RangeItem* aRangeItem);
|
||||
nsresult RegisterSelectionState(SelectionState& aSelState);
|
||||
nsresult DropSelectionState(SelectionState& aSelState);
|
||||
|
||||
// editor selection gravity routines. Note that we can't always depend on
|
||||
// DOM Range gravity to do what we want to the "real" selection. For instance,
|
||||
// if you move a node, that corresponds to deleting it and reinserting it.
|
||||
// DOM Range gravity will promote the selection out of the node on deletion,
|
||||
// which is not what you want if you know you are reinserting it.
|
||||
nsresult SelAdjCreateNode(nsINode* aParent, int32_t aPosition);
|
||||
nsresult SelAdjCreateNode(nsIDOMNode* aParent, int32_t aPosition);
|
||||
nsresult SelAdjInsertNode(nsINode* aParent, int32_t aPosition);
|
||||
nsresult SelAdjInsertNode(nsIDOMNode* aParent, int32_t aPosition);
|
||||
void SelAdjDeleteNode(nsINode* aNode);
|
||||
void SelAdjDeleteNode(nsIDOMNode* aNode);
|
||||
nsresult SelAdjSplitNode(nsIContent& aOldRightNode, int32_t aOffset,
|
||||
nsIContent* aNewLeftNode);
|
||||
nsresult SelAdjJoinNodes(nsINode& aLeftNode,
|
||||
nsINode& aRightNode,
|
||||
nsINode& aParent,
|
||||
int32_t aOffset,
|
||||
int32_t aOldLeftNodeLength);
|
||||
void SelAdjInsertText(dom::Text& aTextNode, int32_t aOffset,
|
||||
const nsAString &aString);
|
||||
nsresult SelAdjDeleteText(nsIContent* aTextNode, int32_t aOffset,
|
||||
int32_t aLength);
|
||||
nsresult SelAdjDeleteText(nsIDOMCharacterData* aTextNode,
|
||||
int32_t aOffset, int32_t aLength);
|
||||
// the following gravity routines need will/did sandwiches, because the other
|
||||
// gravity routines will be called inside of these sandwiches, but should be
|
||||
// ignored.
|
||||
nsresult WillReplaceContainer();
|
||||
nsresult DidReplaceContainer(dom::Element* aOriginalNode,
|
||||
dom::Element* aNewNode);
|
||||
nsresult WillRemoveContainer();
|
||||
nsresult DidRemoveContainer(nsINode* aNode, nsINode* aParent,
|
||||
int32_t aOffset, uint32_t aNodeOrigLen);
|
||||
nsresult DidRemoveContainer(nsIDOMNode* aNode, nsIDOMNode* aParent,
|
||||
int32_t aOffset, uint32_t aNodeOrigLen);
|
||||
nsresult WillInsertContainer();
|
||||
nsresult DidInsertContainer();
|
||||
void WillMoveNode();
|
||||
void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
|
||||
nsINode* aNewParent, int32_t aNewOffset);
|
||||
|
||||
private:
|
||||
friend void ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback&,
|
||||
RangeUpdater&,
|
||||
const char*,
|
||||
uint32_t);
|
||||
friend void ImplCycleCollectionUnlink(RangeUpdater& aField);
|
||||
|
||||
nsTArray<RefPtr<RangeItem>> mArray;
|
||||
bool mLock;
|
||||
};
|
||||
|
||||
inline void
|
||||
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
||||
RangeUpdater& aField,
|
||||
const char* aName,
|
||||
uint32_t aFlags = 0)
|
||||
{
|
||||
ImplCycleCollectionTraverse(aCallback, aField.mArray, aName, aFlags);
|
||||
}
|
||||
|
||||
inline void
|
||||
ImplCycleCollectionUnlink(RangeUpdater& aField)
|
||||
{
|
||||
ImplCycleCollectionUnlink(aField.mArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for using SelectionState. Stack based class for doing
|
||||
* preservation of dom points across editor actions.
|
||||
*/
|
||||
|
||||
class MOZ_STACK_CLASS AutoTrackDOMPoint final
|
||||
{
|
||||
private:
|
||||
RangeUpdater& mRangeUpdater;
|
||||
// Allow tracking either nsIDOMNode or nsINode until nsIDOMNode is gone
|
||||
nsCOMPtr<nsINode>* mNode;
|
||||
nsCOMPtr<nsIDOMNode>* mDOMNode;
|
||||
int32_t* mOffset;
|
||||
RefPtr<RangeItem> mRangeItem;
|
||||
|
||||
public:
|
||||
AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
|
||||
nsCOMPtr<nsINode>* aNode, int32_t* aOffset)
|
||||
: mRangeUpdater(aRangeUpdater)
|
||||
, mNode(aNode)
|
||||
, mDOMNode(nullptr)
|
||||
, mOffset(aOffset)
|
||||
{
|
||||
mRangeItem = new RangeItem();
|
||||
mRangeItem->startNode = *mNode;
|
||||
mRangeItem->endNode = *mNode;
|
||||
mRangeItem->startOffset = *mOffset;
|
||||
mRangeItem->endOffset = *mOffset;
|
||||
mRangeUpdater.RegisterRangeItem(mRangeItem);
|
||||
}
|
||||
|
||||
AutoTrackDOMPoint(RangeUpdater& aRangeUpdater,
|
||||
nsCOMPtr<nsIDOMNode>* aNode, int32_t* aOffset)
|
||||
: mRangeUpdater(aRangeUpdater)
|
||||
, mNode(nullptr)
|
||||
, mDOMNode(aNode)
|
||||
, mOffset(aOffset)
|
||||
{
|
||||
mRangeItem = new RangeItem();
|
||||
mRangeItem->startNode = do_QueryInterface(*mDOMNode);
|
||||
mRangeItem->endNode = do_QueryInterface(*mDOMNode);
|
||||
mRangeItem->startOffset = *mOffset;
|
||||
mRangeItem->endOffset = *mOffset;
|
||||
mRangeUpdater.RegisterRangeItem(mRangeItem);
|
||||
}
|
||||
|
||||
~AutoTrackDOMPoint()
|
||||
{
|
||||
mRangeUpdater.DropRangeItem(mRangeItem);
|
||||
if (mNode) {
|
||||
*mNode = mRangeItem->startNode;
|
||||
} else {
|
||||
*mDOMNode = GetAsDOMNode(mRangeItem->startNode);
|
||||
}
|
||||
*mOffset = mRangeItem->startOffset;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Another helper class for SelectionState. Stack based class for doing
|
||||
* Will/DidReplaceContainer()
|
||||
*/
|
||||
|
||||
class MOZ_STACK_CLASS AutoReplaceContainerSelNotify final
|
||||
{
|
||||
private:
|
||||
RangeUpdater& mRangeUpdater;
|
||||
dom::Element* mOriginalElement;
|
||||
dom::Element* mNewElement;
|
||||
|
||||
public:
|
||||
AutoReplaceContainerSelNotify(RangeUpdater& aRangeUpdater,
|
||||
dom::Element* aOriginalElement,
|
||||
dom::Element* aNewElement)
|
||||
: mRangeUpdater(aRangeUpdater)
|
||||
, mOriginalElement(aOriginalElement)
|
||||
, mNewElement(aNewElement)
|
||||
{
|
||||
mRangeUpdater.WillReplaceContainer();
|
||||
}
|
||||
|
||||
~AutoReplaceContainerSelNotify()
|
||||
{
|
||||
mRangeUpdater.DidReplaceContainer(mOriginalElement, mNewElement);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Another helper class for SelectionState. Stack based class for doing
|
||||
* Will/DidRemoveContainer()
|
||||
*/
|
||||
|
||||
class MOZ_STACK_CLASS AutoRemoveContainerSelNotify final
|
||||
{
|
||||
private:
|
||||
RangeUpdater& mRangeUpdater;
|
||||
nsIDOMNode* mNode;
|
||||
nsIDOMNode* mParent;
|
||||
int32_t mOffset;
|
||||
uint32_t mNodeOrigLen;
|
||||
|
||||
public:
|
||||
AutoRemoveContainerSelNotify(RangeUpdater& aRangeUpdater,
|
||||
nsINode* aNode,
|
||||
nsINode* aParent,
|
||||
int32_t aOffset,
|
||||
uint32_t aNodeOrigLen)
|
||||
: mRangeUpdater(aRangeUpdater)
|
||||
, mNode(aNode->AsDOMNode())
|
||||
, mParent(aParent->AsDOMNode())
|
||||
, mOffset(aOffset)
|
||||
, mNodeOrigLen(aNodeOrigLen)
|
||||
{
|
||||
mRangeUpdater.WillRemoveContainer();
|
||||
}
|
||||
|
||||
~AutoRemoveContainerSelNotify()
|
||||
{
|
||||
mRangeUpdater.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Another helper class for SelectionState. Stack based class for doing
|
||||
* Will/DidInsertContainer()
|
||||
*/
|
||||
|
||||
class MOZ_STACK_CLASS AutoInsertContainerSelNotify final
|
||||
{
|
||||
private:
|
||||
RangeUpdater& mRangeUpdater;
|
||||
|
||||
public:
|
||||
explicit AutoInsertContainerSelNotify(RangeUpdater& aRangeUpdater)
|
||||
: mRangeUpdater(aRangeUpdater)
|
||||
{
|
||||
mRangeUpdater.WillInsertContainer();
|
||||
}
|
||||
|
||||
~AutoInsertContainerSelNotify()
|
||||
{
|
||||
mRangeUpdater.DidInsertContainer();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Another helper class for SelectionState. Stack based class for doing
|
||||
* Will/DidMoveNode()
|
||||
*/
|
||||
|
||||
class MOZ_STACK_CLASS AutoMoveNodeSelNotify final
|
||||
{
|
||||
private:
|
||||
RangeUpdater& mRangeUpdater;
|
||||
nsINode* mOldParent;
|
||||
nsINode* mNewParent;
|
||||
int32_t mOldOffset;
|
||||
int32_t mNewOffset;
|
||||
|
||||
public:
|
||||
AutoMoveNodeSelNotify(RangeUpdater& aRangeUpdater,
|
||||
nsINode* aOldParent,
|
||||
int32_t aOldOffset,
|
||||
nsINode* aNewParent,
|
||||
int32_t aNewOffset)
|
||||
: mRangeUpdater(aRangeUpdater)
|
||||
, mOldParent(aOldParent)
|
||||
, mNewParent(aNewParent)
|
||||
, mOldOffset(aOldOffset)
|
||||
, mNewOffset(aNewOffset)
|
||||
{
|
||||
MOZ_ASSERT(aOldParent);
|
||||
MOZ_ASSERT(aNewParent);
|
||||
mRangeUpdater.WillMoveNode();
|
||||
}
|
||||
|
||||
~AutoMoveNodeSelNotify()
|
||||
{
|
||||
mRangeUpdater.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // #ifndef mozilla_SelectionState_h
|
||||
Loading…
Add table
Add a link
Reference in a new issue