Bug 1540043 - part 1: Move all constants and methods of `nsIPlaintextEditor` to `nsIEditor` and make `nsIPlaintextEditor` inherit `nsIEditor` r=m_kato

For preparing to remove `nsIPlaintextEditor` interface, this patch moves
all of them to `nsIEditor`, but for avoiding bustage in comm-central, makes
`nsIPlaintextEditor` inherit `nsIEditor` for now (i.e., even with this patch,
script can access old `nsIPlaintextEditor` members with the interface.

In C++ code, this patch moves `SetWrapColumn()`, `InsertTextAsAction()`,
`InsertTextAsSubAction()` and `InsertLineBreakAsSubAction()` because
they do common things between `TextEditor` and `HTMLEditor`.  On the other
hand, this does not move `TextEditor::GetTextLength()` because it's designed
only for `TextEditor`.

Differential Revision: https://phabricator.services.mozilla.com/D60820

--HG--
rename : editor/libeditor/tests/test_nsIPlaintextEditor_insertLineBreak.html => editor/libeditor/tests/test_nsIEditor_insertLineBreak.html
extra : moz-landing-system : lando
This commit is contained in:
Masayuki Nakano 2020-01-24 08:33:42 +00:00
Родитель 89ede87cf3
Коммит b1bf7e0db4
30 изменённых файлов: 534 добавлений и 539 удалений

Просмотреть файл

@ -227,8 +227,8 @@ class UrlbarInput {
this._compositionState = UrlbarUtils.COMPOSITION.NONE;
this._compositionClosedPopup = false;
this.editor.QueryInterface(Ci.nsIPlaintextEditor).newlineHandling =
Ci.nsIPlaintextEditor.eNewlinesStripSurroundingWhitespace;
this.editor.newlineHandling =
Ci.nsIEditor.eNewlinesStripSurroundingWhitespace;
this._setOpenViewOnFocus();
Services.prefs.addObserver("browser.urlbar.openViewOnFocus", this);

Просмотреть файл

@ -5343,7 +5343,7 @@ nsresult Document::EditingStateChanged() {
// if this is actually the case.
uint32_t flags = 0;
htmlEditor->GetFlags(&flags);
if (flags & nsIPlaintextEditor::eEditorMailMask) {
if (flags & nsIEditor::eEditorMailMask) {
// We already have a mail editor, then we should not attempt to create
// another one.
return NS_OK;

Просмотреть файл

@ -215,9 +215,9 @@ class MOZ_RAII AutoRestoreEditorState final {
// appearing the method in profile. So, this class should check if it's
// necessary to call.
uint32_t flags = mSavedFlags;
flags &= ~(nsIPlaintextEditor::eEditorDisabledMask);
flags &= ~(nsIPlaintextEditor::eEditorReadonlyMask);
flags |= nsIPlaintextEditor::eEditorDontEchoPassword;
flags &= ~(nsIEditor::eEditorDisabledMask);
flags &= ~(nsIEditor::eEditorReadonlyMask);
flags |= nsIEditor::eEditorDontEchoPassword;
if (mSavedFlags != flags) {
mTextEditor->SetFlags(flags);
}
@ -1719,20 +1719,20 @@ nsresult TextControlState::PrepareEditor(const nsAString* aValue) {
PresShell* presShell = presContext->GetPresShell();
// Setup the editor flags
uint32_t editorFlags = nsIPlaintextEditor::eEditorPlaintextMask;
uint32_t editorFlags = nsIEditor::eEditorPlaintextMask;
if (IsSingleLineTextControl()) {
editorFlags |= nsIPlaintextEditor::eEditorSingleLineMask;
editorFlags |= nsIEditor::eEditorSingleLineMask;
}
if (IsPasswordTextControl()) {
editorFlags |= nsIPlaintextEditor::eEditorPasswordMask;
editorFlags |= nsIEditor::eEditorPasswordMask;
}
// All nsTextControlFrames are widgets
editorFlags |= nsIPlaintextEditor::eEditorWidgetMask;
editorFlags |= nsIEditor::eEditorWidgetMask;
// Spell check is diabled at creation time. It is enabled once
// the editor comes into focus.
editorFlags |= nsIPlaintextEditor::eEditorSkipSpellCheck;
editorFlags |= nsIEditor::eEditorSkipSpellCheck;
bool shouldInitializeEditor = false;
RefPtr<TextEditor> newTextEditor; // the editor that we might create
@ -1766,7 +1766,7 @@ nsresult TextControlState::PrepareEditor(const nsAString* aValue) {
// Don't lose application flags in the process.
if (newTextEditor->IsMailEditor()) {
editorFlags |= nsIPlaintextEditor::eEditorMailMask;
editorFlags |= nsIEditor::eEditorMailMask;
}
}
@ -1871,13 +1871,13 @@ nsresult TextControlState::PrepareEditor(const nsAString* aValue) {
// Check if the readonly attribute is set.
if (mTextCtrlElement->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly)) {
editorFlags |= nsIPlaintextEditor::eEditorReadonlyMask;
editorFlags |= nsIEditor::eEditorReadonlyMask;
}
// Check if the disabled attribute is set.
// TODO: call IsDisabled() here!
if (mTextCtrlElement->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) {
editorFlags |= nsIPlaintextEditor::eEditorDisabledMask;
editorFlags |= nsIEditor::eEditorDisabledMask;
}
// Disable the selection if necessary.

Просмотреть файл

@ -121,9 +121,8 @@ class HTMLInputElement;
* mValue member of the TextControlState object.
*
* * If an editor has been initialized for the control, the value is set and
* retrievd via the nsIPlaintextEditor interface, and is internally managed by
* the editor as the native anonymous content tree attached to the control's
* frame.
* retrievd via the nsIEditor interface, and is internally managed by the
* editor as the native anonymous content tree attached to the control's frame.
*
* * If the text control state object is unbound from the control's frame, the
* value is transferred to the mValue member variable, and will be managed there

Просмотреть файл

@ -29,7 +29,6 @@
#include "mozilla/dom/Document.h" // for Document
#include "nsIEditor.h" // for nsIEditor
#include "nsIInterfaceRequestorUtils.h" // for do_GetInterface
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
#include "nsIRefreshURI.h" // for nsIRefreshURI
#include "nsIRequest.h" // for nsIRequest
#include "nsITimer.h" // for nsITimer, etc
@ -302,20 +301,20 @@ nsresult nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter& aWindow) {
bool needHTMLController = false;
if (mEditorType.EqualsLiteral("textmail")) {
mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
nsIPlaintextEditor::eEditorEnableWrapHackMask |
nsIPlaintextEditor::eEditorMailMask;
mEditorFlags = nsIEditor::eEditorPlaintextMask |
nsIEditor::eEditorEnableWrapHackMask |
nsIEditor::eEditorMailMask;
} else if (mEditorType.EqualsLiteral("text")) {
mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
nsIPlaintextEditor::eEditorEnableWrapHackMask;
mEditorFlags =
nsIEditor::eEditorPlaintextMask | nsIEditor::eEditorEnableWrapHackMask;
} else if (mEditorType.EqualsLiteral("htmlmail")) {
if (mimeCType.EqualsLiteral("text/html")) {
needHTMLController = true;
mEditorFlags = nsIPlaintextEditor::eEditorMailMask;
mEditorFlags = nsIEditor::eEditorMailMask;
} else {
// Set the flags back to textplain.
mEditorFlags = nsIPlaintextEditor::eEditorPlaintextMask |
nsIPlaintextEditor::eEditorEnableWrapHackMask;
mEditorFlags = nsIEditor::eEditorPlaintextMask |
nsIEditor::eEditorEnableWrapHackMask;
}
} else {
// Defaulted to html
@ -323,7 +322,7 @@ nsresult nsEditingSession::SetupEditorOnWindow(nsPIDOMWindowOuter& aWindow) {
}
if (mInteractive) {
mEditorFlags |= nsIPlaintextEditor::eEditorAllowInteraction;
mEditorFlags |= nsIEditor::eEditorAllowInteraction;
}
// make the UI state maintainer

Просмотреть файл

@ -87,7 +87,6 @@
#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
@ -136,6 +135,8 @@ EditorBase::EditorBase()
mFlags(0),
mUpdateCount(0),
mPlaceholderBatch(0),
mWrapColumn(0),
mNewlineHandling(nsIEditor::eNewlinesPasteToFirst),
mDocDirtyState(-1),
mSpellcheckCheckboxState(eTriUnset),
mInitSucceeded(false),
@ -215,6 +216,7 @@ 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(nsIPlaintextEditor)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIEditor)
NS_INTERFACE_MAP_END
@ -539,8 +541,7 @@ EditorBase::SetFlags(uint32_t aFlags) {
}
DebugOnly<bool> changingPasswordEditorFlagDynamically =
mFlags != ~aFlags &&
((mFlags ^ aFlags) & nsIPlaintextEditor::eEditorPasswordMask);
mFlags != ~aFlags && ((mFlags ^ aFlags) & nsIEditor::eEditorPasswordMask);
MOZ_ASSERT(
!changingPasswordEditorFlagDynamically,
"TextEditor does not support dynamic eEditorPasswordMask flag change");
@ -4909,9 +4910,9 @@ nsresult EditorBase::DetermineCurrentDirection() {
// Set the flag here, to enable us to use the same code path below.
// It will be flipped before returning from the function.
if (frame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
mFlags |= nsIEditor::eEditorRightToLeft;
} else {
mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
mFlags |= nsIEditor::eEditorLeftToRight;
}
}
@ -5003,8 +5004,8 @@ nsresult EditorBase::SetTextDirectionTo(TextDirection aTextDirection) {
if (aTextDirection == TextDirection::eLTR) {
NS_ASSERTION(!IsLeftToRight(), "Unexpected mutually exclusive flag");
mFlags &= ~nsIPlaintextEditor::eEditorRightToLeft;
mFlags |= nsIPlaintextEditor::eEditorLeftToRight;
mFlags &= ~nsIEditor::eEditorRightToLeft;
mFlags |= nsIEditor::eEditorLeftToRight;
nsresult rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir,
NS_LITERAL_STRING("ltr"), true);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -5015,8 +5016,8 @@ nsresult EditorBase::SetTextDirectionTo(TextDirection aTextDirection) {
if (aTextDirection == TextDirection::eRTL) {
NS_ASSERTION(!IsRightToLeft(), "Unexpected mutually exclusive flag");
mFlags |= nsIPlaintextEditor::eEditorRightToLeft;
mFlags &= ~nsIPlaintextEditor::eEditorLeftToRight;
mFlags |= nsIEditor::eEditorRightToLeft;
mFlags &= ~nsIEditor::eEditorLeftToRight;
nsresult rv = rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::dir,
NS_LITERAL_STRING("rtl"), true);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -5329,6 +5330,232 @@ void EditorBase::UndefineCaretBidiLevel() const {
}
}
NS_IMETHODIMP EditorBase::GetTextLength(int32_t* aCount) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP EditorBase::GetWrapWidth(int32_t* aWrapColumn) {
if (NS_WARN_IF(!aWrapColumn)) {
return NS_ERROR_INVALID_ARG;
}
*aWrapColumn = WrapWidth();
return NS_OK;
}
//
// See if the style value includes this attribute, and if it does,
// cut out everything from the attribute to the next semicolon.
//
static void CutStyle(const char* stylename, nsString& styleValue) {
// Find the current wrapping type:
int32_t styleStart = styleValue.Find(stylename, true);
if (styleStart >= 0) {
int32_t styleEnd = styleValue.Find(";", false, styleStart);
if (styleEnd > styleStart) {
styleValue.Cut(styleStart, styleEnd - styleStart + 1);
} else {
styleValue.Cut(styleStart, styleValue.Length() - styleStart);
}
}
}
NS_IMETHODIMP EditorBase::SetWrapWidth(int32_t aWrapColumn) {
AutoEditActionDataSetter editActionData(*this, EditAction::eSetWrapWidth);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
}
SetWrapColumn(aWrapColumn);
// Make sure we're a plaintext editor, otherwise we shouldn't
// do the rest of this.
if (!IsPlaintextEditor()) {
return NS_OK;
}
// Ought to set a style sheet here ...
// Probably should keep around an mPlaintextStyleSheet for this purpose.
RefPtr<Element> rootElement = GetRoot();
if (NS_WARN_IF(!rootElement)) {
return NS_ERROR_NOT_INITIALIZED;
}
// Get the current style for this root element:
nsAutoString styleValue;
rootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue);
// We'll replace styles for these values:
CutStyle("white-space", styleValue);
CutStyle("width", styleValue);
CutStyle("font-family", styleValue);
// If we have other style left, trim off any existing semicolons
// or whitespace, then add a known semicolon-space:
if (!styleValue.IsEmpty()) {
styleValue.Trim("; \t", false, true);
styleValue.AppendLiteral("; ");
}
// Make sure we have fixed-width font. This should be done for us,
// but it isn't, see bug 22502, so we have to add "font: -moz-fixed;".
// Only do this if we're wrapping.
if (IsWrapHackEnabled() && aWrapColumn >= 0) {
styleValue.AppendLiteral("font-family: -moz-fixed; ");
}
// and now we're ready to set the new whitespace/wrapping style.
if (aWrapColumn > 0) {
// Wrap to a fixed column.
styleValue.AppendLiteral("white-space: pre-wrap; width: ");
styleValue.AppendInt(aWrapColumn);
styleValue.AppendLiteral("ch;");
} else if (!aWrapColumn) {
styleValue.AppendLiteral("white-space: pre-wrap;");
} else {
styleValue.AppendLiteral("white-space: pre;");
}
return rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue,
true);
}
NS_IMETHODIMP EditorBase::GetNewlineHandling(int32_t* aNewlineHandling) {
if (NS_WARN_IF(!aNewlineHandling)) {
return NS_ERROR_INVALID_ARG;
}
*aNewlineHandling = mNewlineHandling;
return NS_OK;
}
NS_IMETHODIMP EditorBase::SetNewlineHandling(int32_t aNewlineHandling) {
switch (aNewlineHandling) {
case nsIEditor::eNewlinesPasteIntact:
case nsIEditor::eNewlinesPasteToFirst:
case nsIEditor::eNewlinesReplaceWithSpaces:
case nsIEditor::eNewlinesStrip:
case nsIEditor::eNewlinesReplaceWithCommas:
case nsIEditor::eNewlinesStripSurroundingWhitespace:
mNewlineHandling = aNewlineHandling;
return NS_OK;
default:
NS_ERROR("SetNewlineHandling() is called with wrong value");
return NS_ERROR_INVALID_ARG;
}
}
NS_IMETHODIMP EditorBase::InsertText(const nsAString& aStringToInsert) {
nsresult rv = InsertTextAsAction(aStringToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert text");
return rv;
}
nsresult EditorBase::InsertTextAsAction(const nsAString& aStringToInsert,
nsIPrincipal* aPrincipal) {
// Showing this assertion is fine if this method is called by outside via
// mutation event listener or something. Otherwise, this is called by
// wrong method.
NS_ASSERTION(!mPlaceholderBatch,
"Should be called only when this is the only edit action of the "
"operation "
"unless mutation event listener nests some operations");
AutoEditActionDataSetter editActionData(*this, EditAction::eInsertText,
aPrincipal);
// Note that we don't need to replace native line breaks with XP line breaks
// here because Chrome does not do it.
MOZ_ASSERT(!aStringToInsert.IsVoid());
editActionData.SetData(aStringToInsert);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (rv == NS_ERROR_EDITOR_ACTION_CANCELED || NS_WARN_IF(NS_FAILED(rv))) {
return EditorBase::ToGenericNSResult(rv);
}
nsString stringToInsert(aStringToInsert);
if (!AsHTMLEditor()) {
nsContentUtils::PlatformToDOMLineBreaks(stringToInsert);
}
AutoPlaceholderBatch treatAsOneTransaction(*this);
rv = InsertTextAsSubAction(stringToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "InsertTextAsSubAction() failed");
return EditorBase::ToGenericNSResult(rv);
}
nsresult EditorBase::InsertTextAsSubAction(const nsAString& aStringToInsert) {
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(mPlaceholderBatch);
MOZ_ASSERT(AsHTMLEditor() ||
aStringToInsert.FindChar(nsCRT::CR) == kNotFound);
if (NS_WARN_IF(!mInitSucceeded)) {
return NS_ERROR_NOT_INITIALIZED;
}
EditSubAction editSubAction = ShouldHandleIMEComposition()
? EditSubAction::eInsertTextComingFromIME
: EditSubAction::eInsertText;
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
*this, editSubAction, nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult();
}
NS_WARNING_ASSERTION(
!ignoredError.Failed(),
"OnStartToHandleTopLevelEditSubAction() failed, but ignored");
EditActionResult result =
MOZ_KnownLive(AsTextEditor())
->HandleInsertText(editSubAction, aStringToInsert);
NS_WARNING_ASSERTION(result.Succeeded(), "HandleInsertText() failed");
return result.Rv();
}
NS_IMETHODIMP EditorBase::InsertLineBreak() {
AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (rv == NS_ERROR_EDITOR_ACTION_CANCELED || NS_WARN_IF(NS_FAILED(rv))) {
return EditorBase::ToGenericNSResult(rv);
}
if (NS_WARN_IF(IsSingleLineEditor())) {
return NS_ERROR_FAILURE;
}
AutoPlaceholderBatch treatAsOneTransaction(*this);
rv = InsertLineBreakAsSubAction();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "InsertLineBreakAsSubAction() failed");
return EditorBase::ToGenericNSResult(rv);
}
nsresult EditorBase::InsertLineBreakAsSubAction() {
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!mInitSucceeded)) {
return NS_ERROR_NOT_INITIALIZED;
}
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eInsertLineBreak, nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult();
}
NS_WARNING_ASSERTION(
!ignoredError.Failed(),
"OnStartToHandleTopLevelEditSubAction() failed, but ignored");
EditActionResult result =
MOZ_KnownLive(AsTextEditor())->InsertLineFeedCharacterAtSelection();
if (result.EditorDestroyed()) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(
result.Succeeded(),
"InsertLineFeedCharacterAtSelection() failed, but ignored");
return result.Rv();
}
/******************************************************************************
* EditorBase::AutoSelectionRestorer
*****************************************************************************/

Просмотреть файл

@ -135,7 +135,7 @@ enum class SplitAtEdges {
* delegate the actual commands to the editor independent of the XPFE
* implementation.
*/
class EditorBase : public nsIEditor,
class EditorBase : public nsIPlaintextEditor,
public nsISelectionListener,
public nsSupportsWeakReference {
public:
@ -426,6 +426,14 @@ class EditorBase : public nsIEditor,
virtual dom::EventTarget* GetDOMEventTarget() = 0;
/**
* Similar to the setter for wrapWidth, but just sets the editor
* internal state without actually changing the content being edited
* to wrap at that column. This should only be used by callers who
* are sure that their content is already set up correctly.
*/
void SetWrapColumn(int32_t aWrapColumn) { mWrapColumn = aWrapColumn; }
/**
* Accessor methods to flags.
*/
@ -459,60 +467,58 @@ class EditorBase : public nsIEditor,
}
bool IsPlaintextEditor() const {
return (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) != 0;
return (mFlags & nsIEditor::eEditorPlaintextMask) != 0;
}
bool IsSingleLineEditor() const {
return (mFlags & nsIPlaintextEditor::eEditorSingleLineMask) != 0;
return (mFlags & nsIEditor::eEditorSingleLineMask) != 0;
}
bool IsPasswordEditor() const {
return (mFlags & nsIPlaintextEditor::eEditorPasswordMask) != 0;
return (mFlags & nsIEditor::eEditorPasswordMask) != 0;
}
// FYI: Both IsRightToLeft() and IsLeftToRight() may return false if
// the editor inherits the content node's direction.
bool IsRightToLeft() const {
return (mFlags & nsIPlaintextEditor::eEditorRightToLeft) != 0;
return (mFlags & nsIEditor::eEditorRightToLeft) != 0;
}
bool IsLeftToRight() const {
return (mFlags & nsIPlaintextEditor::eEditorLeftToRight) != 0;
return (mFlags & nsIEditor::eEditorLeftToRight) != 0;
}
bool IsReadonly() const {
return (mFlags & nsIPlaintextEditor::eEditorReadonlyMask) != 0;
return (mFlags & nsIEditor::eEditorReadonlyMask) != 0;
}
bool IsDisabled() const {
return (mFlags & nsIPlaintextEditor::eEditorDisabledMask) != 0;
return (mFlags & nsIEditor::eEditorDisabledMask) != 0;
}
bool IsInputFiltered() const {
return (mFlags & nsIPlaintextEditor::eEditorFilterInputMask) != 0;
return (mFlags & nsIEditor::eEditorFilterInputMask) != 0;
}
bool IsMailEditor() const {
return (mFlags & nsIPlaintextEditor::eEditorMailMask) != 0;
return (mFlags & nsIEditor::eEditorMailMask) != 0;
}
bool IsWrapHackEnabled() const {
return (mFlags & nsIPlaintextEditor::eEditorEnableWrapHackMask) != 0;
return (mFlags & nsIEditor::eEditorEnableWrapHackMask) != 0;
}
bool IsFormWidget() const {
return (mFlags & nsIPlaintextEditor::eEditorWidgetMask) != 0;
return (mFlags & nsIEditor::eEditorWidgetMask) != 0;
}
bool NoCSS() const {
return (mFlags & nsIPlaintextEditor::eEditorNoCSSMask) != 0;
}
bool NoCSS() const { return (mFlags & nsIEditor::eEditorNoCSSMask) != 0; }
bool IsInteractionAllowed() const {
return (mFlags & nsIPlaintextEditor::eEditorAllowInteraction) != 0;
return (mFlags & nsIEditor::eEditorAllowInteraction) != 0;
}
bool ShouldSkipSpellCheck() const {
return (mFlags & nsIPlaintextEditor::eEditorSkipSpellCheck) != 0;
return (mFlags & nsIEditor::eEditorSkipSpellCheck) != 0;
}
bool IsTabbable() const {
@ -605,6 +611,20 @@ class EditorBase : public nsIEditor,
*/
void ReinitializeSelection(Element& aElement);
/**
* InsertTextAsAction() inserts aStringToInsert at selection.
* Although this method is implementation of nsIEditor.insertText(),
* this treats the input is an edit action. If you'd like to insert text
* as part of edit action, you probably should use InsertTextAsSubAction().
*
* @param aStringToInsert The string to insert.
* @param aPrincipal Set subject principal if it may be called by
* JS. If set to nullptr, will be treated as
* called by system.
*/
MOZ_CAN_RUN_SCRIPT nsresult InsertTextAsAction(
const nsAString& aStringToInsert, nsIPrincipal* aPrincipal = nullptr);
protected: // May be used by friends.
class AutoEditActionDataSetter;
@ -1312,6 +1332,15 @@ class EditorBase : public nsIEditor,
EditorRawDOMPoint GetCompositionStartPoint() const;
EditorRawDOMPoint GetCompositionEndPoint() const;
/**
* InsertTextAsSubAction() inserts aStringToInsert at selection. This
* should be used for handling it as an edit sub-action.
*
* @param aStringToInsert The string to insert.
*/
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
InsertTextAsSubAction(const nsAString& aStringToInsert);
/**
* InsertTextWithTransaction() inserts aStringToInsert to aPointToInsert or
* better insertion point around it. If aPointToInsert isn't in a text node,
@ -2339,6 +2368,8 @@ class EditorBase : public nsIEditor,
*/
virtual ~EditorBase();
int32_t WrapWidth() const { return mWrapColumn; }
/**
* ToGenericNSResult() computes proper nsresult value for the editor users.
* This should be used only when public methods return result of internal
@ -2573,6 +2604,12 @@ class EditorBase : public nsIEditor,
MOZ_CAN_RUN_SCRIPT EditorDOMPoint
PrepareToInsertBRElement(const EditorDOMPoint& aPointToInsert);
/**
* InsertLineBreakAsSubAction() inserts a line break, i.e., \n if it's
* TextEditor or <br> if it's HTMLEditor.
*/
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult InsertLineBreakAsSubAction();
private:
nsCOMPtr<nsISelectionController> mSelectionController;
RefPtr<Document> mDocument;
@ -2813,7 +2850,7 @@ class EditorBase : public nsIEditor,
// Number of modifications (for undo/redo stack).
uint32_t mModCount;
// Behavior flags. See nsIPlaintextEditor.idl for the flags we use.
// Behavior flags. See nsIEditor.idl for the flags we use.
uint32_t mFlags;
int32_t mUpdateCount;
@ -2821,6 +2858,9 @@ class EditorBase : public nsIEditor,
// Nesting count for batching.
int32_t mPlaceholderBatch;
int32_t mWrapColumn;
int32_t mNewlineHandling;
// -1 = not initialized
int8_t mDocDirtyState;
// A Tristate value.

Просмотреть файл

@ -36,7 +36,6 @@
#include "mozilla/dom/Document.h" // for Document
#include "nsIFormControl.h" // for nsIFormControl, etc.
#include "nsINode.h" // for nsINode, ::NODE_IS_EDITABLE, etc.
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc.
#include "nsIWidget.h" // for nsIWidget
#include "nsLiteralString.h" // for NS_LITERAL_STRING
#include "nsPIWindowRoot.h" // for nsPIWindowRoot
@ -1092,7 +1091,7 @@ void EditorEventListener::SpellCheckIfNeeded() {
// disable it because focused editors are allowed to spell check.
RefPtr<EditorBase> editorBase(mEditorBase);
if (editorBase->ShouldSkipSpellCheck()) {
editorBase->RemoveFlags(nsIPlaintextEditor::eEditorSkipSpellCheck);
editorBase->RemoveFlags(nsIEditor::eEditorSkipSpellCheck);
}
}

Просмотреть файл

@ -74,18 +74,15 @@ nsresult SetDocumentStateCommand::DoCommandParam(
case Command::SetDocumentReadOnly: {
ErrorResult error;
if (aBoolParam.value()) {
nsresult rv =
aTextEditor.AddFlags(nsIPlaintextEditor::eEditorReadonlyMask);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"AddFlags(nsIPlaintextEditor::eEditorReadonlyMask) failed");
nsresult rv = aTextEditor.AddFlags(nsIEditor::eEditorReadonlyMask);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"AddFlags(nsIEditor::eEditorReadonlyMask) failed");
return rv;
}
nsresult rv =
aTextEditor.RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
nsresult rv = aTextEditor.RemoveFlags(nsIEditor::eEditorReadonlyMask);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask) failed");
"RemoveFlags(nsIEditor::eEditorReadonlyMask) failed");
return rv;
}
case Command::SetDocumentUseCSS: {

Просмотреть файл

@ -29,7 +29,6 @@
#include "nsIContent.h"
#include "nsNameSpaceManager.h"
#include "nsINode.h"
#include "nsIPlaintextEditor.h"
#include "nsISupportsBase.h"
#include "nsLiteralString.h"
#include "nsTextNode.h"
@ -337,16 +336,16 @@ void TextEditor::HandleNewLinesInStringForSingleLineEditor(
}
switch (mNewlineHandling) {
case nsIPlaintextEditor::eNewlinesReplaceWithSpaces:
case nsIEditor::eNewlinesReplaceWithSpaces:
// Default of Firefox:
// Strip trailing newlines first so we don't wind up with trailing spaces
aString.Trim(LFSTR, false, true);
aString.ReplaceChar(kLF, ' ');
break;
case nsIPlaintextEditor::eNewlinesStrip:
case nsIEditor::eNewlinesStrip:
aString.StripChar(kLF);
break;
case nsIPlaintextEditor::eNewlinesPasteToFirst:
case nsIEditor::eNewlinesPasteToFirst:
default: {
// we get first *non-empty* line.
int32_t offset = 0;
@ -362,12 +361,12 @@ void TextEditor::HandleNewLinesInStringForSingleLineEditor(
}
break;
}
case nsIPlaintextEditor::eNewlinesReplaceWithCommas:
case nsIEditor::eNewlinesReplaceWithCommas:
// Default of Thunderbird:
aString.Trim(LFSTR, true, true);
aString.ReplaceChar(kLF, ',');
break;
case nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace: {
case nsIEditor::eNewlinesStripSurroundingWhitespace: {
nsAutoString result;
uint32_t offset = 0;
while (offset < aString.Length()) {
@ -390,7 +389,7 @@ void TextEditor::HandleNewLinesInStringForSingleLineEditor(
aString = result;
break;
}
case nsIPlaintextEditor::eNewlinesPasteIntact:
case nsIEditor::eNewlinesPasteIntact:
// even if we're pasting newlines, don't paste leading/trailing ones
aString.Trim(LFSTR, true, true);
break;
@ -949,7 +948,7 @@ EditActionResult TextEditor::TruncateInsertionStringForMaxLength(
bool TextEditor::CanEchoPasswordNow() const {
if (!LookAndFeel::GetEchoPassword() ||
(mFlags & nsIPlaintextEditor::eEditorDontEchoPassword)) {
(mFlags & nsIEditor::eEditorDontEchoPassword)) {
return false;
}

Просмотреть файл

@ -69,9 +69,7 @@ namespace mozilla {
using namespace dom;
TextEditor::TextEditor()
: mWrapColumn(0),
mMaxTextLength(-1),
mNewlineHandling(nsIPlaintextEditor::eNewlinesPasteToFirst),
: mMaxTextLength(-1),
#ifdef XP_WIN
mCaretStyle(1),
#else
@ -115,7 +113,6 @@ NS_IMPL_ADDREF_INHERITED(TextEditor, EditorBase)
NS_IMPL_RELEASE_INHERITED(TextEditor, EditorBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextEditor)
NS_INTERFACE_MAP_ENTRY(nsIPlaintextEditor)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY(nsINamed)
NS_INTERFACE_MAP_END_INHERITING(EditorBase)
@ -160,9 +157,13 @@ static int32_t sNewlineHandlingPref = -1, sCaretStylePref = -1;
static void EditorPrefsChangedCallback(const char* aPrefName, void*) {
if (!nsCRT::strcmp(aPrefName, "editor.singleLine.pasteNewlines")) {
sNewlineHandlingPref =
Preferences::GetInt("editor.singleLine.pasteNewlines",
nsIPlaintextEditor::eNewlinesPasteToFirst);
sNewlineHandlingPref = Preferences::GetInt(
"editor.singleLine.pasteNewlines", nsIEditor::eNewlinesPasteToFirst);
if (NS_WARN_IF(sNewlineHandlingPref < nsIEditor::eNewlinesPasteIntact ||
sNewlineHandlingPref >
nsIEditor::eNewlinesStripSurroundingWhitespace)) {
sNewlineHandlingPref = nsIEditor::eNewlinesPasteToFirst;
}
} else if (!nsCRT::strcmp(aPrefName, "layout.selection.caret_style")) {
sCaretStylePref = Preferences::GetInt("layout.selection.caret_style",
#ifdef XP_WIN
@ -922,118 +923,6 @@ nsresult TextEditor::DeleteSelectionAndPrepareToCreateNode() {
return NS_OK;
}
NS_IMETHODIMP
TextEditor::InsertText(const nsAString& aStringToInsert) {
nsresult rv = InsertTextAsAction(aStringToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert text");
return rv;
}
nsresult TextEditor::InsertTextAsAction(const nsAString& aStringToInsert,
nsIPrincipal* aPrincipal) {
// Showing this assertion is fine if this method is called by outside via
// mutation event listener or something. Otherwise, this is called by
// wrong method.
NS_ASSERTION(!mPlaceholderBatch,
"Should be called only when this is the only edit action of the "
"operation "
"unless mutation event listener nests some operations");
AutoEditActionDataSetter editActionData(*this, EditAction::eInsertText,
aPrincipal);
// Note that we don't need to replace native line breaks with XP line breaks
// here because Chrome does not do it.
MOZ_ASSERT(!aStringToInsert.IsVoid());
editActionData.SetData(aStringToInsert);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (rv == NS_ERROR_EDITOR_ACTION_CANCELED || NS_WARN_IF(NS_FAILED(rv))) {
return EditorBase::ToGenericNSResult(rv);
}
nsString stringToInsert(aStringToInsert);
if (!AsHTMLEditor()) {
nsContentUtils::PlatformToDOMLineBreaks(stringToInsert);
}
AutoPlaceholderBatch treatAsOneTransaction(*this);
rv = InsertTextAsSubAction(stringToInsert);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "InsertTextAsSubAction() failed");
return EditorBase::ToGenericNSResult(rv);
}
nsresult TextEditor::InsertTextAsSubAction(const nsAString& aStringToInsert) {
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(mPlaceholderBatch);
MOZ_ASSERT(AsHTMLEditor() ||
aStringToInsert.FindChar(nsCRT::CR) == kNotFound);
if (NS_WARN_IF(!mInitSucceeded)) {
return NS_ERROR_NOT_INITIALIZED;
}
EditSubAction editSubAction = ShouldHandleIMEComposition()
? EditSubAction::eInsertTextComingFromIME
: EditSubAction::eInsertText;
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
*this, editSubAction, nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult();
}
NS_WARNING_ASSERTION(
!ignoredError.Failed(),
"OnStartToHandleTopLevelEditSubAction() failed, but ignored");
EditActionResult result = HandleInsertText(editSubAction, aStringToInsert);
NS_WARNING_ASSERTION(result.Succeeded(), "HandleInsertText() failed");
return result.Rv();
}
NS_IMETHODIMP
TextEditor::InsertLineBreak() {
AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak);
nsresult rv = editActionData.CanHandleAndMaybeDispatchBeforeInputEvent();
if (rv == NS_ERROR_EDITOR_ACTION_CANCELED || NS_WARN_IF(NS_FAILED(rv))) {
return EditorBase::ToGenericNSResult(rv);
}
if (NS_WARN_IF(IsSingleLineEditor())) {
return NS_ERROR_FAILURE;
}
AutoPlaceholderBatch treatAsOneTransaction(*this);
rv = InsertLineBreakAsSubAction();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "InsertLineBreakAsSubAction() failed");
return EditorBase::ToGenericNSResult(rv);
}
nsresult TextEditor::InsertLineBreakAsSubAction() {
MOZ_ASSERT(IsEditActionDataAvailable());
if (NS_WARN_IF(!mInitSucceeded)) {
return NS_ERROR_NOT_INITIALIZED;
}
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eInsertLineBreak, nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult();
}
NS_WARNING_ASSERTION(
!ignoredError.Failed(),
"OnStartToHandleTopLevelEditSubAction() failed, but ignored");
EditActionResult result = InsertLineFeedCharacterAtSelection();
if (result.EditorDestroyed()) {
return NS_ERROR_EDITOR_DESTROYED;
}
NS_WARNING_ASSERTION(
result.Succeeded(),
"InsertLineFeedCharacterAtSelection() failed, but ignored");
return result.Rv();
}
nsresult TextEditor::SetTextAsAction(const nsAString& aString,
nsIPrincipal* aPrincipal) {
MOZ_ASSERT(aString.FindChar(nsCRT::CR) == kNotFound);
@ -1466,7 +1355,7 @@ TextEditor::GetTextLength(int32_t* aCount) {
PostContentIterator postOrderIter;
postOrderIter.Init(rootElement);
for (; !postOrderIter.IsDone(); postOrderIter.Next()) {
nsCOMPtr<nsINode> currentNode = postOrderIter.GetCurrentNode();
nsINode* currentNode = postOrderIter.GetCurrentNode();
if (IsTextNode(currentNode) && IsEditable(currentNode)) {
totalLength += currentNode->Length();
}
@ -1476,106 +1365,6 @@ TextEditor::GetTextLength(int32_t* aCount) {
return NS_OK;
}
NS_IMETHODIMP
TextEditor::GetWrapWidth(int32_t* aWrapColumn) {
if (NS_WARN_IF(!aWrapColumn)) {
return NS_ERROR_INVALID_ARG;
}
*aWrapColumn = WrapWidth();
return NS_OK;
}
//
// See if the style value includes this attribute, and if it does,
// cut out everything from the attribute to the next semicolon.
//
static void CutStyle(const char* stylename, nsString& styleValue) {
// Find the current wrapping type:
int32_t styleStart = styleValue.Find(stylename, true);
if (styleStart >= 0) {
int32_t styleEnd = styleValue.Find(";", false, styleStart);
if (styleEnd > styleStart) {
styleValue.Cut(styleStart, styleEnd - styleStart + 1);
} else {
styleValue.Cut(styleStart, styleValue.Length() - styleStart);
}
}
}
NS_IMETHODIMP
TextEditor::SetWrapWidth(int32_t aWrapColumn) {
AutoEditActionDataSetter editActionData(*this, EditAction::eSetWrapWidth);
if (NS_WARN_IF(!editActionData.CanHandle())) {
return NS_ERROR_NOT_INITIALIZED;
}
SetWrapColumn(aWrapColumn);
// Make sure we're a plaintext editor, otherwise we shouldn't
// do the rest of this.
if (!IsPlaintextEditor()) {
return NS_OK;
}
// Ought to set a style sheet here ...
// Probably should keep around an mPlaintextStyleSheet for this purpose.
dom::Element* rootElement = GetRoot();
NS_ENSURE_TRUE(rootElement, NS_ERROR_NULL_POINTER);
// Get the current style for this root element:
nsAutoString styleValue;
rootElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue);
// We'll replace styles for these values:
CutStyle("white-space", styleValue);
CutStyle("width", styleValue);
CutStyle("font-family", styleValue);
// If we have other style left, trim off any existing semicolons
// or whitespace, then add a known semicolon-space:
if (!styleValue.IsEmpty()) {
styleValue.Trim("; \t", false, true);
styleValue.AppendLiteral("; ");
}
// Make sure we have fixed-width font. This should be done for us,
// but it isn't, see bug 22502, so we have to add "font: -moz-fixed;".
// Only do this if we're wrapping.
if (IsWrapHackEnabled() && aWrapColumn >= 0) {
styleValue.AppendLiteral("font-family: -moz-fixed; ");
}
// and now we're ready to set the new whitespace/wrapping style.
if (aWrapColumn > 0) {
// Wrap to a fixed column.
styleValue.AppendLiteral("white-space: pre-wrap; width: ");
styleValue.AppendInt(aWrapColumn);
styleValue.AppendLiteral("ch;");
} else if (!aWrapColumn) {
styleValue.AppendLiteral("white-space: pre-wrap;");
} else {
styleValue.AppendLiteral("white-space: pre;");
}
return rootElement->SetAttr(kNameSpaceID_None, nsGkAtoms::style, styleValue,
true);
}
NS_IMETHODIMP
TextEditor::GetNewlineHandling(int32_t* aNewlineHandling) {
NS_ENSURE_ARG_POINTER(aNewlineHandling);
*aNewlineHandling = mNewlineHandling;
return NS_OK;
}
NS_IMETHODIMP
TextEditor::SetNewlineHandling(int32_t aNewlineHandling) {
mNewlineHandling = aNewlineHandling;
return NS_OK;
}
nsresult TextEditor::UndoAsAction(uint32_t aCount, nsIPrincipal* aPrincipal) {
if (aCount == 0 || IsReadonly() || IsDisabled()) {
return NS_OK;

Просмотреть файл

@ -10,7 +10,6 @@
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsINamed.h"
#include "nsIPlaintextEditor.h"
#include "nsISupportsImpl.h"
#include "nsITimer.h"
#include "nscore.h"
@ -36,10 +35,7 @@ class Selection;
* The text editor implementation.
* Use to edit text document represented as a DOM tree.
*/
class TextEditor : public EditorBase,
public nsIPlaintextEditor,
public nsITimerCallback,
public nsINamed {
class TextEditor : public EditorBase, public nsITimerCallback, public nsINamed {
public:
/****************************************************************************
* NOTE: DO NOT MAKE YOUR NEW METHODS PUBLIC IF they are called by other
@ -56,7 +52,6 @@ class TextEditor : public EditorBase,
TextEditor();
NS_DECL_NSIPLAINTEXTEDITOR
NS_DECL_NSITIMERCALLBACK
NS_DECL_NSINAMED
@ -70,6 +65,8 @@ class TextEditor : public EditorBase,
MOZ_CAN_RUN_SCRIPT
NS_IMETHOD SetDocumentCharacterSet(const nsACString& characterSet) override;
NS_IMETHOD GetTextLength(int32_t* aCount) override;
/**
* Do "undo" or "redo".
*
@ -195,20 +192,6 @@ class TextEditor : public EditorBase,
bool aDispatchPasteEvent,
nsIPrincipal* aPrincipal = nullptr);
/**
* InsertTextAsAction() inserts aStringToInsert at selection.
* Although this method is implementation of nsIPlaintextEditor.insertText(),
* this treats the input is an edit action. If you'd like to insert text
* as part of edit action, you probably should use InsertTextAsSubAction().
*
* @param aStringToInsert The string to insert.
* @param aPrincipal Set subject principal if it may be called by
* JS. If set to nullptr, will be treated as
* called by system.
*/
MOZ_CAN_RUN_SCRIPT nsresult InsertTextAsAction(
const nsAString& aStringToInsert, nsIPrincipal* aPrincipal = nullptr);
/**
* PasteAsQuotationAsAction() pastes content in clipboard as quotation.
* If the editor is TextEditor or in plaintext mode, will paste the content
@ -340,14 +323,6 @@ class TextEditor : public EditorBase,
return NS_OK;
}
/**
* Similar to the setter for wrapWidth, but just sets the editor
* internal state without actually changing the content being edited
* to wrap at that column. This should only be used by callers who
* are sure that their content is already set up correctly.
*/
void SetWrapColumn(int32_t aWrapColumn) { mWrapColumn = aWrapColumn; }
/**
* The following methods are available only when the instance is a password
* editor. They return whether there is unmasked range or not and range
@ -407,15 +382,6 @@ class TextEditor : public EditorBase,
using EditorBase::RemoveAttributeOrEquivalent;
using EditorBase::SetAttributeOrEquivalent;
/**
* InsertTextAsSubAction() inserts aStringToInsert at selection. This
* should be used for handling it as an edit sub-action.
*
* @param aStringToInsert The string to insert.
*/
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
InsertTextAsSubAction(const nsAString& aStringToInsert);
/**
* DeleteSelectionAsSubAction() removes selection content or content around
* caret with transactions. This should be used for handling it as an
@ -598,18 +564,18 @@ class TextEditor : public EditorBase,
* Handles the newline characters according to the default system prefs
* (editor.singleLine.pasteNewlines).
* Each value means:
* nsIPlaintextEditor::eNewlinesReplaceWithSpaces (2, Firefox default):
* nsIEditor::eNewlinesReplaceWithSpaces (2, Firefox default):
* replace newlines with spaces.
* nsIPlaintextEditor::eNewlinesStrip (3):
* nsIEditor::eNewlinesStrip (3):
* remove newlines from the string.
* nsIPlaintextEditor::eNewlinesReplaceWithCommas (4, Thunderbird default):
* nsIEditor::eNewlinesReplaceWithCommas (4, Thunderbird default):
* replace newlines with commas.
* nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace (5):
* nsIEditor::eNewlinesStripSurroundingWhitespace (5):
* collapse newlines and surrounding whitespace characters and
* remove them from the string.
* nsIPlaintextEditor::eNewlinesPasteIntact (0):
* nsIEditor::eNewlinesPasteIntact (0):
* only remove the leading and trailing newlines.
* nsIPlaintextEditor::eNewlinesPasteToFirst (1) or any other value:
* nsIEditor::eNewlinesPasteToFirst (1) or any other value:
* remove the first newline and all characters following it.
*
* @param aString the string to be modified in place.
@ -720,8 +686,6 @@ class TextEditor : public EditorBase,
*/
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult InitEditorContentAndSelection();
int32_t WrapWidth() const { return mWrapColumn; }
/**
* CanEchoPasswordNow() returns true if currently we can echo password.
* If it's direct user input such as pasting or dropping text, this
@ -743,12 +707,6 @@ class TextEditor : public EditorBase,
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult
OnInputText(const nsAString& aStringToInsert);
/**
* InsertLineBreakAsSubAction() inserts a line break, i.e., \n if it's
* TextEditor or <br> if it's HTMLEditor.
*/
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult InsertLineBreakAsSubAction();
/**
* PrepareInsertContent() is a helper method of InsertTextAt(),
* HTMLEditor::DoInsertHTMLWithContext(). They insert content coming from
@ -901,9 +859,7 @@ class TextEditor : public EditorBase,
mutable nsString mCachedDocumentEncoderType;
int32_t mWrapColumn;
int32_t mMaxTextLength;
int32_t mNewlineHandling;
int32_t mCaretStyle;
// Unmasked character range. Used only when it's a password field.

Просмотреть файл

@ -247,13 +247,13 @@ skip-if = os == 'android'
[test_label_contenteditable.html]
[test_middle_click_paste.html]
skip-if = headless
[test_nsIEditor_insertLineBreak.html]
[test_nsIEditorMailSupport_insertAsCitedQuotation.html]
[test_nsIHTMLEditor_getSelectedElement.html]
[test_nsIHTMLEditor_removeInlineProperty.html]
[test_nsIHTMLEditor_selectElement.html]
[test_nsIHTMLEditor_setCaretAfterElement.html]
[test_nsIHTMLObjectResizer_hideResizers.html]
[test_nsIPlaintextEditor_insertLineBreak.html]
[test_nsITableEditor_deleteTableCell.html]
[test_nsITableEditor_deleteTableCellContents.html]
[test_nsITableEditor_deleteTableColumn.html]

Просмотреть файл

@ -86,7 +86,7 @@ function makeMailEditor() {
var Ci = SpecialPowers.Ci;
var editingSession = SpecialPowers.wrap(window).docShell.editingSession;
var editor = editingSession.getEditorForWindow(window);
editor.flags |= Ci.nsIPlaintextEditor.eEditorMailMask;
editor.flags |= Ci.nsIEditor.eEditorMailMask;
}
</script>

Просмотреть файл

@ -24,9 +24,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=599983
SimpleTest.waitForExplicitFinish();
const kAllowInteraction = Ci.nsIPlaintextEditor
.eEditorAllowInteraction;
const kMailMask = Ci.nsIPlaintextEditor.eEditorMailMask;
const kAllowInteraction = Ci.nsIEditor.eEditorAllowInteraction;
const kMailMask = Ci.nsIEditor.eEditorMailMask;
function runTest() {
testEditor(false, false);

Просмотреть файл

@ -31,8 +31,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=830600
t.focus();
t.value = "";
var editor = SpecialPowers.wrap(t).editor;
editor.QueryInterface(Ci.nsIPlaintextEditor);
editor.newlineHandling = Ci.nsIPlaintextEditor.eNewlinesStripSurroundingWhitespace;
editor.newlineHandling = Ci.nsIEditor.eNewlinesStripSurroundingWhitespace;
SimpleTest.waitForClipboard(str,
function() {
SpecialPowers.Cc["@mozilla.org/widget/clipboardhelper;1"]

Просмотреть файл

@ -735,8 +735,8 @@ async function runTests() {
ok(!inputEvent, `${aDescription}"input" event should not have been fired at ${action} since "beforeinput" was canceled`);
body.setAttribute("dir", "rtl");
htmlEditor.flags &= ~SpecialPowers.Ci.nsIPlaintextEditor.eEditorLeftToRight;
htmlEditor.flags |= SpecialPowers.Ci.nsIPlaintextEditor.eEditorRightToLeft; // XXX flags update is required, must be a bug.
htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorLeftToRight;
htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorRightToLeft; // XXX flags update is required, must be a bug.
aDocument.documentElement.scrollTop; // XXX Update the body frame
editTarget.focus();
cancelBeforeInput = true;
@ -756,8 +756,8 @@ async function runTests() {
ok(!inputEvent, `${aDescription}"input" event should not have been fired at ${action} since "beforeinput" was canceled`);
body.removeAttribute("dir");
htmlEditor.flags &= ~SpecialPowers.Ci.nsIPlaintextEditor.eEditorRightToLeft;
htmlEditor.flags |= SpecialPowers.Ci.nsIPlaintextEditor.eEditorLeftToRight; // XXX flags update is required, must be a bug.
htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorRightToLeft;
htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorLeftToRight; // XXX flags update is required, must be a bug.
aDocument.documentElement.scrollTop; // XXX Update the body frame
editTarget.focus();
cancelBeforeInput = false;

Просмотреть файл

@ -46,17 +46,17 @@ async function copyPlaintext(aText) {
}
async function doTests() {
// nsIPlaintextEditor::eNewlinesPasteIntact (0):
// nsIEditor::eNewlinesPasteIntact (0):
// only remove the leading and trailing newlines.
// nsIPlaintextEditor::eNewlinesPasteToFirst (1) or any other value:
// nsIEditor::eNewlinesPasteToFirst (1) or any other value:
// remove the first newline and all characters following it.
// nsIPlaintextEditor::eNewlinesReplaceWithSpaces (2, Firefox default):
// nsIEditor::eNewlinesReplaceWithSpaces (2, Firefox default):
// replace newlines with spaces.
// nsIPlaintextEditor::eNewlinesStrip (3):
// nsIEditor::eNewlinesStrip (3):
// remove newlines from the string.
// nsIPlaintextEditor::eNewlinesReplaceWithCommas (4, Thunderbird default):
// nsIEditor::eNewlinesReplaceWithCommas (4, Thunderbird default):
// replace newlines with commas.
// nsIPlaintextEditor::eNewlinesStripSurroundingWhitespace (5):
// nsIEditor::eNewlinesStripSurroundingWhitespace (5):
// collapse newlines and surrounding whitespace characters and
// remove them from the string.

Просмотреть файл

@ -601,45 +601,45 @@ function runTests() {
doTest(htmlEditor, "contenteditable=\"true\"", false, true, false);
const nsIPlaintextEditor = SpecialPowers.Ci.nsIPlaintextEditor;
const nsIEditor = SpecialPowers.Ci.nsIEditor;
var editor = SpecialPowers.wrap(window).docShell.editor;
var flags = editor.flags;
// readonly
editor.flags = flags | nsIPlaintextEditor.eEditorReadonlyMask;
editor.flags = flags | nsIEditor.eEditorReadonlyMask;
doTest(htmlEditor, "readonly HTML editor", true, true, false);
// non-tabbable
editor.flags = flags & ~(nsIPlaintextEditor.eEditorAllowInteraction);
editor.flags = flags & ~(nsIEditor.eEditorAllowInteraction);
doTest(htmlEditor, "non-tabbable HTML editor", false, false, false);
// readonly and non-tabbable
editor.flags =
(flags | nsIPlaintextEditor.eEditorReadonlyMask) &
~(nsIPlaintextEditor.eEditorAllowInteraction);
(flags | nsIEditor.eEditorReadonlyMask) &
~(nsIEditor.eEditorAllowInteraction);
doTest(htmlEditor, "readonly and non-tabbable HTML editor",
true, false, false);
// plaintext
editor.flags = flags | nsIPlaintextEditor.eEditorPlaintextMask;
editor.flags = flags | nsIEditor.eEditorPlaintextMask;
doTest(htmlEditor, "HTML editor but plaintext mode", false, true, true);
// plaintext and non-tabbable
editor.flags = (flags | nsIPlaintextEditor.eEditorPlaintextMask) &
~(nsIPlaintextEditor.eEditorAllowInteraction);
editor.flags = (flags | nsIEditor.eEditorPlaintextMask) &
~(nsIEditor.eEditorAllowInteraction);
doTest(htmlEditor, "non-tabbable HTML editor but plaintext mode",
false, false, true);
// readonly and plaintext
editor.flags = flags | nsIPlaintextEditor.eEditorPlaintextMask |
nsIPlaintextEditor.eEditorReadonlyMask;
editor.flags = flags | nsIEditor.eEditorPlaintextMask |
nsIEditor.eEditorReadonlyMask;
doTest(htmlEditor, "readonly HTML editor but plaintext mode",
true, true, true);
// readonly, plaintext and non-tabbable
editor.flags = (flags | nsIPlaintextEditor.eEditorPlaintextMask |
nsIPlaintextEditor.eEditorReadonlyMask) &
~(nsIPlaintextEditor.eEditorAllowInteraction);
editor.flags = (flags | nsIEditor.eEditorPlaintextMask |
nsIEditor.eEditorReadonlyMask) &
~(nsIEditor.eEditorAllowInteraction);
doTest(htmlEditor, "readonly and non-tabbable HTML editor but plaintext mode",
true, false, true);

Просмотреть файл

@ -58,7 +58,7 @@ SimpleTest.waitForFocus(async () => {
// Tests when the editor is in plaintext mode.
getEditor().flags |= SpecialPowers.Ci.nsIPlaintextEditor.eEditorPlaintextMask;
getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorPlaintextMask;
beforeInputEvents = [];
inputEvents = [];
@ -82,7 +82,7 @@ SimpleTest.waitForFocus(async () => {
"after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor");
// Tests when the editor is in HTML editor mode.
getEditor().flags &= ~SpecialPowers.Ci.nsIPlaintextEditor.eEditorPlaintextMask;
getEditor().flags &= ~SpecialPowers.Ci.nsIEditor.eEditorPlaintextMask;
editor.innerHTML = "";

Просмотреть файл

@ -1,7 +1,7 @@
<!DOCTYPE>
<html>
<head>
<title>Test for nsIPlaintextEditor.insertLineBreak()</title>
<title>Test for nsIEditor.insertLineBreak()</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
</head>
@ -67,10 +67,10 @@ SimpleTest.waitForFocus(async () => {
}
input.removeEventListener("beforeinput", onBeforeInput);
input.removeEventListener("input", onInput);
is(input.value, "abcdef", "nsIPlaintextEditor.insertLineBreak() should do nothing on single line editor");
is(beforeInputEvents.length, 1, 'nsIPlaintextEditor.insertLineBreak() should cause a "beforeinput" event on single line editor');
is(input.value, "abcdef", "nsIEditor.insertLineBreak() should do nothing on single line editor");
is(beforeInputEvents.length, 1, 'nsIEditor.insertLineBreak() should cause a "beforeinput" event on single line editor');
checkInputEvent(beforeInputEvents[0], "insertLineBreak", "on single line editor");
is(inputEvents.length, 0, 'nsIPlaintextEditor.insertLineBreak() should not cause "input" event on single line editor');
is(inputEvents.length, 0, 'nsIEditor.insertLineBreak() should not cause "input" event on single line editor');
textarea.focus();
textarea.selectionStart = textarea.selectionEnd = 3;
@ -81,10 +81,10 @@ SimpleTest.waitForFocus(async () => {
getPlaintextEditor(textarea).insertLineBreak();
textarea.removeEventListener("beforeinput", onBeforeInput);
textarea.removeEventListener("input", onInput);
is(textarea.value, "abc\ndef", "nsIPlaintextEditor.insertLineBreak() should insert \\n into multi-line editor");
is(beforeInputEvents.length, 1, 'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on multi-line editor');
is(textarea.value, "abc\ndef", "nsIEditor.insertLineBreak() should insert \\n into multi-line editor");
is(beforeInputEvents.length, 1, 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on multi-line editor');
checkInputEvent(beforeInputEvents[0], "insertLineBreak", "on multi-line editor");
is(inputEvents.length, 1, 'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on multi-line editor');
is(inputEvents.length, 1, 'nsIEditor.insertLineBreak() should cause "input" event once on multi-line editor');
checkInputEvent(inputEvents[0], "insertLineBreak", "on multi-line editor");
// Note that despite of the name, insertLineBreak() should insert paragraph separator in HTMLEditor.
@ -103,12 +103,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "abc<br>def",
'nsIPlaintextEditor.insertLineBreak() should insert <br> element into text node when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should insert <br> element into text node when defaultParagraphSeparator is "br"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "br"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'on HTMLEditor (when defaultParagraphSeparator is "br")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "br"');
checkInputEvent(inputEvents[0], "insertParagraph", 'on HTMLEditor (when defaultParagraphSeparator is "br")');
contenteditable.innerHTML = "<p>abcdef</p>";
@ -123,12 +123,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<p>abc</p><p>def</p>",
'nsIPlaintextEditor.insertLineBreak() should add <p> element after <p> element even when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should add <p> element after <p> element even when defaultParagraphSeparator is "br"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "br"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "br")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "br"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "br")');
contenteditable.innerHTML = "<div>abcdef</div>";
@ -143,12 +143,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<div>abc<br>def</div>",
'nsIPlaintextEditor.insertLineBreak() should insert <br> element into <div> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should insert <br> element into <div> element when defaultParagraphSeparator is "br"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "br"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "br")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "br"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "br")');
contenteditable.innerHTML = "<pre>abcdef</pre>";
@ -163,12 +163,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<pre>abc<br>def</pre>",
'nsIPlaintextEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "br"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "br"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "br")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "br"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "br"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "br")');
document.execCommand("defaultParagraphSeparator", false, "p");
@ -185,12 +185,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<p>abc</p><p>def</p>",
'nsIPlaintextEditor.insertLineBreak() should create <p> elements when there is only text node and defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should create <p> elements when there is only text node and defaultParagraphSeparator is "p"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "p"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'on HTMLEditor (when defaultParagraphSeparator is "p")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "p"');
checkInputEvent(inputEvents[0], "insertParagraph", 'on HTMLEditor (when defaultParagraphSeparator is "p")');
contenteditable.innerHTML = "<p>abcdef</p>";
@ -205,12 +205,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<p>abc</p><p>def</p>",
'nsIPlaintextEditor.insertLineBreak() should add <p> element after <p> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should add <p> element after <p> element when defaultParagraphSeparator is "p"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "p"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "p")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "p"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "p")');
contenteditable.innerHTML = "<div>abcdef</div>";
@ -225,12 +225,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<div>abc</div><div>def</div>",
'nsIPlaintextEditor.insertLineBreak() should add <div> element after <div> element even when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should add <div> element after <div> element even when defaultParagraphSeparator is "p"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "p"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "p")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "p"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "p")');
contenteditable.innerHTML = "<pre>abcdef</pre>";
@ -245,12 +245,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<pre>abc<br>def</pre>",
'nsIPlaintextEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "p"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "p"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "p")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "p"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "p"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "p")');
document.execCommand("defaultParagraphSeparator", false, "div");
@ -267,12 +267,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<div>abc</div><div>def</div>",
'nsIPlaintextEditor.insertLineBreak() should create <div> elements when there is only text node and defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should create <div> elements when there is only text node and defaultParagraphSeparator is "div"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "div"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'on HTMLEditor (when defaultParagraphSeparator is "div")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "div"');
checkInputEvent(inputEvents[0], "insertParagraph", 'on HTMLEditor (when defaultParagraphSeparator is "div")');
contenteditable.innerHTML = "<p>abcdef</p>";
@ -287,12 +287,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<p>abc</p><p>def</p>",
'nsIPlaintextEditor.insertLineBreak() should add <p> element after <p> element even when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should add <p> element after <p> element even when defaultParagraphSeparator is "div"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "div"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "div")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "div"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "div")');
contenteditable.innerHTML = "<div>abcdef</div>";
@ -307,12 +307,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<div>abc</div><div>def</div>",
'nsIPlaintextEditor.insertLineBreak() should add <div> element after <div> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should add <div> element after <div> element when defaultParagraphSeparator is "div"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "div"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "div")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "div"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "div")');
contenteditable.innerHTML = "<pre>abcdef</pre>";
@ -327,12 +327,12 @@ SimpleTest.waitForFocus(async () => {
contenteditable.removeEventListener("beforeinput", onBeforeInput);
contenteditable.removeEventListener("input", onInput);
is(contenteditable.innerHTML, "<pre>abc<br>def</pre>",
'nsIPlaintextEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "div"');
is(beforeInputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "div"');
checkInputEvent(beforeInputEvents[0], "insertParagraph", 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "div")');
is(inputEvents.length, 1,
'nsIPlaintextEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "div"');
'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "div"');
checkInputEvent(inputEvents[0], "insertParagraph", 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "div")');
SimpleTest.finish();
@ -343,7 +343,7 @@ function getPlaintextEditor(aEditorElement) {
if (!editor) {
editor = SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window);
}
return editor.QueryInterface(SpecialPowers.Ci.nsIPlaintextEditor);
return editor;
}
</script>

Просмотреть файл

@ -47,8 +47,8 @@ SimpleTest.waitForFocus(async () => {
is(textarea.value, "ab\ncd\nef", "Pasting \\r from clipboard should be converted to \\n");
textarea.value = "";
SpecialPowers.wrap(textarea).editor.QueryInterface(SpecialPowers.Ci.nsIPlaintextEditor).insertText("ab\r\ncd\ref");
is(textarea.value, "ab\ncd\nef", "Inserting \\r with nsIPlaintextEditor.insertText() should be converted to \\n");
SpecialPowers.wrap(textarea).editor.insertText("ab\r\ncd\ref");
is(textarea.value, "ab\ncd\nef", "Inserting \\r with nsIEditor.insertText() should be converted to \\n");
textarea.value = "";
synthesizeCompositionChange(

Просмотреть файл

@ -350,11 +350,11 @@ function runTests() {
// make non-tabbable plaintext editor
textarea.removeAttribute("readonly");
const nsIPlaintextEditor = SpecialPowers.Ci.nsIPlaintextEditor;
const nsIEditor = SpecialPowers.Ci.nsIEditor;
var editor = SpecialPowers.wrap(textarea).editor;
var flags = editor.flags;
editor.flags = flags & ~(nsIPlaintextEditor.eEditorWidgetMask |
nsIPlaintextEditor.eEditorAllowInteraction);
editor.flags = flags & ~(nsIEditor.eEditorWidgetMask |
nsIEditor.eEditorAllowInteraction);
doTest(textarea, "non-tabbable <textarea>", false, false, false);
textarea.setAttribute("readonly", "readonly");

Просмотреть файл

@ -50,6 +50,54 @@ interface nsIEditor : nsISupports
const short eStrip = 0;
const short eNoStrip = 1;
// only plain text entry is allowed via events
const long eEditorPlaintextMask = 0x0001;
// enter key and CR-LF handled specially
const long eEditorSingleLineMask = 0x0002;
// text is not entered into content, only a representative character
const long eEditorPasswordMask = 0x0004;
// editing events are disabled. Editor may still accept focus.
const long eEditorReadonlyMask = 0x0008;
// all events are disabled (like scrolling). Editor will not accept focus.
const long eEditorDisabledMask = 0x0010;
// text input is limited to certain character types, use mFilter
const long eEditorFilterInputMask = 0x0020;
// use mail-compose editing rules
const long eEditorMailMask = 0x0040;
// allow the editor to set font: monospace on the root node
const long eEditorEnableWrapHackMask = 0x0080;
// bit for widgets (form elements)
const long eEditorWidgetMask = 0x0100;
// this HTML editor should not create css styles
const long eEditorNoCSSMask = 0x0200;
// whether HTML document specific actions are executed or not.
// e.g., if this flag is set, the editor doesn't handle Tab key.
// besides, anchors of HTML are not clickable.
const long eEditorAllowInteraction = 0x0400;
// when this is set, the characters in password editor are always masked.
// see bug 530367 for the detail.
const long eEditorDontEchoPassword = 0x0800;
// when this flag is set, the internal direction of the editor is RTL.
// if neither of the direction flags are set, the direction is determined
// from the text control's content node.
const long eEditorRightToLeft = 0x1000;
// when this flag is set, the internal direction of the editor is LTR.
const long eEditorLeftToRight = 0x2000;
// when this flag is set, the editor's text content is not spell checked.
const long eEditorSkipSpellCheck = 0x4000;
/*
* The valid values for newlines handling.
* Can't change the values unless we remove
* use of the pref.
*/
const long eNewlinesPasteIntact = 0;
const long eNewlinesPasteToFirst = 1;
const long eNewlinesReplaceWithSpaces = 2;
const long eNewlinesStrip = 3;
const long eNewlinesReplaceWithCommas = 4;
const long eNewlinesStripSurroundingWhitespace = 5;
readonly attribute Selection selection;
[can_run_script]
@ -501,6 +549,46 @@ interface nsIEditor : nsISupports
*/
readonly attribute AString passwordMask;
/**
* The length of the contents in characters.
* XXX change this type to 'unsigned long'
*/
readonly attribute long textLength;
/** Get and set the body wrap width.
*
* Special values:
* 0 = wrap to window width
* -1 = no wrap at all
*/
attribute long wrapWidth;
/** Get and set newline handling.
*
* Values are the constants defined above.
*/
attribute long newlineHandling;
/**
* Inserts a string at the current location,
* given by the selection.
* If the selection is not collapsed, the selection is deleted
* and the insertion takes place at the resulting collapsed selection.
*
* @param aString the string to be inserted
*/
[can_run_script]
void insertText(in AString aStringToInsert);
/**
* Insert a line break into the content model.
* The interpretation of a break is up to the implementation:
* it may enter a character, split a node in the tree, etc.
* This may be more efficient than calling InsertText with a newline.
*/
[can_run_script]
void insertLineBreak();
%{C++
/**
* AsEditorBase() returns a pointer to EditorBase class.

Просмотреть файл

@ -3,98 +3,9 @@
* 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 "nsISupports.idl"
#include "nsIEditor.idl"
[scriptable, builtinclass, uuid(b74fb158-1265-4102-91eb-edd0136b49f8)]
interface nsIPlaintextEditor : nsISupports
interface nsIPlaintextEditor : nsIEditor
{
// XXX Why aren't these in nsIEditor?
// only plain text entry is allowed via events
const long eEditorPlaintextMask = 0x0001;
// enter key and CR-LF handled specially
const long eEditorSingleLineMask = 0x0002;
// text is not entered into content, only a representative character
const long eEditorPasswordMask = 0x0004;
// editing events are disabled. Editor may still accept focus.
const long eEditorReadonlyMask = 0x0008;
// all events are disabled (like scrolling). Editor will not accept focus.
const long eEditorDisabledMask = 0x0010;
// text input is limited to certain character types, use mFilter
const long eEditorFilterInputMask = 0x0020;
// use mail-compose editing rules
const long eEditorMailMask = 0x0040;
// allow the editor to set font: monospace on the root node
const long eEditorEnableWrapHackMask = 0x0080;
// bit for widgets (form elements)
const long eEditorWidgetMask = 0x0100;
// this HTML editor should not create css styles
const long eEditorNoCSSMask = 0x0200;
// whether HTML document specific actions are executed or not.
// e.g., if this flag is set, the editor doesn't handle Tab key.
// besides, anchors of HTML are not clickable.
const long eEditorAllowInteraction = 0x0400;
// when this is set, the characters in password editor are always masked.
// see bug 530367 for the detail.
const long eEditorDontEchoPassword = 0x0800;
// when this flag is set, the internal direction of the editor is RTL.
// if neither of the direction flags are set, the direction is determined
// from the text control's content node.
const long eEditorRightToLeft = 0x1000;
// when this flag is set, the internal direction of the editor is LTR.
const long eEditorLeftToRight = 0x2000;
// when this flag is set, the editor's text content is not spell checked.
const long eEditorSkipSpellCheck = 0x4000;
/*
* The valid values for newlines handling.
* Can't change the values unless we remove
* use of the pref.
*/
const long eNewlinesPasteIntact = 0;
const long eNewlinesPasteToFirst = 1;
const long eNewlinesReplaceWithSpaces = 2;
const long eNewlinesStrip = 3;
const long eNewlinesReplaceWithCommas = 4;
const long eNewlinesStripSurroundingWhitespace = 5;
/**
* The length of the contents in characters.
* XXX change this type to 'unsigned long'
*/
readonly attribute long textLength;
/** Get and set the body wrap width.
*
* Special values:
* 0 = wrap to window width
* -1 = no wrap at all
*/
attribute long wrapWidth;
/** Get and set newline handling.
*
* Values are the constants defined above.
*/
attribute long newlineHandling;
/**
* Inserts a string at the current location,
* given by the selection.
* If the selection is not collapsed, the selection is deleted
* and the insertion takes place at the resulting collapsed selection.
*
* @param aString the string to be inserted
*/
[can_run_script]
void insertText(in AString aStringToInsert);
/**
* Insert a line break into the content model.
* The interpretation of a break is up to the implementation:
* it may enter a character, split a node in the tree, etc.
* This may be more efficient than calling InsertText with a newline.
*/
[can_run_script]
void insertLineBreak();
};

Просмотреть файл

@ -41,7 +41,6 @@
#include "nsStringFwd.h" // for nsAFlatString
#include "nsStyleUtil.h" // for nsStyleUtil
#include "nsXULAppAPI.h" // for XRE_GetProcessType
#include "nsIPlaintextEditor.h" // for editor flags
namespace mozilla {
@ -536,7 +535,7 @@ EditorSpellCheck::SetCurrentDictionary(const nsAString& aDictionary) {
uint32_t flags = 0;
mEditor->GetFlags(&flags);
if (!(flags & nsIPlaintextEditor::eEditorMailMask)) {
if (!(flags & nsIEditor::eEditorMailMask)) {
if (!aDictionary.IsEmpty() &&
(mPreferredLang.IsEmpty() ||
!mPreferredLang.Equals(aDictionary,
@ -623,7 +622,7 @@ EditorSpellCheck::UpdateCurrentDictionary(
nsCOMPtr<nsIContent> rootContent;
HTMLEditor* htmlEditor = mEditor->AsHTMLEditor();
if (htmlEditor) {
if (flags & nsIPlaintextEditor::eEditorMailMask) {
if (flags & nsIEditor::eEditorMailMask) {
// Always determine the root content for a mail editor,
// even if not focused, to enable further processing below.
rootContent = htmlEditor->GetActiveEditingHost();
@ -639,7 +638,7 @@ EditorSpellCheck::UpdateCurrentDictionary(
}
// Try to get topmost document's document element for embedded mail editor.
if (flags & nsIPlaintextEditor::eEditorMailMask) {
if (flags & nsIEditor::eEditorMailMask) {
RefPtr<Document> ownerDoc = rootContent->OwnerDoc();
Document* parentDoc = ownerDoc->GetInProcessParentDocument();
if (parentDoc) {
@ -773,7 +772,7 @@ nsresult EditorSpellCheck::DictionaryFetched(DictionaryFetcher* aFetcher) {
nsAutoString dictName;
uint32_t flags;
mEditor->GetFlags(&flags);
if (!(flags & nsIPlaintextEditor::eEditorMailMask)) {
if (!(flags & nsIEditor::eEditorMailMask)) {
dictName.Assign(aFetcher->mDictionary);
if (!dictName.IsEmpty()) {
AutoTArray<nsString, 1> tryDictList;

Просмотреть файл

@ -10,7 +10,7 @@
#include "nsCOMPtr.h"
#include "nsFontMetrics.h"
#include "nsTextControlFrame.h"
#include "nsIPlaintextEditor.h"
#include "nsIEditor.h"
#include "nsCaret.h"
#include "nsCSSPseudoElements.h"
#include "nsGenericHTMLElement.h"
@ -1099,13 +1099,13 @@ nsresult nsTextControlFrame::AttributeChanged(int32_t aNameSpaceID,
if (nsContentUtils::IsFocusedContent(mContent)) {
selCon->SetCaretEnabled(false);
}
textEditor->AddFlags(nsIPlaintextEditor::eEditorReadonlyMask);
textEditor->AddFlags(nsIEditor::eEditorReadonlyMask);
} else { // unset readonly
if (!textEditor->IsDisabled() &&
nsContentUtils::IsFocusedContent(mContent)) {
selCon->SetCaretEnabled(true);
}
textEditor->RemoveFlags(nsIPlaintextEditor::eEditorReadonlyMask);
textEditor->RemoveFlags(nsIEditor::eEditorReadonlyMask);
}
return NS_OK;
}
@ -1127,9 +1127,9 @@ nsresult nsTextControlFrame::AttributeChanged(int32_t aNameSpaceID,
selCon->SetCaretEnabled(!hasAttr);
}
if (disable) {
textEditor->AddFlags(nsIPlaintextEditor::eEditorDisabledMask);
textEditor->AddFlags(nsIEditor::eEditorDisabledMask);
} else {
textEditor->RemoveFlags(nsIPlaintextEditor::eEditorDisabledMask);
textEditor->RemoveFlags(nsIEditor::eEditorDisabledMask);
}
return NS_OK;
}

Просмотреть файл

@ -42,11 +42,7 @@ addLoadEvent(function() {
function synthesizeDropText(aElement, aText)
{
var editor = SpecialPowers.wrap(aElement)
.editor
.QueryInterface(SpecialPowers.Ci.nsIPlaintextEditor);
editor.insertText(aText);
SpecialPowers.wrap(aElement).editor.insertText(aText);
}
// We insert "bar" and we should only see "bar" now.

Просмотреть файл

@ -1013,8 +1013,7 @@ function runComplexContenteditableTests() {
description + "The editor doesn't get focus");
is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
description + "IME isn't enabled on HTML editor");
const kReadonly =
Ci.nsIPlaintextEditor.eEditorReadonlyMask;
const kReadonly = Ci.nsIEditor.eEditorReadonlyMask;
var editor = window.docShell.editor;
var flags = editor.flags;
editor.flags = flags | kReadonly;
@ -1209,8 +1208,8 @@ function runEditorFlagChangeTests() {
is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,
description + "IME isn't enabled on HTML editor");
const kIMEStateChangeFlags =
Ci.nsIPlaintextEditor.eEditorReadonlyMask |
Ci.nsIPlaintextEditor.eEditorDisabledMask;
Ci.nsIEditor.eEditorReadonlyMask |
Ci.nsIEditor.eEditorDisabledMask;
var editor = window.docShell.editor;
var flags = editor.flags;
@ -1233,7 +1232,7 @@ function runEditorFlagChangeTests() {
description + "#1 IME isn't enabled on HTML editor");
editor.flags |=
~(kIMEStateChangeFlags | Ci.nsIPlaintextEditor.eEditorPasswordMask);
~(kIMEStateChangeFlags | Ci.nsIEditor.eEditorPasswordMask);
ok(editor.composing,
description + "#2 IME composition was committed unexpectedly");
is(gUtils.IMEStatus, gUtils.IME_STATUS_ENABLED,

Просмотреть файл

@ -166,8 +166,7 @@ function runTests() {
}
function testOnEditorFlagChange(aDescription, aIsInDesignMode) {
const kReadonly =
Ci.nsIPlaintextEditor.eEditorReadonlyMask;
const kReadonly = Ci.nsIEditor.eEditorReadonlyMask;
var description = "testOnEditorFlagChange: " + aDescription;
resetFocusToParentHTML(description);
var htmlEditor = iframe.contentWindow.docShell.editor;