/* -*- 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/. */ #include "mozilla/EditorBase.h" #include "mozilla/DebugOnly.h" // for DebugOnly #include "mozilla/Encoding.h" // for Encoding #include // for nullptr, stdout #include // for strcmp #include "ChangeAttributeTransaction.h" // for ChangeAttributeTransaction #include "CompositionTransaction.h" // for CompositionTransaction #include "CreateElementTransaction.h" // for CreateElementTransaction #include "DeleteNodeTransaction.h" // for DeleteNodeTransaction #include "DeleteRangeTransaction.h" // for DeleteRangeTransaction #include "DeleteTextTransaction.h" // for DeleteTextTransaction #include "EditAggregateTransaction.h" // for EditAggregateTransaction #include "EditorEventListener.h" // for EditorEventListener #include "HTMLEditRules.h" // for HTMLEditRules #include "InsertNodeTransaction.h" // for InsertNodeTransaction #include "InsertTextTransaction.h" // for InsertTextTransaction #include "JoinNodeTransaction.h" // for JoinNodeTransaction #include "PlaceholderTransaction.h" // for PlaceholderTransaction #include "SplitNodeTransaction.h" // for SplitNodeTransaction #include "TextEditUtils.h" // for TextEditUtils #include "mozilla/CheckedInt.h" // for CheckedInt #include "mozilla/ComputedStyle.h" // for ComputedStyle #include "mozilla/CSSEditUtils.h" // for CSSEditUtils #include "mozilla/EditAction.h" // for EditSubAction #include "mozilla/EditorDOMPoint.h" // for EditorDOMPoint #include "mozilla/EditorSpellCheck.h" // for EditorSpellCheck #include "mozilla/EditorUtils.h" // for various helper classes. #include "mozilla/EditTransactionBase.h" // for EditTransactionBase #include "mozilla/FlushType.h" // for FlushType::Frames #include "mozilla/IMEContentObserver.h" // for IMEContentObserver #include "mozilla/IMEStateManager.h" // for IMEStateManager #include "mozilla/mozalloc.h" // for operator new, etc. #include "mozilla/mozInlineSpellChecker.h" // for mozInlineSpellChecker #include "mozilla/mozSpellChecker.h" // for mozSpellChecker #include "mozilla/Preferences.h" // for Preferences #include "mozilla/PresShell.h" // for PresShell #include "mozilla/RangeBoundary.h" // for RawRangeBoundary, RangeBoundary #include "mozilla/Services.h" // for GetObserverService #include "mozilla/ServoCSSParser.h" // for ServoCSSParser #include "mozilla/StaticPrefs_bidi.h" // for StaticPrefs::bidi_* #include "mozilla/TextComposition.h" // for TextComposition #include "mozilla/TextInputListener.h" // for TextInputListener #include "mozilla/TextServicesDocument.h" // for TextServicesDocument #include "mozilla/TextEvents.h" #include "mozilla/TransactionManager.h" // for TransactionManager #include "mozilla/dom/AbstractRange.h" // for AbstractRange #include "mozilla/dom/CharacterData.h" // for CharacterData #include "mozilla/dom/DataTransfer.h" // for DataTransfer #include "mozilla/dom/Element.h" // for Element, nsINode::AsElement #include "mozilla/dom/EventTarget.h" // for EventTarget #include "mozilla/dom/HTMLBodyElement.h" #include "mozilla/dom/HTMLBRElement.h" #include "mozilla/dom/Selection.h" // for Selection, etc. #include "mozilla/dom/Text.h" #include "mozilla/dom/Event.h" #include "nsAString.h" // for nsAString::Length, etc. #include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker #include "nsCaret.h" // for nsCaret #include "nsCaseTreatment.h" #include "nsCharTraits.h" // for NS_IS_HIGH_SURROGATE, etc. #include "nsComponentManagerUtils.h" // for do_CreateInstance #include "nsComputedDOMStyle.h" // for nsComputedDOMStyle #include "nsContentUtils.h" // for nsContentUtils #include "nsDOMString.h" // for DOMStringIsNull #include "nsDebug.h" // for NS_ENSURE_TRUE, etc. #include "nsError.h" // for NS_OK, etc. #include "nsFocusManager.h" // for nsFocusManager #include "nsFrameSelection.h" // for nsFrameSelection #include "nsGenericHTMLElement.h" // for nsGenericHTMLElement #include "nsGkAtoms.h" // for nsGkAtoms, nsGkAtoms::dir #include "nsIAbsorbingTransaction.h" // for nsIAbsorbingTransaction #include "nsAtom.h" // for nsAtom #include "nsIContent.h" // for nsIContent #include "mozilla/dom/Document.h" // for Document #include "nsIDOMEventListener.h" // for nsIDOMEventListener #include "nsIDocumentStateListener.h" // for nsIDocumentStateListener #include "nsIEditActionListener.h" // for nsIEditActionListener #include "nsIEditorObserver.h" // for nsIEditorObserver #include "nsIEditorSpellCheck.h" // for nsIEditorSpellCheck #include "nsIFrame.h" // for nsIFrame #include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc. #include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc. #include "nsINode.h" // for nsINode, etc. #include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc. #include "nsISelectionController.h" // for nsISelectionController, etc. #include "nsISelectionDisplay.h" // for nsISelectionDisplay, etc. #include "nsISupportsBase.h" // for nsISupports #include "nsISupportsUtils.h" // for NS_ADDREF, NS_IF_ADDREF #include "nsITransferable.h" // for nsITransferable #include "nsITransaction.h" // for nsITransaction #include "nsITransactionManager.h" #include "nsIWeakReference.h" // for nsISupportsWeakReference #include "nsIWidget.h" // for nsIWidget, IMEState, etc. #include "nsPIDOMWindow.h" // for nsPIDOMWindow #include "nsPresContext.h" // for nsPresContext #include "nsRange.h" // for nsRange #include "nsReadableUtils.h" // for EmptyString, ToNewCString #include "nsString.h" // for nsAutoString, nsString, etc. #include "nsStringFwd.h" // for nsString #include "nsStyleConsts.h" // for NS_STYLE_DIRECTION_RTL, etc. #include "nsStyleStruct.h" // for nsStyleDisplay, nsStyleText, etc. #include "nsStyleStructFwd.h" // for nsIFrame::StyleUIReset, etc. #include "nsStyleUtil.h" // for nsStyleUtil #include "nsTextNode.h" // for nsTextNode #include "nsThreadUtils.h" // for nsRunnable #include "prtime.h" // for PR_Now class nsIOutputStream; class nsITransferable; namespace mozilla { using namespace dom; using namespace widget; /***************************************************************************** * mozilla::EditorBase *****************************************************************************/ template EditActionResult EditorBase::SetCaretBidiLevelForDeletion( const EditorDOMPoint& aPointAtCaret, nsIEditor::EDirection aDirectionAndAmount) const; template EditActionResult EditorBase::SetCaretBidiLevelForDeletion( const EditorRawDOMPoint& aPointAtCaret, nsIEditor::EDirection aDirectionAndAmount) const; EditorBase::EditorBase() : mEditActionData(nullptr), mPlaceholderName(nullptr), mModCount(0), mFlags(0), mUpdateCount(0), mPlaceholderBatch(0), mDocDirtyState(-1), mSpellcheckCheckboxState(eTriUnset), mAllowsTransactionsToChangeSelection(true), mDidPreDestroy(false), mDidPostCreate(false), mDispatchInputEvent(true), mIsInEditSubAction(false), mHidingCaret(false), mSpellCheckerDictionaryUpdated(true), mIsHTMLEditorClass(false) {} EditorBase::~EditorBase() { MOZ_ASSERT(!IsInitialized() || mDidPreDestroy, "Why PreDestroy hasn't been called?"); if (mComposition) { mComposition->OnEditorDestroyed(); mComposition = nullptr; } // If this editor is still hiding the caret, we need to restore it. HideCaret(false); mTransactionManager = nullptr; } NS_IMPL_CYCLE_COLLECTION_CLASS(EditorBase) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase) // Remove event listeners first since EditorEventListener may need // mDocument, mEventTarget, etc. if (tmp->mEventListener) { tmp->mEventListener->Disconnect(); tmp->mEventListener = nullptr; } NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootElement) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaddingBRElementForEmptyEditor) NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelectionController) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mIMEContentObserver) NS_IMPL_CYCLE_COLLECTION_UNLINK(mInlineSpellChecker) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextServicesDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextInputListener) NS_IMPL_CYCLE_COLLECTION_UNLINK(mTransactionManager) NS_IMPL_CYCLE_COLLECTION_UNLINK(mActionListeners) NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers) NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners) NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaceholderTransaction) NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EditorBase) Document* currentDoc = tmp->mRootElement ? tmp->mRootElement->GetUncomposedDoc() : nullptr; if (currentDoc && nsCCUncollectableMarker::InGeneration( cb, currentDoc->GetMarkedCCGeneration())) { return NS_SUCCESS_INTERRUPTED_TRAVERSE; } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootElement) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaddingBRElementForEmptyEditor) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelectionController) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIMEContentObserver) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInlineSpellChecker) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextServicesDocument) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextInputListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTransactionManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mActionListeners) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorObservers) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocStateListeners) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlaceholderTransaction) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EditorBase) NS_INTERFACE_MAP_ENTRY(nsISelectionListener) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsIEditor) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor) NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTING_ADDREF(EditorBase) NS_IMPL_CYCLE_COLLECTING_RELEASE(EditorBase) nsresult EditorBase::Init(Document& aDocument, Element* aRoot, nsISelectionController* aSelectionController, uint32_t aFlags, const nsAString& aValue) { MOZ_ASSERT(GetTopLevelEditSubAction() == EditSubAction::eNone, "Initializing during an edit action is an error"); // First only set flags, but other stuff shouldn't be initialized now. // Note that SetFlags() will be called by PostCreate(). mFlags = aFlags; mDocument = &aDocument; // HTML editors currently don't have their own selection controller, // so they'll pass null as aSelCon, and we'll get the selection controller // off of the presshell. nsCOMPtr selectionController; if (aSelectionController) { mSelectionController = aSelectionController; selectionController = aSelectionController; } else { selectionController = GetPresShell(); } MOZ_ASSERT(selectionController, "Selection controller should be available at this point"); if (mEditActionData) { // During edit action, selection is cached. But this selection is invalid // now since selection controller is updated, so we have to update this // cache. Selection* selection = selectionController->GetSelection( nsISelectionController::SELECTION_NORMAL); NS_WARNING_ASSERTION(selection, "We cannot update selection cache in the edit action"); if (selection) { mEditActionData->UpdateSelectionCache(*selection); } } // set up root element if we are passed one. if (aRoot) { mRootElement = aRoot; } mUpdateCount = 0; // If this is an editor for or