2001-09-25 22:53:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* 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/. */
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
#include "WSRunObject.h"
|
2014-12-02 05:07:42 +00:00
|
|
|
|
2016-07-07 04:44:32 +00:00
|
|
|
#include "TextEditUtils.h"
|
2016-07-07 02:49:42 +00:00
|
|
|
|
2012-07-13 06:33:42 +00:00
|
|
|
#include "mozilla/Assertions.h"
|
2014-08-20 12:25:16 +00:00
|
|
|
#include "mozilla/Casting.h"
|
2017-11-01 05:41:03 +00:00
|
|
|
#include "mozilla/EditorDOMPoint.h"
|
2016-07-09 02:42:33 +00:00
|
|
|
#include "mozilla/HTMLEditor.h"
|
2012-07-13 06:33:42 +00:00
|
|
|
#include "mozilla/mozalloc.h"
|
2016-07-09 02:42:33 +00:00
|
|
|
#include "mozilla/OwningNonNull.h"
|
2016-07-09 02:34:41 +00:00
|
|
|
#include "mozilla/SelectionState.h"
|
2014-08-20 12:25:16 +00:00
|
|
|
|
2012-07-13 06:33:42 +00:00
|
|
|
#include "nsAString.h"
|
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsDebug.h"
|
|
|
|
#include "nsError.h"
|
2001-04-28 12:04:45 +00:00
|
|
|
#include "nsIContent.h"
|
2018-06-08 19:57:13 +00:00
|
|
|
#include "nsIContentInlines.h"
|
2012-07-13 06:33:42 +00:00
|
|
|
#include "nsISupportsImpl.h"
|
2012-01-10 14:19:54 +00:00
|
|
|
#include "nsRange.h"
|
2012-07-13 06:33:42 +00:00
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsTextFragment.h"
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
using namespace dom;
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2017-12-21 10:27:31 +00:00
|
|
|
const char16_t kNBSP = 160;
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2018-03-15 08:56:20 +00:00
|
|
|
template WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
const EditorDOMPoint& aScanStartPoint,
|
|
|
|
const EditorDOMPoint& aScanEndPoint);
|
2018-03-15 08:56:20 +00:00
|
|
|
template WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
const EditorRawDOMPoint& aScanStartPoint,
|
|
|
|
const EditorRawDOMPoint& aScanEndPoint);
|
2018-03-15 09:23:50 +00:00
|
|
|
template void WSRunObject::PriorVisibleNode(const EditorDOMPoint& aPoint,
|
|
|
|
nsCOMPtr<nsINode>* outVisNode,
|
|
|
|
int32_t* outVisOffset,
|
2018-08-14 09:26:46 +00:00
|
|
|
WSType* outType) const;
|
2018-03-15 09:23:50 +00:00
|
|
|
template void WSRunObject::PriorVisibleNode(const EditorRawDOMPoint& aPoint,
|
|
|
|
nsCOMPtr<nsINode>* outVisNode,
|
|
|
|
int32_t* outVisOffset,
|
2018-08-14 09:26:46 +00:00
|
|
|
WSType* outType) const;
|
2018-03-15 09:23:50 +00:00
|
|
|
template void WSRunObject::NextVisibleNode(const EditorDOMPoint& aPoint,
|
|
|
|
nsCOMPtr<nsINode>* outVisNode,
|
|
|
|
int32_t* outVisOffset,
|
2018-08-14 09:26:46 +00:00
|
|
|
WSType* outType) const;
|
2018-03-15 09:23:50 +00:00
|
|
|
template void WSRunObject::NextVisibleNode(const EditorRawDOMPoint& aPoint,
|
|
|
|
nsCOMPtr<nsINode>* outVisNode,
|
|
|
|
int32_t* outVisOffset,
|
2018-08-14 09:26:46 +00:00
|
|
|
WSType* outType) const;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
template void WSRunObject::GetASCIIWhitespacesBounds(
|
|
|
|
int16_t aDir, const EditorDOMPoint& aPoint, dom::Text** outStartNode,
|
|
|
|
int32_t* outStartOffset, dom::Text** outEndNode, int32_t* outEndOffset);
|
|
|
|
template void WSRunObject::GetASCIIWhitespacesBounds(
|
|
|
|
int16_t aDir, const EditorRawDOMPoint& aPoint, dom::Text** outStartNode,
|
|
|
|
int32_t* outStartOffset, dom::Text** outEndNode, int32_t* outEndOffset);
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2018-03-15 08:56:20 +00:00
|
|
|
template <typename PT, typename CT>
|
|
|
|
WSRunObject::WSRunObject(HTMLEditor* aHTMLEditor,
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
const EditorDOMPointBase<PT, CT>& aScanStartPoint,
|
|
|
|
const EditorDOMPointBase<PT, CT>& aScanEndPoint)
|
|
|
|
: mScanStartPoint(aScanStartPoint),
|
|
|
|
mScanEndPoint(aScanEndPoint),
|
2019-05-27 12:10:23 +00:00
|
|
|
mEditingHost(aHTMLEditor->GetActiveEditingHost()),
|
2014-05-02 11:11:26 +00:00
|
|
|
mPRE(false),
|
|
|
|
mStartOffset(0),
|
|
|
|
mEndOffset(0),
|
|
|
|
mFirstNBSPOffset(0),
|
|
|
|
mLastNBSPOffset(0),
|
|
|
|
mStartRun(nullptr),
|
|
|
|
mEndRun(nullptr),
|
2016-07-07 10:00:51 +00:00
|
|
|
mHTMLEditor(aHTMLEditor) {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
MOZ_ASSERT(nsContentUtils::ComparePoints(aScanStartPoint, aScanEndPoint) <=
|
|
|
|
0);
|
2014-05-02 11:11:26 +00:00
|
|
|
GetWSNodes();
|
|
|
|
GetRuns();
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
WSRunObject::~WSRunObject() { ClearRuns(); }
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2016-07-09 02:42:33 +00:00
|
|
|
nsresult WSRunObject::ScrubBlockBoundary(HTMLEditor* aHTMLEditor,
|
2016-07-07 10:00:51 +00:00
|
|
|
BlockBoundary aBoundary,
|
|
|
|
nsINode* aBlock, int32_t aOffset) {
|
|
|
|
NS_ENSURE_TRUE(aHTMLEditor && aBlock, NS_ERROR_NULL_POINTER);
|
2014-05-02 11:11:26 +00:00
|
|
|
|
|
|
|
int32_t offset;
|
|
|
|
if (aBoundary == kBlockStart) {
|
|
|
|
offset = 0;
|
|
|
|
} else if (aBoundary == kBlockEnd) {
|
|
|
|
offset = aBlock->Length();
|
|
|
|
} else {
|
|
|
|
// Else we are scrubbing an outer boundary - just before or after a block
|
|
|
|
// element.
|
|
|
|
NS_ENSURE_STATE(aOffset >= 0);
|
|
|
|
offset = aOffset;
|
|
|
|
}
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
WSRunObject theWSObj(aHTMLEditor, aBlock, offset);
|
2001-12-09 09:24:33 +00:00
|
|
|
return theWSObj.Scrub();
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:42:33 +00:00
|
|
|
nsresult WSRunObject::PrepareToJoinBlocks(HTMLEditor* aHTMLEditor,
|
2016-07-07 10:00:51 +00:00
|
|
|
Element* aLeftBlock,
|
|
|
|
Element* aRightBlock) {
|
|
|
|
NS_ENSURE_TRUE(aLeftBlock && aRightBlock && aHTMLEditor,
|
|
|
|
NS_ERROR_NULL_POINTER);
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
WSRunObject leftWSObj(aHTMLEditor, aLeftBlock, aLeftBlock->Length());
|
|
|
|
WSRunObject rightWSObj(aHTMLEditor, aRightBlock, 0);
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2001-05-10 11:55:49 +00:00
|
|
|
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:42:33 +00:00
|
|
|
nsresult WSRunObject::PrepareToDeleteRange(HTMLEditor* aHTMLEditor,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsCOMPtr<nsINode>* aStartNode,
|
|
|
|
int32_t* aStartOffset,
|
|
|
|
nsCOMPtr<nsINode>* aEndNode,
|
|
|
|
int32_t* aEndOffset) {
|
|
|
|
NS_ENSURE_TRUE(aHTMLEditor && aStartNode && *aStartNode && aStartOffset &&
|
2014-05-02 12:15:26 +00:00
|
|
|
aEndNode && *aEndNode && aEndOffset,
|
|
|
|
NS_ERROR_NULL_POINTER);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2018-11-26 06:31:56 +00:00
|
|
|
AutoTrackDOMPoint trackerStart(aHTMLEditor->RangeUpdaterRef(), aStartNode,
|
2016-07-07 10:00:51 +00:00
|
|
|
aStartOffset);
|
2018-11-26 06:31:56 +00:00
|
|
|
AutoTrackDOMPoint trackerEnd(aHTMLEditor->RangeUpdaterRef(), aEndNode,
|
2016-07-07 10:00:51 +00:00
|
|
|
aEndOffset);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
WSRunObject leftWSObj(aHTMLEditor, *aStartNode, *aStartOffset);
|
|
|
|
WSRunObject rightWSObj(aHTMLEditor, *aEndNode, *aEndOffset);
|
2001-05-10 11:55:49 +00:00
|
|
|
|
|
|
|
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:42:33 +00:00
|
|
|
nsresult WSRunObject::PrepareToDeleteNode(HTMLEditor* aHTMLEditor,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsIContent* aContent) {
|
|
|
|
NS_ENSURE_TRUE(aContent && aHTMLEditor, NS_ERROR_NULL_POINTER);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsINode> parent = aContent->GetParentNode();
|
2014-05-02 11:11:26 +00:00
|
|
|
NS_ENSURE_STATE(parent);
|
2018-01-23 13:30:18 +00:00
|
|
|
int32_t offset = parent->ComputeIndexOf(aContent);
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
WSRunObject leftWSObj(aHTMLEditor, parent, offset);
|
|
|
|
WSRunObject rightWSObj(aHTMLEditor, parent, offset + 1);
|
2001-05-10 11:55:49 +00:00
|
|
|
|
|
|
|
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:42:33 +00:00
|
|
|
nsresult WSRunObject::PrepareToSplitAcrossBlocks(HTMLEditor* aHTMLEditor,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsCOMPtr<nsINode>* aSplitNode,
|
|
|
|
int32_t* aSplitOffset) {
|
|
|
|
NS_ENSURE_TRUE(aHTMLEditor && aSplitNode && *aSplitNode && aSplitOffset,
|
2014-05-02 12:15:26 +00:00
|
|
|
NS_ERROR_NULL_POINTER);
|
2001-05-11 12:43:22 +00:00
|
|
|
|
2018-11-26 06:31:56 +00:00
|
|
|
AutoTrackDOMPoint tracker(aHTMLEditor->RangeUpdaterRef(), aSplitNode,
|
2016-07-07 10:00:51 +00:00
|
|
|
aSplitOffset);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
WSRunObject wsObj(aHTMLEditor, *aSplitNode, *aSplitOffset);
|
2001-05-11 12:43:22 +00:00
|
|
|
|
|
|
|
return wsObj.PrepareToSplitAcrossBlocksPriv();
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2017-11-21 09:12:12 +00:00
|
|
|
already_AddRefed<Element> WSRunObject::InsertBreak(
|
2019-05-08 09:40:17 +00:00
|
|
|
Selection& aSelection, const EditorDOMPoint& aPointToInsert,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsIEditor::EDirection aSelect) {
|
2017-11-21 09:12:12 +00:00
|
|
|
if (NS_WARN_IF(!aPointToInsert.IsSet())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
// MOOSE: for now, we always assume non-PRE formatting. Fix this later.
|
2014-05-02 11:11:26 +00:00
|
|
|
// meanwhile, the pre case is handled in WillInsertText in
|
2016-07-07 10:05:51 +00:00
|
|
|
// HTMLEditRules.cpp
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2017-11-21 10:03:03 +00:00
|
|
|
WSFragment* beforeRun = FindNearestRun(aPointToInsert, false);
|
|
|
|
WSFragment* afterRun = FindNearestRun(aPointToInsert, true);
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2017-11-21 09:12:12 +00:00
|
|
|
EditorDOMPoint pointToInsert(aPointToInsert);
|
2001-04-28 12:04:45 +00:00
|
|
|
{
|
2016-06-24 06:08:16 +00:00
|
|
|
// Some scoping for AutoTrackDOMPoint. This will track our insertion
|
2014-05-02 11:11:26 +00:00
|
|
|
// point while we tweak any surrounding whitespace
|
2018-11-26 06:31:56 +00:00
|
|
|
AutoTrackDOMPoint tracker(mHTMLEditor->RangeUpdaterRef(), &pointToInsert);
|
2002-04-13 23:54:59 +00:00
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
// Handle any changes needed to ws run after inserted br
|
|
|
|
if (!afterRun || (afterRun->mType & WSType::trailingWS)) {
|
|
|
|
// Don't need to do anything. Just insert break. ws won't change.
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (afterRun->mType & WSType::leadingWS) {
|
2014-05-02 11:11:26 +00:00
|
|
|
// Delete the leading ws that is after insertion point. We don't
|
|
|
|
// have to (it would still not be significant after br), but it's
|
2002-04-13 23:54:59 +00:00
|
|
|
// just more aesthetically pleasing to.
|
2018-03-20 05:05:47 +00:00
|
|
|
nsresult rv = DeleteRange(pointToInsert, afterRun->EndPoint());
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (afterRun->mType == WSType::normalWS) {
|
2014-05-02 11:11:26 +00:00
|
|
|
// Need to determine if break at front of non-nbsp run. If so, convert
|
|
|
|
// run to nbsp.
|
2018-03-20 05:05:47 +00:00
|
|
|
WSPoint thePoint = GetNextCharPoint(pointToInsert);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (thePoint.mTextNode && nsCRT::IsAsciiSpace(thePoint.mChar)) {
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint prevPoint = GetPreviousCharPoint(thePoint);
|
2017-09-04 06:01:16 +00:00
|
|
|
if (!prevPoint.mTextNode ||
|
|
|
|
(prevPoint.mTextNode && !nsCRT::IsAsciiSpace(prevPoint.mChar))) {
|
2014-05-02 11:11:26 +00:00
|
|
|
// We are at start of non-nbsps. Convert to a single nbsp.
|
2017-12-21 10:27:31 +00:00
|
|
|
nsresult rv = InsertNBSPAndRemoveFollowingASCIIWhitespaces(thePoint);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2002-04-13 23:54:59 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
|
|
|
|
// Handle any changes needed to ws run before inserted br
|
|
|
|
if (!beforeRun || (beforeRun->mType & WSType::leadingWS)) {
|
|
|
|
// Don't need to do anything. Just insert break. ws won't change.
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (beforeRun->mType & WSType::trailingWS) {
|
2014-05-02 11:11:26 +00:00
|
|
|
// Need to delete the trailing ws that is before insertion point, because
|
2002-04-13 23:54:59 +00:00
|
|
|
// it would become significant after break inserted.
|
2018-03-20 05:05:47 +00:00
|
|
|
nsresult rv = DeleteRange(beforeRun->StartPoint(), pointToInsert);
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (beforeRun->mType == WSType::normalWS) {
|
2014-05-02 11:11:26 +00:00
|
|
|
// Try to change an nbsp to a space, just to prevent nbsp proliferation
|
2018-03-20 05:05:47 +00:00
|
|
|
nsresult rv = ReplacePreviousNBSPIfUnncessary(beforeRun, pointToInsert);
|
2017-11-21 17:45:08 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2002-04-13 23:54:59 +00:00
|
|
|
}
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2018-04-16 10:21:29 +00:00
|
|
|
RefPtr<Element> newBrElement =
|
2019-05-07 22:34:28 +00:00
|
|
|
MOZ_KnownLive(mHTMLEditor)
|
|
|
|
->InsertBrElementWithTransaction(pointToInsert, aSelect);
|
2018-04-16 10:21:29 +00:00
|
|
|
if (NS_WARN_IF(!newBrElement)) {
|
2017-11-21 05:38:19 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2018-04-16 10:21:29 +00:00
|
|
|
return newBrElement.forget();
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2017-11-09 04:24:06 +00:00
|
|
|
nsresult WSRunObject::InsertText(Document& aDocument,
|
2019-01-02 13:05:23 +00:00
|
|
|
const nsAString& aStringToInsert,
|
2019-03-30 11:55:29 +00:00
|
|
|
EditorRawDOMPoint* aPointAfterInsertedString)
|
|
|
|
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
|
2001-04-28 12:04:45 +00:00
|
|
|
// MOOSE: for now, we always assume non-PRE formatting. Fix this later.
|
2014-05-02 12:15:27 +00:00
|
|
|
// meanwhile, the pre case is handled in WillInsertText in
|
2016-07-07 10:05:51 +00:00
|
|
|
// HTMLEditRules.cpp
|
2001-04-28 12:04:45 +00:00
|
|
|
|
|
|
|
// MOOSE: for now, just getting the ws logic straight. This implementation
|
|
|
|
// is very slow. Will need to replace edit rules impl with a more efficient
|
|
|
|
// text sink here that does the minimal amount of searching/replacing/copying
|
|
|
|
|
2014-05-02 12:15:27 +00:00
|
|
|
if (aStringToInsert.IsEmpty()) {
|
2017-11-09 04:24:06 +00:00
|
|
|
if (aPointAfterInsertedString) {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
*aPointAfterInsertedString = mScanStartPoint;
|
2017-11-09 04:24:06 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSFragment* beforeRun = FindNearestRun(mScanStartPoint, false);
|
|
|
|
WSFragment* afterRun = FindNearestRun(mScanEndPoint, true);
|
2017-11-21 10:03:03 +00:00
|
|
|
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
EditorDOMPoint pointToInsert(mScanStartPoint);
|
2001-04-28 12:04:45 +00:00
|
|
|
nsAutoString theString(aStringToInsert);
|
|
|
|
{
|
2016-06-24 06:08:16 +00:00
|
|
|
// Some scoping for AutoTrackDOMPoint. This will track our insertion
|
2014-05-02 12:15:27 +00:00
|
|
|
// point while we tweak any surrounding whitespace
|
2018-11-26 06:31:56 +00:00
|
|
|
AutoTrackDOMPoint tracker(mHTMLEditor->RangeUpdaterRef(), &pointToInsert);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Handle any changes needed to ws run after inserted text
|
|
|
|
if (!afterRun || afterRun->mType & WSType::trailingWS) {
|
|
|
|
// Don't need to do anything. Just insert text. ws won't change.
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (afterRun->mType & WSType::leadingWS) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Delete the leading ws that is after insertion point, because it
|
2002-04-13 23:54:59 +00:00
|
|
|
// would become significant after text inserted.
|
2018-03-20 05:05:47 +00:00
|
|
|
nsresult rv = DeleteRange(pointToInsert, afterRun->EndPoint());
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (afterRun->mType == WSType::normalWS) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
|
|
|
// proliferation
|
2019-05-07 10:58:08 +00:00
|
|
|
nsresult rv = CheckLeadingNBSP(
|
|
|
|
afterRun, MOZ_KnownLive(pointToInsert.GetContainer()),
|
|
|
|
pointToInsert.Offset());
|
2016-10-19 09:09:33 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2002-04-13 23:54:59 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Handle any changes needed to ws run before inserted text
|
|
|
|
if (!beforeRun || beforeRun->mType & WSType::leadingWS) {
|
|
|
|
// Don't need to do anything. Just insert text. ws won't change.
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (beforeRun->mType & WSType::trailingWS) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Need to delete the trailing ws that is before insertion point, because
|
|
|
|
// it would become significant after text inserted.
|
2018-03-20 05:05:47 +00:00
|
|
|
nsresult rv = DeleteRange(beforeRun->StartPoint(), pointToInsert);
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (beforeRun->mType == WSType::normalWS) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
|
|
|
// proliferation
|
2018-03-20 05:05:47 +00:00
|
|
|
nsresult rv = ReplacePreviousNBSPIfUnncessary(beforeRun, pointToInsert);
|
2017-11-21 17:45:08 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2017-10-23 12:47:56 +00:00
|
|
|
}
|
|
|
|
|
2017-11-09 04:24:06 +00:00
|
|
|
// After this block, pointToInsert is modified by AutoTrackDOMPoint.
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Next up, tweak head and tail of string as needed. First the head: there
|
|
|
|
// are a variety of circumstances that would require us to convert a leading
|
|
|
|
// ws char into an nbsp:
|
|
|
|
|
|
|
|
if (nsCRT::IsAsciiSpace(theString[0])) {
|
|
|
|
// We have a leading space
|
2012-07-13 06:33:43 +00:00
|
|
|
if (beforeRun) {
|
|
|
|
if (beforeRun->mType & WSType::leadingWS) {
|
2017-12-21 10:27:31 +00:00
|
|
|
theString.SetCharAt(kNBSP, 0);
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (beforeRun->mType & WSType::normalWS) {
|
2018-03-20 05:05:47 +00:00
|
|
|
WSPoint wspoint = GetPreviousCharPoint(pointToInsert);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (wspoint.mTextNode && nsCRT::IsAsciiSpace(wspoint.mChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
theString.SetCharAt(kNBSP, 0);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
} else if (mStartReason & WSType::block || mStartReason == WSType::br) {
|
2017-12-21 10:27:31 +00:00
|
|
|
theString.SetCharAt(kNBSP, 0);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-02 12:15:27 +00:00
|
|
|
// Then the tail
|
|
|
|
uint32_t lastCharIndex = theString.Length() - 1;
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2014-05-02 12:15:27 +00:00
|
|
|
if (nsCRT::IsAsciiSpace(theString[lastCharIndex])) {
|
|
|
|
// We have a leading space
|
|
|
|
if (afterRun) {
|
2012-07-13 06:33:43 +00:00
|
|
|
if (afterRun->mType & WSType::trailingWS) {
|
2017-12-21 10:27:31 +00:00
|
|
|
theString.SetCharAt(kNBSP, lastCharIndex);
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (afterRun->mType & WSType::normalWS) {
|
2018-03-20 05:05:47 +00:00
|
|
|
WSPoint wspoint = GetNextCharPoint(pointToInsert);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (wspoint.mTextNode && nsCRT::IsAsciiSpace(wspoint.mChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
theString.SetCharAt(kNBSP, lastCharIndex);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
} else if (mEndReason & WSType::block) {
|
2017-12-21 10:27:31 +00:00
|
|
|
theString.SetCharAt(kNBSP, lastCharIndex);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Next, scan string for adjacent ws and convert to nbsp/space combos
|
|
|
|
// MOOSE: don't need to convert tabs here since that is done by
|
|
|
|
// WillInsertText() before we are called. Eventually, all that logic will be
|
|
|
|
// pushed down into here and made more efficient.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool prevWS = false;
|
2014-05-02 12:15:27 +00:00
|
|
|
for (uint32_t i = 0; i <= lastCharIndex; i++) {
|
|
|
|
if (nsCRT::IsAsciiSpace(theString[i])) {
|
|
|
|
if (prevWS) {
|
|
|
|
// i - 1 can't be negative because prevWS starts out false
|
2017-12-21 10:27:31 +00:00
|
|
|
theString.SetCharAt(kNBSP, i - 1);
|
2014-05-02 12:15:27 +00:00
|
|
|
} else {
|
2011-10-17 14:59:28 +00:00
|
|
|
prevWS = true;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
} else {
|
2011-10-17 14:59:28 +00:00
|
|
|
prevWS = false;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2019-05-23 06:06:18 +00:00
|
|
|
// XXX If the point is not editable, InsertTextWithTransaction() returns
|
|
|
|
// error, but we keep handling it. But I think that it wastes the
|
|
|
|
// runtime cost. So, perhaps, we should return error code which couldn't
|
|
|
|
// modify it and make each caller of this method decide whether it should
|
|
|
|
// keep or stop handling the edit action.
|
2019-03-30 11:55:29 +00:00
|
|
|
nsresult rv =
|
|
|
|
MOZ_KnownLive(mHTMLEditor)
|
|
|
|
->InsertTextWithTransaction(aDocument, theString, pointToInsert,
|
|
|
|
aPointAfterInsertedString);
|
2017-11-08 16:00:36 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2019-05-23 06:06:18 +00:00
|
|
|
// XXX Temporarily, set new insertion point to the original point.
|
2019-05-30 10:32:44 +00:00
|
|
|
if (aPointAfterInsertedString) {
|
|
|
|
*aPointAfterInsertedString = pointToInsert;
|
|
|
|
}
|
2017-11-08 16:00:36 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::DeleteWSBackward() {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = GetPreviousCharPoint(mScanStartPoint);
|
2010-06-17 19:41:16 +00:00
|
|
|
NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2016-10-24 02:27:45 +00:00
|
|
|
// Easy case, preformatted ws.
|
2017-12-21 10:27:31 +00:00
|
|
|
if (mPRE && (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == kNBSP)) {
|
2017-11-21 16:00:35 +00:00
|
|
|
nsresult rv =
|
2019-05-08 09:40:17 +00:00
|
|
|
DeleteRange(EditorDOMPoint(point.mTextNode, point.mOffset),
|
|
|
|
EditorDOMPoint(point.mTextNode, point.mOffset + 1));
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2002-02-19 11:52:50 +00:00
|
|
|
}
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
// Caller's job to ensure that previous char is really ws. If it is normal
|
|
|
|
// ws, we need to delete the whole run.
|
|
|
|
if (nsCRT::IsAsciiSpace(point.mChar)) {
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> startNodeText, endNodeText;
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t startOffset, endOffset;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
GetASCIIWhitespacesBounds(
|
|
|
|
eBoth, EditorRawDOMPoint(point.mTextNode, point.mOffset + 1),
|
|
|
|
getter_AddRefs(startNodeText), &startOffset,
|
|
|
|
getter_AddRefs(endNodeText), &endOffset);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2001-05-10 11:55:49 +00:00
|
|
|
// adjust surrounding ws
|
2014-05-02 11:11:26 +00:00
|
|
|
nsCOMPtr<nsINode> startNode = startNodeText.get();
|
|
|
|
nsCOMPtr<nsINode> endNode = endNodeText.get();
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult rv = WSRunObject::PrepareToDeleteRange(
|
2019-05-07 10:58:08 +00:00
|
|
|
MOZ_KnownLive(mHTMLEditor), address_of(startNode), &startOffset,
|
|
|
|
address_of(endNode), &endOffset);
|
2016-10-19 09:09:33 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2001-05-10 11:55:49 +00:00
|
|
|
// finally, delete that ws
|
2019-05-08 09:40:17 +00:00
|
|
|
rv = DeleteRange(EditorDOMPoint(startNode, startOffset),
|
|
|
|
EditorDOMPoint(endNode, endOffset));
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2016-10-24 02:27:45 +00:00
|
|
|
}
|
|
|
|
|
2017-12-21 10:27:31 +00:00
|
|
|
if (point.mChar == kNBSP) {
|
2014-05-02 11:11:26 +00:00
|
|
|
nsCOMPtr<nsINode> node(point.mTextNode);
|
2001-05-10 11:55:49 +00:00
|
|
|
// adjust surrounding ws
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t startOffset = point.mOffset;
|
2014-05-02 11:11:26 +00:00
|
|
|
int32_t endOffset = point.mOffset + 1;
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult rv = WSRunObject::PrepareToDeleteRange(
|
2019-05-07 10:58:08 +00:00
|
|
|
MOZ_KnownLive(mHTMLEditor), address_of(node), &startOffset,
|
|
|
|
address_of(node), &endOffset);
|
2016-10-19 09:09:33 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
2001-05-10 11:55:49 +00:00
|
|
|
// finally, delete that ws
|
2019-05-08 09:40:17 +00:00
|
|
|
rv = DeleteRange(EditorDOMPoint(node, startOffset),
|
|
|
|
EditorDOMPoint(node, endOffset));
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
2016-10-24 02:27:45 +00:00
|
|
|
|
2001-05-10 11:55:49 +00:00
|
|
|
return NS_OK;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::DeleteWSForward() {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = GetNextCharPoint(mScanStartPoint);
|
2014-05-02 12:15:26 +00:00
|
|
|
NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
|
|
|
|
|
2016-10-24 02:27:45 +00:00
|
|
|
// Easy case, preformatted ws.
|
2017-12-21 10:27:31 +00:00
|
|
|
if (mPRE && (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == kNBSP)) {
|
2017-11-21 16:00:35 +00:00
|
|
|
nsresult rv =
|
2019-05-08 09:40:17 +00:00
|
|
|
DeleteRange(EditorDOMPoint(point.mTextNode, point.mOffset),
|
|
|
|
EditorDOMPoint(point.mTextNode, point.mOffset + 1));
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2002-02-19 11:52:50 +00:00
|
|
|
}
|
2014-05-02 12:15:26 +00:00
|
|
|
|
|
|
|
// Caller's job to ensure that next char is really ws. If it is normal ws,
|
|
|
|
// we need to delete the whole run.
|
|
|
|
if (nsCRT::IsAsciiSpace(point.mChar)) {
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> startNodeText, endNodeText;
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t startOffset, endOffset;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
GetASCIIWhitespacesBounds(
|
|
|
|
eBoth, EditorRawDOMPoint(point.mTextNode, point.mOffset + 1),
|
|
|
|
getter_AddRefs(startNodeText), &startOffset,
|
|
|
|
getter_AddRefs(endNodeText), &endOffset);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
|
|
|
// Adjust surrounding ws
|
|
|
|
nsCOMPtr<nsINode> startNode(startNodeText), endNode(endNodeText);
|
2016-10-19 09:09:33 +00:00
|
|
|
nsresult rv = WSRunObject::PrepareToDeleteRange(
|
2019-05-07 10:58:08 +00:00
|
|
|
MOZ_KnownLive(mHTMLEditor), address_of(startNode), &startOffset,
|
|
|
|
address_of(endNode), &endOffset);
|
2016-10-19 09:09:33 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
|
|
|
// Finally, delete that ws
|
2019-05-08 09:40:17 +00:00
|
|
|
rv = DeleteRange(EditorDOMPoint(startNode, startOffset),
|
|
|
|
EditorDOMPoint(endNode, endOffset));
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2016-10-24 02:27:45 +00:00
|
|
|
}
|
|
|
|
|
2017-12-21 10:27:31 +00:00
|
|
|
if (point.mChar == kNBSP) {
|
2014-05-02 12:15:26 +00:00
|
|
|
nsCOMPtr<nsINode> node(point.mTextNode);
|
|
|
|
// Adjust surrounding ws
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t startOffset = point.mOffset;
|
|
|
|
int32_t endOffset = point.mOffset + 1;
|
2016-10-19 09:09:33 +00:00
|
|
|
nsresult rv = WSRunObject::PrepareToDeleteRange(
|
2019-05-07 10:58:08 +00:00
|
|
|
MOZ_KnownLive(mHTMLEditor), address_of(node), &startOffset,
|
|
|
|
address_of(node), &endOffset);
|
2016-10-19 09:09:33 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2014-05-02 12:15:26 +00:00
|
|
|
|
|
|
|
// Finally, delete that ws
|
2019-05-08 09:40:17 +00:00
|
|
|
rv = DeleteRange(EditorDOMPoint(node, startOffset),
|
|
|
|
EditorDOMPoint(node, endOffset));
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2016-10-24 02:27:45 +00:00
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
template <typename PT, typename CT>
|
|
|
|
void WSRunObject::PriorVisibleNode(const EditorDOMPointBase<PT, CT>& aPoint,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsCOMPtr<nsINode>* outVisNode,
|
|
|
|
int32_t* outVisOffset,
|
2018-08-14 09:26:46 +00:00
|
|
|
WSType* outType) const {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Find first visible thing before the point. Position
|
|
|
|
// outVisNode/outVisOffset just _after_ that thing. If we don't find
|
|
|
|
// anything return start of ws.
|
2018-08-14 09:26:46 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSet() && outType);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
WSFragment* run = FindNearestRun(aPoint, false);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Is there a visible run there or earlier?
|
|
|
|
for (; run; run = run->mLeft) {
|
2012-07-13 06:33:43 +00:00
|
|
|
if (run->mType == WSType::normalWS) {
|
2018-03-15 09:23:50 +00:00
|
|
|
WSPoint point = GetPreviousCharPoint(aPoint);
|
Bug 1315065 When selection is collapsed in an empty text node, Backspace/Delete key press should modify the nearest text node r=smaug
Currently, when selection is collapsed at an empty text node, the behavior of each major browser is different.
When you remove the last character of non-empty text node followed by empty text nodes, Chromium removes all following empty text nodes. However, Edge never removes empty text nodes even when selection is collapsed at an empty text node.
With this patch, our behavior becomes same as Edge. I think that we should take this for keeping backward compatibility since Gecko never removes empty text nodes. So, in other words, this patch makes Backspace key press at an empty text node modify the preceding non-empty text node.
When you remove the first character of non-empty text node preceded with empty text nodes, Edge removes all preceding empty text nodes. However, Chromium and Gecko keeps previous empty text nodes than caret position. So, we should keep current behavior for backward compatibility. In other words, this patch makes Delete key press at an empty text node modify the following non-empty text node and keep current behavior.
The fixing approach of this is, making WSRunObject::PriorVisibleNode() and WSRunObject::NextVisibleNode() ignore empty text node. This should make sense because empty text node is not a visible node. (On the other hand, when the DOMPoint has a null character, it should treat as visible character. That is visible with Unicode codepoint.)
MozReview-Commit-ID: 11YtqBktEvK
--HG--
extra : rebase_source : 70fa858866cc768179c1ca6a869e1a5c7cfe6e1a
2016-11-11 03:24:21 +00:00
|
|
|
// When it's a non-empty text node, return it.
|
|
|
|
if (point.mTextNode && point.mTextNode->Length()) {
|
2018-08-14 09:26:46 +00:00
|
|
|
if (outVisNode) {
|
|
|
|
*outVisNode = point.mTextNode;
|
|
|
|
}
|
|
|
|
if (outVisOffset) {
|
|
|
|
*outVisOffset = point.mOffset + 1;
|
|
|
|
}
|
2017-12-21 10:27:31 +00:00
|
|
|
if (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == kNBSP) {
|
2012-07-13 06:33:43 +00:00
|
|
|
*outType = WSType::normalWS;
|
2014-05-02 12:15:27 +00:00
|
|
|
} else {
|
2012-07-13 06:33:43 +00:00
|
|
|
*outType = WSType::text;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2012-06-01 11:03:17 +00:00
|
|
|
return;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
// If no text node, keep looking. We should eventually fall out of loop
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-12 12:12:47 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2018-08-14 09:26:46 +00:00
|
|
|
if (outVisNode) {
|
|
|
|
// If we get here, then nothing in ws data to find. Return start reason.
|
|
|
|
*outVisNode = mStartReasonNode;
|
|
|
|
}
|
|
|
|
if (outVisOffset) {
|
|
|
|
// This really isn't meaningful if mStartReasonNode != mStartNode
|
|
|
|
*outVisOffset = mStartOffset;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
*outType = mStartReason;
|
|
|
|
}
|
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
template <typename PT, typename CT>
|
|
|
|
void WSRunObject::NextVisibleNode(const EditorDOMPointBase<PT, CT>& aPoint,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsCOMPtr<nsINode>* outVisNode,
|
|
|
|
int32_t* outVisOffset,
|
2018-08-14 09:26:46 +00:00
|
|
|
WSType* outType) const {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Find first visible thing after the point. Position
|
|
|
|
// outVisNode/outVisOffset just _before_ that thing. If we don't find
|
|
|
|
// anything return end of ws.
|
2018-08-14 09:26:46 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSet() && outType);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
WSFragment* run = FindNearestRun(aPoint, true);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Is there a visible run there or later?
|
|
|
|
for (; run; run = run->mRight) {
|
2012-07-13 06:33:43 +00:00
|
|
|
if (run->mType == WSType::normalWS) {
|
2018-03-15 09:23:50 +00:00
|
|
|
WSPoint point = GetNextCharPoint(aPoint);
|
Bug 1315065 When selection is collapsed in an empty text node, Backspace/Delete key press should modify the nearest text node r=smaug
Currently, when selection is collapsed at an empty text node, the behavior of each major browser is different.
When you remove the last character of non-empty text node followed by empty text nodes, Chromium removes all following empty text nodes. However, Edge never removes empty text nodes even when selection is collapsed at an empty text node.
With this patch, our behavior becomes same as Edge. I think that we should take this for keeping backward compatibility since Gecko never removes empty text nodes. So, in other words, this patch makes Backspace key press at an empty text node modify the preceding non-empty text node.
When you remove the first character of non-empty text node preceded with empty text nodes, Edge removes all preceding empty text nodes. However, Chromium and Gecko keeps previous empty text nodes than caret position. So, we should keep current behavior for backward compatibility. In other words, this patch makes Delete key press at an empty text node modify the following non-empty text node and keep current behavior.
The fixing approach of this is, making WSRunObject::PriorVisibleNode() and WSRunObject::NextVisibleNode() ignore empty text node. This should make sense because empty text node is not a visible node. (On the other hand, when the DOMPoint has a null character, it should treat as visible character. That is visible with Unicode codepoint.)
MozReview-Commit-ID: 11YtqBktEvK
--HG--
extra : rebase_source : 70fa858866cc768179c1ca6a869e1a5c7cfe6e1a
2016-11-11 03:24:21 +00:00
|
|
|
// When it's a non-empty text node, return it.
|
|
|
|
if (point.mTextNode && point.mTextNode->Length()) {
|
2018-08-14 09:26:46 +00:00
|
|
|
if (outVisNode) {
|
|
|
|
*outVisNode = point.mTextNode;
|
|
|
|
}
|
|
|
|
if (outVisOffset) {
|
|
|
|
*outVisOffset = point.mOffset;
|
|
|
|
}
|
2017-12-21 10:27:31 +00:00
|
|
|
if (nsCRT::IsAsciiSpace(point.mChar) || point.mChar == kNBSP) {
|
2012-07-13 06:33:43 +00:00
|
|
|
*outType = WSType::normalWS;
|
2014-05-02 12:15:27 +00:00
|
|
|
} else {
|
2012-07-13 06:33:43 +00:00
|
|
|
*outType = WSType::text;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2012-06-01 11:03:17 +00:00
|
|
|
return;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
// If no text node, keep looking. We should eventually fall out of loop
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-12 12:12:47 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2018-08-14 09:26:46 +00:00
|
|
|
if (outVisNode) {
|
|
|
|
// If we get here, then nothing in ws data to find. Return end reason
|
|
|
|
*outVisNode = mEndReasonNode;
|
|
|
|
}
|
|
|
|
if (outVisOffset) {
|
|
|
|
// This really isn't meaningful if mEndReasonNode != mEndNode
|
|
|
|
*outVisOffset = mEndOffset;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
*outType = mEndReason;
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::AdjustWhitespace() {
|
2001-05-11 12:43:22 +00:00
|
|
|
// this routine examines a run of ws and tries to get rid of some unneeded
|
|
|
|
// nbsp's, replacing them with regualr ascii space if possible. Keeping
|
|
|
|
// things simple for now and just trying to fix up the trailing ws in the run.
|
2011-07-14 21:06:37 +00:00
|
|
|
if (!mLastNBSPNode) {
|
|
|
|
// nothing to do!
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-05-11 12:43:22 +00:00
|
|
|
WSFragment* curRun = mStartRun;
|
2016-10-24 02:27:45 +00:00
|
|
|
while (curRun) {
|
2001-05-11 12:43:22 +00:00
|
|
|
// look for normal ws run
|
2012-07-13 06:33:43 +00:00
|
|
|
if (curRun->mType == WSType::normalWS) {
|
2016-10-19 09:09:33 +00:00
|
|
|
nsresult rv = CheckTrailingNBSPOfRun(curRun);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
|
|
|
curRun = curRun->mRight;
|
|
|
|
}
|
2016-10-19 09:09:33 +00:00
|
|
|
return NS_OK;
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
|
|
// protected methods
|
|
|
|
//--------------------------------------------------------------------------------------------
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsINode* WSRunObject::GetWSBoundingParent() {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
if (NS_WARN_IF(!mScanStartPoint.IsSet())) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
// XXX What should we do if scan range crosses block boundary? Currently,
|
|
|
|
// it's not collapsed only when inserting composition string so that
|
|
|
|
// it's possible but shouldn't occur actually.
|
|
|
|
OwningNonNull<nsINode> wsBoundingParent = *mScanStartPoint.GetContainer();
|
2014-05-02 11:11:26 +00:00
|
|
|
while (!IsBlockNode(wsBoundingParent)) {
|
|
|
|
nsCOMPtr<nsINode> parent = wsBoundingParent->GetParentNode();
|
|
|
|
if (!parent || !mHTMLEditor->IsEditable(parent)) {
|
2009-02-21 04:28:09 +00:00
|
|
|
break;
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2015-04-19 12:28:49 +00:00
|
|
|
wsBoundingParent = parent;
|
2009-02-21 04:28:09 +00:00
|
|
|
}
|
2016-05-01 18:29:23 +00:00
|
|
|
return wsBoundingParent;
|
2009-02-21 04:28:09 +00:00
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::GetWSNodes() {
|
2001-04-28 12:04:45 +00:00
|
|
|
// collect up an array of nodes that are contiguous with the insertion point
|
2015-05-28 15:58:42 +00:00
|
|
|
// and which contain only whitespace. Stop if you reach non-ws text or a new
|
2001-04-28 12:04:45 +00:00
|
|
|
// block boundary.
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
EditorDOMPoint start(mScanStartPoint), end(mScanEndPoint);
|
2014-05-02 11:11:26 +00:00
|
|
|
nsCOMPtr<nsINode> wsBoundingParent = GetWSBoundingParent();
|
2001-04-28 12:04:45 +00:00
|
|
|
|
|
|
|
// first look backwards to find preceding ws nodes
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
if (Text* textNode = mScanStartPoint.GetContainerAsText()) {
|
2019-05-22 05:18:48 +00:00
|
|
|
const nsTextFragment* textFrag = &textNode->TextFragment();
|
2014-08-13 11:53:32 +00:00
|
|
|
mNodeArray.InsertElementAt(0, textNode);
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
if (!mScanStartPoint.IsStartOfContainer()) {
|
|
|
|
for (uint32_t i = mScanStartPoint.Offset(); i; i--) {
|
2002-05-23 22:05:35 +00:00
|
|
|
// sanity bounds check the char position. bug 136165
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
if (i > textFrag->GetLength()) {
|
2018-06-18 05:43:11 +00:00
|
|
|
MOZ_ASSERT_UNREACHABLE("looking beyond end of text fragment");
|
2002-05-23 22:05:35 +00:00
|
|
|
continue;
|
|
|
|
}
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
char16_t theChar = textFrag->CharAt(i - 1);
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!nsCRT::IsAsciiSpace(theChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
if (theChar != kNBSP) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mStartNode = textNode;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
mStartOffset = i;
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartReason = WSType::text;
|
2014-08-13 11:53:32 +00:00
|
|
|
mStartReasonNode = textNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// as we look backwards update our earliest found nbsp
|
2014-08-13 11:53:32 +00:00
|
|
|
mFirstNBSPNode = textNode;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
mFirstNBSPOffset = i - 1;
|
2001-04-28 12:04:45 +00:00
|
|
|
// also keep track of latest nbsp so far
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!mLastNBSPNode) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mLastNBSPNode = textNode;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
mLastNBSPOffset = i - 1;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
start.Set(textNode, i - 1);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-02-07 03:56:20 +00:00
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
while (!mStartNode) {
|
2001-04-28 12:04:45 +00:00
|
|
|
// we haven't found the start of ws yet. Keep looking
|
2014-10-22 12:45:30 +00:00
|
|
|
nsCOMPtr<nsIContent> priorNode = GetPreviousWSNode(start, wsBoundingParent);
|
2014-05-02 11:11:26 +00:00
|
|
|
if (priorNode) {
|
|
|
|
if (IsBlockNode(priorNode)) {
|
2017-12-07 09:45:52 +00:00
|
|
|
mStartNode = start.GetContainer();
|
2017-11-01 05:41:03 +00:00
|
|
|
mStartOffset = start.Offset();
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartReason = WSType::otherBlock;
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartReasonNode = priorNode;
|
2018-04-12 22:41:00 +00:00
|
|
|
} else if (priorNode->IsText() && priorNode->IsEditable()) {
|
2017-09-11 06:52:05 +00:00
|
|
|
RefPtr<Text> textNode = priorNode->GetAsText();
|
2014-08-13 11:53:32 +00:00
|
|
|
mNodeArray.InsertElementAt(0, textNode);
|
2019-05-22 05:18:48 +00:00
|
|
|
if (!textNode) {
|
2006-07-19 04:36:36 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2019-05-22 05:18:48 +00:00
|
|
|
const nsTextFragment* textFrag = &textNode->TextFragment();
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t len = textNode->TextLength();
|
2002-02-08 15:20:19 +00:00
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
if (len < 1) {
|
2002-02-08 15:20:19 +00:00
|
|
|
// Zero length text node. Set start point to it
|
|
|
|
// so we can get past it!
|
2017-11-01 05:41:03 +00:00
|
|
|
start.Set(priorNode, 0);
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
|
|
|
for (int32_t pos = len - 1; pos >= 0; pos--) {
|
2002-05-23 22:05:35 +00:00
|
|
|
// sanity bounds check the char position. bug 136165
|
2014-05-02 11:11:26 +00:00
|
|
|
if (uint32_t(pos) >= textFrag->GetLength()) {
|
2018-06-18 05:43:11 +00:00
|
|
|
MOZ_ASSERT_UNREACHABLE("looking beyond end of text fragment");
|
2002-05-23 22:05:35 +00:00
|
|
|
continue;
|
|
|
|
}
|
2014-01-04 15:02:17 +00:00
|
|
|
char16_t theChar = textFrag->CharAt(pos);
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!nsCRT::IsAsciiSpace(theChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
if (theChar != kNBSP) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mStartNode = textNode;
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartOffset = pos + 1;
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartReason = WSType::text;
|
2014-08-13 11:53:32 +00:00
|
|
|
mStartReasonNode = textNode;
|
2002-02-08 15:20:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// as we look backwards update our earliest found nbsp
|
2014-08-13 11:53:32 +00:00
|
|
|
mFirstNBSPNode = textNode;
|
2002-02-08 15:20:19 +00:00
|
|
|
mFirstNBSPOffset = pos;
|
|
|
|
// also keep track of latest nbsp so far
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!mLastNBSPNode) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mLastNBSPNode = textNode;
|
2002-02-08 15:20:19 +00:00
|
|
|
mLastNBSPOffset = pos;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2017-11-01 05:41:03 +00:00
|
|
|
start.Set(textNode, pos);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
2002-02-07 03:56:20 +00:00
|
|
|
// it's a break or a special node, like <img>, that is not a block and
|
2001-04-28 12:04:45 +00:00
|
|
|
// not a break but still serves as a terminator to ws runs.
|
2017-12-07 09:45:52 +00:00
|
|
|
mStartNode = start.GetContainer();
|
2017-11-01 05:41:03 +00:00
|
|
|
mStartOffset = start.Offset();
|
2016-07-07 04:44:32 +00:00
|
|
|
if (TextEditUtils::IsBreak(priorNode)) {
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartReason = WSType::br;
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartReason = WSType::special;
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
|
|
|
mStartReasonNode = priorNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
2009-02-21 04:28:09 +00:00
|
|
|
// no prior node means we exhausted wsBoundingParent
|
2017-12-07 09:45:52 +00:00
|
|
|
mStartNode = start.GetContainer();
|
2017-11-01 05:41:03 +00:00
|
|
|
mStartOffset = start.Offset();
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartReason = WSType::thisBlock;
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartReasonNode = wsBoundingParent;
|
2015-05-28 15:58:42 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
// then look ahead to find following ws nodes
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
if (Text* textNode = mScanEndPoint.GetContainerAsText()) {
|
2005-11-25 08:16:51 +00:00
|
|
|
// don't need to put it on list. it already is from code above
|
2019-05-22 05:18:48 +00:00
|
|
|
const nsTextFragment* textFrag = &textNode->TextFragment();
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
if (!mScanEndPoint.IsEndOfContainer()) {
|
|
|
|
for (uint32_t i = mScanEndPoint.Offset(); i < textNode->TextLength();
|
|
|
|
i++) {
|
2002-05-23 22:05:35 +00:00
|
|
|
// sanity bounds check the char position. bug 136165
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
if (i >= textFrag->GetLength()) {
|
2018-06-18 05:43:11 +00:00
|
|
|
MOZ_ASSERT_UNREACHABLE("looking beyond end of text fragment");
|
2002-05-23 22:05:35 +00:00
|
|
|
continue;
|
|
|
|
}
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
char16_t theChar = textFrag->CharAt(i);
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!nsCRT::IsAsciiSpace(theChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
if (theChar != kNBSP) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mEndNode = textNode;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
mEndOffset = i;
|
2012-07-13 06:33:43 +00:00
|
|
|
mEndReason = WSType::text;
|
2014-08-13 11:53:32 +00:00
|
|
|
mEndReasonNode = textNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// as we look forwards update our latest found nbsp
|
2014-08-13 11:53:32 +00:00
|
|
|
mLastNBSPNode = textNode;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
mLastNBSPOffset = i;
|
2001-04-28 12:04:45 +00:00
|
|
|
// also keep track of earliest nbsp so far
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!mFirstNBSPNode) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mFirstNBSPNode = textNode;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
mFirstNBSPOffset = i;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
end.Set(textNode, i + 1);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
while (!mEndNode) {
|
2001-04-28 12:04:45 +00:00
|
|
|
// we haven't found the end of ws yet. Keep looking
|
2014-10-22 12:45:30 +00:00
|
|
|
nsCOMPtr<nsIContent> nextNode = GetNextWSNode(end, wsBoundingParent);
|
2014-05-02 11:11:26 +00:00
|
|
|
if (nextNode) {
|
|
|
|
if (IsBlockNode(nextNode)) {
|
2001-04-28 12:04:45 +00:00
|
|
|
// we encountered a new block. therefore no more ws.
|
2017-12-07 09:45:52 +00:00
|
|
|
mEndNode = end.GetContainer();
|
2017-11-01 05:41:03 +00:00
|
|
|
mEndOffset = end.Offset();
|
2012-07-13 06:33:43 +00:00
|
|
|
mEndReason = WSType::otherBlock;
|
2014-05-02 11:11:26 +00:00
|
|
|
mEndReasonNode = nextNode;
|
2018-04-12 22:41:00 +00:00
|
|
|
} else if (nextNode->IsText() && nextNode->IsEditable()) {
|
2017-09-11 06:52:05 +00:00
|
|
|
RefPtr<Text> textNode = nextNode->GetAsText();
|
2014-08-13 11:53:32 +00:00
|
|
|
mNodeArray.AppendElement(textNode);
|
2019-05-22 05:18:48 +00:00
|
|
|
if (!textNode) {
|
2006-07-19 04:36:36 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2019-05-22 05:18:48 +00:00
|
|
|
const nsTextFragment* textFrag = &textNode->TextFragment();
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t len = textNode->TextLength();
|
2002-02-08 15:20:19 +00:00
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
if (len < 1) {
|
2002-02-08 15:20:19 +00:00
|
|
|
// Zero length text node. Set end point to it
|
|
|
|
// so we can get past it!
|
2017-11-01 05:41:03 +00:00
|
|
|
end.Set(textNode, 0);
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
|
|
|
for (uint32_t pos = 0; pos < len; pos++) {
|
2002-05-23 22:05:35 +00:00
|
|
|
// sanity bounds check the char position. bug 136165
|
2014-05-02 11:11:26 +00:00
|
|
|
if (pos >= textFrag->GetLength()) {
|
2018-06-18 05:43:11 +00:00
|
|
|
MOZ_ASSERT_UNREACHABLE("looking beyond end of text fragment");
|
2002-05-23 22:05:35 +00:00
|
|
|
continue;
|
|
|
|
}
|
2014-01-04 15:02:17 +00:00
|
|
|
char16_t theChar = textFrag->CharAt(pos);
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!nsCRT::IsAsciiSpace(theChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
if (theChar != kNBSP) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mEndNode = textNode;
|
2002-02-08 15:20:19 +00:00
|
|
|
mEndOffset = pos;
|
2012-07-13 06:33:43 +00:00
|
|
|
mEndReason = WSType::text;
|
2014-08-13 11:53:32 +00:00
|
|
|
mEndReasonNode = textNode;
|
2002-02-08 15:20:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
// as we look forwards update our latest found nbsp
|
2014-08-13 11:53:32 +00:00
|
|
|
mLastNBSPNode = textNode;
|
2002-02-08 15:20:19 +00:00
|
|
|
mLastNBSPOffset = pos;
|
|
|
|
// also keep track of earliest nbsp so far
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!mFirstNBSPNode) {
|
2014-08-13 11:53:32 +00:00
|
|
|
mFirstNBSPNode = textNode;
|
2002-02-08 15:20:19 +00:00
|
|
|
mFirstNBSPOffset = pos;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2017-11-01 05:41:03 +00:00
|
|
|
end.Set(textNode, pos + 1);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
2015-05-28 15:58:42 +00:00
|
|
|
// we encountered a break or a special node, like <img>,
|
|
|
|
// that is not a block and not a break but still
|
2002-02-07 03:56:20 +00:00
|
|
|
// serves as a terminator to ws runs.
|
2017-12-07 09:45:52 +00:00
|
|
|
mEndNode = end.GetContainer();
|
2017-11-01 05:41:03 +00:00
|
|
|
mEndOffset = end.Offset();
|
2016-07-07 04:44:32 +00:00
|
|
|
if (TextEditUtils::IsBreak(nextNode)) {
|
2012-07-13 06:33:43 +00:00
|
|
|
mEndReason = WSType::br;
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
2012-07-13 06:33:43 +00:00
|
|
|
mEndReason = WSType::special;
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
|
|
|
mEndReasonNode = nextNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
} else {
|
2009-02-21 04:28:09 +00:00
|
|
|
// no next node means we exhausted wsBoundingParent
|
2017-12-07 09:45:52 +00:00
|
|
|
mEndNode = end.GetContainer();
|
2017-11-01 05:41:03 +00:00
|
|
|
mEndOffset = end.Offset();
|
2012-07-13 06:33:43 +00:00
|
|
|
mEndReason = WSType::thisBlock;
|
2014-05-02 11:11:26 +00:00
|
|
|
mEndReasonNode = wsBoundingParent;
|
2015-05-28 15:58:42 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
void WSRunObject::GetRuns() {
|
2001-04-28 12:04:45 +00:00
|
|
|
ClearRuns();
|
2015-05-28 15:58:42 +00:00
|
|
|
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
// Handle preformatted case first since it's simple. Note that if end of
|
|
|
|
// the scan range isn't in preformatted element, we need to check only the
|
|
|
|
// style at mScanStartPoint since the range would be replaced and the start
|
|
|
|
// style will be applied to all new string.
|
|
|
|
mPRE = EditorBase::IsPreformatted(mScanStartPoint.GetContainer());
|
2002-02-19 11:52:50 +00:00
|
|
|
// if it's preformatedd, or if we are surrounded by text or special, it's all
|
2001-04-28 12:04:45 +00:00
|
|
|
// one big normal ws run
|
2012-07-13 06:33:43 +00:00
|
|
|
if (mPRE ||
|
|
|
|
((mStartReason == WSType::text || mStartReason == WSType::special) &&
|
|
|
|
(mEndReason == WSType::text || mEndReason == WSType::special ||
|
|
|
|
mEndReason == WSType::br))) {
|
|
|
|
MakeSingleWSRun(WSType::normalWS);
|
2012-06-01 11:03:17 +00:00
|
|
|
return;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// if we are before or after a block (or after a break), and there are no
|
|
|
|
// nbsp's, then it's all non-rendering ws.
|
2012-07-13 06:33:43 +00:00
|
|
|
if (!mFirstNBSPNode && !mLastNBSPNode &&
|
|
|
|
((mStartReason & WSType::block) || mStartReason == WSType::br ||
|
|
|
|
(mEndReason & WSType::block))) {
|
|
|
|
WSType wstype;
|
|
|
|
if ((mStartReason & WSType::block) || mStartReason == WSType::br) {
|
|
|
|
wstype = WSType::leadingWS;
|
|
|
|
}
|
|
|
|
if (mEndReason & WSType::block) {
|
|
|
|
wstype |= WSType::trailingWS;
|
|
|
|
}
|
2012-06-01 11:03:17 +00:00
|
|
|
MakeSingleWSRun(wstype);
|
|
|
|
return;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
// otherwise a little trickier. shucks.
|
|
|
|
mStartRun = new WSFragment();
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartRun->mStartNode = mStartNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
mStartRun->mStartOffset = mStartOffset;
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2012-07-13 06:33:43 +00:00
|
|
|
if (mStartReason & WSType::block || mStartReason == WSType::br) {
|
2001-04-28 12:04:45 +00:00
|
|
|
// set up mStartRun
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartRun->mType = WSType::leadingWS;
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartRun->mEndNode = mFirstNBSPNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
mStartRun->mEndOffset = mFirstNBSPOffset;
|
|
|
|
mStartRun->mLeftType = mStartReason;
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartRun->mRightType = WSType::normalWS;
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
// set up next run
|
|
|
|
WSFragment* normalRun = new WSFragment();
|
|
|
|
mStartRun->mRight = normalRun;
|
2012-07-13 06:33:43 +00:00
|
|
|
normalRun->mType = WSType::normalWS;
|
2014-05-02 11:11:26 +00:00
|
|
|
normalRun->mStartNode = mFirstNBSPNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
normalRun->mStartOffset = mFirstNBSPOffset;
|
2012-07-13 06:33:43 +00:00
|
|
|
normalRun->mLeftType = WSType::leadingWS;
|
2001-04-28 12:04:45 +00:00
|
|
|
normalRun->mLeft = mStartRun;
|
2012-07-13 06:33:43 +00:00
|
|
|
if (mEndReason != WSType::block) {
|
2001-04-28 12:04:45 +00:00
|
|
|
// then no trailing ws. this normal run ends the overall ws run.
|
|
|
|
normalRun->mRightType = mEndReason;
|
2014-05-02 11:11:26 +00:00
|
|
|
normalRun->mEndNode = mEndNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
normalRun->mEndOffset = mEndOffset;
|
|
|
|
mEndRun = normalRun;
|
2016-10-24 02:27:45 +00:00
|
|
|
} else {
|
2001-04-28 12:04:45 +00:00
|
|
|
// we might have trailing ws.
|
2001-05-11 12:43:22 +00:00
|
|
|
// it so happens that *if* there is an nbsp at end,
|
|
|
|
// {mEndNode,mEndOffset-1} will point to it, even though in general
|
|
|
|
// start/end points not guaranteed to be in text nodes.
|
2016-10-24 02:27:45 +00:00
|
|
|
if (mLastNBSPNode == mEndNode && mLastNBSPOffset == mEndOffset - 1) {
|
2001-04-28 12:04:45 +00:00
|
|
|
// normal ws runs right up to adjacent block (nbsp next to block)
|
|
|
|
normalRun->mRightType = mEndReason;
|
2014-05-02 11:11:26 +00:00
|
|
|
normalRun->mEndNode = mEndNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
normalRun->mEndOffset = mEndOffset;
|
|
|
|
mEndRun = normalRun;
|
2016-10-24 02:27:45 +00:00
|
|
|
} else {
|
2014-05-02 11:11:26 +00:00
|
|
|
normalRun->mEndNode = mLastNBSPNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
normalRun->mEndOffset = mLastNBSPOffset + 1;
|
2012-07-13 06:33:43 +00:00
|
|
|
normalRun->mRightType = WSType::trailingWS;
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
// set up next run
|
|
|
|
WSFragment* lastRun = new WSFragment();
|
2012-07-13 06:33:43 +00:00
|
|
|
lastRun->mType = WSType::trailingWS;
|
2014-05-02 11:11:26 +00:00
|
|
|
lastRun->mStartNode = mLastNBSPNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
lastRun->mStartOffset = mLastNBSPOffset + 1;
|
2014-05-02 11:11:26 +00:00
|
|
|
lastRun->mEndNode = mEndNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
lastRun->mEndOffset = mEndOffset;
|
2012-07-13 06:33:43 +00:00
|
|
|
lastRun->mLeftType = WSType::normalWS;
|
2001-04-28 12:04:45 +00:00
|
|
|
lastRun->mLeft = normalRun;
|
|
|
|
lastRun->mRightType = mEndReason;
|
|
|
|
mEndRun = lastRun;
|
|
|
|
normalRun->mRight = lastRun;
|
|
|
|
}
|
|
|
|
}
|
2012-07-13 06:33:43 +00:00
|
|
|
} else {
|
|
|
|
// mStartReason is not WSType::block or WSType::br; set up mStartRun
|
|
|
|
mStartRun->mType = WSType::normalWS;
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartRun->mEndNode = mLastNBSPNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
mStartRun->mEndOffset = mLastNBSPOffset + 1;
|
|
|
|
mStartRun->mLeftType = mStartReason;
|
|
|
|
|
|
|
|
// we might have trailing ws.
|
2001-05-11 12:43:22 +00:00
|
|
|
// it so happens that *if* there is an nbsp at end, {mEndNode,mEndOffset-1}
|
|
|
|
// will point to it, even though in general start/end points not
|
|
|
|
// guaranteed to be in text nodes.
|
2016-10-24 02:27:45 +00:00
|
|
|
if (mLastNBSPNode == mEndNode && mLastNBSPOffset == (mEndOffset - 1)) {
|
2002-11-17 01:25:30 +00:00
|
|
|
mStartRun->mRightType = mEndReason;
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartRun->mEndNode = mEndNode;
|
2002-11-17 01:25:30 +00:00
|
|
|
mStartRun->mEndOffset = mEndOffset;
|
|
|
|
mEndRun = mStartRun;
|
2016-10-24 02:27:45 +00:00
|
|
|
} else {
|
2001-04-28 12:04:45 +00:00
|
|
|
// set up next run
|
|
|
|
WSFragment* lastRun = new WSFragment();
|
2012-07-13 06:33:43 +00:00
|
|
|
lastRun->mType = WSType::trailingWS;
|
2014-05-02 11:11:26 +00:00
|
|
|
lastRun->mStartNode = mLastNBSPNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
lastRun->mStartOffset = mLastNBSPOffset + 1;
|
2012-07-13 06:33:43 +00:00
|
|
|
lastRun->mLeftType = WSType::normalWS;
|
2001-04-28 12:04:45 +00:00
|
|
|
lastRun->mLeft = mStartRun;
|
|
|
|
lastRun->mRightType = mEndReason;
|
|
|
|
mEndRun = lastRun;
|
|
|
|
mStartRun->mRight = lastRun;
|
2012-07-13 06:33:43 +00:00
|
|
|
mStartRun->mRightType = WSType::trailingWS;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
void WSRunObject::ClearRuns() {
|
2001-04-28 12:04:45 +00:00
|
|
|
WSFragment *tmp, *run;
|
|
|
|
run = mStartRun;
|
2016-10-24 02:27:45 +00:00
|
|
|
while (run) {
|
2001-04-28 12:04:45 +00:00
|
|
|
tmp = run->mRight;
|
|
|
|
delete run;
|
|
|
|
run = tmp;
|
|
|
|
}
|
|
|
|
mStartRun = 0;
|
|
|
|
mEndRun = 0;
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
void WSRunObject::MakeSingleWSRun(WSType aType) {
|
2001-04-28 12:04:45 +00:00
|
|
|
mStartRun = new WSFragment();
|
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartRun->mStartNode = mStartNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
mStartRun->mStartOffset = mStartOffset;
|
|
|
|
mStartRun->mType = aType;
|
2014-05-02 11:11:26 +00:00
|
|
|
mStartRun->mEndNode = mEndNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
mStartRun->mEndOffset = mEndOffset;
|
|
|
|
mStartRun->mLeftType = mStartReason;
|
|
|
|
mStartRun->mRightType = mEndReason;
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
mEndRun = mStartRun;
|
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsIContent* WSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode,
|
|
|
|
nsINode* aBlockParent) {
|
2014-10-22 12:45:30 +00:00
|
|
|
// Can't really recycle various getnext/prior routines because we have
|
2014-05-02 11:11:26 +00:00
|
|
|
// special needs here. Need to step into inline containers but not block
|
|
|
|
// containers.
|
2014-10-22 12:45:30 +00:00
|
|
|
MOZ_ASSERT(aStartNode && aBlockParent);
|
|
|
|
|
2019-05-27 12:10:23 +00:00
|
|
|
if (NS_WARN_IF(aStartNode == mEditingHost)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-22 12:45:30 +00:00
|
|
|
nsCOMPtr<nsIContent> priorNode = aStartNode->GetPreviousSibling();
|
2015-04-19 12:28:49 +00:00
|
|
|
OwningNonNull<nsINode> curNode = *aStartNode;
|
2014-10-22 12:45:30 +00:00
|
|
|
while (!priorNode) {
|
|
|
|
// We have exhausted nodes in parent of aStartNode.
|
|
|
|
nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
|
2019-05-27 12:10:23 +00:00
|
|
|
if (NS_WARN_IF(!curParent)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
if (curParent == aBlockParent) {
|
|
|
|
// We have exhausted nodes in the block parent. The convention here is
|
2014-05-02 11:11:26 +00:00
|
|
|
// to return null.
|
2014-10-22 12:45:30 +00:00
|
|
|
return nullptr;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2019-05-27 12:10:23 +00:00
|
|
|
if (NS_WARN_IF(curParent == mEditingHost)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// We have a parent: look for previous sibling
|
|
|
|
priorNode = curParent->GetPreviousSibling();
|
|
|
|
curNode = curParent;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// We have a prior node. If it's a block, return it.
|
|
|
|
if (IsBlockNode(priorNode)) {
|
|
|
|
return priorNode;
|
|
|
|
}
|
|
|
|
if (mHTMLEditor->IsContainer(priorNode)) {
|
|
|
|
// Else if it's a container, get deep rightmost child
|
|
|
|
nsCOMPtr<nsIContent> child = mHTMLEditor->GetRightmostChild(priorNode);
|
|
|
|
if (child) {
|
|
|
|
return child;
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// Else return the node itself
|
|
|
|
return priorNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2017-11-01 05:41:03 +00:00
|
|
|
nsIContent* WSRunObject::GetPreviousWSNode(const EditorDOMPoint& aPoint,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsINode* aBlockParent) {
|
2014-10-22 12:45:30 +00:00
|
|
|
// Can't really recycle various getnext/prior routines because we
|
2003-09-27 04:18:26 +00:00
|
|
|
// have special needs here. Need to step into inline containers but
|
|
|
|
// not block containers.
|
2017-11-01 05:41:03 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSet() && aBlockParent);
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2017-12-07 09:45:52 +00:00
|
|
|
if (aPoint.IsInTextNode()) {
|
|
|
|
return GetPreviousWSNodeInner(aPoint.GetContainer(), aBlockParent);
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2017-12-07 09:45:52 +00:00
|
|
|
if (!mHTMLEditor->IsContainer(aPoint.GetContainer())) {
|
|
|
|
return GetPreviousWSNodeInner(aPoint.GetContainer(), aBlockParent);
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
|
2017-11-01 05:41:03 +00:00
|
|
|
if (!aPoint.Offset()) {
|
2017-12-07 09:45:52 +00:00
|
|
|
if (aPoint.GetContainer() == aBlockParent) {
|
2014-10-22 12:45:30 +00:00
|
|
|
// We are at start of the block.
|
|
|
|
return nullptr;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2014-10-22 12:45:30 +00:00
|
|
|
// We are at start of non-block container
|
2017-12-07 09:45:52 +00:00
|
|
|
return GetPreviousWSNodeInner(aPoint.GetContainer(), aBlockParent);
|
2017-11-01 05:41:03 +00:00
|
|
|
}
|
|
|
|
|
2017-12-07 09:45:52 +00:00
|
|
|
if (NS_WARN_IF(!aPoint.GetContainerAsContent())) {
|
2017-11-01 05:41:03 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-12-07 10:08:56 +00:00
|
|
|
nsCOMPtr<nsIContent> priorNode = aPoint.GetPreviousSiblingOfChild();
|
2017-11-01 05:41:03 +00:00
|
|
|
if (NS_WARN_IF(!priorNode)) {
|
|
|
|
return nullptr;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2014-10-22 12:45:30 +00:00
|
|
|
// We have a prior node. If it's a block, return it.
|
|
|
|
if (IsBlockNode(priorNode)) {
|
|
|
|
return priorNode;
|
|
|
|
}
|
|
|
|
if (mHTMLEditor->IsContainer(priorNode)) {
|
|
|
|
// Else if it's a container, get deep rightmost child
|
|
|
|
nsCOMPtr<nsIContent> child = mHTMLEditor->GetRightmostChild(priorNode);
|
|
|
|
if (child) {
|
|
|
|
return child;
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// Else return the node itself
|
|
|
|
return priorNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsIContent* WSRunObject::GetNextWSNodeInner(nsINode* aStartNode,
|
|
|
|
nsINode* aBlockParent) {
|
2014-10-22 12:45:30 +00:00
|
|
|
// Can't really recycle various getnext/prior routines because we have
|
2014-05-02 11:11:26 +00:00
|
|
|
// special needs here. Need to step into inline containers but not block
|
|
|
|
// containers.
|
2014-10-22 12:45:30 +00:00
|
|
|
MOZ_ASSERT(aStartNode && aBlockParent);
|
|
|
|
|
2019-05-27 12:10:23 +00:00
|
|
|
if (NS_WARN_IF(aStartNode == mEditingHost)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-10-22 12:45:30 +00:00
|
|
|
nsCOMPtr<nsIContent> nextNode = aStartNode->GetNextSibling();
|
|
|
|
nsCOMPtr<nsINode> curNode = aStartNode;
|
|
|
|
while (!nextNode) {
|
|
|
|
// We have exhausted nodes in parent of aStartNode.
|
|
|
|
nsCOMPtr<nsINode> curParent = curNode->GetParentNode();
|
2019-05-27 12:10:23 +00:00
|
|
|
if (NS_WARN_IF(!curParent)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
if (curParent == aBlockParent) {
|
|
|
|
// We have exhausted nodes in the block parent. The convention here is
|
2014-05-02 11:11:26 +00:00
|
|
|
// to return null.
|
2014-10-22 12:45:30 +00:00
|
|
|
return nullptr;
|
2002-02-07 03:56:20 +00:00
|
|
|
}
|
2019-05-27 12:10:23 +00:00
|
|
|
if (NS_WARN_IF(curParent == mEditingHost)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// We have a parent: look for next sibling
|
|
|
|
nextNode = curParent->GetNextSibling();
|
|
|
|
curNode = curParent;
|
2002-02-07 03:56:20 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// We have a next node. If it's a block, return it.
|
|
|
|
if (IsBlockNode(nextNode)) {
|
|
|
|
return nextNode;
|
|
|
|
}
|
|
|
|
if (mHTMLEditor->IsContainer(nextNode)) {
|
|
|
|
// Else if it's a container, get deep leftmost child
|
|
|
|
nsCOMPtr<nsIContent> child = mHTMLEditor->GetLeftmostChild(nextNode);
|
|
|
|
if (child) {
|
|
|
|
return child;
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2002-02-07 03:56:20 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// Else return the node itself
|
|
|
|
return nextNode;
|
2002-02-07 03:56:20 +00:00
|
|
|
}
|
|
|
|
|
2017-11-01 05:41:03 +00:00
|
|
|
nsIContent* WSRunObject::GetNextWSNode(const EditorDOMPoint& aPoint,
|
2016-07-07 10:00:51 +00:00
|
|
|
nsINode* aBlockParent) {
|
2014-10-22 12:45:30 +00:00
|
|
|
// Can't really recycle various getnext/prior routines because we have
|
2014-05-02 11:11:26 +00:00
|
|
|
// special needs here. Need to step into inline containers but not block
|
|
|
|
// containers.
|
2017-11-01 05:41:03 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSet() && aBlockParent);
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2017-12-07 09:45:52 +00:00
|
|
|
if (aPoint.IsInTextNode()) {
|
|
|
|
return GetNextWSNodeInner(aPoint.GetContainer(), aBlockParent);
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2017-12-07 09:45:52 +00:00
|
|
|
if (!mHTMLEditor->IsContainer(aPoint.GetContainer())) {
|
|
|
|
return GetNextWSNodeInner(aPoint.GetContainer(), aBlockParent);
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
|
2017-12-07 09:45:52 +00:00
|
|
|
if (NS_WARN_IF(!aPoint.GetContainerAsContent())) {
|
2017-11-01 05:41:03 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
|
2017-12-07 10:08:56 +00:00
|
|
|
nsCOMPtr<nsIContent> nextNode = aPoint.GetChild();
|
2014-10-22 12:45:30 +00:00
|
|
|
if (!nextNode) {
|
2017-12-07 09:45:52 +00:00
|
|
|
if (aPoint.GetContainer() == aBlockParent) {
|
2014-10-22 12:45:30 +00:00
|
|
|
// We are at end of the block.
|
|
|
|
return nullptr;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2003-09-27 04:18:26 +00:00
|
|
|
|
2014-10-22 12:45:30 +00:00
|
|
|
// We are at end of non-block container
|
2017-12-07 09:45:52 +00:00
|
|
|
return GetNextWSNodeInner(aPoint.GetContainer(), aBlockParent);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
|
|
|
|
// We have a next node. If it's a block, return it.
|
|
|
|
if (IsBlockNode(nextNode)) {
|
|
|
|
return nextNode;
|
|
|
|
}
|
|
|
|
if (mHTMLEditor->IsContainer(nextNode)) {
|
2014-05-02 11:11:26 +00:00
|
|
|
// else if it's a container, get deep leftmost child
|
2014-10-22 12:45:30 +00:00
|
|
|
nsCOMPtr<nsIContent> child = mHTMLEditor->GetLeftmostChild(nextNode);
|
|
|
|
if (child) {
|
|
|
|
return child;
|
2014-05-02 11:11:26 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2014-10-22 12:45:30 +00:00
|
|
|
// Else return the node itself
|
|
|
|
return nextNode;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject) {
|
2001-05-10 11:55:49 +00:00
|
|
|
// this routine adjust whitespace before *this* and after aEndObject
|
2015-05-28 15:58:42 +00:00
|
|
|
// in preperation for the two areas to become adjacent after the
|
2001-05-10 11:55:49 +00:00
|
|
|
// intervening content is deleted. It's overly agressive right
|
|
|
|
// now. There might be a block boundary remaining between them after
|
|
|
|
// the deletion, in which case these adjstments are unneeded (though
|
|
|
|
// I don't think they can ever be harmful?)
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2010-06-17 20:40:48 +00:00
|
|
|
NS_ENSURE_TRUE(aEndObject, NS_ERROR_NULL_POINTER);
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-05-10 11:55:49 +00:00
|
|
|
// get the runs before and after selection
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSFragment* beforeRun = FindNearestRun(mScanStartPoint, false);
|
|
|
|
WSFragment* afterRun =
|
|
|
|
aEndObject->FindNearestRun(aEndObject->mScanStartPoint, true);
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-05-10 11:55:49 +00:00
|
|
|
// trim after run of any leading ws
|
2012-07-13 06:33:43 +00:00
|
|
|
if (afterRun && (afterRun->mType & WSType::leadingWS)) {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
nsresult rv = aEndObject->DeleteRange(aEndObject->mScanStartPoint,
|
|
|
|
afterRun->EndPoint());
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
// adjust normal ws in afterRun if needed
|
2012-07-13 06:33:43 +00:00
|
|
|
if (afterRun && afterRun->mType == WSType::normalWS && !aEndObject->mPRE) {
|
|
|
|
if ((beforeRun && (beforeRun->mType & WSType::leadingWS)) ||
|
|
|
|
(!beforeRun &&
|
|
|
|
((mStartReason & WSType::block) || mStartReason == WSType::br))) {
|
2001-05-10 11:55:49 +00:00
|
|
|
// make sure leading char of following ws is an nbsp, so that it will show
|
|
|
|
// up
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = aEndObject->GetNextCharPoint(aEndObject->mScanStartPoint);
|
2016-10-24 02:27:45 +00:00
|
|
|
if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
nsresult rv =
|
|
|
|
aEndObject->InsertNBSPAndRemoveFollowingASCIIWhitespaces(point);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// trim before run of any trailing ws
|
2012-07-13 06:33:43 +00:00
|
|
|
if (beforeRun && (beforeRun->mType & WSType::trailingWS)) {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
nsresult rv = DeleteRange(beforeRun->StartPoint(), mScanStartPoint);
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2012-07-13 06:33:43 +00:00
|
|
|
} else if (beforeRun && beforeRun->mType == WSType::normalWS && !mPRE) {
|
|
|
|
if ((afterRun && (afterRun->mType & WSType::trailingWS)) ||
|
|
|
|
(afterRun && afterRun->mType == WSType::normalWS) ||
|
|
|
|
(!afterRun && (aEndObject->mEndReason & WSType::block))) {
|
2001-05-10 11:55:49 +00:00
|
|
|
// make sure trailing char of starting ws is an nbsp, so that it will show
|
|
|
|
// up
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = GetPreviousCharPoint(mScanStartPoint);
|
2016-10-24 02:27:45 +00:00
|
|
|
if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> wsStartNode, wsEndNode;
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t wsStartOffset, wsEndOffset;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
GetASCIIWhitespacesBounds(eBoth, mScanStartPoint,
|
2017-12-21 10:27:31 +00:00
|
|
|
getter_AddRefs(wsStartNode), &wsStartOffset,
|
|
|
|
getter_AddRefs(wsEndNode), &wsEndOffset);
|
2014-05-02 12:15:27 +00:00
|
|
|
point.mTextNode = wsStartNode;
|
2001-05-10 11:55:49 +00:00
|
|
|
point.mOffset = wsStartOffset;
|
2017-12-21 10:27:31 +00:00
|
|
|
nsresult rv = InsertNBSPAndRemoveFollowingASCIIWhitespaces(point);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-19 09:09:33 +00:00
|
|
|
return NS_OK;
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::PrepareToSplitAcrossBlocksPriv() {
|
2015-05-28 15:58:42 +00:00
|
|
|
// used to prepare ws to be split across two blocks. The main issue
|
2001-05-11 12:43:22 +00:00
|
|
|
// here is make sure normalWS doesn't end up becoming non-significant
|
|
|
|
// leading or trailing ws after the split.
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-05-11 12:43:22 +00:00
|
|
|
// get the runs before and after selection
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSFragment* beforeRun = FindNearestRun(mScanStartPoint, false);
|
|
|
|
WSFragment* afterRun = FindNearestRun(mScanStartPoint, true);
|
2015-05-28 15:58:42 +00:00
|
|
|
|
2001-05-11 12:43:22 +00:00
|
|
|
// adjust normal ws in afterRun if needed
|
2012-07-13 06:33:43 +00:00
|
|
|
if (afterRun && afterRun->mType == WSType::normalWS) {
|
2001-05-11 12:43:22 +00:00
|
|
|
// make sure leading char of following ws is an nbsp, so that it will show
|
|
|
|
// up
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = GetNextCharPoint(mScanStartPoint);
|
2016-10-24 02:27:45 +00:00
|
|
|
if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
|
2017-12-21 10:27:31 +00:00
|
|
|
nsresult rv = InsertNBSPAndRemoveFollowingASCIIWhitespaces(point);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// adjust normal ws in beforeRun if needed
|
2012-07-13 06:33:43 +00:00
|
|
|
if (beforeRun && beforeRun->mType == WSType::normalWS) {
|
2001-05-11 12:43:22 +00:00
|
|
|
// make sure trailing char of starting ws is an nbsp, so that it will show
|
|
|
|
// up
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = GetPreviousCharPoint(mScanStartPoint);
|
2016-10-24 02:27:45 +00:00
|
|
|
if (point.mTextNode && nsCRT::IsAsciiSpace(point.mChar)) {
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> wsStartNode, wsEndNode;
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t wsStartOffset, wsEndOffset;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
GetASCIIWhitespacesBounds(eBoth, mScanStartPoint,
|
2017-12-21 10:27:31 +00:00
|
|
|
getter_AddRefs(wsStartNode), &wsStartOffset,
|
|
|
|
getter_AddRefs(wsEndNode), &wsEndOffset);
|
2014-05-02 12:15:27 +00:00
|
|
|
point.mTextNode = wsStartNode;
|
2001-05-11 12:43:22 +00:00
|
|
|
point.mOffset = wsStartOffset;
|
2017-12-21 10:27:31 +00:00
|
|
|
nsresult rv = InsertNBSPAndRemoveFollowingASCIIWhitespaces(point);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
|
|
|
}
|
2016-10-19 09:09:33 +00:00
|
|
|
return NS_OK;
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
|
|
|
|
2019-05-08 09:40:17 +00:00
|
|
|
nsresult WSRunObject::DeleteRange(const EditorDOMPoint& aStartPoint,
|
|
|
|
const EditorDOMPoint& aEndPoint) {
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(!aStartPoint.IsSet()) || NS_WARN_IF(!aEndPoint.IsSet())) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(aStartPoint.IsSetAndValid());
|
|
|
|
MOZ_ASSERT(aEndPoint.IsSetAndValid());
|
|
|
|
|
2001-04-28 12:04:45 +00:00
|
|
|
// MOOSE: this routine needs to be modified to preserve the integrity of the
|
|
|
|
// wsFragment info.
|
2001-05-10 11:55:49 +00:00
|
|
|
|
2017-11-21 16:00:35 +00:00
|
|
|
if (aStartPoint == aEndPoint) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Nothing to delete
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2018-04-10 07:23:54 +00:00
|
|
|
MOZ_ASSERT(mHTMLEditor);
|
|
|
|
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
|
|
|
|
2017-12-07 09:45:52 +00:00
|
|
|
if (aStartPoint.GetContainer() == aEndPoint.GetContainer() &&
|
|
|
|
aStartPoint.IsInTextNode()) {
|
2019-05-08 06:31:48 +00:00
|
|
|
RefPtr<Text> textNode = aStartPoint.GetContainerAsText();
|
2018-04-10 07:50:06 +00:00
|
|
|
return htmlEditor->DeleteTextWithTransaction(
|
2019-05-08 06:31:48 +00:00
|
|
|
*textNode, aStartPoint.Offset(),
|
2018-04-10 07:50:06 +00:00
|
|
|
aEndPoint.Offset() - aStartPoint.Offset());
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<nsRange> range;
|
2014-05-02 12:15:27 +00:00
|
|
|
int32_t count = mNodeArray.Length();
|
2017-12-07 09:45:52 +00:00
|
|
|
int32_t idx = mNodeArray.IndexOf(aStartPoint.GetContainer());
|
2017-11-21 16:00:35 +00:00
|
|
|
if (idx == -1) {
|
|
|
|
// If our starting point wasn't one of our ws text nodes, then just go
|
|
|
|
// through them from the beginning.
|
|
|
|
idx = 0;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
for (; idx < count; idx++) {
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> node = mNodeArray[idx];
|
2014-05-02 12:15:27 +00:00
|
|
|
if (!node) {
|
|
|
|
// We ran out of ws nodes; must have been deleting to end
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2017-12-07 09:45:52 +00:00
|
|
|
if (node == aStartPoint.GetContainer()) {
|
2017-11-21 16:00:35 +00:00
|
|
|
if (!aStartPoint.IsEndOfContainer()) {
|
2018-04-10 07:50:06 +00:00
|
|
|
nsresult rv = htmlEditor->DeleteTextWithTransaction(
|
|
|
|
*node, aStartPoint.Offset(),
|
|
|
|
aStartPoint.GetContainer()->Length() - aStartPoint.Offset());
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
2017-12-07 09:45:52 +00:00
|
|
|
} else if (node == aEndPoint.GetContainer()) {
|
2017-11-21 16:00:35 +00:00
|
|
|
if (!aEndPoint.IsStartOfContainer()) {
|
2018-04-10 07:50:06 +00:00
|
|
|
nsresult rv =
|
|
|
|
htmlEditor->DeleteTextWithTransaction(*node, 0, aEndPoint.Offset());
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
break;
|
2014-05-02 12:15:27 +00:00
|
|
|
} else {
|
|
|
|
if (!range) {
|
2017-12-07 09:45:52 +00:00
|
|
|
range = new nsRange(aStartPoint.GetContainer());
|
2017-11-21 16:00:35 +00:00
|
|
|
nsresult rv = range->SetStartAndEnd(aStartPoint, aEndPoint);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2011-09-29 06:19:26 +00:00
|
|
|
bool nodeBefore, nodeAfter;
|
2016-10-19 09:09:33 +00:00
|
|
|
nsresult rv =
|
|
|
|
nsRange::CompareNodeToRange(node, range, &nodeBefore, &nodeAfter);
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
if (nodeAfter) {
|
2001-04-28 12:04:45 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
if (!nodeBefore) {
|
2018-04-10 07:23:54 +00:00
|
|
|
rv = htmlEditor->DeleteNodeWithTransaction(*node);
|
2017-11-21 16:00:35 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
mNodeArray.RemoveElement(node);
|
2003-01-16 19:27:50 +00:00
|
|
|
--count;
|
|
|
|
--idx;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
return NS_OK;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
template <typename PT, typename CT>
|
2018-08-14 09:26:46 +00:00
|
|
|
WSRunObject::WSPoint WSRunObject::GetNextCharPoint(
|
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSetAndValid());
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2017-12-07 09:45:52 +00:00
|
|
|
int32_t idx = mNodeArray.IndexOf(aPoint.GetContainer());
|
2014-05-02 12:15:27 +00:00
|
|
|
if (idx == -1) {
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
// Use range comparisons to get next text node which is in mNodeArray.
|
|
|
|
return GetNextCharPointInternal(aPoint);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
// Use WSPoint version of GetNextCharPoint()
|
|
|
|
return GetNextCharPoint(WSPoint(mNodeArray[idx], aPoint.Offset(), 0));
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
template <typename PT, typename CT>
|
2018-08-14 09:26:46 +00:00
|
|
|
WSRunObject::WSPoint WSRunObject::GetPreviousCharPoint(
|
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSetAndValid());
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2017-12-07 09:45:52 +00:00
|
|
|
int32_t idx = mNodeArray.IndexOf(aPoint.GetContainer());
|
2014-05-02 12:15:27 +00:00
|
|
|
if (idx == -1) {
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
// Use range comparisons to get previous text node which is in mNodeArray.
|
|
|
|
return GetPreviousCharPointInternal(aPoint);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
// Use WSPoint version of GetPreviousCharPoint()
|
|
|
|
return GetPreviousCharPoint(WSPoint(mNodeArray[idx], aPoint.Offset(), 0));
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-14 09:26:46 +00:00
|
|
|
WSRunObject::WSPoint WSRunObject::GetNextCharPoint(
|
|
|
|
const WSPoint& aPoint) const {
|
2012-06-01 11:03:17 +00:00
|
|
|
MOZ_ASSERT(aPoint.mTextNode);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2012-06-01 11:03:17 +00:00
|
|
|
WSPoint outPoint;
|
2012-07-30 14:20:58 +00:00
|
|
|
outPoint.mTextNode = nullptr;
|
2012-06-01 11:03:17 +00:00
|
|
|
outPoint.mOffset = 0;
|
|
|
|
outPoint.mChar = 0;
|
2002-11-12 19:40:11 +00:00
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
int32_t idx = mNodeArray.IndexOf(aPoint.mTextNode);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (idx == -1) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Can't find point, but it's not an error
|
2012-06-01 11:03:17 +00:00
|
|
|
return outPoint;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2016-10-24 02:27:45 +00:00
|
|
|
if (static_cast<uint16_t>(aPoint.mOffset) < aPoint.mTextNode->TextLength()) {
|
2012-06-01 11:03:17 +00:00
|
|
|
outPoint = aPoint;
|
|
|
|
outPoint.mChar = GetCharAt(aPoint.mTextNode, aPoint.mOffset);
|
|
|
|
return outPoint;
|
2016-10-24 02:27:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int32_t numNodes = mNodeArray.Length();
|
|
|
|
if (idx + 1 < numNodes) {
|
2014-05-02 12:15:27 +00:00
|
|
|
outPoint.mTextNode = mNodeArray[idx + 1];
|
2014-05-02 12:15:27 +00:00
|
|
|
MOZ_ASSERT(outPoint.mTextNode);
|
2012-06-01 11:03:17 +00:00
|
|
|
outPoint.mOffset = 0;
|
|
|
|
outPoint.mChar = GetCharAt(outPoint.mTextNode, 0);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2016-10-24 02:27:45 +00:00
|
|
|
|
2012-06-01 11:03:17 +00:00
|
|
|
return outPoint;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-14 09:26:46 +00:00
|
|
|
WSRunObject::WSPoint WSRunObject::GetPreviousCharPoint(
|
|
|
|
const WSPoint& aPoint) const {
|
2012-06-01 11:03:17 +00:00
|
|
|
MOZ_ASSERT(aPoint.mTextNode);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2012-06-01 11:03:17 +00:00
|
|
|
WSPoint outPoint;
|
2012-07-30 14:20:58 +00:00
|
|
|
outPoint.mTextNode = nullptr;
|
2012-06-01 11:03:17 +00:00
|
|
|
outPoint.mOffset = 0;
|
|
|
|
outPoint.mChar = 0;
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
int32_t idx = mNodeArray.IndexOf(aPoint.mTextNode);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (idx == -1) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Can't find point, but it's not an error
|
2012-06-01 11:03:17 +00:00
|
|
|
return outPoint;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2016-10-24 02:27:45 +00:00
|
|
|
if (aPoint.mOffset) {
|
2012-06-01 11:03:17 +00:00
|
|
|
outPoint = aPoint;
|
|
|
|
outPoint.mOffset--;
|
2014-05-02 12:15:27 +00:00
|
|
|
outPoint.mChar = GetCharAt(aPoint.mTextNode, aPoint.mOffset - 1);
|
2012-06-01 11:03:17 +00:00
|
|
|
return outPoint;
|
2016-10-24 02:27:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (idx) {
|
2014-05-02 12:15:27 +00:00
|
|
|
outPoint.mTextNode = mNodeArray[idx - 1];
|
2004-05-07 20:55:17 +00:00
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
uint32_t len = outPoint.mTextNode->TextLength();
|
2014-05-02 12:15:27 +00:00
|
|
|
if (len) {
|
|
|
|
outPoint.mOffset = len - 1;
|
|
|
|
outPoint.mChar = GetCharAt(outPoint.mTextNode, len - 1);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-01 11:03:17 +00:00
|
|
|
return outPoint;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2017-12-21 10:27:31 +00:00
|
|
|
nsresult WSRunObject::InsertNBSPAndRemoveFollowingASCIIWhitespaces(
|
|
|
|
WSPoint aPoint) {
|
2001-04-28 12:04:45 +00:00
|
|
|
// MOOSE: this routine needs to be modified to preserve the integrity of the
|
|
|
|
// wsFragment info.
|
2017-12-21 10:27:31 +00:00
|
|
|
if (NS_WARN_IF(!aPoint.mTextNode)) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2018-08-01 12:30:14 +00:00
|
|
|
if (NS_WARN_IF(!mHTMLEditor)) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
|
|
|
|
|
|
|
// First, insert an NBSP.
|
|
|
|
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
|
|
|
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
|
2019-05-07 10:58:08 +00:00
|
|
|
nsDependentSubstring(&kNBSP, 1), MOZ_KnownLive(*aPoint.mTextNode),
|
|
|
|
aPoint.mOffset, true);
|
2017-12-21 10:27:31 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now, the text node may have been modified by mutation observer.
|
|
|
|
// So, the NBSP may have gone.
|
|
|
|
if (aPoint.mTextNode->TextDataLength() <= aPoint.mOffset ||
|
2019-05-22 05:18:48 +00:00
|
|
|
aPoint.mTextNode->TextFragment().CharAt(aPoint.mOffset) != kNBSP) {
|
2017-12-21 10:27:31 +00:00
|
|
|
// This is just preparation of an edit action. Let's return NS_OK.
|
|
|
|
// XXX Perhaps, we should return another success code which indicates
|
|
|
|
// mutation observer touched the DOM tree. However, that should
|
|
|
|
// be returned from each transaction's DoTransaction.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2017-12-21 10:27:31 +00:00
|
|
|
// Next, find range of whitespaces it will be replaced.
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> startNode, endNode;
|
2014-05-02 12:15:27 +00:00
|
|
|
int32_t startOffset = 0, endOffset = 0;
|
|
|
|
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
GetASCIIWhitespacesBounds(
|
|
|
|
eAfter, EditorRawDOMPoint(aPoint.mTextNode, aPoint.mOffset + 1),
|
|
|
|
getter_AddRefs(startNode), &startOffset, getter_AddRefs(endNode),
|
|
|
|
&endOffset);
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Finally, delete that replaced ws, if any
|
|
|
|
if (startNode) {
|
2017-11-21 16:00:35 +00:00
|
|
|
rv = DeleteRange(EditorRawDOMPoint(startNode, startOffset),
|
|
|
|
EditorRawDOMPoint(endNode, endOffset));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
template <typename PT, typename CT>
|
2017-12-21 10:27:31 +00:00
|
|
|
void WSRunObject::GetASCIIWhitespacesBounds(
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
int16_t aDir, const EditorDOMPointBase<PT, CT>& aPoint, Text** outStartNode,
|
2017-12-21 10:27:31 +00:00
|
|
|
int32_t* outStartOffset, Text** outEndNode, int32_t* outEndOffset) {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSet());
|
|
|
|
MOZ_ASSERT(outStartNode);
|
|
|
|
MOZ_ASSERT(outStartOffset);
|
|
|
|
MOZ_ASSERT(outEndNode);
|
|
|
|
MOZ_ASSERT(outEndOffset);
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> startNode, endNode;
|
2014-05-02 12:15:27 +00:00
|
|
|
int32_t startOffset = 0, endOffset = 0;
|
2001-05-10 11:55:49 +00:00
|
|
|
|
2014-05-02 12:15:27 +00:00
|
|
|
if (aDir & eAfter) {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = GetNextCharPoint(aPoint);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (point.mTextNode) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// We found a text node, at least
|
|
|
|
startNode = endNode = point.mTextNode;
|
|
|
|
startOffset = endOffset = point.mOffset;
|
|
|
|
|
|
|
|
// Scan ahead to end of ASCII ws
|
|
|
|
for (; nsCRT::IsAsciiSpace(point.mChar) && point.mTextNode;
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
point = GetNextCharPoint(point)) {
|
2014-05-02 12:15:27 +00:00
|
|
|
endNode = point.mTextNode;
|
|
|
|
// endOffset is _after_ ws
|
|
|
|
point.mOffset++;
|
2001-05-10 11:55:49 +00:00
|
|
|
endOffset = point.mOffset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
if (aDir & eBefore) {
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
WSPoint point = GetPreviousCharPoint(aPoint);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (point.mTextNode) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// We found a text node, at least
|
|
|
|
startNode = point.mTextNode;
|
|
|
|
startOffset = point.mOffset + 1;
|
|
|
|
if (!endNode) {
|
2001-05-10 11:55:49 +00:00
|
|
|
endNode = startNode;
|
|
|
|
endOffset = startOffset;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Scan back to start of ASCII ws
|
|
|
|
for (; nsCRT::IsAsciiSpace(point.mChar) && point.mTextNode;
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
point = GetPreviousCharPoint(point)) {
|
2014-05-02 12:15:27 +00:00
|
|
|
startNode = point.mTextNode;
|
2001-05-10 11:55:49 +00:00
|
|
|
startOffset = point.mOffset;
|
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
startNode.forget(outStartNode);
|
2001-05-10 11:55:49 +00:00
|
|
|
*outStartOffset = startOffset;
|
2014-05-02 12:15:27 +00:00
|
|
|
endNode.forget(outEndNode);
|
2001-05-10 11:55:49 +00:00
|
|
|
*outEndOffset = endOffset;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
template <typename PT, typename CT>
|
|
|
|
WSRunObject::WSFragment* WSRunObject::FindNearestRun(
|
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint, bool aForward) const {
|
2017-11-21 10:03:03 +00:00
|
|
|
MOZ_ASSERT(aPoint.IsSetAndValid());
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
for (WSFragment* run = mStartRun; run; run = run->mRight) {
|
2017-11-21 10:03:03 +00:00
|
|
|
int32_t comp = run->mStartNode ? nsContentUtils::ComparePoints(
|
|
|
|
aPoint, run->StartPoint())
|
|
|
|
: -1;
|
2014-05-02 12:15:27 +00:00
|
|
|
if (comp <= 0) {
|
2017-11-21 10:03:03 +00:00
|
|
|
// aPoint equals or before start of the run. Return the run if we're
|
|
|
|
// scanning forward, otherwise, nullptr.
|
|
|
|
return aForward ? run : nullptr;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2017-11-21 10:03:03 +00:00
|
|
|
|
|
|
|
comp = run->mEndNode
|
|
|
|
? nsContentUtils::ComparePoints(aPoint, run->EndPoint())
|
|
|
|
: -1;
|
2014-05-02 12:15:27 +00:00
|
|
|
if (comp < 0) {
|
2017-11-21 10:03:03 +00:00
|
|
|
// If aPoint is in the run, return the run.
|
|
|
|
return run;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!comp) {
|
|
|
|
// If aPoint is at end of the run, return next run if we're scanning
|
|
|
|
// forward, otherwise, return the run.
|
|
|
|
return aForward ? run->mRight : run;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2017-11-21 10:03:03 +00:00
|
|
|
|
2014-05-02 12:15:27 +00:00
|
|
|
if (!run->mRight) {
|
2017-11-21 10:03:03 +00:00
|
|
|
// If the run is the last run and aPoint is after end of the last run,
|
|
|
|
// return nullptr if we're scanning forward, otherwise, return this
|
|
|
|
// last run.
|
|
|
|
return aForward ? nullptr : run;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
}
|
2017-11-21 10:03:03 +00:00
|
|
|
|
|
|
|
return nullptr;
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
char16_t WSRunObject::GetCharAt(Text* aTextNode, int32_t aOffset) const {
|
2001-04-28 12:04:45 +00:00
|
|
|
// return 0 if we can't get a char, for whatever reason
|
2010-06-17 20:40:48 +00:00
|
|
|
NS_ENSURE_TRUE(aTextNode, 0);
|
2006-07-19 04:36:36 +00:00
|
|
|
|
2019-05-22 05:18:48 +00:00
|
|
|
int32_t len = int32_t(aTextNode->TextDataLength());
|
2016-10-24 02:27:45 +00:00
|
|
|
if (aOffset < 0 || aOffset >= len) {
|
2001-04-28 12:04:45 +00:00
|
|
|
return 0;
|
2016-10-24 02:27:45 +00:00
|
|
|
}
|
2019-05-22 05:18:48 +00:00
|
|
|
return aTextNode->TextFragment().CharAt(aOffset);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
template <typename PT, typename CT>
|
2018-08-14 09:26:46 +00:00
|
|
|
WSRunObject::WSPoint WSRunObject::GetNextCharPointInternal(
|
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
2017-12-07 09:45:52 +00:00
|
|
|
// Note: only to be called if aPoint.GetContainer() is not a ws node.
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Binary search on wsnodes
|
|
|
|
uint32_t numNodes = mNodeArray.Length();
|
|
|
|
|
2012-06-01 11:03:17 +00:00
|
|
|
if (!numNodes) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Do nothing if there are no nodes to search
|
2012-06-01 11:03:17 +00:00
|
|
|
WSPoint outPoint;
|
|
|
|
return outPoint;
|
|
|
|
}
|
2006-08-08 00:22:52 +00:00
|
|
|
|
2014-05-02 12:15:27 +00:00
|
|
|
// Begin binary search. We do this because we need to minimize calls to
|
|
|
|
// ComparePoints(), which is expensive.
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
uint32_t firstNum = 0, curNum = numNodes / 2, lastNum = numNodes;
|
2014-05-02 12:15:27 +00:00
|
|
|
while (curNum != lastNum) {
|
2018-08-14 09:26:46 +00:00
|
|
|
Text* curNode = mNodeArray[curNum];
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
int16_t cmp =
|
|
|
|
nsContentUtils::ComparePoints(aPoint, EditorRawDOMPoint(curNode, 0));
|
2014-05-02 12:15:27 +00:00
|
|
|
if (cmp < 0) {
|
2006-08-08 00:22:52 +00:00
|
|
|
lastNum = curNum;
|
2014-05-02 12:15:27 +00:00
|
|
|
} else {
|
2006-08-08 00:22:52 +00:00
|
|
|
firstNum = curNum + 1;
|
2014-05-02 12:15:27 +00:00
|
|
|
}
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
curNum = (lastNum - firstNum) / 2 + firstNum;
|
2014-05-02 12:15:27 +00:00
|
|
|
MOZ_ASSERT(firstNum <= curNum && curNum <= lastNum, "Bad binary search");
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2006-08-08 00:22:52 +00:00
|
|
|
|
|
|
|
// When the binary search is complete, we always know that the current node
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
// is the same as the end node, which is always past our range. Therefore,
|
2006-08-08 00:22:52 +00:00
|
|
|
// we've found the node immediately after the point of interest.
|
2014-05-02 12:15:27 +00:00
|
|
|
if (curNum == mNodeArray.Length()) {
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
// hey asked for past our range (it's after the last node).
|
|
|
|
// GetNextCharPoint() will do the work for us when we pass it the last
|
|
|
|
// index of the last node.
|
2018-08-14 09:26:46 +00:00
|
|
|
Text* textNode = mNodeArray[curNum - 1];
|
2004-05-07 20:55:17 +00:00
|
|
|
WSPoint point(textNode, textNode->TextLength(), 0);
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
return GetNextCharPoint(point);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
|
|
|
|
// The char after the point is the first character of our range.
|
2018-08-14 09:26:46 +00:00
|
|
|
Text* textNode = mNodeArray[curNum];
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint point(textNode, 0, 0);
|
|
|
|
return GetNextCharPoint(point);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 09:23:50 +00:00
|
|
|
template <typename PT, typename CT>
|
|
|
|
WSRunObject::WSPoint WSRunObject::GetPreviousCharPointInternal(
|
2018-08-14 09:26:46 +00:00
|
|
|
const EditorDOMPointBase<PT, CT>& aPoint) const {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Note: only to be called if aNode is not a ws node.
|
|
|
|
|
|
|
|
// Binary search on wsnodes
|
|
|
|
uint32_t numNodes = mNodeArray.Length();
|
|
|
|
|
2012-06-01 11:03:17 +00:00
|
|
|
if (!numNodes) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Do nothing if there are no nodes to search
|
2012-06-01 11:03:17 +00:00
|
|
|
WSPoint outPoint;
|
|
|
|
return outPoint;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
uint32_t firstNum = 0, curNum = numNodes / 2, lastNum = numNodes;
|
|
|
|
int16_t cmp = 0;
|
|
|
|
|
|
|
|
// Begin binary search. We do this because we need to minimize calls to
|
|
|
|
// ComparePoints(), which is expensive.
|
|
|
|
while (curNum != lastNum) {
|
2018-08-14 09:26:46 +00:00
|
|
|
Text* curNode = mNodeArray[curNum];
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
cmp = nsContentUtils::ComparePoints(aPoint, EditorRawDOMPoint(curNode, 0));
|
2014-05-02 12:15:27 +00:00
|
|
|
if (cmp < 0) {
|
2006-08-08 00:22:52 +00:00
|
|
|
lastNum = curNum;
|
2014-05-02 12:15:27 +00:00
|
|
|
} else {
|
2006-08-08 00:22:52 +00:00
|
|
|
firstNum = curNum + 1;
|
2014-05-02 12:15:27 +00:00
|
|
|
}
|
|
|
|
curNum = (lastNum - firstNum) / 2 + firstNum;
|
|
|
|
MOZ_ASSERT(firstNum <= curNum && curNum <= lastNum, "Bad binary search");
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
2006-08-08 00:22:52 +00:00
|
|
|
|
|
|
|
// When the binary search is complete, we always know that the current node
|
|
|
|
// is the same as the end node, which is always past our range. Therefore,
|
|
|
|
// we've found the node immediately after the point of interest.
|
2014-05-02 12:15:27 +00:00
|
|
|
if (curNum == mNodeArray.Length()) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Get the point before the end of the last node, we can pass the length of
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
// the node into GetPreviousCharPoint(), and it will return the last
|
|
|
|
// character.
|
2018-08-14 09:26:46 +00:00
|
|
|
Text* textNode = mNodeArray[curNum - 1];
|
2004-05-07 20:55:17 +00:00
|
|
|
WSPoint point(textNode, textNode->TextLength(), 0);
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
return GetPreviousCharPoint(point);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
|
|
|
|
// We can just ask the current node for the point immediately before it,
|
|
|
|
// it will handle moving to the previous node (if any) and returning the
|
|
|
|
// appropriate character
|
2018-08-14 09:26:46 +00:00
|
|
|
Text* textNode = mNodeArray[curNum];
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint point(textNode, 0, 0);
|
|
|
|
return GetPreviousCharPoint(point);
|
2001-04-28 12:04:45 +00:00
|
|
|
}
|
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::CheckTrailingNBSPOfRun(WSFragment* aRun) {
|
2014-05-02 11:11:26 +00:00
|
|
|
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
|
|
|
// proliferation. Examine what is before and after the trailing nbsp, if
|
|
|
|
// any.
|
2010-06-17 19:41:16 +00:00
|
|
|
NS_ENSURE_TRUE(aRun, NS_ERROR_NULL_POINTER);
|
2011-09-29 06:19:26 +00:00
|
|
|
bool leftCheck = false;
|
|
|
|
bool spaceNBSP = false;
|
|
|
|
bool rightCheck = false;
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2001-05-11 12:43:22 +00:00
|
|
|
// confirm run is normalWS
|
2012-07-13 06:33:43 +00:00
|
|
|
if (aRun->mType != WSType::normalWS) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
|
2017-12-11 07:01:50 +00:00
|
|
|
if (NS_WARN_IF(!mHTMLEditor)) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
|
|
|
|
2001-05-11 12:43:22 +00:00
|
|
|
// first check for trailing nbsp
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint thePoint = GetPreviousCharPoint(aRun->EndPoint());
|
2017-12-21 10:27:31 +00:00
|
|
|
if (thePoint.mTextNode && thePoint.mChar == kNBSP) {
|
2001-05-11 12:43:22 +00:00
|
|
|
// now check that what is to the left of it is compatible with replacing
|
|
|
|
// nbsp with space
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint prevPoint = GetPreviousCharPoint(thePoint);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (prevPoint.mTextNode) {
|
2014-05-02 11:11:26 +00:00
|
|
|
if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) {
|
|
|
|
leftCheck = true;
|
|
|
|
} else {
|
|
|
|
spaceNBSP = true;
|
|
|
|
}
|
|
|
|
} else if (aRun->mLeftType == WSType::text ||
|
|
|
|
aRun->mLeftType == WSType::special) {
|
2012-07-13 06:33:43 +00:00
|
|
|
leftCheck = true;
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
if (leftCheck || spaceNBSP) {
|
|
|
|
// now check that what is to the right of it is compatible with replacing
|
|
|
|
// nbsp with space
|
|
|
|
if (aRun->mRightType == WSType::text ||
|
|
|
|
aRun->mRightType == WSType::special ||
|
|
|
|
aRun->mRightType == WSType::br) {
|
2012-07-13 06:33:43 +00:00
|
|
|
rightCheck = true;
|
|
|
|
}
|
|
|
|
if ((aRun->mRightType & WSType::block) &&
|
2016-05-01 18:29:23 +00:00
|
|
|
IsBlockNode(GetWSBoundingParent())) {
|
2018-04-16 10:21:29 +00:00
|
|
|
RefPtr<Selection> selection = htmlEditor->GetSelection();
|
|
|
|
if (NS_WARN_IF(!selection)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2014-05-02 11:11:26 +00:00
|
|
|
// We are at a block boundary. Insert a <br>. Why? Well, first note
|
|
|
|
// that the br will have no visible effect since it is up against a
|
|
|
|
// block boundary. |foo<br><p>bar| renders like |foo<p>bar| and
|
|
|
|
// similarly |<p>foo<br></p>bar| renders like |<p>foo</p>bar|. What
|
|
|
|
// this <br> addition gets us is the ability to convert a trailing nbsp
|
|
|
|
// to a space. Consider: |<body>foo. '</body>|, where ' represents
|
|
|
|
// selection. User types space attempting to put 2 spaces after the
|
|
|
|
// end of their sentence. We used to do this as: |<body>foo.
|
|
|
|
//  </body>| This caused problems with soft wrapping: the nbsp
|
|
|
|
// would wrap to the next line, which looked attrocious. If you try to
|
|
|
|
// do: |<body>foo.  </body>| instead, the trailing space is
|
|
|
|
// invisible because it is against a block boundary. If you do:
|
|
|
|
// |<body>foo.  </body>| then you get an even uglier soft
|
|
|
|
// wrapping problem, where foo is on one line until you type the final
|
|
|
|
// space, and then "foo " jumps down to the next line. Ugh. The best
|
|
|
|
// way I can find out of this is to throw in a harmless <br> here,
|
|
|
|
// which allows us to do: |<body>foo.  <br></body>|, which doesn't
|
|
|
|
// cause foo to jump lines, doesn't cause spaces to show up at the
|
|
|
|
// beginning of soft wrapped lines, and lets the user see 2 spaces when
|
|
|
|
// they type 2 spaces.
|
|
|
|
|
2018-04-16 10:21:29 +00:00
|
|
|
RefPtr<Element> brElement =
|
2018-10-30 10:01:38 +00:00
|
|
|
htmlEditor->InsertBrElementWithTransaction(aRun->EndPoint());
|
2018-04-16 10:21:29 +00:00
|
|
|
if (NS_WARN_IF(!brElement)) {
|
2017-12-11 07:01:50 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
|
|
|
|
// Refresh thePoint, prevPoint
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
thePoint = GetPreviousCharPoint(aRun->EndPoint());
|
|
|
|
prevPoint = GetPreviousCharPoint(thePoint);
|
2011-10-17 14:59:28 +00:00
|
|
|
rightCheck = true;
|
2002-11-17 01:25:30 +00:00
|
|
|
}
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
if (leftCheck && rightCheck) {
|
|
|
|
// Now replace nbsp with space. First, insert a space
|
2018-08-01 12:30:14 +00:00
|
|
|
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
2014-01-04 15:02:17 +00:00
|
|
|
nsAutoString spaceStr(char16_t(32));
|
2018-04-12 08:58:14 +00:00
|
|
|
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
|
2019-05-07 10:58:08 +00:00
|
|
|
spaceStr, MOZ_KnownLive(*thePoint.mTextNode), thePoint.mOffset, true);
|
2018-08-01 12:30:14 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
|
|
|
|
// Finally, delete that nbsp
|
2017-11-21 16:00:35 +00:00
|
|
|
rv = DeleteRange(
|
|
|
|
EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset + 1),
|
|
|
|
EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset + 2));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
} else if (!mPRE && spaceNBSP && rightCheck) {
|
|
|
|
// Don't mess with this preformatted for now. We have a run of ASCII
|
|
|
|
// whitespace (which will render as one space) followed by an nbsp (which
|
|
|
|
// is at the end of the whitespace run). Let's switch their order. This
|
|
|
|
// will ensure that if someone types two spaces after a sentence, and the
|
|
|
|
// editor softwraps at this point, the spaces won't be split across lines,
|
|
|
|
// which looks ugly and is bad for the moose.
|
|
|
|
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<Text> startNode, endNode;
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t startOffset, endOffset;
|
Bug 1530649 - Improve composition string handling which ends with whitespaces r=m_kato
If insertion string ends with ASCII whitespace and there is no following
content in the block, `HTMLEditRules::AdjustWhitespaces()` needs to insert
`<br>` element. It's called only by `HTMLEditRules::AfterEditInner()` and
that does only simple things with `WSRunObject`. Therefore, this moves the
code into `AfterEditInner()`.
For making it adjust the whitespaces, `HTMLEditRules::WillInsertText()` needs
to notify `AfterEditInner()` of dirty range with `mDocChangeRange`. Therefore,
this patch makes it set `mDocChangeRange` manually after inserting composition
string.
On the other hand, there is another bug. `WSRunObject` was designed to treat
only inserting text for `WSRunObject::InsertText()`. I.e., not designed to
treat replacing existing composition string with new string. Therefore,
`WSRunObject::InsertText()` adjusts whitespaces only around start of
composition string. Therefore, if composition string ends with an ASCII
whitespace, it's not replaced with NBSP and that causes:
- failing `WSRunObject::AdjustWhitespaces()` inserts `<br>` element at
`AfterEditInner()` of committing composition.
- then, next composition's first `WSRunObject::InsertText()` removes the
last whitespace due to not followed by `<br>` nor any other content.
Therefore, this patch makes `WSRunObject` takes 2 DOM points to be able to
treat replaced range.
In strictly speaking, the latter change require more changes and tests for
supporting replacement with any other methods. However, it's risky and out
of scope of this bug.
Differential Revision: https://phabricator.services.mozilla.com/D26423
--HG--
extra : moz-landing-system : lando
2019-04-09 05:28:38 +00:00
|
|
|
GetASCIIWhitespacesBounds(
|
|
|
|
eBoth, EditorRawDOMPoint(prevPoint.mTextNode, prevPoint.mOffset + 1),
|
|
|
|
getter_AddRefs(startNode), &startOffset, getter_AddRefs(endNode),
|
|
|
|
&endOffset);
|
2014-05-02 11:11:26 +00:00
|
|
|
|
|
|
|
// Delete that nbsp
|
2017-11-21 16:00:35 +00:00
|
|
|
nsresult rv = DeleteRange(
|
|
|
|
EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset),
|
|
|
|
EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset + 1));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-05-02 11:11:26 +00:00
|
|
|
|
|
|
|
// Finally, insert that nbsp before the ASCII ws run
|
2018-08-01 12:30:14 +00:00
|
|
|
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
2018-04-12 08:58:14 +00:00
|
|
|
rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
|
|
|
|
nsDependentSubstring(&kNBSP, 1), *startNode, startOffset, true);
|
2018-08-01 12:30:14 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2002-11-17 01:25:30 +00:00
|
|
|
}
|
2001-05-11 12:43:22 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-03-20 05:05:47 +00:00
|
|
|
nsresult WSRunObject::ReplacePreviousNBSPIfUnncessary(
|
2019-05-08 09:40:17 +00:00
|
|
|
WSFragment* aRun, const EditorDOMPoint& aPoint) {
|
2017-11-21 17:45:08 +00:00
|
|
|
if (NS_WARN_IF(!aRun) || NS_WARN_IF(!aPoint.IsSet())) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(aPoint.IsSetAndValid());
|
|
|
|
|
|
|
|
// Try to change an NBSP to a space, if possible, just to prevent NBSP
|
2014-05-02 12:15:27 +00:00
|
|
|
// proliferation. This routine is called when we are about to make this
|
|
|
|
// point in the ws abut an inserted break or text, so we don't have to worry
|
|
|
|
// about what is after it. What is after it now will end up after the
|
|
|
|
// inserted object.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool canConvert = false;
|
2017-11-21 17:45:08 +00:00
|
|
|
WSPoint thePoint = GetPreviousCharPoint(aPoint);
|
2017-12-21 10:27:31 +00:00
|
|
|
if (thePoint.mTextNode && thePoint.mChar == kNBSP) {
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint prevPoint = GetPreviousCharPoint(thePoint);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (prevPoint.mTextNode) {
|
2014-05-02 12:15:27 +00:00
|
|
|
if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) {
|
2017-11-21 17:45:08 +00:00
|
|
|
// If previous character is a NBSP and its previous character isn't
|
|
|
|
// ASCII space, we can replace the NBSP with ASCII space.
|
2014-05-02 12:15:27 +00:00
|
|
|
canConvert = true;
|
|
|
|
}
|
|
|
|
} else if (aRun->mLeftType == WSType::text ||
|
|
|
|
aRun->mLeftType == WSType::special) {
|
2017-11-21 17:45:08 +00:00
|
|
|
// If previous character is a NBSP and it's the first character of the
|
|
|
|
// text node, additionally, if its previous node is a text node including
|
|
|
|
// non-whitespace characters or <img> node or something inline
|
|
|
|
// non-container element node, we can replace the NBSP with ASCII space.
|
2012-07-13 06:33:43 +00:00
|
|
|
canConvert = true;
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
2017-11-21 17:45:08 +00:00
|
|
|
if (!canConvert) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-08-01 12:30:14 +00:00
|
|
|
if (NS_WARN_IF(!mHTMLEditor)) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
|
|
|
|
2017-11-21 17:45:08 +00:00
|
|
|
// First, insert a space before the previous NBSP.
|
2018-08-01 12:30:14 +00:00
|
|
|
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
2017-11-21 17:45:08 +00:00
|
|
|
nsAutoString spaceStr(char16_t(32));
|
2018-08-01 12:30:14 +00:00
|
|
|
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
|
2019-05-07 10:58:08 +00:00
|
|
|
spaceStr, MOZ_KnownLive(*thePoint.mTextNode), thePoint.mOffset, true);
|
2017-11-21 17:45:08 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, delete the previous NBSP.
|
|
|
|
rv = DeleteRange(EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset + 1),
|
|
|
|
EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset + 2));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-04-28 12:04:45 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
|
|
|
|
int32_t aOffset) {
|
2014-05-02 12:15:27 +00:00
|
|
|
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
|
|
|
// proliferation This routine is called when we are about to make this point
|
|
|
|
// in the ws abut an inserted text, so we don't have to worry about what is
|
|
|
|
// before it. What is before it now will end up before the inserted text.
|
2011-09-29 06:19:26 +00:00
|
|
|
bool canConvert = false;
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint thePoint = GetNextCharPoint(EditorRawDOMPoint(aNode, aOffset));
|
2017-12-21 10:27:31 +00:00
|
|
|
if (thePoint.mChar == kNBSP) {
|
2012-06-01 11:03:17 +00:00
|
|
|
WSPoint tmp = thePoint;
|
2014-05-02 12:15:27 +00:00
|
|
|
// we want to be after thePoint
|
|
|
|
tmp.mOffset++;
|
Bug 1408227 - part 5: Redesign GetCharAfter(), GetCharBefore(), GetWSPointAfter() and GetWSPointBefore() of WSRunObject r=m_kato
WSRunObject::GetChar(After|Before)(nsINode*, int32_t) returns next/previous
character's DOM point as WSPoint. If the container node is a text node in
mNodeArray, it calls WSRunObject::GetChar(After|Before)(const WSPoint&) which
returns next/previous offset if the point isn't end/start of the text node.
If the point is at end/start of the text node, it returns start/end of
next/previous text node in mNodeArray. If the container node is not a text
node in mNodeArray, it calls WSRunObject::GetWSPoint(After|Before)(). It looks
for next/previous text node in mNodeArray from the point. Then, it calls
WSRunObject::GetChar(After|Before)(const WSPoint&) and returns the result.
So, we should rename GetCharAfter() to GetNextCharPoint(), GetCharBefore() to
GetPreviousCharPoint(), GetWSPointAfter() to GetNextCharPointInternal() and
GetWSPointBefore() to GetPreviousCharPointInternal().
Then, they should take |const EditorRawDOMPoint&| instead of a set of container
node and offset in it.
So, looks like that "WS"RunObject is not good name for this class, perhaps,
AutoTextRunManager or something? But I'm still not sure.
MozReview-Commit-ID: 85cX3MdlFwz
--HG--
extra : rebase_source : 217dbb75653bf2a4c593fb9a0498824b1b764cf4
2017-11-21 17:12:27 +00:00
|
|
|
WSPoint nextPoint = GetNextCharPoint(tmp);
|
2012-06-01 11:03:17 +00:00
|
|
|
if (nextPoint.mTextNode) {
|
2014-05-02 12:15:27 +00:00
|
|
|
if (!nsCRT::IsAsciiSpace(nextPoint.mChar)) {
|
|
|
|
canConvert = true;
|
|
|
|
}
|
|
|
|
} else if (aRun->mRightType == WSType::text ||
|
|
|
|
aRun->mRightType == WSType::special ||
|
|
|
|
aRun->mRightType == WSType::br) {
|
2012-07-13 06:33:43 +00:00
|
|
|
canConvert = true;
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
if (canConvert) {
|
2018-08-01 12:30:14 +00:00
|
|
|
if (NS_WARN_IF(!mHTMLEditor)) {
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
|
|
|
|
|
2014-05-02 12:15:27 +00:00
|
|
|
// First, insert a space
|
2018-08-01 12:30:14 +00:00
|
|
|
AutoTransactionsConserveSelection dontChangeMySelection(*htmlEditor);
|
2014-01-04 15:02:17 +00:00
|
|
|
nsAutoString spaceStr(char16_t(32));
|
2018-08-01 12:30:14 +00:00
|
|
|
nsresult rv = htmlEditor->InsertTextIntoTextNodeWithTransaction(
|
2019-05-07 10:58:08 +00:00
|
|
|
spaceStr, MOZ_KnownLive(*thePoint.mTextNode), thePoint.mOffset, true);
|
2018-08-01 12:30:14 +00:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2014-05-02 12:15:27 +00:00
|
|
|
|
|
|
|
// Finally, delete that nbsp
|
2017-11-21 16:00:35 +00:00
|
|
|
rv = DeleteRange(
|
|
|
|
EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset + 1),
|
|
|
|
EditorRawDOMPoint(thePoint.mTextNode, thePoint.mOffset + 2));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-05-10 11:55:49 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-12-09 09:24:33 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
nsresult WSRunObject::Scrub() {
|
2001-12-09 09:24:33 +00:00
|
|
|
WSFragment* run = mStartRun;
|
2016-10-24 02:27:45 +00:00
|
|
|
while (run) {
|
2012-07-13 06:33:43 +00:00
|
|
|
if (run->mType & (WSType::leadingWS | WSType::trailingWS)) {
|
2017-11-21 16:00:35 +00:00
|
|
|
nsresult rv = DeleteRange(run->StartPoint(), run->EndPoint());
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
2001-12-09 09:24:33 +00:00
|
|
|
}
|
|
|
|
run = run->mRight;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-07-07 09:40:45 +00:00
|
|
|
|
2016-07-07 10:00:51 +00:00
|
|
|
bool WSRunObject::IsBlockNode(nsINode* aNode) {
|
2016-07-07 09:40:45 +00:00
|
|
|
return aNode && aNode->IsElement() &&
|
2016-07-09 02:42:33 +00:00
|
|
|
HTMLEditor::NodeIsBlockStatic(aNode->AsElement());
|
2016-07-07 09:40:45 +00:00
|
|
|
}
|
2016-07-07 10:00:51 +00:00
|
|
|
|
|
|
|
} // namespace mozilla
|