зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1465702 - part 7: Make protected/private methods of EditorBase/TextEditor/HTMLEditor use SelectionRefPtr() instead of GetSelection() r=m_kato
Now, any protected/private methods of editor classes can refer SelectionRefPtr() safely. So, we can cut the cost of calling GetSelection() only once per edit action handling. Differential Revision: https://phabricator.services.mozilla.com/D10011 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
53578eb0db
Коммит
d97102c926
|
@ -939,25 +939,24 @@ EditorBase::EndTransactionInternal()
|
|||
void
|
||||
EditorBase::BeginPlaceholderTransaction(nsAtom* aTransactionName)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(mPlaceholderBatch >= 0, "negative placeholder batch count!");
|
||||
|
||||
if (!mPlaceholderBatch) {
|
||||
NotifyEditorObservers(eNotifyEditorObserversOfBefore);
|
||||
// time to turn on the batch
|
||||
BeginUpdateViewBatch();
|
||||
mPlaceholderTransaction = nullptr;
|
||||
mPlaceholderName = aTransactionName;
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (selection) {
|
||||
mSelState.emplace();
|
||||
mSelState->SaveSelection(selection);
|
||||
// Composition transaction can modify multiple nodes and it merges text
|
||||
// node for ime into single text node.
|
||||
// So if current selection is into IME text node, it might be failed
|
||||
// to restore selection by UndoTransaction.
|
||||
// So we need update selection by range updater.
|
||||
if (mPlaceholderName == nsGkAtoms::IMETxnName) {
|
||||
mRangeUpdater.RegisterSelectionState(*mSelState);
|
||||
}
|
||||
mSelState.emplace();
|
||||
mSelState->SaveSelection(SelectionRefPtr());
|
||||
// Composition transaction can modify multiple nodes and it merges text
|
||||
// node for ime into single text node.
|
||||
// So if current selection is into IME text node, it might be failed
|
||||
// to restore selection by UndoTransaction.
|
||||
// So we need update selection by range updater.
|
||||
if (mPlaceholderName == nsGkAtoms::IMETxnName) {
|
||||
mRangeUpdater.RegisterSelectionState(*mSelState);
|
||||
}
|
||||
}
|
||||
mPlaceholderBatch++;
|
||||
|
@ -966,20 +965,18 @@ EditorBase::BeginPlaceholderTransaction(nsAtom* aTransactionName)
|
|||
void
|
||||
EditorBase::EndPlaceholderTransaction()
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(mPlaceholderBatch > 0,
|
||||
"zero or negative placeholder batch count when ending batch!");
|
||||
if (mPlaceholderBatch == 1) {
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
|
||||
if (mPlaceholderBatch == 1) {
|
||||
// By making the assumption that no reflow happens during the calls
|
||||
// to EndUpdateViewBatch and ScrollSelectionIntoView, we are able to
|
||||
// allow the selection to cache a frame offset which is used by the
|
||||
// caret drawing code. We only enable this cache here; at other times,
|
||||
// we have no way to know whether reflow invalidates it
|
||||
// See bugs 35296 and 199412.
|
||||
if (selection) {
|
||||
selection->SetCanCacheFrameOffset(true);
|
||||
}
|
||||
SelectionRefPtr()->SetCanCacheFrameOffset(true);
|
||||
|
||||
// time to turn off the batch
|
||||
EndUpdateViewBatch();
|
||||
|
@ -990,9 +987,7 @@ EditorBase::EndPlaceholderTransaction()
|
|||
ScrollSelectionIntoView(false);
|
||||
|
||||
// cached for frame offset are Not available now
|
||||
if (selection) {
|
||||
selection->SetCanCacheFrameOffset(false);
|
||||
}
|
||||
SelectionRefPtr()->SetCanCacheFrameOffset(false);
|
||||
|
||||
if (mSelState) {
|
||||
// we saved the selection state, but never got to hand it to placeholder
|
||||
|
@ -3256,6 +3251,8 @@ EditorBase::DoJoinNodes(nsINode* aNodeToKeep,
|
|||
nsINode* aNodeToJoin,
|
||||
nsINode* aParent)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
MOZ_ASSERT(aNodeToKeep);
|
||||
MOZ_ASSERT(aNodeToJoin);
|
||||
MOZ_ASSERT(aParent);
|
||||
|
@ -3399,11 +3396,11 @@ EditorBase::DoJoinNodes(nsINode* aNodeToKeep,
|
|||
|
||||
if (allowedTransactionsToChangeSelection) {
|
||||
// Editor wants us to set selection at join point.
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
selection->Collapse(aNodeToKeep, AssertedCast<int32_t>(firstNodeLength));
|
||||
DebugOnly<nsresult> rv =
|
||||
SelectionRefPtr()->Collapse(aNodeToKeep,
|
||||
AssertedCast<int32_t>(firstNodeLength));
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Failed to collapse Selection at end of the node");
|
||||
}
|
||||
|
||||
return err.StealNSResult();
|
||||
|
@ -4163,14 +4160,12 @@ EditorBase::JoinNodesDeepWithTransaction(nsIContent& aLeftNode,
|
|||
void
|
||||
EditorBase::BeginUpdateViewBatch()
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(mUpdateCount >= 0, "bad state");
|
||||
|
||||
if (!mUpdateCount) {
|
||||
// Turn off selection updates and notifications.
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (selection) {
|
||||
selection->StartBatchChanges();
|
||||
}
|
||||
SelectionRefPtr()->StartBatchChanges();
|
||||
}
|
||||
|
||||
mUpdateCount++;
|
||||
|
@ -4179,6 +4174,7 @@ EditorBase::BeginUpdateViewBatch()
|
|||
void
|
||||
EditorBase::EndUpdateViewBatch()
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(mUpdateCount > 0, "bad state");
|
||||
|
||||
if (mUpdateCount <= 0) {
|
||||
|
@ -4191,10 +4187,7 @@ EditorBase::EndUpdateViewBatch()
|
|||
}
|
||||
|
||||
// Turn selection updating and notifications back on.
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (selection) {
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
SelectionRefPtr()->EndBatchChanges();
|
||||
|
||||
HTMLEditor* htmlEditor = AsHTMLEditor();
|
||||
if (!htmlEditor) {
|
||||
|
@ -4207,10 +4200,6 @@ EditorBase::EndUpdateViewBatch()
|
|||
// to a document may result in multiple events, some of them quite hard
|
||||
// to listen too (in particular when an ancestor of the selection is
|
||||
// changed but the selection itself is not changed).
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv = htmlEditor->RefereshEditingUI();
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RefereshEditingUI() failed");
|
||||
}
|
||||
|
@ -4278,13 +4267,10 @@ EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
|
|||
int32_t* aOffset,
|
||||
int32_t* aLength)
|
||||
{
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// Check whether the selection is collapsed and we should do nothing:
|
||||
if (NS_WARN_IF(selection->IsCollapsed() && aAction == eNone)) {
|
||||
if (NS_WARN_IF(SelectionRefPtr()->IsCollapsed() && aAction == eNone)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -4292,8 +4278,10 @@ EditorBase::CreateTxnForDeleteSelection(EDirection aAction,
|
|||
RefPtr<EditAggregateTransaction> aggregateTransaction =
|
||||
EditAggregateTransaction::Create();
|
||||
|
||||
for (uint32_t rangeIdx = 0; rangeIdx < selection->RangeCount(); ++rangeIdx) {
|
||||
RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
|
||||
for (uint32_t rangeIdx = 0;
|
||||
rangeIdx < SelectionRefPtr()->RangeCount();
|
||||
++rangeIdx) {
|
||||
RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(rangeIdx);
|
||||
if (NS_WARN_IF(!range)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -4530,33 +4518,44 @@ EditorBase::CreateRange(nsINode* aStartContainer,
|
|||
nsresult
|
||||
EditorBase::AppendNodeToSelectionAsRange(nsINode* aNode)
|
||||
{
|
||||
NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (NS_WARN_IF(!aNode)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> parentNode = aNode->GetParentNode();
|
||||
NS_ENSURE_TRUE(parentNode, NS_ERROR_NULL_POINTER);
|
||||
if (NS_WARN_IF(!parentNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
int32_t offset = GetChildOffset(aNode, parentNode);
|
||||
|
||||
RefPtr<nsRange> range;
|
||||
nsresult rv = CreateRange(parentNode, offset, parentNode, offset + 1,
|
||||
getter_AddRefs(range));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(!range)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult err;
|
||||
selection->AddRange(*range, err);
|
||||
SelectionRefPtr()->AddRange(*range, err);
|
||||
NS_WARNING_ASSERTION(!err.Failed(), "Failed to add range to Selection");
|
||||
return err.StealNSResult();
|
||||
}
|
||||
|
||||
nsresult
|
||||
EditorBase::ClearSelection()
|
||||
{
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
ErrorResult rv;
|
||||
selection->RemoveAllRanges(rv);
|
||||
SelectionRefPtr()->RemoveAllRanges(rv);
|
||||
NS_WARNING_ASSERTION(!rv.Failed(),
|
||||
"Failed to remove all ranges from Selection");
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
|
@ -4708,18 +4707,21 @@ EditorBase::InitializeSelectionAncestorLimit(nsIContent& aAncestorLimit)
|
|||
nsresult
|
||||
EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
nsCOMPtr<nsINode> targetNode = do_QueryInterface(aFocusEventTarget);
|
||||
NS_ENSURE_TRUE(targetNode, NS_ERROR_INVALID_ARG);
|
||||
if (NS_WARN_IF(!targetNode)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsCOMPtr<nsIContent> selectionRootContent = FindSelectionRoot(targetNode);
|
||||
if (!selectionRootContent) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_STATE(selection);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_INITIALIZED);
|
||||
if (NS_WARN_IF(!presShell)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISelectionController> selectionController =
|
||||
GetSelectionController();
|
||||
|
@ -4729,9 +4731,11 @@ EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
|
|||
|
||||
// Init the caret
|
||||
RefPtr<nsCaret> caret = presShell->GetCaret();
|
||||
NS_ENSURE_TRUE(caret, NS_ERROR_UNEXPECTED);
|
||||
if (NS_WARN_IF(!caret)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
caret->SetIgnoreUserModify(false);
|
||||
caret->SetSelection(selection);
|
||||
caret->SetSelection(SelectionRefPtr());
|
||||
selectionController->SetCaretReadOnly(IsReadonly());
|
||||
selectionController->SetCaretEnabled(true);
|
||||
|
||||
|
@ -4751,7 +4755,7 @@ EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
|
|||
if (selectionRootContent->GetParent()) {
|
||||
InitializeSelectionAncestorLimit(*selectionRootContent);
|
||||
} else {
|
||||
selection->SetAncestorLimiter(nullptr);
|
||||
SelectionRefPtr()->SetAncestorLimiter(nullptr);
|
||||
}
|
||||
|
||||
// If there is composition when this is called, we may need to restore IME
|
||||
|
@ -4760,7 +4764,7 @@ EditorBase::InitializeSelection(EventTarget* aFocusEventTarget)
|
|||
if (mComposition && mComposition->IsMovingToNewTextNode()) {
|
||||
// We need to look for the new text node from current selection.
|
||||
// XXX If selection is changed during reframe, this doesn't work well!
|
||||
nsRange* firstRange = selection->GetRangeAt(0);
|
||||
nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -564,6 +564,8 @@ HTMLEditor::SetPositionToAbsoluteOrStatic(Element& aElement,
|
|||
nsresult
|
||||
HTMLEditor::SetPositionToAbsolute(Element& aElement)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
|
||||
int32_t x, y;
|
||||
|
@ -580,10 +582,6 @@ HTMLEditor::SetPositionToAbsolute(Element& aElement)
|
|||
// container
|
||||
nsINode* parentNode = aElement.GetParentNode();
|
||||
if (parentNode->GetChildCount() == 1) {
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
RefPtr<Element> newBrElement =
|
||||
InsertBrElementWithTransaction(EditorRawDOMPoint(parentNode, 0));
|
||||
if (NS_WARN_IF(!newBrElement)) {
|
||||
|
|
|
@ -661,15 +661,7 @@ nsresult
|
|||
HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
|
||||
bool aIgnoreIfSelectionInEditingHost)
|
||||
{
|
||||
// XXX Why doesn't this check if the document is alive?
|
||||
if (!IsInitialized()) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// Use editing host. If you use root element here, selection may be
|
||||
// moved to <head> element, e.g., if there is a text node in <script>
|
||||
|
@ -682,8 +674,8 @@ HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
|
|||
// If selection range is already in the editing host and the range is not
|
||||
// start of the editing host, we shouldn't reset selection. E.g., window
|
||||
// is activated when the editor had focus before inactivated.
|
||||
if (aIgnoreIfSelectionInEditingHost && selection->RangeCount() == 1) {
|
||||
nsRange* range = selection->GetRangeAt(0);
|
||||
if (aIgnoreIfSelectionInEditingHost && SelectionRefPtr()->RangeCount() == 1) {
|
||||
nsRange* range = SelectionRefPtr()->GetRangeAt(0);
|
||||
if (!range->Collapsed() ||
|
||||
range->GetStartContainer() != editingHost.get() ||
|
||||
range->StartOffset()) {
|
||||
|
@ -775,7 +767,11 @@ HTMLEditor::MaybeCollapseSelectionAtFirstEditableNode(
|
|||
pointToPutCaret.Set(visNode, 0);
|
||||
}
|
||||
}
|
||||
return selection->Collapse(pointToPutCaret);
|
||||
nsresult rv = SelectionRefPtr()->Collapse(pointToPutCaret);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -826,7 +822,10 @@ HTMLEditor::HandleKeyPressEvent(WidgetKeyboardEvent* aKeyboardEvent)
|
|||
}
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection && selection->RangeCount(), NS_ERROR_FAILURE);
|
||||
if (NS_WARN_IF(!selection) ||
|
||||
NS_WARN_IF(!selection->RangeCount())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> node = selection->GetRangeAt(0)->GetStartContainer();
|
||||
MOZ_ASSERT(node);
|
||||
|
@ -1241,6 +1240,8 @@ HTMLEditor::TabInTable(bool inIsShift,
|
|||
nsresult
|
||||
HTMLEditor::InsertBrElementAtSelectionWithTransaction()
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// calling it text insertion to trigger moz br treatment by rules
|
||||
// XXX Why do we use EditSubAction::eInsertText here? Looks like
|
||||
// EditSubAction::eInsertParagraphSeparator or EditSubAction::eInsertNode
|
||||
|
@ -1249,17 +1250,15 @@ HTMLEditor::InsertBrElementAtSelectionWithTransaction()
|
|||
*this, EditSubAction::eInsertText,
|
||||
nsIEditor::eNext);
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_STATE(selection);
|
||||
|
||||
if (!selection->IsCollapsed()) {
|
||||
if (!SelectionRefPtr()->IsCollapsed()) {
|
||||
nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
EditorRawDOMPoint atStartOfSelection(EditorBase::GetStartPoint(*selection));
|
||||
EditorRawDOMPoint atStartOfSelection(
|
||||
EditorBase::GetStartPoint(*SelectionRefPtr()));
|
||||
if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1300,13 +1299,13 @@ nsresult
|
|||
HTMLEditor::ReplaceHeadContentsWithSourceWithTransaction(
|
||||
const nsAString& aSourceToInsert)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// don't do any post processing, rules get confused
|
||||
AutoTopLevelEditSubActionNotifier
|
||||
maybeTopLevelEditSubAction(*this,
|
||||
EditSubAction::eReplaceHeadWithHTMLSource,
|
||||
nsIEditor::eNone);
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
CommitComposition();
|
||||
|
||||
|
@ -1346,7 +1345,7 @@ HTMLEditor::ReplaceHeadContentsWithSourceWithTransaction(
|
|||
AutoPlaceholderBatch treatAsOneTransaction(*this);
|
||||
|
||||
// Get the first range in the selection, for context:
|
||||
RefPtr<nsRange> range = selection->GetRangeAt(0);
|
||||
RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(0);
|
||||
if (NS_WARN_IF(!range)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2007,38 +2006,49 @@ HTMLEditor::GetCSSBackgroundColorState(bool* aMixed,
|
|||
nsAString& aOutColor,
|
||||
bool aBlockLevel)
|
||||
{
|
||||
NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (NS_WARN_IF(!aMixed)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aMixed = false;
|
||||
// the default background color is transparent
|
||||
aOutColor.AssignLiteral("transparent");
|
||||
|
||||
// get selection
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_STATE(selection && selection->GetRangeAt(0));
|
||||
RefPtr<nsRange> firstRange = SelectionRefPtr()->GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// get selection location
|
||||
nsCOMPtr<nsINode> parent = selection->GetRangeAt(0)->GetStartContainer();
|
||||
NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsINode> parent = firstRange->GetStartContainer();
|
||||
if (NS_WARN_IF(!parent)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// is the selection collapsed?
|
||||
nsCOMPtr<nsINode> nodeToExamine;
|
||||
if (selection->IsCollapsed() || IsTextNode(parent)) {
|
||||
if (SelectionRefPtr()->IsCollapsed() || IsTextNode(parent)) {
|
||||
// we want to look at the parent and ancestors
|
||||
nodeToExamine = parent;
|
||||
} else {
|
||||
// otherwise we want to look at the first editable node after
|
||||
// {parent,offset} and its ancestors for divs with alignment on them
|
||||
nodeToExamine = selection->GetRangeAt(0)->GetChildAtStartOffset();
|
||||
nodeToExamine = firstRange->GetChildAtStartOffset();
|
||||
//GetNextNode(parent, offset, true, address_of(nodeToExamine));
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
|
||||
if (NS_WARN_IF(!nodeToExamine)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aBlockLevel) {
|
||||
// we are querying the block background (and not the text background), let's
|
||||
// climb to the block container
|
||||
nsCOMPtr<Element> blockParent = GetBlock(*nodeToExamine);
|
||||
NS_ENSURE_TRUE(blockParent, NS_OK);
|
||||
if (NS_WARN_IF(!blockParent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Make sure to not walk off onto the Document node
|
||||
do {
|
||||
|
@ -2093,16 +2103,16 @@ nsresult
|
|||
HTMLEditor::GetHTMLBackgroundColorState(bool* aMixed,
|
||||
nsAString& aOutColor)
|
||||
{
|
||||
//TODO: We don't handle "mixed" correctly!
|
||||
NS_ENSURE_TRUE(aMixed, NS_ERROR_NULL_POINTER);
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// TODO: We don't handle "mixed" correctly!
|
||||
if (NS_WARN_IF(!aMixed)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aMixed = false;
|
||||
aOutColor.Truncate();
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult error;
|
||||
RefPtr<Element> cellOrRowOrTableElement =
|
||||
GetSelectedOrParentTableElement(error);
|
||||
|
@ -2132,8 +2142,10 @@ HTMLEditor::GetHTMLBackgroundColorState(bool* aMixed,
|
|||
}
|
||||
|
||||
// If no table or cell found, get page body
|
||||
dom::Element* bodyElement = GetRoot();
|
||||
NS_ENSURE_TRUE(bodyElement, NS_ERROR_NULL_POINTER);
|
||||
Element* bodyElement = GetRoot();
|
||||
if (NS_WARN_IF(!bodyElement)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bodyElement->GetAttr(kNameSpaceID_None, nsGkAtoms::bgcolor, aOutColor);
|
||||
return NS_OK;
|
||||
|
@ -3126,12 +3138,7 @@ HTMLEditor::InsertLinkAroundSelection(Element* aAnchorElement)
|
|||
nsresult
|
||||
HTMLEditor::SetHTMLBackgroundColorWithTransaction(const nsAString& aColor)
|
||||
{
|
||||
MOZ_ASSERT(IsInitialized(), "The HTMLEditor hasn't been initialized yet");
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// Find a selected or enclosing table element to set background on
|
||||
ErrorResult error;
|
||||
|
@ -3481,26 +3488,31 @@ nsresult
|
|||
HTMLEditor::DeleteSelectionWithTransaction(EDirection aAction,
|
||||
EStripWrappers aStripWrappers)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);
|
||||
|
||||
nsresult rv =
|
||||
TextEditor::DeleteSelectionWithTransaction(aAction, aStripWrappers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// If we weren't asked to strip any wrappers, we're done.
|
||||
if (aStripWrappers == eNoStrip) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
// Just checking that the selection itself is collapsed doesn't seem to work
|
||||
// right in the multi-range case
|
||||
NS_ENSURE_STATE(selection);
|
||||
NS_ENSURE_STATE(selection->GetAnchorFocusRange());
|
||||
NS_ENSURE_STATE(selection->GetAnchorFocusRange()->Collapsed());
|
||||
if (NS_WARN_IF(!SelectionRefPtr()->GetAnchorFocusRange()) ||
|
||||
NS_WARN_IF(!SelectionRefPtr()->GetAnchorFocusRange()->Collapsed()) ||
|
||||
NS_WARN_IF(!SelectionRefPtr()->GetAnchorNode()->IsContent())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(selection->GetAnchorNode()->IsContent());
|
||||
nsCOMPtr<nsIContent> content = selection->GetAnchorNode()->AsContent();
|
||||
nsCOMPtr<nsIContent> content =
|
||||
SelectionRefPtr()->GetAnchorNode()->AsContent();
|
||||
|
||||
// Don't strip wrappers if this is the only wrapper in the block. Then we'll
|
||||
// add a <br> later, so it won't be an empty wrapper in the end.
|
||||
|
@ -3513,7 +3525,9 @@ HTMLEditor::DeleteSelectionWithTransaction(EDirection aAction,
|
|||
}
|
||||
bool emptyBlockParent;
|
||||
rv = IsEmptyNode(blockParent, &emptyBlockParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (emptyBlockParent) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -3527,7 +3541,9 @@ HTMLEditor::DeleteSelectionWithTransaction(EDirection aAction,
|
|||
content = content->GetParent();
|
||||
}
|
||||
rv = DeleteNodeWithTransaction(*content);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -3846,6 +3862,8 @@ HTMLEditor::SelectEntireDocument()
|
|||
nsresult
|
||||
HTMLEditor::SelectAllInternal()
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
CommitComposition();
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return NS_ERROR_EDITOR_DESTROYED;
|
||||
|
@ -3857,12 +3875,7 @@ HTMLEditor::SelectAllInternal()
|
|||
// before committing composition and check if selection is still in
|
||||
// same editing host.
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsINode* anchorNode = selection->GetAnchorNode();
|
||||
nsINode* anchorNode = SelectionRefPtr()->GetAnchorNode();
|
||||
if (NS_WARN_IF(!anchorNode) || NS_WARN_IF(!anchorNode->IsContent())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -3870,7 +3883,7 @@ HTMLEditor::SelectAllInternal()
|
|||
nsIContent* anchorContent = anchorNode->AsContent();
|
||||
nsIContent* rootContent;
|
||||
if (anchorContent->HasIndependentSelection()) {
|
||||
selection->SetAncestorLimiter(nullptr);
|
||||
SelectionRefPtr()->SetAncestorLimiter(nullptr);
|
||||
rootContent = mRootElement;
|
||||
} else {
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
|
@ -3881,12 +3894,12 @@ HTMLEditor::SelectAllInternal()
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
Maybe<mozilla::dom::Selection::AutoUserInitiated> userSelection;
|
||||
Maybe<Selection::AutoUserInitiated> userSelection;
|
||||
if (!rootContent->IsEditable()) {
|
||||
userSelection.emplace(selection);
|
||||
userSelection.emplace(SelectionRefPtr());
|
||||
}
|
||||
ErrorResult errorResult;
|
||||
selection->SelectAllChildren(*rootContent, errorResult);
|
||||
SelectionRefPtr()->SelectAllChildren(*rootContent, errorResult);
|
||||
NS_WARNING_ASSERTION(!errorResult.Failed(), "SelectAllChildren() failed");
|
||||
return errorResult.StealNSResult();
|
||||
}
|
||||
|
@ -3935,6 +3948,8 @@ HTMLEditor::IsTextPropertySetByContent(nsINode* aNode,
|
|||
bool
|
||||
HTMLEditor::SetCaretInTableCell(Element* aElement)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (!aElement || !aElement->IsHTMLElement() ||
|
||||
!HTMLEditUtils::IsTableElement(aElement) ||
|
||||
!IsDescendantOfEditorRoot(aElement)) {
|
||||
|
@ -3947,10 +3962,10 @@ HTMLEditor::SetCaretInTableCell(Element* aElement)
|
|||
}
|
||||
|
||||
// Set selection at beginning of the found node
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, false);
|
||||
|
||||
return NS_SUCCEEDED(selection->Collapse(node, 0));
|
||||
nsresult rv = SelectionRefPtr()->Collapse(node, 0);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Failed to collapse Selection in aElement");
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4049,10 +4064,7 @@ HTMLEditor::SetSelectionAtDocumentStart()
|
|||
nsresult
|
||||
HTMLEditor::RemoveBlockContainerWithTransaction(Element& aElement)
|
||||
{
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// Two possibilities: the container could be empty of editable content. If
|
||||
// that is the case, we need to compare what is before and after aNode to
|
||||
|
@ -4819,6 +4831,8 @@ HTMLEditor::CopyLastEditableChildStylesWithTransaction(
|
|||
Element& aNewBlock,
|
||||
RefPtr<Element>* aNewBrElement)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (NS_WARN_IF(!aNewBrElement)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -4906,10 +4920,6 @@ HTMLEditor::CopyLastEditableChildStylesWithTransaction(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
RefPtr<Element> brElement =
|
||||
InsertBrElementWithTransaction(EditorRawDOMPoint(firstClonsedElement, 0));
|
||||
if (NS_WARN_IF(!brElement)) {
|
||||
|
|
|
@ -1039,16 +1039,15 @@ HTMLEditor::GetInlinePropertyBase(nsAtom& aProperty,
|
|||
bool* aAll,
|
||||
nsAString* outValue)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
*aAny = false;
|
||||
*aAll = true;
|
||||
*aFirst = false;
|
||||
bool first = true;
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
|
||||
|
||||
bool isCollapsed = selection->IsCollapsed();
|
||||
RefPtr<nsRange> range = selection->GetRangeAt(0);
|
||||
bool isCollapsed = SelectionRefPtr()->IsCollapsed();
|
||||
RefPtr<nsRange> range = SelectionRefPtr()->GetRangeAt(0);
|
||||
// XXX: Should be a while loop, to get each separate range
|
||||
// XXX: ERROR_HANDLING can currentItem be null?
|
||||
if (range) {
|
||||
|
@ -1057,7 +1056,9 @@ HTMLEditor::GetInlinePropertyBase(nsAtom& aProperty,
|
|||
|
||||
if (isCollapsed) {
|
||||
nsCOMPtr<nsINode> collapsedNode = range->GetStartContainer();
|
||||
NS_ENSURE_TRUE(collapsedNode, NS_ERROR_FAILURE);
|
||||
if (NS_WARN_IF(!collapsedNode)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
bool isSet, theSetting;
|
||||
nsString tOutString;
|
||||
if (aAttribute) {
|
||||
|
@ -1506,23 +1507,29 @@ HTMLEditor::DecreaseFontSize()
|
|||
nsresult
|
||||
HTMLEditor::RelativeFontChange(FontSize aDir)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
CommitComposition();
|
||||
|
||||
// Get the selection
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
|
||||
// If selection is collapsed, set typing state
|
||||
if (selection->IsCollapsed()) {
|
||||
if (SelectionRefPtr()->IsCollapsed()) {
|
||||
nsAtom& atom = aDir == FontSize::incr ? *nsGkAtoms::big :
|
||||
*nsGkAtoms::small;
|
||||
*nsGkAtoms::small;
|
||||
|
||||
// Let's see in what kind of element the selection is
|
||||
NS_ENSURE_TRUE(selection->RangeCount() &&
|
||||
selection->GetRangeAt(0)->GetStartContainer(), NS_OK);
|
||||
OwningNonNull<nsINode> selectedNode =
|
||||
*selection->GetRangeAt(0)->GetStartContainer();
|
||||
if (NS_WARN_IF(!SelectionRefPtr()->RangeCount())) {
|
||||
return NS_OK;
|
||||
}
|
||||
RefPtr<nsRange> firstRange = SelectionRefPtr()->GetRangeAt(0);
|
||||
if (NS_WARN_IF(!firstRange) ||
|
||||
NS_WARN_IF(!firstRange->GetStartContainer())) {
|
||||
return NS_OK;
|
||||
}
|
||||
OwningNonNull<nsINode> selectedNode = *firstRange->GetStartContainer();
|
||||
if (IsTextNode(selectedNode)) {
|
||||
NS_ENSURE_TRUE(selectedNode->GetParentNode(), NS_OK);
|
||||
if (NS_WARN_IF(!selectedNode->GetParentNode())) {
|
||||
return NS_OK;
|
||||
}
|
||||
selectedNode = *selectedNode->GetParentNode();
|
||||
}
|
||||
if (!CanContainTag(selectedNode, atom)) {
|
||||
|
@ -1544,11 +1551,13 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
|
|||
AutoTransactionsConserveSelection dontChangeMySelection(*this);
|
||||
|
||||
// Loop through the ranges in the selection
|
||||
AutoRangeArray arrayOfRanges(selection);
|
||||
AutoRangeArray arrayOfRanges(SelectionRefPtr());
|
||||
for (auto& range : arrayOfRanges.mRanges) {
|
||||
// Adjust range to include any ancestors with entirely selected children
|
||||
nsresult rv = PromoteInlineRange(*range);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Check for easy case: both range endpoints in same text node
|
||||
nsCOMPtr<nsINode> startNode = range->GetStartContainer();
|
||||
|
@ -1557,7 +1566,9 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
|
|||
rv = RelativeFontChangeOnTextNode(aDir, *startNode->GetAsText(),
|
||||
range->StartOffset(),
|
||||
range->EndOffset());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
// Not the easy case. Range not contained in single text node. There
|
||||
// are up to three phases here. There are all the nodes reported by the
|
||||
|
@ -1577,7 +1588,9 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
|
|||
if (NS_SUCCEEDED(rv)) {
|
||||
nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
|
||||
for (; !iter->IsDone(); iter->Next()) {
|
||||
NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE);
|
||||
if (NS_WARN_IF(!iter->GetCurrentNode()->IsContent())) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
OwningNonNull<nsIContent> node = *iter->GetCurrentNode()->AsContent();
|
||||
|
||||
if (IsEditable(node)) {
|
||||
|
@ -1588,7 +1601,9 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
|
|||
// Now that we have the list, do the font size change on each node
|
||||
for (auto& node : arrayOfNodes) {
|
||||
rv = RelativeFontChangeOnNode(aDir == FontSize::incr ? +1 : -1, node);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Now check the start and end parents of the range to see if they need
|
||||
|
@ -1598,12 +1613,16 @@ HTMLEditor::RelativeFontChange(FontSize aDir)
|
|||
rv = RelativeFontChangeOnTextNode(aDir, *startNode->GetAsText(),
|
||||
range->StartOffset(),
|
||||
startNode->Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
if (IsTextNode(endNode) && IsEditable(endNode)) {
|
||||
rv = RelativeFontChangeOnTextNode(aDir, *endNode->GetAsText(), 0,
|
||||
range->EndOffset());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1401,6 +1401,8 @@ nsresult
|
|||
HTMLEditor::DeleteTableColumnWithTransaction(Element& aTableElement,
|
||||
int32_t aColumnIndex)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
// XXX Why don't this method remove proper <col> (and <colgroup>)?
|
||||
ErrorResult error;
|
||||
IgnoredErrorResult ignoredError;
|
||||
|
@ -1473,10 +1475,6 @@ HTMLEditor::DeleteTableColumnWithTransaction(Element& aTableElement,
|
|||
|
||||
if (tableSize.mRowCount == 1) {
|
||||
// We're deleting the last row. So, let's remove the <table> now.
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsresult rv = DeleteTableElementAndChildrenWithTransaction(aTableElement);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -3958,12 +3956,9 @@ HTMLEditor::SetSelectionAfterTableEdit(Element* aTable,
|
|||
int32_t aDirection,
|
||||
bool aSelected)
|
||||
{
|
||||
if (NS_WARN_IF(!aTable) || Destroyed()) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (!selection) {
|
||||
if (NS_WARN_IF(!aTable) || Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4026,7 +4021,9 @@ HTMLEditor::SetSelectionAfterTableEdit(Element* aTable,
|
|||
if (NS_WARN_IF(!atTable.IsSetAndValid())) {
|
||||
return;
|
||||
}
|
||||
selection->Collapse(atTable);
|
||||
DebugOnly<nsresult> rv = SelectionRefPtr()->Collapse(atTable);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Failed to collapse Selection at the table");
|
||||
return;
|
||||
}
|
||||
// Last resort: Set selection to start of doc
|
||||
|
|
|
@ -881,17 +881,14 @@ TextEditor::DeleteSelectionWithTransaction(EDirection aDirection,
|
|||
already_AddRefed<Element>
|
||||
TextEditor::DeleteSelectionAndCreateElement(nsAtom& aTag)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
nsresult rv = DeleteSelectionAndPrepareToCreateNode();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EditorRawDOMPoint pointToInsert(selection->AnchorRef());
|
||||
EditorRawDOMPoint pointToInsert(SelectionRefPtr()->AnchorRef());
|
||||
if (!pointToInsert.IsSet()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -904,7 +901,7 @@ TextEditor::DeleteSelectionAndCreateElement(nsAtom& aTag)
|
|||
NS_WARNING_ASSERTION(advanced,
|
||||
"Failed to move offset next to the new element");
|
||||
ErrorResult error;
|
||||
selection->Collapse(afterNewElement, error);
|
||||
SelectionRefPtr()->Collapse(afterNewElement, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
// XXX Even if it succeeded to create new element, this returns error
|
||||
// when Selection.Collapse() fails something. This could occur with
|
||||
|
@ -918,28 +915,25 @@ TextEditor::DeleteSelectionAndCreateElement(nsAtom& aTag)
|
|||
nsresult
|
||||
TextEditor::DeleteSelectionAndPrepareToCreateNode()
|
||||
{
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (NS_WARN_IF(!selection->GetAnchorFocusRange())) {
|
||||
if (NS_WARN_IF(!SelectionRefPtr()->GetAnchorFocusRange())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!selection->GetAnchorFocusRange()->Collapsed()) {
|
||||
if (!SelectionRefPtr()->GetAnchorFocusRange()->Collapsed()) {
|
||||
nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
MOZ_ASSERT(selection->GetAnchorFocusRange() &&
|
||||
selection->GetAnchorFocusRange()->Collapsed(),
|
||||
MOZ_ASSERT(SelectionRefPtr()->GetAnchorFocusRange() &&
|
||||
SelectionRefPtr()->GetAnchorFocusRange()->Collapsed(),
|
||||
"Selection not collapsed after delete");
|
||||
}
|
||||
|
||||
// If the selection is a chardata node, split it if necessary and compute
|
||||
// where to put the new node
|
||||
EditorDOMPoint atAnchor(selection->AnchorRef());
|
||||
EditorDOMPoint atAnchor(SelectionRefPtr()->AnchorRef());
|
||||
if (NS_WARN_IF(!atAnchor.IsSet()) || !atAnchor.IsInDataNode()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -954,7 +948,7 @@ TextEditor::DeleteSelectionAndPrepareToCreateNode()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ErrorResult error;
|
||||
selection->Collapse(atAnchorContainer, error);
|
||||
SelectionRefPtr()->Collapse(atAnchorContainer, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
@ -967,7 +961,7 @@ TextEditor::DeleteSelectionAndPrepareToCreateNode()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ErrorResult error;
|
||||
selection->Collapse(afterAnchorContainer, error);
|
||||
SelectionRefPtr()->Collapse(afterAnchorContainer, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
@ -985,7 +979,7 @@ TextEditor::DeleteSelectionAndPrepareToCreateNode()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
MOZ_ASSERT(atRightNode.IsSetAndValid());
|
||||
selection->Collapse(atRightNode, error);
|
||||
SelectionRefPtr()->Collapse(atRightNode, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
@ -1803,17 +1797,14 @@ TextEditor::Redo(uint32_t aCount)
|
|||
bool
|
||||
TextEditor::CanCutOrCopy(PasswordFieldAllowed aPasswordFieldAllowed)
|
||||
{
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (!selection) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (aPasswordFieldAllowed == ePasswordFieldNotAllowed &&
|
||||
IsPasswordEditor()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !selection->IsCollapsed();
|
||||
return !SelectionRefPtr()->IsCollapsed();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1821,20 +1812,20 @@ TextEditor::FireClipboardEvent(EventMessage aEventMessage,
|
|||
int32_t aSelectionType,
|
||||
bool* aActionTaken)
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (aEventMessage == ePaste) {
|
||||
CommitComposition();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
NS_ENSURE_TRUE(presShell, false);
|
||||
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (!selection) {
|
||||
if (NS_WARN_IF(!presShell)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nsCopySupport::FireClipboardEvent(aEventMessage, aSelectionType,
|
||||
presShell, selection, aActionTaken)) {
|
||||
presShell, SelectionRefPtr(),
|
||||
aActionTaken)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1935,6 +1926,8 @@ TextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
|
|||
uint32_t aDocumentEncoderFlags,
|
||||
const nsACString& aCharset) const
|
||||
{
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
nsCOMPtr<nsIDocumentEncoder> docEncoder;
|
||||
if (!mCachedDocumentEncoder ||
|
||||
!mCachedDocumentEncoderType.Equals(aFormatType)) {
|
||||
|
@ -1975,11 +1968,7 @@ TextEditor::GetAndInitDocEncoder(const nsAString& aFormatType,
|
|||
// We do this either if the OutputSelectionOnly flag is set,
|
||||
// in which case we use our existing selection ...
|
||||
if (aDocumentEncoderFlags & nsIDocumentEncoder::OutputSelectionOnly) {
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
if (NS_WARN_IF(!selection)) {
|
||||
return nullptr;
|
||||
}
|
||||
rv = docEncoder->SetSelection(selection);
|
||||
rv = docEncoder->SetSelection(SelectionRefPtr());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2179,10 +2168,9 @@ TextEditor::SharedOutputString(uint32_t aFlags,
|
|||
bool* aIsCollapsed,
|
||||
nsAString& aResult)
|
||||
{
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_TRUE(selection, NS_ERROR_NOT_INITIALIZED);
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
*aIsCollapsed = selection->IsCollapsed();
|
||||
*aIsCollapsed = SelectionRefPtr()->IsCollapsed();
|
||||
|
||||
if (!*aIsCollapsed) {
|
||||
aFlags |= nsIDocumentEncoder::OutputSelectionOnly;
|
||||
|
|
|
@ -70,10 +70,9 @@ TextEditor::InsertTextAt(const nsAString& aStringToInsert,
|
|||
int32_t aDestOffset,
|
||||
bool aDoDeleteSelection)
|
||||
{
|
||||
if (aDestinationNode) {
|
||||
RefPtr<Selection> selection = GetSelection();
|
||||
NS_ENSURE_STATE(selection);
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
|
||||
if (aDestinationNode) {
|
||||
nsCOMPtr<nsINode> targetNode = aDestinationNode;
|
||||
int32_t targetOffset = aDestOffset;
|
||||
|
||||
|
@ -88,7 +87,8 @@ TextEditor::InsertTextAt(const nsAString& aStringToInsert,
|
|||
}
|
||||
|
||||
ErrorResult error;
|
||||
selection->Collapse(RawRangeBoundary(targetNode, targetOffset), error);
|
||||
SelectionRefPtr()->Collapse(RawRangeBoundary(targetNode, targetOffset),
|
||||
error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
return error.StealNSResult();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче