зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
89ede87cf3
Коммит
b1bf7e0db4
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче