2016-07-09 05:42:33 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#ifndef mozilla_HTMLEditor_h
|
|
|
|
#define mozilla_HTMLEditor_h
|
|
|
|
|
|
|
|
#include "mozilla/Attributes.h"
|
2018-01-26 08:38:05 +03:00
|
|
|
#include "mozilla/ComposerCommandsUpdater.h"
|
2016-07-08 08:03:31 +03:00
|
|
|
#include "mozilla/CSSEditUtils.h"
|
2017-08-02 22:37:44 +03:00
|
|
|
#include "mozilla/ManualNAC.h"
|
2016-09-26 15:03:25 +03:00
|
|
|
#include "mozilla/StyleSheet.h"
|
2016-07-09 05:54:50 +03:00
|
|
|
#include "mozilla/TextEditor.h"
|
2017-12-21 08:52:32 +03:00
|
|
|
#include "mozilla/TextEditRules.h"
|
2017-02-08 12:14:24 +03:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2016-07-09 05:42:33 +03:00
|
|
|
#include "mozilla/dom/Element.h"
|
|
|
|
#include "mozilla/dom/File.h"
|
|
|
|
|
|
|
|
#include "nsAttrName.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsICSSLoaderObserver.h"
|
|
|
|
#include "nsIDocumentObserver.h"
|
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsIEditorMailSupport.h"
|
|
|
|
#include "nsIEditorStyleSheets.h"
|
|
|
|
#include "nsIEditorUtils.h"
|
|
|
|
#include "nsIHTMLAbsPosEditor.h"
|
|
|
|
#include "nsIHTMLEditor.h"
|
|
|
|
#include "nsIHTMLInlineTableEditor.h"
|
|
|
|
#include "nsIHTMLObjectResizer.h"
|
|
|
|
#include "nsITableEditor.h"
|
|
|
|
#include "nsPoint.h"
|
|
|
|
#include "nsStubMutationObserver.h"
|
|
|
|
#include "nsTArray.h"
|
|
|
|
|
|
|
|
class nsDocumentFragment;
|
2018-04-06 08:53:05 +03:00
|
|
|
class nsHTMLDocument;
|
2016-07-09 05:42:33 +03:00
|
|
|
class nsITransferable;
|
|
|
|
class nsIClipboard;
|
2018-01-26 11:25:45 +03:00
|
|
|
class nsIDOMDocument;
|
2018-03-19 08:14:45 +03:00
|
|
|
class nsIDOMElement;
|
2016-07-09 05:42:33 +03:00
|
|
|
class nsILinkHandler;
|
|
|
|
class nsTableWrapperFrame;
|
|
|
|
class nsIDOMRange;
|
|
|
|
class nsRange;
|
2018-01-26 11:25:45 +03:00
|
|
|
class nsISelection;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
namespace mozilla {
|
2017-08-08 04:57:19 +03:00
|
|
|
class AutoSelectionSetterAfterTableEdit;
|
2016-07-09 05:42:33 +03:00
|
|
|
class HTMLEditorEventListener;
|
|
|
|
class HTMLEditRules;
|
2018-01-26 09:14:04 +03:00
|
|
|
class ResizerSelectionListener;
|
2016-07-09 05:42:33 +03:00
|
|
|
class TypeInState;
|
|
|
|
class WSRunObject;
|
2018-01-12 13:01:04 +03:00
|
|
|
enum class EditAction : int32_t;
|
2016-07-09 05:42:33 +03:00
|
|
|
struct PropItem;
|
|
|
|
template<class T> class OwningNonNull;
|
|
|
|
namespace dom {
|
|
|
|
class DocumentFragment;
|
2018-04-20 19:53:17 +03:00
|
|
|
class Event;
|
2018-03-20 07:16:05 +03:00
|
|
|
class MouseEvent;
|
2016-07-09 05:42:33 +03:00
|
|
|
} // namespace dom
|
|
|
|
namespace widget {
|
|
|
|
struct IMEState;
|
|
|
|
} // namespace widget
|
|
|
|
|
2016-08-24 15:53:52 +03:00
|
|
|
enum class ParagraphSeparator { div, p, br };
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
/**
|
|
|
|
* The HTML editor implementation.<br>
|
|
|
|
* Use to edit HTML document represented as a DOM tree.
|
|
|
|
*/
|
2016-07-09 05:54:50 +03:00
|
|
|
class HTMLEditor final : public TextEditor
|
2016-07-09 05:42:33 +03:00
|
|
|
, public nsIHTMLEditor
|
|
|
|
, public nsIHTMLObjectResizer
|
|
|
|
, public nsIHTMLAbsPosEditor
|
|
|
|
, public nsITableEditor
|
|
|
|
, public nsIHTMLInlineTableEditor
|
|
|
|
, public nsIEditorStyleSheets
|
|
|
|
, public nsICSSLoaderObserver
|
|
|
|
, public nsStubMutationObserver
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
enum BlockTransformationType
|
|
|
|
{
|
|
|
|
eNoOp,
|
|
|
|
eReplaceParent = 1,
|
|
|
|
eInsertParent = 2
|
|
|
|
};
|
|
|
|
|
|
|
|
const char16_t kNBSP = 160;
|
|
|
|
|
|
|
|
public:
|
|
|
|
enum ResizingRequestID
|
|
|
|
{
|
|
|
|
kX = 0,
|
|
|
|
kY = 1,
|
|
|
|
kWidth = 2,
|
|
|
|
kHeight = 3
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
2016-07-09 05:54:50 +03:00
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor)
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
HTMLEditor();
|
|
|
|
|
|
|
|
bool GetReturnInParagraphCreatesNewParagraph();
|
|
|
|
Element* GetSelectionContainer();
|
|
|
|
|
2018-01-26 11:25:45 +03:00
|
|
|
// nsISelectionListener overrides
|
|
|
|
NS_IMETHOD NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
|
|
|
|
nsISelection* aSelection,
|
|
|
|
int16_t aReason) override;
|
|
|
|
|
2016-07-09 05:54:50 +03:00
|
|
|
// TextEditor overrides
|
2018-02-07 09:28:04 +03:00
|
|
|
virtual nsresult Init(nsIDocument& aDoc, Element* aRoot,
|
|
|
|
nsISelectionController* aSelCon, uint32_t aFlags,
|
|
|
|
const nsAString& aValue) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
NS_IMETHOD BeginningOfDocument() override;
|
2017-02-08 14:18:17 +03:00
|
|
|
virtual nsresult HandleKeyPressEvent(
|
|
|
|
WidgetKeyboardEvent* aKeyboardEvent) override;
|
2018-01-09 16:41:42 +03:00
|
|
|
virtual nsIContent* GetFocusedContent() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
|
|
|
|
virtual bool IsActiveInDOMWindow() override;
|
2018-01-09 16:41:42 +03:00
|
|
|
virtual dom::EventTarget* GetDOMEventTarget() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual Element* GetEditorRoot() override;
|
|
|
|
virtual already_AddRefed<nsIContent> FindSelectionRoot(
|
|
|
|
nsINode *aNode) override;
|
2017-01-17 11:17:06 +03:00
|
|
|
virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
|
2016-07-08 07:10:13 +03:00
|
|
|
using EditorBase::IsEditable;
|
2016-12-20 13:24:08 +03:00
|
|
|
virtual nsresult RemoveAttributeOrEquivalent(
|
|
|
|
Element* aElement,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-12-20 13:24:08 +03:00
|
|
|
bool aSuppressTransaction) override;
|
|
|
|
virtual nsresult SetAttributeOrEquivalent(Element* aElement,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-12-20 13:24:08 +03:00
|
|
|
const nsAString& aValue,
|
|
|
|
bool aSuppressTransaction) override;
|
|
|
|
using EditorBase::RemoveAttributeOrEquivalent;
|
|
|
|
using EditorBase::SetAttributeOrEquivalent;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// nsStubMutationObserver overrides
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
|
|
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
|
|
|
|
|
|
|
// nsIHTMLEditor methods
|
|
|
|
NS_DECL_NSIHTMLEDITOR
|
|
|
|
|
|
|
|
// nsIHTMLObjectResizer methods (implemented in HTMLObjectResizer.cpp)
|
|
|
|
NS_DECL_NSIHTMLOBJECTRESIZER
|
|
|
|
|
|
|
|
// nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp)
|
|
|
|
NS_DECL_NSIHTMLABSPOSEDITOR
|
|
|
|
|
|
|
|
// nsIHTMLInlineTableEditor methods (implemented in HTMLInlineTableEditor.cpp)
|
|
|
|
NS_DECL_NSIHTMLINLINETABLEEDITOR
|
|
|
|
|
|
|
|
// XXX Following methods are not overriding but defined here...
|
2017-10-10 03:36:16 +03:00
|
|
|
nsresult CopyLastEditableChildStyles(nsINode* aPreviousBlock,
|
|
|
|
nsINode* aNewBlock,
|
2016-07-09 05:42:33 +03:00
|
|
|
Element** aOutBrNode);
|
|
|
|
|
|
|
|
nsresult LoadHTML(const nsAString& aInputString);
|
|
|
|
|
|
|
|
nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor,
|
|
|
|
bool aBlockLevel);
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// nsIEditorStyleSheets methods
|
2017-01-27 05:11:09 +03:00
|
|
|
NS_DECL_NSIEDITORSTYLESHEETS
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// nsIEditorMailSupport methods
|
|
|
|
NS_DECL_NSIEDITORMAILSUPPORT
|
|
|
|
|
|
|
|
// nsITableEditor methods
|
2017-01-27 05:11:09 +03:00
|
|
|
NS_DECL_NSITABLEEDITOR
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult GetLastCellInRow(nsIDOMNode* aRowNode,
|
|
|
|
nsIDOMNode** aCellNode);
|
|
|
|
|
|
|
|
nsresult GetCellFromRange(nsRange* aRange, nsIDOMElement** aCell);
|
|
|
|
|
|
|
|
// Miscellaneous
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This sets background on the appropriate container element (table, cell,)
|
|
|
|
* or calls into nsTextEditor to set the page background.
|
|
|
|
*/
|
|
|
|
nsresult SetCSSBackgroundColor(const nsAString& aColor);
|
|
|
|
nsresult SetHTMLBackgroundColor(const nsAString& aColor);
|
|
|
|
|
2017-10-26 16:54:30 +03:00
|
|
|
/**
|
|
|
|
* GetBlockNodeParent() returns parent or nearest ancestor of aNode if
|
|
|
|
* there is a block parent. If aAncestorLimiter is not nullptr,
|
|
|
|
* this stops looking for the result.
|
|
|
|
*/
|
|
|
|
static Element* GetBlockNodeParent(nsINode* aNode,
|
|
|
|
nsINode* aAncestorLimiter = nullptr);
|
|
|
|
/**
|
|
|
|
* GetBlock() returns aNode itself, or parent or nearest ancestor of aNode
|
|
|
|
* if there is a block parent. If aAncestorLimiter is not nullptr,
|
|
|
|
* this stops looking for the result.
|
|
|
|
*/
|
|
|
|
static Element* GetBlock(nsINode& aNode,
|
|
|
|
nsINode* aAncestorLimiter = nullptr);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
void IsNextCharInNodeWhitespace(nsIContent* aContent,
|
|
|
|
int32_t aOffset,
|
|
|
|
bool* outIsSpace,
|
|
|
|
bool* outIsNBSP,
|
|
|
|
nsIContent** outNode = nullptr,
|
|
|
|
int32_t* outOffset = 0);
|
|
|
|
void IsPrevCharInNodeWhitespace(nsIContent* aContent,
|
|
|
|
int32_t aOffset,
|
|
|
|
bool* outIsSpace,
|
|
|
|
bool* outIsNBSP,
|
|
|
|
nsIContent** outNode = nullptr,
|
|
|
|
int32_t* outOffset = 0);
|
|
|
|
|
2016-07-08 07:10:13 +03:00
|
|
|
// Overrides of EditorBase interface methods
|
2017-02-01 11:09:54 +03:00
|
|
|
virtual nsresult EndUpdateViewBatch() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
NS_IMETHOD PreDestroy(bool aDestroyingFrames) override;
|
|
|
|
|
2018-02-07 09:28:04 +03:00
|
|
|
virtual nsresult GetPreferredIMEState(widget::IMEState* aState) override;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
/**
|
|
|
|
* @param aElement Must not be null.
|
|
|
|
*/
|
|
|
|
static bool NodeIsBlockStatic(const nsINode* aElement);
|
|
|
|
|
2017-08-04 12:30:13 +03:00
|
|
|
// non-virtual methods of interface methods
|
|
|
|
bool AbsolutePositioningEnabled() const
|
|
|
|
{
|
|
|
|
return mIsAbsolutelyPositioningEnabled;
|
|
|
|
}
|
2018-02-01 04:55:25 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* returns the deepest absolutely positioned container of the selection
|
|
|
|
* if it exists or null.
|
|
|
|
*/
|
2018-01-30 07:42:52 +03:00
|
|
|
already_AddRefed<Element> GetAbsolutelyPositionedSelectionContainer();
|
2018-02-01 04:55:25 +03:00
|
|
|
|
2017-08-04 12:30:13 +03:00
|
|
|
Element* GetPositionedElement() const
|
|
|
|
{
|
|
|
|
return mAbsolutelyPositionedObject;
|
|
|
|
}
|
2018-02-01 04:55:25 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* extracts the selection from the normal flow of the document and
|
|
|
|
* positions it.
|
|
|
|
* @param aEnabled [IN] true to absolutely position the selection,
|
|
|
|
* false to put it back in the normal flow
|
|
|
|
*/
|
|
|
|
nsresult SetSelectionToAbsoluteOrStatic(bool aEnabled);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* extracts an element from the normal flow of the document and
|
|
|
|
* positions it, and puts it back in the normal flow.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aEnabled [IN] true to absolutely position the element,
|
|
|
|
* false to put it back in the normal flow
|
|
|
|
*/
|
|
|
|
nsresult SetPositionToAbsoluteOrStatic(Element& aElement,
|
|
|
|
bool aEnabled);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* returns the absolute z-index of a positioned element. Never returns 'auto'
|
|
|
|
* @return the z-index of the element
|
|
|
|
* @param aElement [IN] the element.
|
|
|
|
*/
|
|
|
|
int32_t GetZIndex(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adds aChange to the z-index of the currently positioned element.
|
|
|
|
* @param aChange [IN] relative change to apply to current z-index
|
|
|
|
*/
|
|
|
|
nsresult AddZIndex(int32_t aChange);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adds aChange to the z-index of an arbitrary element.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aChange [IN] relative change to apply to current z-index of
|
|
|
|
* the element
|
|
|
|
* @param aReturn [OUT] the new z-index of the element
|
|
|
|
*/
|
|
|
|
nsresult RelativeChangeElementZIndex(Element& aElement, int32_t aChange,
|
|
|
|
int32_t* aReturn);
|
2017-08-04 12:30:13 +03:00
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult SetInlineProperty(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2017-08-25 08:40:45 +03:00
|
|
|
const nsAString& aValue);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult GetInlineProperty(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2017-08-25 08:40:45 +03:00
|
|
|
const nsAString& aValue,
|
|
|
|
bool* aFirst,
|
|
|
|
bool* aAny,
|
|
|
|
bool* aAll);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult GetInlinePropertyWithAttrValue(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttr,
|
2017-08-25 08:40:45 +03:00
|
|
|
const nsAString& aValue,
|
|
|
|
bool* aFirst,
|
|
|
|
bool* aAny,
|
|
|
|
bool* aAll,
|
|
|
|
nsAString& outValue);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult RemoveInlineProperty(nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute);
|
2018-01-26 08:38:05 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SetComposerCommandsUpdater() sets or unsets mComposerCommandsUpdater.
|
|
|
|
* This will crash in debug build if the editor already has an instance
|
|
|
|
* but called with another instance.
|
|
|
|
*/
|
|
|
|
void SetComposerCommandsUpdater(
|
|
|
|
ComposerCommandsUpdater* aComposerCommandsUpdater)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!aComposerCommandsUpdater || !mComposerCommandsUpdater ||
|
|
|
|
aComposerCommandsUpdater == mComposerCommandsUpdater);
|
|
|
|
mComposerCommandsUpdater = aComposerCommandsUpdater;
|
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
protected:
|
|
|
|
virtual ~HTMLEditor();
|
|
|
|
|
2016-07-08 07:10:13 +03:00
|
|
|
using EditorBase::IsBlockNode;
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual bool IsBlockNode(nsINode *aNode) override;
|
|
|
|
|
Bug 662591 - HTMLEditor should set caret to start of first editable text node or before first editable inline node r=m_kato
Currently, HTMLEditor doesn't initialize caret position when it gets focus by
itself in most cases. Only when it's in designMode, it may move caret to the
first visible (not checking CSS actually).
In most cases, caret position is adjusted when EditorBase::InitializeSelection()
calls Selection::SetAncestorLimiter(). If selected range is outside of
new limiter, it moves caret to start of the new limiter. However, this is
really different behavior from the other browsers. The other browsers try
to move caret to the first editable text node or before the first editable
content such as <img>, <input>, etc.
This difference causes a serious incompatible issue with Draft.js. It doesn't
initialize caret position when it gets focus but it assumes that caret is
always set to before <br> element if there is no other content.
So, let's try to behave as what other browsers do as far as possible.
This patch makes editor behave as:
* if selection is already in the editing host except start of the editing host,
does nothing.
* if there is non-editable element before any editable node, move caret to
start of the editing host.
* if there is editable text node or element node which cannot have a text node,
move its start or before it.
* if there is no editable nodes which can contain text nodes, move caret to
start of the editing host.
Note that before applying this patch, in designMode, BeginningOfDocument() used
document element instead of <body> element. Therefore, it may set odd position
if <head> element has some text nodes with <script> or <style>. However,
this doesn't make sense and for making more consistent behavior between
designMode and contenteditable, this patch makes it use editing host (it's
<body> element if it's in designMode).
MozReview-Commit-ID: 5neYoTMq6Cc
--HG--
extra : rebase_source : c4d06b6864a221d7cd2833a007d73f7d67821e95
2018-03-02 08:20:25 +03:00
|
|
|
virtual void
|
|
|
|
InitializeSelectionAncestorLimit(Selection& aSelection,
|
|
|
|
nsIContent& aAncestorLimit) override;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
public:
|
|
|
|
// XXX Why don't we move following methods above for grouping by the origins?
|
|
|
|
NS_IMETHOD SetFlags(uint32_t aFlags) override;
|
|
|
|
|
|
|
|
NS_IMETHOD Paste(int32_t aSelectionType) override;
|
|
|
|
NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
|
|
|
|
|
|
|
|
NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
|
|
|
|
NS_IMETHOD CanPasteTransferable(nsITransferable* aTransferable,
|
|
|
|
bool* aCanPaste) override;
|
|
|
|
|
|
|
|
NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
|
|
|
|
int32_t* outNumTestsFailed) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* All editor operations which alter the doc should be prefaced
|
|
|
|
* with a call to StartOperation, naming the action and direction.
|
|
|
|
*/
|
2018-04-11 11:37:49 +03:00
|
|
|
virtual nsresult StartOperation(EditAction opID,
|
|
|
|
nsIEditor::EDirection aDirection) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* All editor operations which alter the doc should be followed
|
|
|
|
* with a call to EndOperation.
|
|
|
|
*/
|
2018-04-11 11:37:49 +03:00
|
|
|
virtual nsresult EndOperation() override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* returns true if aParentTag can contain a child of type aChildTag.
|
|
|
|
*/
|
2017-10-03 01:05:19 +03:00
|
|
|
virtual bool TagCanContainTag(nsAtom& aParentTag,
|
2017-10-26 19:27:44 +03:00
|
|
|
nsAtom& aChildTag) const override;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if aNode is a container.
|
|
|
|
*/
|
|
|
|
virtual bool IsContainer(nsINode* aNode) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Make the given selection span the entire document.
|
|
|
|
*/
|
|
|
|
virtual nsresult SelectEntireDocument(Selection* aSelection) override;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Join together any adjacent editable text nodes in the range.
|
|
|
|
*/
|
|
|
|
nsresult CollapseAdjacentTextNodes(nsRange* aRange);
|
|
|
|
|
|
|
|
virtual bool AreNodesSameType(nsIContent* aNode1,
|
|
|
|
nsIContent* aNode2) override;
|
|
|
|
|
2018-04-11 13:11:15 +03:00
|
|
|
/**
|
|
|
|
* DeleteSelectionWithTransaction() removes selected content or content
|
|
|
|
* around caret with transactions.
|
|
|
|
*
|
|
|
|
* @param aDirection How much range should be removed.
|
|
|
|
* @param aStripWrappers Whether the parent blocks should be removed
|
|
|
|
* when they become empty.
|
|
|
|
*/
|
|
|
|
virtual nsresult
|
|
|
|
DeleteSelectionWithTransaction(EDirection aAction,
|
|
|
|
EStripWrappers aStripWrappers) override;
|
2018-04-10 10:23:54 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* DeleteNodeWithTransaction() removes aNode from the DOM tree if it's
|
|
|
|
* modifiable. Note that this is not an override of same method of
|
|
|
|
* EditorBase.
|
|
|
|
*
|
|
|
|
* @param aNode The node to be removed from the DOM tree.
|
|
|
|
*/
|
|
|
|
nsresult DeleteNodeWithTransaction(nsINode& aNode);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
NS_IMETHOD DeleteNode(nsIDOMNode* aNode) override;
|
2018-04-10 10:23:54 +03:00
|
|
|
|
2018-04-10 10:50:06 +03:00
|
|
|
/**
|
|
|
|
* DeleteTextWithTransaction() removes text in the range from aCharData if
|
|
|
|
* it's modifiable. Note that this not an override of same method of
|
|
|
|
* EditorBase.
|
|
|
|
*
|
|
|
|
* @param aCharData The data node which should be modified.
|
|
|
|
* @param aOffset Start offset of removing text in aCharData.
|
|
|
|
* @param aLength Length of removing text.
|
|
|
|
*/
|
|
|
|
nsresult DeleteTextWithTransaction(dom::CharacterData& aTextNode,
|
|
|
|
uint32_t aOffset, uint32_t aLength);
|
|
|
|
|
2018-04-12 11:58:14 +03:00
|
|
|
/**
|
|
|
|
* InsertTextWithTransaction() inserts aStringToInsert at aPointToInsert.
|
|
|
|
*/
|
2017-11-08 19:00:36 +03:00
|
|
|
virtual nsresult
|
2018-04-12 11:58:14 +03:00
|
|
|
InsertTextWithTransaction(nsIDocument& aDocument,
|
|
|
|
const nsAString& aStringToInsert,
|
|
|
|
const EditorRawDOMPoint& aPointToInsert,
|
|
|
|
EditorRawDOMPoint* aPointAfterInsertedString =
|
|
|
|
nullptr) override;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
virtual bool IsModifiableNode(nsINode* aNode) override;
|
|
|
|
|
|
|
|
NS_IMETHOD SelectAll() override;
|
|
|
|
|
|
|
|
// nsICSSLoaderObserver
|
2016-09-26 15:03:25 +03:00
|
|
|
NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
|
2016-07-09 05:42:33 +03:00
|
|
|
bool aWasAlternate, nsresult aStatus) override;
|
|
|
|
|
|
|
|
// Utility Routines, not part of public API
|
|
|
|
NS_IMETHOD TypedText(const nsAString& aString,
|
|
|
|
ETypingAction aAction) override;
|
2017-11-28 16:28:07 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* InsertNodeIntoProperAncestor() attempts to insert aNode into the document,
|
|
|
|
* at aPointToInsert. Checks with strict dtd to see if containment is
|
|
|
|
* allowed. If not allowed, will attempt to find a parent in the parent
|
2017-12-07 12:45:52 +03:00
|
|
|
* hierarchy of aPointToInsert.GetContainer() that will accept aNode as a
|
|
|
|
* child. If such a parent is found, will split the document tree from
|
|
|
|
* aPointToInsert up to parent, and then insert aNode. aPointToInsert is then
|
|
|
|
* adjusted to point to the actual location that aNode was inserted at.
|
|
|
|
* aSplitAtEdges specifies if the splitting process is allowed to result in
|
|
|
|
* empty nodes.
|
2017-11-28 16:28:07 +03:00
|
|
|
*
|
|
|
|
* @param aNode Node to insert.
|
|
|
|
* @param aPointToInsert Insertion point.
|
|
|
|
* @param aSplitAtEdges Splitting can result in empty nodes?
|
|
|
|
* @return Returns inserted point if succeeded.
|
|
|
|
* Otherwise, the result is not set.
|
|
|
|
*/
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-28 16:28:07 +03:00
|
|
|
EditorDOMPoint
|
|
|
|
InsertNodeIntoProperAncestor(nsIContent& aNode,
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPointToInsert,
|
2017-11-28 16:28:07 +03:00
|
|
|
SplitAtEdges aSplitAtEdges);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Use this to assure that selection is set after attribute nodes when
|
|
|
|
* trying to collapse selection at begining of a block node
|
|
|
|
* e.g., when setting at beginning of a table cell
|
|
|
|
* This will stop at a table, however, since we don't want to
|
|
|
|
* "drill down" into nested tables.
|
|
|
|
* @param aSelection Optional. If null, we get current selection.
|
|
|
|
*/
|
|
|
|
void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
|
|
|
|
nsINode* aNode);
|
|
|
|
|
2017-12-20 09:07:37 +03:00
|
|
|
/**
|
|
|
|
* IsInVisibleTextFrames() returns true if all text in aText is in visible
|
|
|
|
* text frames. Callers have to guarantee that there is no pending reflow.
|
|
|
|
*/
|
|
|
|
bool IsInVisibleTextFrames(dom::Text& aText);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* IsVisibleTextNode() returns true if aText has visible text. If it has
|
|
|
|
* only whitespaces and they are collapsed, returns false.
|
|
|
|
*/
|
|
|
|
bool IsVisibleTextNode(Text& aText);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
/**
|
|
|
|
* aNode must be a non-null text node.
|
|
|
|
* outIsEmptyNode must be non-null.
|
|
|
|
*/
|
|
|
|
nsresult IsEmptyNode(nsINode* aNode, bool* outIsEmptyBlock,
|
|
|
|
bool aMozBRDoesntCount = false,
|
|
|
|
bool aListOrCellNotEmpty = false,
|
|
|
|
bool aSafeToAskFrames = false);
|
|
|
|
nsresult IsEmptyNodeImpl(nsINode* aNode,
|
|
|
|
bool* outIsEmptyBlock,
|
|
|
|
bool aMozBRDoesntCount,
|
|
|
|
bool aListOrCellNotEmpty,
|
|
|
|
bool aSafeToAskFrames,
|
|
|
|
bool* aSeenBR);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns TRUE if sheet was loaded, false if it wasn't.
|
|
|
|
*/
|
|
|
|
bool EnableExistingStyleSheet(const nsAString& aURL);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dealing with the internal style sheet lists.
|
|
|
|
*/
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* GetStyleSheetForURL(const nsAString& aURL);
|
|
|
|
void GetURLForStyleSheet(StyleSheet* aStyleSheet,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsAString& aURL);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a url + known style sheet to the internal lists.
|
|
|
|
*/
|
|
|
|
nsresult AddNewStyleSheetToList(const nsAString &aURL,
|
2016-09-26 15:03:25 +03:00
|
|
|
StyleSheet* aStyleSheet);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult RemoveStyleSheetFromList(const nsAString &aURL);
|
|
|
|
|
2018-02-02 12:42:25 +03:00
|
|
|
bool IsCSSEnabled() const
|
2016-07-09 05:42:33 +03:00
|
|
|
{
|
|
|
|
// TODO: removal of mCSSAware and use only the presence of mCSSEditUtils
|
|
|
|
return mCSSAware && mCSSEditUtils && mCSSEditUtils->IsCSSPrefChecked();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool HasAttributes(Element* aElement)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aElement);
|
|
|
|
uint32_t attrCount = aElement->GetAttrCount();
|
|
|
|
return attrCount > 1 ||
|
|
|
|
(1 == attrCount &&
|
|
|
|
!aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
|
|
|
|
}
|
|
|
|
|
2016-08-24 15:53:52 +03:00
|
|
|
ParagraphSeparator GetDefaultParagraphSeparator() const
|
|
|
|
{
|
|
|
|
return mDefaultParagraphSeparator;
|
|
|
|
}
|
|
|
|
void SetDefaultParagraphSeparator(ParagraphSeparator aSep)
|
|
|
|
{
|
|
|
|
mDefaultParagraphSeparator = aSep;
|
|
|
|
}
|
|
|
|
|
2018-01-10 06:47:16 +03:00
|
|
|
/**
|
|
|
|
* event callback when a mouse button is pressed
|
|
|
|
* @param aX [IN] horizontal position of the pointer
|
|
|
|
* @param aY [IN] vertical position of the pointer
|
|
|
|
* @param aTarget [IN] the element triggering the event
|
|
|
|
* @param aMouseEvent [IN] the event
|
|
|
|
*/
|
|
|
|
nsresult OnMouseDown(int32_t aX, int32_t aY, nsIDOMElement* aTarget,
|
2018-04-20 19:53:17 +03:00
|
|
|
dom::Event* aMouseEvent);
|
2018-01-10 06:47:16 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* event callback when a mouse button is released
|
|
|
|
* @param aX [IN] horizontal position of the pointer
|
|
|
|
* @param aY [IN] vertical position of the pointer
|
|
|
|
* @param aTarget [IN] the element triggering the event
|
|
|
|
*/
|
|
|
|
nsresult OnMouseUp(int32_t aX, int32_t aY, nsIDOMElement* aTarget);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* event callback when the mouse pointer is moved
|
|
|
|
* @param aMouseEvent [IN] the event
|
|
|
|
*/
|
2018-03-20 07:16:05 +03:00
|
|
|
nsresult OnMouseMove(dom::MouseEvent* aMouseEvent);
|
2018-01-10 06:47:16 +03:00
|
|
|
|
2018-01-19 10:41:41 +03:00
|
|
|
/**
|
|
|
|
* Modifies the table containing the selection according to the
|
|
|
|
* activation of an inline table editing UI element
|
|
|
|
* @param aUIAnonymousElement [IN] the inline table editing UI element
|
|
|
|
*/
|
2018-01-25 16:16:32 +03:00
|
|
|
nsresult DoInlineTableEditingAction(const Element& aUIAnonymousElement);
|
2018-01-19 10:41:41 +03:00
|
|
|
|
Bug 662591 - HTMLEditor should set caret to start of first editable text node or before first editable inline node r=m_kato
Currently, HTMLEditor doesn't initialize caret position when it gets focus by
itself in most cases. Only when it's in designMode, it may move caret to the
first visible (not checking CSS actually).
In most cases, caret position is adjusted when EditorBase::InitializeSelection()
calls Selection::SetAncestorLimiter(). If selected range is outside of
new limiter, it moves caret to start of the new limiter. However, this is
really different behavior from the other browsers. The other browsers try
to move caret to the first editable text node or before the first editable
content such as <img>, <input>, etc.
This difference causes a serious incompatible issue with Draft.js. It doesn't
initialize caret position when it gets focus but it assumes that caret is
always set to before <br> element if there is no other content.
So, let's try to behave as what other browsers do as far as possible.
This patch makes editor behave as:
* if selection is already in the editing host except start of the editing host,
does nothing.
* if there is non-editable element before any editable node, move caret to
start of the editing host.
* if there is editable text node or element node which cannot have a text node,
move its start or before it.
* if there is no editable nodes which can contain text nodes, move caret to
start of the editing host.
Note that before applying this patch, in designMode, BeginningOfDocument() used
document element instead of <body> element. Therefore, it may set odd position
if <head> element has some text nodes with <script> or <style>. However,
this doesn't make sense and for making more consistent behavior between
designMode and contenteditable, this patch makes it use editing host (it's
<body> element if it's in designMode).
MozReview-Commit-ID: 5neYoTMq6Cc
--HG--
extra : rebase_source : c4d06b6864a221d7cd2833a007d73f7d67821e95
2018-03-02 08:20:25 +03:00
|
|
|
/**
|
|
|
|
* MaybeCollapseSelectionAtFirstEditableNode() may collapse selection at
|
|
|
|
* proper position to staring to edit. If there is a non-editable node
|
|
|
|
* before any editable text nodes or inline elements which can have text
|
|
|
|
* nodes as their children, collapse selection at start of the editing
|
|
|
|
* host. If there is an editable text node which is not collapsed, collapses
|
|
|
|
* selection at the start of the text node. If there is an editable inline
|
|
|
|
* element which cannot have text nodes as its child, collapses selection at
|
|
|
|
* before the element node. Otherwise, collapses selection at start of the
|
|
|
|
* editing host.
|
|
|
|
*
|
|
|
|
* @param aIgnoreIfSelectionInEditingHost
|
|
|
|
* This method does nothing if selection is in the
|
|
|
|
* editing host except if it's collapsed at start of
|
|
|
|
* the editing host.
|
|
|
|
* Note that if selection ranges were outside of
|
|
|
|
* current selection limiter, selection was collapsed
|
|
|
|
* at the start of the editing host therefore, if
|
|
|
|
* you call this with setting this to true, you can
|
|
|
|
* keep selection ranges if user has already been
|
|
|
|
* changed.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
MaybeCollapseSelectionAtFirstEditableNode(
|
|
|
|
bool aIgnoreIfSelectionInEditingHost);
|
|
|
|
|
2018-04-06 08:53:05 +03:00
|
|
|
nsHTMLDocument* GetHTMLDocument() const;
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
protected:
|
|
|
|
class BlobReader final : public nsIEditorBlobListener
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
|
2018-04-06 08:53:05 +03:00
|
|
|
bool aIsSafe, nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestinationNode, int32_t aDestOffset,
|
2016-07-09 05:42:33 +03:00
|
|
|
bool aDoDeleteSelection);
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIEDITORBLOBLISTENER
|
|
|
|
|
|
|
|
private:
|
|
|
|
~BlobReader()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<dom::BlobImpl> mBlob;
|
|
|
|
RefPtr<HTMLEditor> mHTMLEditor;
|
|
|
|
bool mIsSafe;
|
2018-04-06 08:53:05 +03:00
|
|
|
nsCOMPtr<nsIDocument> mSourceDoc;
|
2018-03-27 14:19:35 +03:00
|
|
|
nsCOMPtr<nsINode> mDestinationNode;
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t mDestOffset;
|
|
|
|
bool mDoDeleteSelection;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHOD InitRules() override;
|
|
|
|
|
|
|
|
virtual void CreateEventListeners() override;
|
|
|
|
virtual nsresult InstallEventListeners() override;
|
|
|
|
virtual void RemoveEventListeners() override;
|
|
|
|
|
|
|
|
bool ShouldReplaceRootElement();
|
2017-08-28 21:57:46 +03:00
|
|
|
void NotifyRootChanged();
|
2018-01-30 08:25:36 +03:00
|
|
|
Element* GetBodyElement();
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the focused node of this editor.
|
|
|
|
* @return If the editor has focus, this returns the focused node.
|
|
|
|
* Otherwise, returns null.
|
|
|
|
*/
|
|
|
|
already_AddRefed<nsINode> GetFocusedNode();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return TRUE if aElement is a table-related elemet and caret was set.
|
|
|
|
*/
|
|
|
|
bool SetCaretInTableCell(nsIDOMElement* aElement);
|
|
|
|
|
2017-07-14 09:48:40 +03:00
|
|
|
nsresult TabInTable(bool inIsShift, bool* outHandled);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-11-21 08:38:19 +03:00
|
|
|
/**
|
|
|
|
* InsertBR() inserts a new <br> element at selection. If there is
|
|
|
|
* non-collapsed selection ranges, the selected ranges is deleted first.
|
|
|
|
*/
|
2017-11-17 15:10:07 +03:00
|
|
|
nsresult InsertBR();
|
2017-01-23 06:39:47 +03:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
// Table Editing (implemented in nsTableEditor.cpp)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert a new cell after or before supplied aCell.
|
|
|
|
* Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
|
|
|
|
* of course)
|
|
|
|
* This doesn't change or use the current selection.
|
|
|
|
*/
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult InsertCell(nsIDOMElement* aCell, int32_t aRowSpan,
|
|
|
|
int32_t aColSpan, bool aAfter, bool aIsHeader,
|
|
|
|
nsIDOMElement** aNewCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helpers that don't touch the selection or do batch transactions.
|
|
|
|
*/
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult DeleteRow(nsIDOMElement* aTable, int32_t aRowIndex);
|
|
|
|
nsresult DeleteColumn(nsIDOMElement* aTable, int32_t aColIndex);
|
|
|
|
nsresult DeleteCellContents(nsIDOMElement* aCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Move all contents from aCellToMerge into aTargetCell (append at end).
|
|
|
|
*/
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
|
|
|
|
nsCOMPtr<nsIDOMElement> aCellToMerge,
|
|
|
|
bool aDeleteCellToMerge);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsresult DeleteTable2(nsIDOMElement* aTable, Selection* aSelection);
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult SetColSpan(nsIDOMElement* aCell, int32_t aColSpan);
|
|
|
|
nsresult SetRowSpan(nsIDOMElement* aCell, int32_t aRowSpan);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper used to get nsTableWrapperFrame for a table.
|
|
|
|
*/
|
|
|
|
nsTableWrapperFrame* GetTableFrame(nsIDOMElement* aTable);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Needed to do appropriate deleting when last cell or row is about to be
|
|
|
|
* deleted. This doesn't count cells that don't start in the given row (are
|
|
|
|
* spanning from row above).
|
|
|
|
*/
|
|
|
|
int32_t GetNumberOfCellsInRow(nsIDOMElement* aTable, int32_t rowIndex);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test if all cells in row or column at given index are selected.
|
|
|
|
*/
|
|
|
|
bool AllCellsInRowSelected(nsIDOMElement* aTable, int32_t aRowIndex,
|
|
|
|
int32_t aNumberOfColumns);
|
|
|
|
bool AllCellsInColumnSelected(nsIDOMElement* aTable, int32_t aColIndex,
|
|
|
|
int32_t aNumberOfRows);
|
|
|
|
|
|
|
|
bool IsEmptyCell(Element* aCell);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Most insert methods need to get the same basic context data.
|
|
|
|
* Any of the pointers may be null if you don't need that datum (for more
|
|
|
|
* efficiency).
|
|
|
|
* Input: *aCell is a known cell,
|
|
|
|
* if null, cell is obtained from the anchor node of the selection.
|
|
|
|
* Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is
|
|
|
|
* null.
|
|
|
|
*/
|
|
|
|
nsresult GetCellContext(Selection** aSelection, nsIDOMElement** aTable,
|
|
|
|
nsIDOMElement** aCell, nsIDOMNode** aCellParent,
|
|
|
|
int32_t* aCellOffset, int32_t* aRowIndex,
|
|
|
|
int32_t* aColIndex);
|
|
|
|
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult GetCellSpansAt(nsIDOMElement* aTable, int32_t aRowIndex,
|
|
|
|
int32_t aColIndex, int32_t& aActualRowSpan,
|
|
|
|
int32_t& aActualColSpan);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult SplitCellIntoColumns(nsIDOMElement* aTable, int32_t aRowIndex,
|
|
|
|
int32_t aColIndex, int32_t aColSpanLeft,
|
|
|
|
int32_t aColSpanRight,
|
|
|
|
nsIDOMElement** aNewCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult SplitCellIntoRows(nsIDOMElement* aTable, int32_t aRowIndex,
|
|
|
|
int32_t aColIndex, int32_t aRowSpanAbove,
|
|
|
|
int32_t aRowSpanBelow, nsIDOMElement** aNewCell);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsresult CopyCellBackgroundColor(nsIDOMElement* destCell,
|
|
|
|
nsIDOMElement* sourceCell);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reduce rowspan/colspan when cells span into nonexistent rows/columns.
|
|
|
|
*/
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult FixBadRowSpan(nsIDOMElement* aTable, int32_t aRowIndex,
|
|
|
|
int32_t& aNewRowCount);
|
|
|
|
nsresult FixBadColSpan(nsIDOMElement* aTable, int32_t aColIndex,
|
|
|
|
int32_t& aNewColCount);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Fallback method: Call this after using ClearSelection() and you
|
|
|
|
* failed to set selection to some other content in the document.
|
|
|
|
*/
|
|
|
|
nsresult SetSelectionAtDocumentStart(Selection* aSelection);
|
|
|
|
|
2017-12-15 19:14:54 +03:00
|
|
|
nsresult GetTableSize(Element* aTable,
|
|
|
|
int32_t* aRowCount, int32_t* aColCount);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
// End of Table Editing utilities
|
|
|
|
|
|
|
|
static Element* GetEnclosingTable(nsINode* aNode);
|
|
|
|
static nsIDOMNode* GetEnclosingTable(nsIDOMNode* aNode);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Content-based query returns true if <aProperty aAttribute=aValue> effects
|
|
|
|
* aNode. If <aProperty aAttribute=aValue> contains aNode, but
|
|
|
|
* <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
|
|
|
|
* more deeply nested than the first, then the first does not effect aNode.
|
|
|
|
*
|
|
|
|
* @param aNode The target of the query
|
|
|
|
* @param aProperty The property that we are querying for
|
|
|
|
* @param aAttribute The attribute of aProperty, example: color in
|
|
|
|
* <FONT color="blue"> May be null.
|
|
|
|
* @param aValue The value of aAttribute, example: blue in
|
|
|
|
* <FONT color="blue"> May be null. Ignored if aAttribute
|
|
|
|
* is null.
|
|
|
|
* @param outValue [OUT] the value of the attribute, if aIsSet is true
|
2017-10-12 10:28:28 +03:00
|
|
|
* @return true if <aProperty aAttribute=aValue> effects
|
|
|
|
* aNode.
|
2016-07-09 05:42:33 +03:00
|
|
|
*
|
|
|
|
* The nsIContent variant returns aIsSet instead of using an out parameter.
|
|
|
|
*/
|
|
|
|
bool IsTextPropertySetByContent(nsINode* aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString* aValue,
|
|
|
|
nsAString* outValue = nullptr);
|
|
|
|
|
|
|
|
// Methods for handling plaintext quotations
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult PasteAsPlaintextQuotation(int32_t aSelectionType);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Insert a string as quoted text, replacing the selected text (if any).
|
|
|
|
* @param aQuotedText The string to insert.
|
|
|
|
* @param aAddCites Whether to prepend extra ">" to each line
|
|
|
|
* (usually true, unless those characters
|
|
|
|
* have already been added.)
|
|
|
|
* @return aNodeInserted The node spanning the insertion, if applicable.
|
|
|
|
* If aAddCites is false, this will be null.
|
|
|
|
*/
|
2018-01-25 07:31:01 +03:00
|
|
|
nsresult InsertAsPlaintextQuotation(const nsAString& aQuotedText,
|
|
|
|
bool aAddCites,
|
|
|
|
nsIDOMNode** aNodeInserted);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2016-10-26 05:10:29 +03:00
|
|
|
nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
|
|
|
|
bool aIsSafe,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestinationNode,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aDestOffset,
|
|
|
|
bool aDoDeleteSelection);
|
|
|
|
|
|
|
|
// factored methods for handling insertion of data from transferables
|
|
|
|
// (drag&drop or clipboard)
|
|
|
|
NS_IMETHOD PrepareTransferable(nsITransferable** transferable) override;
|
|
|
|
nsresult PrepareHTMLTransferable(nsITransferable** transferable);
|
|
|
|
nsresult InsertFromTransferable(nsITransferable* transferable,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aContextStr,
|
|
|
|
const nsAString& aInfoStr,
|
|
|
|
bool havePrivateHTMLFlavor,
|
|
|
|
bool aDoDeleteSelection);
|
2017-02-01 11:09:54 +03:00
|
|
|
virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
|
|
|
|
int32_t aIndex,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestinationNode,
|
2017-02-01 11:09:54 +03:00
|
|
|
int32_t aDestOffset,
|
|
|
|
bool aDoDeleteSelection) override;
|
2016-07-09 05:42:33 +03:00
|
|
|
bool HavePrivateHTMLFlavor(nsIClipboard* clipboard );
|
|
|
|
nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste,
|
|
|
|
char16_t** aCfcontext);
|
|
|
|
|
2018-01-30 07:10:52 +03:00
|
|
|
bool IsInLink(nsINode* aNode, nsCOMPtr<nsINode>* outLink = nullptr);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
|
|
|
|
nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString,
|
|
|
|
const nsAString& aContextStr,
|
|
|
|
const nsAString& aInfoStr,
|
2018-01-30 07:10:51 +03:00
|
|
|
nsCOMPtr<nsINode>* outFragNode,
|
|
|
|
nsCOMPtr<nsINode>* outStartNode,
|
|
|
|
nsCOMPtr<nsINode>* outEndNode,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t* outStartOffset,
|
|
|
|
int32_t* outEndOffset,
|
|
|
|
bool aTrustedInput);
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult ParseFragment(const nsAString& aStr, nsAtom* aContextLocalName,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIDocument* aTargetDoc,
|
|
|
|
dom::DocumentFragment** aFragment, bool aTrustedInput);
|
|
|
|
void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& outNodeList,
|
2017-07-11 17:10:42 +03:00
|
|
|
nsINode* aStartContainer,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aStartOffset,
|
2017-07-11 18:09:37 +03:00
|
|
|
nsINode* aEndContainer,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aEndOffset);
|
|
|
|
nsresult CreateTagStack(nsTArray<nsString>& aTagStack,
|
|
|
|
nsIDOMNode* aNode);
|
|
|
|
enum class StartOrEnd { start, end };
|
|
|
|
void GetListAndTableParents(StartOrEnd aStartOrEnd,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aNodeList,
|
|
|
|
nsTArray<OwningNonNull<Element>>& outArray);
|
|
|
|
int32_t DiscoverPartialListsAndTables(
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
|
|
|
|
nsTArray<OwningNonNull<Element>>& aListsAndTables);
|
|
|
|
nsINode* ScanForListAndTableStructure(
|
|
|
|
StartOrEnd aStartOrEnd,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aNodes,
|
|
|
|
Element& aListOrTable);
|
|
|
|
void ReplaceOrphanedStructure(
|
|
|
|
StartOrEnd aStartOrEnd,
|
|
|
|
nsTArray<OwningNonNull<nsINode>>& aNodeArray,
|
|
|
|
nsTArray<OwningNonNull<Element>>& aListAndTableArray,
|
|
|
|
int32_t aHighWaterMark);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Small utility routine to test if a break node is visible to user.
|
|
|
|
*/
|
2017-07-21 10:10:10 +03:00
|
|
|
bool IsVisibleBRElement(nsINode* aNode);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
2017-12-05 09:36:49 +03:00
|
|
|
* GetBetterInsertionPointFor() returns better insertion point to insert
|
|
|
|
* aNodeToInsert.
|
|
|
|
*
|
|
|
|
* @param aNodeToInsert The node to insert.
|
|
|
|
* @param aPointToInsert A candidate point to insert the node.
|
|
|
|
* @return Better insertion point if next visible node
|
|
|
|
* is a <br> element and previous visible node
|
|
|
|
* is neither none, another <br> element nor
|
|
|
|
* different block level element.
|
|
|
|
*/
|
|
|
|
EditorRawDOMPoint
|
|
|
|
GetBetterInsertionPointFor(nsINode& aNodeToInsert,
|
|
|
|
const EditorRawDOMPoint& aPointToInsert);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helpers for block transformations.
|
|
|
|
*/
|
|
|
|
nsresult MakeDefinitionItem(const nsAString& aItemType);
|
|
|
|
nsresult InsertBasicBlock(const nsAString& aBlockType);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Increase/decrease the font size of selection.
|
|
|
|
*/
|
|
|
|
enum class FontSize { incr, decr };
|
|
|
|
nsresult RelativeFontChange(FontSize aDir);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper routines for font size changing.
|
|
|
|
*/
|
|
|
|
nsresult RelativeFontChangeOnTextNode(FontSize aDir,
|
|
|
|
Text& aTextNode,
|
|
|
|
int32_t aStartOffset,
|
|
|
|
int32_t aEndOffset);
|
|
|
|
nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
|
|
|
|
nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper routines for inline style.
|
|
|
|
*/
|
|
|
|
nsresult SetInlinePropertyOnTextNode(Text& aData,
|
|
|
|
int32_t aStartOffset,
|
|
|
|
int32_t aEndOffset,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aValue);
|
|
|
|
nsresult SetInlinePropertyOnNode(nsIContent& aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aValue);
|
|
|
|
|
|
|
|
nsresult PromoteInlineRange(nsRange& aRange);
|
|
|
|
nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
|
|
|
|
nsresult SplitStyleAboveRange(nsRange* aRange,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIContent** aOutLeftNode = nullptr,
|
|
|
|
nsIContent** aOutRightNode = nullptr);
|
|
|
|
nsresult RemoveStyleInside(nsIContent& aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const bool aChildrenOnly = false);
|
|
|
|
|
|
|
|
bool NodeIsProperty(nsINode& aNode);
|
|
|
|
bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
|
|
|
|
bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
|
2017-12-26 06:25:45 +03:00
|
|
|
bool IsOnlyAttribute(const Element* aElement, nsAtom* aAttribute);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-04-12 16:23:04 +03:00
|
|
|
/**
|
|
|
|
* RemoveBlockContainerWithTransaction() removes aElement from the DOM tree
|
|
|
|
* but moves its all children to its parent node and if its parent needs <br>
|
|
|
|
* element to have at least one line-height, this inserts <br> element
|
|
|
|
* automatically.
|
|
|
|
*
|
|
|
|
* @param aElement Block element to be removed.
|
|
|
|
*/
|
|
|
|
nsresult RemoveBlockContainerWithTransaction(Element& aElement);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsIContent* GetPriorHTMLSibling(nsINode* aNode);
|
|
|
|
|
|
|
|
nsIContent* GetNextHTMLSibling(nsINode* aNode);
|
|
|
|
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
/**
|
|
|
|
* GetPreviousHTMLElementOrText*() methods are similar to
|
|
|
|
* EditorBase::GetPreviousElementOrText*() but this won't return nodes
|
|
|
|
* outside active editing host.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousHTMLElementOrText(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetPreviousHTMLElementOrTextInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetPreviousHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
nsIContent*
|
2018-03-20 08:05:47 +03:00
|
|
|
GetPreviousHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetPreviousHTMLElementOrTextInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetPreviousHTMLElementOrTextInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousHTMLElementOrTextInternal(nsINode& aNode,
|
|
|
|
bool aNoBlockCrossing);
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
nsIContent*
|
2018-03-20 08:05:47 +03:00
|
|
|
GetPreviousHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint,
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
bool aNoBlockCrossing);
|
|
|
|
|
2017-11-09 17:31:59 +03:00
|
|
|
/**
|
|
|
|
* GetPreviousEditableHTMLNode*() methods are similar to
|
|
|
|
* EditorBase::GetPreviousEditableNode() but this won't return nodes outside
|
|
|
|
* active editing host.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousEditableHTMLNode(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetPreviousEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 17:31:59 +03:00
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-09 17:31:59 +03:00
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInBlock(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 17:31:59 +03:00
|
|
|
{
|
|
|
|
return GetPreviousEditableHTMLNodeInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetPreviousEditableHTMLNodeInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInternal(nsINode& aNode,
|
|
|
|
bool aNoBlockCrossing);
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-09 17:31:59 +03:00
|
|
|
nsIContent* GetPreviousEditableHTMLNodeInternal(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint,
|
2017-11-09 17:31:59 +03:00
|
|
|
bool aNoBlockCrossing);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
/**
|
|
|
|
* GetNextHTMLElementOrText*() methods are similar to
|
|
|
|
* EditorBase::GetNextElementOrText*() but this won't return nodes outside
|
|
|
|
* active editing host.
|
|
|
|
*
|
|
|
|
* Note that same as EditorBase::GetTextEditableNode(), methods which take
|
|
|
|
* |const EditorRawDOMPoint&| start to search from the node pointed by it.
|
|
|
|
* On the other hand, methods which take |nsINode&| start to search from
|
|
|
|
* next node of aNode.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextHTMLElementOrText(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetNextHTMLElementOrTextInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetNextHTMLElementOrText(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetNextHTMLElementOrTextInBlock(const EditorDOMPointBase<PT, CT>& aPoint)
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
{
|
|
|
|
return GetNextHTMLElementOrTextInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetNextHTMLNodeInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextHTMLElementOrTextInternal(nsINode& aNode,
|
|
|
|
bool aNoBlockCrossing);
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent*
|
|
|
|
GetNextHTMLElementOrTextInternal(const EditorDOMPointBase<PT, CT>& aPoint,
|
|
|
|
bool aNoBlockCrossing);
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
|
2017-11-09 18:12:22 +03:00
|
|
|
/**
|
|
|
|
* GetNextEditableHTMLNode*() methods are similar to
|
|
|
|
* EditorBase::GetNextEditableNode() but this won't return nodes outside
|
|
|
|
* active editing host.
|
|
|
|
*
|
Bug 1406726 - HTMLEditRules::WillInsertBreak() should reset mNewNode with caret position r=m_kato
HTMLEditRules::WillInsertBreak() started to use HTMLEditRules::MakeBasicBlock()
to wrap existing inline elements with default paragraph separator if inline
elements are children of editing host. However,
HTMLEditRules::ApplyBlockStyle() called by HTMLEditRules::MakeBasicBlock() sets
mNewNode to last new block node. So, if it wraps inline elements after caret
position, mNewNode becomes after expected caret position and
HTMLEditRules::AfterEditInner() will move caret into it.
This patch make HTMLEditRules::WillInsertBreak() reset mNewNode with
caret position after calling HTMLEditRules::MakeBasicBlock().
Additionally, this patch fixes a bug of HTMLEditor::IsVisibleBRElement().
That is, it uses only editable nodes to check if given <br> element is
visible. However, editable state is not related to this check. If <br>
element is followed by non-editable inline node (except invisible data
nodes), it always visible. This bug caused getting wrong nodes with
HTMLEditRules::GetNodesFromSelection() which is used by
HTMLEditRules::MakeBasicBlock(). Therefore, this patch also adds lots of
EditorBase::Get(Next|Previous)ElementOrText*() and
HTMLEditor::Get(Next|Previous)HTMLElementOrText*() to ignore only invisible
data nodes.
Note that even with this fix, the range of nodes computed by
HTMLEditRules::GetNodesFromSelection() is still odd if only non-editable
elements follow a <br> node which is first <br> element after the caret
position. However, what is expected by the execCommand spec is unclear.
So, automated test added by this patch checks current inconsistent behavior
for now.
MozReview-Commit-ID: 2m52StwoEEH
--HG--
extra : rebase_source : 6b9b2338e35c4d2e89a405fd8e1ffc7b0873ca1e
2018-02-13 13:01:42 +03:00
|
|
|
* Note that same as EditorBase::GetTextEditableNode(), methods which take
|
2017-11-09 18:12:22 +03:00
|
|
|
* |const EditorRawDOMPoint&| start to search from the node pointed by it.
|
|
|
|
* On the other hand, methods which take |nsINode&| start to search from
|
|
|
|
* next node of aNode.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextEditableHTMLNode(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aNode, false);
|
|
|
|
}
|
|
|
|
nsIContent* GetNextEditableHTMLNodeInBlock(nsINode& aNode)
|
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aNode, true);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
|
|
|
nsIContent* GetNextEditableHTMLNode(const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 18:12:22 +03:00
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aPoint, false);
|
|
|
|
}
|
2018-03-20 08:05:47 +03:00
|
|
|
template<typename PT, typename CT>
|
2017-11-09 18:12:22 +03:00
|
|
|
nsIContent* GetNextEditableHTMLNodeInBlock(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint)
|
2017-11-09 18:12:22 +03:00
|
|
|
{
|
|
|
|
return GetNextEditableHTMLNodeInternal(aPoint, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GetNextEditableHTMLNodeInternal() methods are common implementation
|
|
|
|
* of above methods. Please don't use this method directly.
|
|
|
|
*/
|
|
|
|
nsIContent* GetNextEditableHTMLNodeInternal(nsINode& aNode,
|
2018-03-20 08:05:47 +03:00
|
|
|
bool aNoBlockCrossing);
|
|
|
|
template<typename PT, typename CT>
|
2017-11-09 18:12:22 +03:00
|
|
|
nsIContent* GetNextEditableHTMLNodeInternal(
|
2018-03-20 08:05:47 +03:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint,
|
2017-11-09 18:12:22 +03:00
|
|
|
bool aNoBlockCrossing);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-01-11 13:07:33 +03:00
|
|
|
bool IsFirstEditableChild(nsINode* aNode);
|
|
|
|
bool IsLastEditableChild(nsINode* aNode);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIContent* GetFirstEditableChild(nsINode& aNode);
|
|
|
|
nsIContent* GetLastEditableChild(nsINode& aNode);
|
|
|
|
|
|
|
|
nsIContent* GetFirstEditableLeaf(nsINode& aNode);
|
|
|
|
nsIContent* GetLastEditableLeaf(nsINode& aNode);
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsresult GetInlinePropertyBase(nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString* aValue,
|
|
|
|
bool* aFirst,
|
|
|
|
bool* aAny,
|
|
|
|
bool* aAll,
|
2017-08-25 09:59:17 +03:00
|
|
|
nsAString* outValue);
|
2016-07-09 05:42:33 +03:00
|
|
|
bool HasStyleOrIdOrClass(Element* aElement);
|
|
|
|
nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Whether the outer window of the DOM event target has focus or not.
|
|
|
|
*/
|
|
|
|
bool OurWindowHasFocus();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function is used to insert a string of HTML input optionally with some
|
|
|
|
* context information into the editable field. The HTML input either comes
|
|
|
|
* from a transferable object created as part of a drop/paste operation, or
|
|
|
|
* from the InsertHTML method. We may want the HTML input to be sanitized
|
|
|
|
* (for example, if it's coming from a transferable object), in which case
|
|
|
|
* aTrustedInput should be set to false, otherwise, the caller should set it
|
|
|
|
* to true, which means that the HTML will be inserted in the DOM verbatim.
|
|
|
|
*
|
|
|
|
* aClearStyle should be set to false if you want the paste to be affected by
|
|
|
|
* local style (e.g., for the insertHTML command).
|
|
|
|
*/
|
|
|
|
nsresult DoInsertHTMLWithContext(const nsAString& aInputString,
|
|
|
|
const nsAString& aContextStr,
|
|
|
|
const nsAString& aInfoStr,
|
|
|
|
const nsAString& aFlavor,
|
2018-04-06 08:53:05 +03:00
|
|
|
nsIDocument* aSourceDoc,
|
2018-03-27 14:19:35 +03:00
|
|
|
nsINode* aDestNode,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t aDestOffset,
|
|
|
|
bool aDeleteSelection,
|
|
|
|
bool aTrustedInput,
|
|
|
|
bool aClearStyle = true);
|
|
|
|
|
|
|
|
nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aProperty, nsAtom* aAttribute);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
/**
|
|
|
|
* sets the position of an element; warning it does NOT check if the
|
|
|
|
* element is already positioned or not and that's on purpose.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aX [IN] the x position in pixels.
|
|
|
|
* @param aY [IN] the y position in pixels.
|
|
|
|
*/
|
|
|
|
void SetTopAndLeft(Element& aElement, int32_t aX, int32_t aY);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-08 04:57:19 +03:00
|
|
|
/**
|
|
|
|
* Reset a selected cell or collapsed selection (the caret) after table
|
|
|
|
* editing.
|
|
|
|
*
|
|
|
|
* @param aTable A table in the document.
|
|
|
|
* @param aRow The row ...
|
|
|
|
* @param aCol ... and column defining the cell where we will try to
|
|
|
|
* place the caret.
|
|
|
|
* @param aSelected If true, we select the whole cell instead of setting
|
|
|
|
* caret.
|
|
|
|
* @param aDirection If cell at (aCol, aRow) is not found, search for
|
|
|
|
* previous cell in the same column (aPreviousColumn) or
|
|
|
|
* row (ePreviousRow) or don't search for another cell
|
|
|
|
* (aNoSearch). If no cell is found, caret is place just
|
|
|
|
* before table; and if that fails, at beginning of
|
|
|
|
* document. Thus we generally don't worry about the
|
|
|
|
* return value and can use the
|
|
|
|
* AutoSelectionSetterAfterTableEdit stack-based object to
|
|
|
|
* insure we reset the caret in a table-editing method.
|
|
|
|
*/
|
|
|
|
void SetSelectionAfterTableEdit(nsIDOMElement* aTable,
|
|
|
|
int32_t aRow, int32_t aCol,
|
|
|
|
int32_t aDirection, bool aSelected);
|
|
|
|
|
2018-01-30 07:27:59 +03:00
|
|
|
/**
|
|
|
|
* A more C++-friendly version of nsIHTMLEditor::GetSelectedElement
|
|
|
|
* that just returns null on errors.
|
|
|
|
*/
|
|
|
|
already_AddRefed<dom::Element> GetSelectedElement(const nsAString& aTagName);
|
|
|
|
|
2018-04-12 11:20:21 +03:00
|
|
|
/**
|
|
|
|
* RemoveStyleSheetWithTransaction() removes the given URL stylesheet
|
|
|
|
* from mStyleSheets and mStyleSheetURLs.
|
|
|
|
*/
|
|
|
|
nsresult RemoveStyleSheetWithTransaction(const nsAString& aURL);
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
protected:
|
|
|
|
RefPtr<TypeInState> mTypeInState;
|
2018-01-26 08:38:05 +03:00
|
|
|
RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
bool mCRInParagraphCreatesParagraph;
|
|
|
|
|
|
|
|
bool mCSSAware;
|
2017-02-08 12:14:24 +03:00
|
|
|
UniquePtr<CSSEditUtils> mCSSEditUtils;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// Used by GetFirstSelectedCell and GetNextSelectedCell
|
|
|
|
int32_t mSelectedCellIndex;
|
|
|
|
|
|
|
|
nsString mLastStyleSheetURL;
|
|
|
|
nsString mLastOverrideStyleSheetURL;
|
|
|
|
|
|
|
|
// Maintain a list of associated style sheets and their urls.
|
|
|
|
nsTArray<nsString> mStyleSheetURLs;
|
2016-09-26 15:03:25 +03:00
|
|
|
nsTArray<RefPtr<StyleSheet>> mStyleSheets;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// ANONYMOUS UTILS
|
|
|
|
void RemoveListenerAndDeleteRef(const nsAString& aEvent,
|
|
|
|
nsIDOMEventListener* aListener,
|
|
|
|
bool aUseCapture,
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr aElement,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIPresShell* aShell);
|
2017-08-02 22:37:44 +03:00
|
|
|
void DeleteRefToAnonymousNode(ManualNACPtr aContent,
|
2016-07-09 05:42:33 +03:00
|
|
|
nsIPresShell* aShell);
|
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
nsresult ShowResizersInner(Element& aResizedElement);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the offset of an element's frame to its absolute containing block.
|
|
|
|
*/
|
2017-08-07 08:09:51 +03:00
|
|
|
nsresult GetElementOrigin(Element& aElement,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t& aX, int32_t& aY);
|
2017-08-07 08:09:51 +03:00
|
|
|
nsresult GetPositionAndDimensions(Element& aElement,
|
2016-07-09 05:42:33 +03:00
|
|
|
int32_t& aX, int32_t& aY,
|
|
|
|
int32_t& aW, int32_t& aH,
|
|
|
|
int32_t& aBorderLeft,
|
|
|
|
int32_t& aBorderTop,
|
|
|
|
int32_t& aMarginLeft,
|
|
|
|
int32_t& aMarginTop);
|
|
|
|
|
2018-03-01 14:36:58 +03:00
|
|
|
bool IsInObservedSubtree(nsIContent* aChild);
|
2016-11-30 01:07:27 +03:00
|
|
|
|
2017-08-28 21:57:46 +03:00
|
|
|
void UpdateRootElement();
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
// resizing
|
|
|
|
bool mIsObjectResizingEnabled;
|
|
|
|
bool mIsResizing;
|
|
|
|
bool mPreserveRatio;
|
|
|
|
bool mResizedObjectIsAnImage;
|
|
|
|
|
|
|
|
// absolute positioning
|
|
|
|
bool mIsAbsolutelyPositioningEnabled;
|
|
|
|
bool mResizedObjectIsAbsolutelyPositioned;
|
|
|
|
|
|
|
|
bool mGrabberClicked;
|
|
|
|
bool mIsMoving;
|
|
|
|
|
|
|
|
bool mSnapToGridEnabled;
|
|
|
|
|
|
|
|
// inline table editing
|
|
|
|
bool mIsInlineTableEditingEnabled;
|
|
|
|
|
|
|
|
// resizing
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mTopLeftHandle;
|
|
|
|
ManualNACPtr mTopHandle;
|
|
|
|
ManualNACPtr mTopRightHandle;
|
|
|
|
ManualNACPtr mLeftHandle;
|
|
|
|
ManualNACPtr mRightHandle;
|
|
|
|
ManualNACPtr mBottomLeftHandle;
|
|
|
|
ManualNACPtr mBottomHandle;
|
|
|
|
ManualNACPtr mBottomRightHandle;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsCOMPtr<Element> mActivatedHandle;
|
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mResizingShadow;
|
|
|
|
ManualNACPtr mResizingInfo;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsCOMPtr<Element> mResizedObject;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventListener> mMouseMotionListenerP;
|
|
|
|
nsCOMPtr<nsIDOMEventListener> mResizeEventListenerP;
|
|
|
|
|
|
|
|
int32_t mOriginalX;
|
|
|
|
int32_t mOriginalY;
|
|
|
|
|
|
|
|
int32_t mResizedObjectX;
|
|
|
|
int32_t mResizedObjectY;
|
|
|
|
int32_t mResizedObjectWidth;
|
|
|
|
int32_t mResizedObjectHeight;
|
|
|
|
|
|
|
|
int32_t mResizedObjectMarginLeft;
|
|
|
|
int32_t mResizedObjectMarginTop;
|
|
|
|
int32_t mResizedObjectBorderLeft;
|
|
|
|
int32_t mResizedObjectBorderTop;
|
|
|
|
|
|
|
|
int32_t mXIncrementFactor;
|
|
|
|
int32_t mYIncrementFactor;
|
|
|
|
int32_t mWidthIncrementFactor;
|
|
|
|
int32_t mHeightIncrementFactor;
|
|
|
|
|
|
|
|
int8_t mInfoXIncrement;
|
|
|
|
int8_t mInfoYIncrement;
|
|
|
|
|
|
|
|
nsresult SetAllResizersPosition();
|
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
/**
|
|
|
|
* Shows active resizers around an element's frame
|
|
|
|
* @param aResizedElement [IN] a DOM Element
|
|
|
|
*/
|
|
|
|
nsresult ShowResizers(Element& aResizedElement);
|
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateResizer(int16_t aLocation, nsIContent& aParentContent);
|
2016-07-09 05:42:33 +03:00
|
|
|
void SetAnonymousElementPosition(int32_t aX, int32_t aY,
|
2016-11-24 09:58:01 +03:00
|
|
|
Element* aResizer);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateShadow(nsIContent& aParentContent,
|
|
|
|
Element& aOriginalObject);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SetShadowPosition(Element* aShadow, Element* aOriginalObject,
|
|
|
|
int32_t aOriginalObjectX,
|
|
|
|
int32_t aOriginalObjectY);
|
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateResizingInfo(nsIContent& aParentContent);
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
|
|
|
|
int32_t aW, int32_t aH);
|
|
|
|
|
|
|
|
int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID);
|
|
|
|
nsresult StartResizing(nsIDOMElement* aHandle);
|
|
|
|
int32_t GetNewResizingX(int32_t aX, int32_t aY);
|
|
|
|
int32_t GetNewResizingY(int32_t aX, int32_t aY);
|
|
|
|
int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
|
|
|
|
int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
|
|
|
|
void HideShadowAndInfo();
|
|
|
|
void SetFinalSize(int32_t aX, int32_t aY);
|
|
|
|
void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
|
|
|
|
bool aPreserveRatio);
|
|
|
|
void HideAnonymousEditingUIs();
|
|
|
|
|
|
|
|
// absolute positioning
|
|
|
|
int32_t mPositionedObjectX;
|
|
|
|
int32_t mPositionedObjectY;
|
|
|
|
int32_t mPositionedObjectWidth;
|
|
|
|
int32_t mPositionedObjectHeight;
|
|
|
|
|
|
|
|
int32_t mPositionedObjectMarginLeft;
|
|
|
|
int32_t mPositionedObjectMarginTop;
|
|
|
|
int32_t mPositionedObjectBorderLeft;
|
|
|
|
int32_t mPositionedObjectBorderTop;
|
|
|
|
|
|
|
|
nsCOMPtr<Element> mAbsolutelyPositionedObject;
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mGrabber;
|
|
|
|
ManualNACPtr mPositioningShadow;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
int32_t mGridSize;
|
|
|
|
|
2018-02-01 04:55:25 +03:00
|
|
|
nsresult SetPositionToAbsolute(Element& aElement);
|
|
|
|
nsresult SetPositionToStatic(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sets the z-index of an element.
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
* @param aZorder [IN] the z-index
|
|
|
|
*/
|
|
|
|
void SetZIndex(Element& aElement, int32_t aZorder);
|
|
|
|
|
2018-01-30 07:42:52 +03:00
|
|
|
/**
|
|
|
|
* shows a grabber attached to an arbitrary element. The grabber is an image
|
|
|
|
* positioned on the left hand side of the top border of the element. Draggin
|
|
|
|
* and dropping it allows to change the element's absolute position in the
|
|
|
|
* document. See chrome://editor/content/images/grabber.gif
|
|
|
|
* @param aElement [IN] the element
|
|
|
|
*/
|
2018-02-01 04:55:25 +03:00
|
|
|
nsresult ShowGrabber(Element& aElement);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* hide the grabber if it shown.
|
|
|
|
*/
|
|
|
|
void HideGrabber();
|
2018-01-30 07:42:52 +03:00
|
|
|
|
2017-08-07 08:09:51 +03:00
|
|
|
ManualNACPtr CreateGrabber(nsIContent& aParentContent);
|
2018-03-19 08:14:45 +03:00
|
|
|
nsresult StartMoving();
|
2016-07-09 05:42:33 +03:00
|
|
|
nsresult SetFinalPosition(int32_t aX, int32_t aY);
|
|
|
|
void AddPositioningOffset(int32_t& aX, int32_t& aY);
|
|
|
|
void SnapToGrid(int32_t& newX, int32_t& newY);
|
|
|
|
nsresult GrabberClicked();
|
|
|
|
nsresult EndMoving();
|
2018-01-30 07:42:52 +03:00
|
|
|
nsresult GetTemporaryStyleForFocusedPositionedElement(Element& aElement,
|
|
|
|
nsAString& aReturn);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
// inline table editing
|
2017-12-15 19:14:54 +03:00
|
|
|
RefPtr<Element> mInlineEditedCell;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mAddColumnBeforeButton;
|
|
|
|
ManualNACPtr mRemoveColumnButton;
|
|
|
|
ManualNACPtr mAddColumnAfterButton;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2017-08-02 22:37:44 +03:00
|
|
|
ManualNACPtr mAddRowBeforeButton;
|
|
|
|
ManualNACPtr mRemoveRowButton;
|
|
|
|
ManualNACPtr mAddRowAfterButton;
|
2016-07-09 05:42:33 +03:00
|
|
|
|
2018-01-19 10:41:41 +03:00
|
|
|
/**
|
|
|
|
* Shows inline table editing UI around a table cell
|
|
|
|
* @param aCell [IN] a DOM Element being a table cell, td or th
|
|
|
|
*/
|
2017-12-15 19:14:54 +03:00
|
|
|
nsresult ShowInlineTableEditingUI(Element* aCell);
|
|
|
|
|
2018-01-19 10:41:41 +03:00
|
|
|
/**
|
|
|
|
* Hide all inline table editing UI
|
|
|
|
*/
|
|
|
|
nsresult HideInlineTableEditingUI();
|
|
|
|
|
2016-11-24 09:58:01 +03:00
|
|
|
void AddMouseClickListener(Element* aElement);
|
|
|
|
void RemoveMouseClickListener(Element* aElement);
|
2016-07-09 05:42:33 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsILinkHandler> mLinkHandler;
|
|
|
|
|
2017-04-06 15:02:42 +03:00
|
|
|
ParagraphSeparator mDefaultParagraphSeparator;
|
2016-08-24 15:53:52 +03:00
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
public:
|
2017-08-08 04:57:19 +03:00
|
|
|
friend class AutoSelectionSetterAfterTableEdit;
|
2016-07-09 05:42:33 +03:00
|
|
|
friend class HTMLEditorEventListener;
|
|
|
|
friend class HTMLEditRules;
|
|
|
|
friend class TextEditRules;
|
|
|
|
friend class WSRunObject;
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool IsSimpleModifiableNode(nsIContent* aContent,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString* aValue);
|
|
|
|
nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom& aProperty,
|
2017-12-26 06:25:45 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-07-09 05:42:33 +03:00
|
|
|
const nsAString& aValue);
|
|
|
|
typedef enum { eInserted, eAppended } InsertedOrAppended;
|
2018-03-01 14:36:58 +03:00
|
|
|
void DoContentInserted(nsIContent* aChild, InsertedOrAppended);
|
2016-07-09 05:42:33 +03:00
|
|
|
already_AddRefed<Element> GetElementOrParentByTagName(
|
|
|
|
const nsAString& aTagName, nsINode* aNode);
|
|
|
|
already_AddRefed<Element> CreateElementWithDefaults(
|
|
|
|
const nsAString& aTagName);
|
2016-11-24 10:12:04 +03:00
|
|
|
/**
|
|
|
|
* Returns an anonymous Element of type aTag,
|
2017-08-07 08:09:51 +03:00
|
|
|
* child of aParentContent. If aIsCreatedHidden is true, the class
|
2016-11-24 10:12:04 +03:00
|
|
|
* "hidden" is added to the created element. If aAnonClass is not
|
|
|
|
* the empty string, it becomes the value of the attribute "_moz_anonclass"
|
|
|
|
* @return a Element
|
|
|
|
* @param aTag [IN] desired type of the element to create
|
2017-08-07 08:09:51 +03:00
|
|
|
* @param aParentContent [IN] the parent node of the created anonymous
|
2016-11-24 10:12:04 +03:00
|
|
|
* element
|
|
|
|
* @param aAnonClass [IN] contents of the _moz_anonclass attribute
|
|
|
|
* @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
|
|
|
|
* is to be added to the created anonymous
|
|
|
|
* element
|
|
|
|
*/
|
2017-10-03 01:05:19 +03:00
|
|
|
ManualNACPtr CreateAnonymousElement(nsAtom* aTag,
|
2017-08-07 08:09:51 +03:00
|
|
|
nsIContent& aParentContent,
|
2017-08-02 22:37:44 +03:00
|
|
|
const nsAString& aAnonClass,
|
|
|
|
bool aIsCreatedHidden);
|
2016-07-09 05:42:33 +03:00
|
|
|
};
|
|
|
|
|
2017-08-04 09:01:36 +03:00
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
mozilla::HTMLEditor*
|
|
|
|
nsIEditor::AsHTMLEditor()
|
2017-08-04 00:18:50 +03:00
|
|
|
{
|
2017-08-04 09:01:36 +03:00
|
|
|
return static_cast<mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
|
|
|
|
static_cast<mozilla::HTMLEditor*>(this) : nullptr;
|
2017-08-04 00:18:50 +03:00
|
|
|
}
|
|
|
|
|
2017-08-04 09:01:36 +03:00
|
|
|
const mozilla::HTMLEditor*
|
|
|
|
nsIEditor::AsHTMLEditor() const
|
2017-08-04 00:18:50 +03:00
|
|
|
{
|
2017-08-04 09:01:36 +03:00
|
|
|
return static_cast<const mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
|
|
|
|
static_cast<const mozilla::HTMLEditor*>(this) : nullptr;
|
2017-08-04 00:18:50 +03:00
|
|
|
}
|
|
|
|
|
2016-07-09 05:42:33 +03:00
|
|
|
#endif // #ifndef mozilla_HTMLEditor_h
|