Bug 1260651 part.47 Rename nsWSRunObject to mozilla::WSRunObject (and also their file names) r=mccr8
Perhaps, there may be better name like WhitespaceRunObject or something, however, for now keep using the term because I don't understand well what it does. With this patch, following objects are renamed: nsWSRunObject -> mozilla::WSRunObject WSType -> mozilla::WSType nsWSRunObject::WSFragment -> mozilla::WSRunObject::WSFragment nsWSRunObject::WSPoint -> mozilla::WSRunObject::WSPoint MozReview-Commit-ID: JgAWiPjOtMW
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "nsWSRunObject.h"
|
#include "WSRunObject.h"
|
||||||
|
|
||||||
#include "EditorUtils.h"
|
#include "EditorUtils.h"
|
||||||
#include "SelectionState.h"
|
#include "SelectionState.h"
|
||||||
@@ -28,80 +28,60 @@
|
|||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
namespace mozilla {
|
||||||
using namespace mozilla::dom;
|
|
||||||
|
using namespace dom;
|
||||||
|
|
||||||
const char16_t nbsp = 160;
|
const char16_t nbsp = 160;
|
||||||
|
|
||||||
//- constructor / destructor -----------------------------------------------
|
WSRunObject::WSRunObject(nsHTMLEditor* aHTMLEditor,
|
||||||
nsWSRunObject::nsWSRunObject(nsHTMLEditor* aEd, nsINode* aNode, int32_t aOffset)
|
nsINode* aNode,
|
||||||
|
int32_t aOffset)
|
||||||
: mNode(aNode)
|
: mNode(aNode)
|
||||||
, mOffset(aOffset)
|
, mOffset(aOffset)
|
||||||
, mPRE(false)
|
, mPRE(false)
|
||||||
, mStartNode()
|
|
||||||
, mStartOffset(0)
|
, mStartOffset(0)
|
||||||
, mStartReason()
|
|
||||||
, mStartReasonNode()
|
|
||||||
, mEndNode()
|
|
||||||
, mEndOffset(0)
|
, mEndOffset(0)
|
||||||
, mEndReason()
|
|
||||||
, mEndReasonNode()
|
|
||||||
, mFirstNBSPNode()
|
|
||||||
, mFirstNBSPOffset(0)
|
, mFirstNBSPOffset(0)
|
||||||
, mLastNBSPNode()
|
|
||||||
, mLastNBSPOffset(0)
|
, mLastNBSPOffset(0)
|
||||||
, mNodeArray()
|
|
||||||
, mStartRun(nullptr)
|
, mStartRun(nullptr)
|
||||||
, mEndRun(nullptr)
|
, mEndRun(nullptr)
|
||||||
, mHTMLEditor(aEd)
|
, mHTMLEditor(aHTMLEditor)
|
||||||
{
|
{
|
||||||
GetWSNodes();
|
GetWSNodes();
|
||||||
GetRuns();
|
GetRuns();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::nsWSRunObject(nsHTMLEditor *aEd, nsIDOMNode *aNode, int32_t aOffset) :
|
WSRunObject::WSRunObject(nsHTMLEditor* aHTMLEditor,
|
||||||
mNode(do_QueryInterface(aNode))
|
nsIDOMNode* aNode,
|
||||||
,mOffset(aOffset)
|
int32_t aOffset)
|
||||||
,mPRE(false)
|
: mNode(do_QueryInterface(aNode))
|
||||||
,mStartNode()
|
, mOffset(aOffset)
|
||||||
,mStartOffset(0)
|
, mPRE(false)
|
||||||
,mStartReason()
|
, mStartOffset(0)
|
||||||
,mStartReasonNode()
|
, mEndOffset(0)
|
||||||
,mEndNode()
|
, mFirstNBSPOffset(0)
|
||||||
,mEndOffset(0)
|
, mLastNBSPOffset(0)
|
||||||
,mEndReason()
|
, mStartRun(nullptr)
|
||||||
,mEndReasonNode()
|
, mEndRun(nullptr)
|
||||||
,mFirstNBSPNode()
|
, mHTMLEditor(aHTMLEditor)
|
||||||
,mFirstNBSPOffset(0)
|
|
||||||
,mLastNBSPNode()
|
|
||||||
,mLastNBSPOffset(0)
|
|
||||||
,mNodeArray()
|
|
||||||
,mStartRun(nullptr)
|
|
||||||
,mEndRun(nullptr)
|
|
||||||
,mHTMLEditor(aEd)
|
|
||||||
{
|
{
|
||||||
GetWSNodes();
|
GetWSNodes();
|
||||||
GetRuns();
|
GetRuns();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::~nsWSRunObject()
|
WSRunObject::~WSRunObject()
|
||||||
{
|
{
|
||||||
ClearRuns();
|
ClearRuns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
// public static methods
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::ScrubBlockBoundary(nsHTMLEditor* aHTMLEd,
|
WSRunObject::ScrubBlockBoundary(nsHTMLEditor* aHTMLEditor,
|
||||||
BlockBoundary aBoundary,
|
BlockBoundary aBoundary,
|
||||||
nsINode* aBlock,
|
nsINode* aBlock,
|
||||||
int32_t aOffset)
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(aHTMLEd && aBlock, NS_ERROR_NULL_POINTER);
|
NS_ENSURE_TRUE(aHTMLEditor && aBlock, NS_ERROR_NULL_POINTER);
|
||||||
|
|
||||||
int32_t offset;
|
int32_t offset;
|
||||||
if (aBoundary == kBlockStart) {
|
if (aBoundary == kBlockStart) {
|
||||||
@@ -115,82 +95,81 @@ nsWSRunObject::ScrubBlockBoundary(nsHTMLEditor* aHTMLEd,
|
|||||||
offset = aOffset;
|
offset = aOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject theWSObj(aHTMLEd, aBlock, offset);
|
WSRunObject theWSObj(aHTMLEditor, aBlock, offset);
|
||||||
return theWSObj.Scrub();
|
return theWSObj.Scrub();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::PrepareToJoinBlocks(nsHTMLEditor* aHTMLEd,
|
WSRunObject::PrepareToJoinBlocks(nsHTMLEditor* aHTMLEditor,
|
||||||
Element* aLeftBlock,
|
Element* aLeftBlock,
|
||||||
Element* aRightBlock)
|
Element* aRightBlock)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(aLeftBlock && aRightBlock && aHTMLEd, NS_ERROR_NULL_POINTER);
|
NS_ENSURE_TRUE(aLeftBlock && aRightBlock && aHTMLEditor,
|
||||||
|
NS_ERROR_NULL_POINTER);
|
||||||
|
|
||||||
nsWSRunObject leftWSObj(aHTMLEd, aLeftBlock, aLeftBlock->Length());
|
WSRunObject leftWSObj(aHTMLEditor, aLeftBlock, aLeftBlock->Length());
|
||||||
nsWSRunObject rightWSObj(aHTMLEd, aRightBlock, 0);
|
WSRunObject rightWSObj(aHTMLEditor, aRightBlock, 0);
|
||||||
|
|
||||||
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::PrepareToDeleteRange(nsHTMLEditor* aHTMLEd,
|
WSRunObject::PrepareToDeleteRange(nsHTMLEditor* aHTMLEditor,
|
||||||
nsCOMPtr<nsINode>* aStartNode,
|
nsCOMPtr<nsINode>* aStartNode,
|
||||||
int32_t* aStartOffset,
|
int32_t* aStartOffset,
|
||||||
nsCOMPtr<nsINode>* aEndNode,
|
nsCOMPtr<nsINode>* aEndNode,
|
||||||
int32_t* aEndOffset)
|
int32_t* aEndOffset)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(aHTMLEd && aStartNode && *aStartNode && aStartOffset &&
|
NS_ENSURE_TRUE(aHTMLEditor && aStartNode && *aStartNode && aStartOffset &&
|
||||||
aEndNode && *aEndNode && aEndOffset, NS_ERROR_NULL_POINTER);
|
aEndNode && *aEndNode && aEndOffset, NS_ERROR_NULL_POINTER);
|
||||||
|
|
||||||
AutoTrackDOMPoint trackerStart(aHTMLEd->mRangeUpdater, aStartNode,
|
AutoTrackDOMPoint trackerStart(aHTMLEditor->mRangeUpdater,
|
||||||
aStartOffset);
|
aStartNode, aStartOffset);
|
||||||
AutoTrackDOMPoint trackerEnd(aHTMLEd->mRangeUpdater, aEndNode, aEndOffset);
|
AutoTrackDOMPoint trackerEnd(aHTMLEditor->mRangeUpdater,
|
||||||
|
aEndNode, aEndOffset);
|
||||||
|
|
||||||
nsWSRunObject leftWSObj(aHTMLEd, *aStartNode, *aStartOffset);
|
WSRunObject leftWSObj(aHTMLEditor, *aStartNode, *aStartOffset);
|
||||||
nsWSRunObject rightWSObj(aHTMLEd, *aEndNode, *aEndOffset);
|
WSRunObject rightWSObj(aHTMLEditor, *aEndNode, *aEndOffset);
|
||||||
|
|
||||||
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::PrepareToDeleteNode(nsHTMLEditor* aHTMLEd,
|
WSRunObject::PrepareToDeleteNode(nsHTMLEditor* aHTMLEditor,
|
||||||
nsIContent* aContent)
|
nsIContent* aContent)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(aContent && aHTMLEd, NS_ERROR_NULL_POINTER);
|
NS_ENSURE_TRUE(aContent && aHTMLEditor, NS_ERROR_NULL_POINTER);
|
||||||
|
|
||||||
nsCOMPtr<nsINode> parent = aContent->GetParentNode();
|
nsCOMPtr<nsINode> parent = aContent->GetParentNode();
|
||||||
NS_ENSURE_STATE(parent);
|
NS_ENSURE_STATE(parent);
|
||||||
int32_t offset = parent->IndexOf(aContent);
|
int32_t offset = parent->IndexOf(aContent);
|
||||||
|
|
||||||
nsWSRunObject leftWSObj(aHTMLEd, parent, offset);
|
WSRunObject leftWSObj(aHTMLEditor, parent, offset);
|
||||||
nsWSRunObject rightWSObj(aHTMLEd, parent, offset + 1);
|
WSRunObject rightWSObj(aHTMLEditor, parent, offset + 1);
|
||||||
|
|
||||||
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
return leftWSObj.PrepareToDeleteRangePriv(&rightWSObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::PrepareToSplitAcrossBlocks(nsHTMLEditor* aHTMLEd,
|
WSRunObject::PrepareToSplitAcrossBlocks(nsHTMLEditor* aHTMLEditor,
|
||||||
nsCOMPtr<nsINode>* aSplitNode,
|
nsCOMPtr<nsINode>* aSplitNode,
|
||||||
int32_t* aSplitOffset)
|
int32_t* aSplitOffset)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(aHTMLEd && aSplitNode && *aSplitNode && aSplitOffset,
|
NS_ENSURE_TRUE(aHTMLEditor && aSplitNode && *aSplitNode && aSplitOffset,
|
||||||
NS_ERROR_NULL_POINTER);
|
NS_ERROR_NULL_POINTER);
|
||||||
|
|
||||||
AutoTrackDOMPoint tracker(aHTMLEd->mRangeUpdater, aSplitNode, aSplitOffset);
|
AutoTrackDOMPoint tracker(aHTMLEditor->mRangeUpdater,
|
||||||
|
aSplitNode, aSplitOffset);
|
||||||
|
|
||||||
nsWSRunObject wsObj(aHTMLEd, *aSplitNode, *aSplitOffset);
|
WSRunObject wsObj(aHTMLEditor, *aSplitNode, *aSplitOffset);
|
||||||
|
|
||||||
return wsObj.PrepareToSplitAcrossBlocksPriv();
|
return wsObj.PrepareToSplitAcrossBlocksPriv();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
// public instance methods
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Element*
|
Element*
|
||||||
nsWSRunObject::InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
|
WSRunObject::InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
|
||||||
int32_t* aInOutOffset,
|
int32_t* aInOutOffset,
|
||||||
nsIEditor::EDirection aSelect)
|
nsIEditor::EDirection aSelect)
|
||||||
{
|
{
|
||||||
// MOOSE: for now, we always assume non-PRE formatting. Fix this later.
|
// MOOSE: for now, we always assume non-PRE formatting. Fix this later.
|
||||||
// meanwhile, the pre case is handled in WillInsertText in
|
// meanwhile, the pre case is handled in WillInsertText in
|
||||||
@@ -255,10 +234,10 @@ nsWSRunObject::InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::InsertText(const nsAString& aStringToInsert,
|
WSRunObject::InsertText(const nsAString& aStringToInsert,
|
||||||
nsCOMPtr<nsINode>* aInOutParent,
|
nsCOMPtr<nsINode>* aInOutParent,
|
||||||
int32_t* aInOutOffset,
|
int32_t* aInOutOffset,
|
||||||
nsIDocument* aDoc)
|
nsIDocument* aDoc)
|
||||||
{
|
{
|
||||||
// MOOSE: for now, we always assume non-PRE formatting. Fix this later.
|
// MOOSE: for now, we always assume non-PRE formatting. Fix this later.
|
||||||
// meanwhile, the pre case is handled in WillInsertText in
|
// meanwhile, the pre case is handled in WillInsertText in
|
||||||
@@ -384,7 +363,7 @@ nsWSRunObject::InsertText(const nsAString& aStringToInsert,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::DeleteWSBackward()
|
WSRunObject::DeleteWSBackward()
|
||||||
{
|
{
|
||||||
WSPoint point = GetCharBefore(mNode, mOffset);
|
WSPoint point = GetCharBefore(mNode, mOffset);
|
||||||
NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
|
NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
|
||||||
@@ -410,9 +389,9 @@ nsWSRunObject::DeleteWSBackward()
|
|||||||
nsCOMPtr<nsINode> startNode = startNodeText.get();
|
nsCOMPtr<nsINode> startNode = startNodeText.get();
|
||||||
nsCOMPtr<nsINode> endNode = endNodeText.get();
|
nsCOMPtr<nsINode> endNode = endNodeText.get();
|
||||||
nsresult res =
|
nsresult res =
|
||||||
nsWSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
WSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
||||||
address_of(startNode), &startOffset,
|
address_of(startNode), &startOffset,
|
||||||
address_of(endNode), &endOffset);
|
address_of(endNode), &endOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
// finally, delete that ws
|
// finally, delete that ws
|
||||||
@@ -423,9 +402,9 @@ nsWSRunObject::DeleteWSBackward()
|
|||||||
int32_t startOffset = point.mOffset;
|
int32_t startOffset = point.mOffset;
|
||||||
int32_t endOffset = point.mOffset + 1;
|
int32_t endOffset = point.mOffset + 1;
|
||||||
nsresult res =
|
nsresult res =
|
||||||
nsWSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
WSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
||||||
address_of(node), &startOffset,
|
address_of(node), &startOffset,
|
||||||
address_of(node), &endOffset);
|
address_of(node), &endOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
// finally, delete that ws
|
// finally, delete that ws
|
||||||
@@ -435,7 +414,7 @@ nsWSRunObject::DeleteWSBackward()
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::DeleteWSForward()
|
WSRunObject::DeleteWSForward()
|
||||||
{
|
{
|
||||||
WSPoint point = GetCharAfter(mNode, mOffset);
|
WSPoint point = GetCharAfter(mNode, mOffset);
|
||||||
NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
|
NS_ENSURE_TRUE(point.mTextNode, NS_OK); // nothing to delete
|
||||||
@@ -459,7 +438,7 @@ nsWSRunObject::DeleteWSForward()
|
|||||||
|
|
||||||
// Adjust surrounding ws
|
// Adjust surrounding ws
|
||||||
nsCOMPtr<nsINode> startNode(startNodeText), endNode(endNodeText);
|
nsCOMPtr<nsINode> startNode(startNodeText), endNode(endNodeText);
|
||||||
nsresult res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
nsresult res = WSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
||||||
address_of(startNode), &startOffset, address_of(endNode), &endOffset);
|
address_of(startNode), &startOffset, address_of(endNode), &endOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
@@ -470,7 +449,7 @@ nsWSRunObject::DeleteWSForward()
|
|||||||
// Adjust surrounding ws
|
// Adjust surrounding ws
|
||||||
int32_t startOffset = point.mOffset;
|
int32_t startOffset = point.mOffset;
|
||||||
int32_t endOffset = point.mOffset+1;
|
int32_t endOffset = point.mOffset+1;
|
||||||
nsresult res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
nsresult res = WSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
||||||
address_of(node), &startOffset, address_of(node), &endOffset);
|
address_of(node), &startOffset, address_of(node), &endOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
@@ -481,11 +460,11 @@ nsWSRunObject::DeleteWSForward()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWSRunObject::PriorVisibleNode(nsINode* aNode,
|
WSRunObject::PriorVisibleNode(nsINode* aNode,
|
||||||
int32_t aOffset,
|
int32_t aOffset,
|
||||||
nsCOMPtr<nsINode>* outVisNode,
|
nsCOMPtr<nsINode>* outVisNode,
|
||||||
int32_t* outVisOffset,
|
int32_t* outVisOffset,
|
||||||
WSType* outType)
|
WSType* outType)
|
||||||
{
|
{
|
||||||
// Find first visible thing before the point. Position
|
// Find first visible thing before the point. Position
|
||||||
// outVisNode/outVisOffset just _after_ that thing. If we don't find
|
// outVisNode/outVisOffset just _after_ that thing. If we don't find
|
||||||
@@ -525,11 +504,11 @@ nsWSRunObject::PriorVisibleNode(nsINode* aNode,
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWSRunObject::NextVisibleNode(nsINode* aNode,
|
WSRunObject::NextVisibleNode(nsINode* aNode,
|
||||||
int32_t aOffset,
|
int32_t aOffset,
|
||||||
nsCOMPtr<nsINode>* outVisNode,
|
nsCOMPtr<nsINode>* outVisNode,
|
||||||
int32_t* outVisOffset,
|
int32_t* outVisOffset,
|
||||||
WSType* outType)
|
WSType* outType)
|
||||||
{
|
{
|
||||||
// Find first visible thing after the point. Position
|
// Find first visible thing after the point. Position
|
||||||
// outVisNode/outVisOffset just _before_ that thing. If we don't find
|
// outVisNode/outVisOffset just _before_ that thing. If we don't find
|
||||||
@@ -568,7 +547,7 @@ nsWSRunObject::NextVisibleNode(nsINode* aNode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::AdjustWhitespace()
|
WSRunObject::AdjustWhitespace()
|
||||||
{
|
{
|
||||||
// this routine examines a run of ws and tries to get rid of some unneeded nbsp's,
|
// 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
|
// replacing them with regualr ascii space if possible. Keeping things simple
|
||||||
@@ -597,7 +576,7 @@ nsWSRunObject::AdjustWhitespace()
|
|||||||
//--------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
nsINode*
|
nsINode*
|
||||||
nsWSRunObject::GetWSBoundingParent()
|
WSRunObject::GetWSBoundingParent()
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(mNode, nullptr);
|
NS_ENSURE_TRUE(mNode, nullptr);
|
||||||
OwningNonNull<nsINode> wsBoundingParent = *mNode;
|
OwningNonNull<nsINode> wsBoundingParent = *mNode;
|
||||||
@@ -612,7 +591,7 @@ nsWSRunObject::GetWSBoundingParent()
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::GetWSNodes()
|
WSRunObject::GetWSNodes()
|
||||||
{
|
{
|
||||||
// collect up an array of nodes that are contiguous with the insertion point
|
// collect up an array of nodes that are contiguous with the insertion point
|
||||||
// and which contain only whitespace. Stop if you reach non-ws text or a new
|
// and which contain only whitespace. Stop if you reach non-ws text or a new
|
||||||
@@ -838,7 +817,7 @@ nsWSRunObject::GetWSNodes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWSRunObject::GetRuns()
|
WSRunObject::GetRuns()
|
||||||
{
|
{
|
||||||
ClearRuns();
|
ClearRuns();
|
||||||
|
|
||||||
@@ -968,7 +947,7 @@ nsWSRunObject::GetRuns()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWSRunObject::ClearRuns()
|
WSRunObject::ClearRuns()
|
||||||
{
|
{
|
||||||
WSFragment *tmp, *run;
|
WSFragment *tmp, *run;
|
||||||
run = mStartRun;
|
run = mStartRun;
|
||||||
@@ -983,7 +962,7 @@ nsWSRunObject::ClearRuns()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWSRunObject::MakeSingleWSRun(WSType aType)
|
WSRunObject::MakeSingleWSRun(WSType aType)
|
||||||
{
|
{
|
||||||
mStartRun = new WSFragment();
|
mStartRun = new WSFragment();
|
||||||
|
|
||||||
@@ -999,8 +978,8 @@ nsWSRunObject::MakeSingleWSRun(WSType aType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsIContent*
|
nsIContent*
|
||||||
nsWSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode,
|
WSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode,
|
||||||
nsINode* aBlockParent)
|
nsINode* aBlockParent)
|
||||||
{
|
{
|
||||||
// Can't really recycle various getnext/prior routines because we have
|
// Can't really recycle various getnext/prior routines because we have
|
||||||
// special needs here. Need to step into inline containers but not block
|
// special needs here. Need to step into inline containers but not block
|
||||||
@@ -1038,8 +1017,8 @@ nsWSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsIContent*
|
nsIContent*
|
||||||
nsWSRunObject::GetPreviousWSNode(EditorDOMPoint aPoint,
|
WSRunObject::GetPreviousWSNode(EditorDOMPoint aPoint,
|
||||||
nsINode* aBlockParent)
|
nsINode* aBlockParent)
|
||||||
{
|
{
|
||||||
// Can't really recycle various getnext/prior routines because we
|
// Can't really recycle various getnext/prior routines because we
|
||||||
// have special needs here. Need to step into inline containers but
|
// have special needs here. Need to step into inline containers but
|
||||||
@@ -1083,8 +1062,8 @@ nsWSRunObject::GetPreviousWSNode(EditorDOMPoint aPoint,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsIContent*
|
nsIContent*
|
||||||
nsWSRunObject::GetNextWSNodeInner(nsINode* aStartNode,
|
WSRunObject::GetNextWSNodeInner(nsINode* aStartNode,
|
||||||
nsINode* aBlockParent)
|
nsINode* aBlockParent)
|
||||||
{
|
{
|
||||||
// Can't really recycle various getnext/prior routines because we have
|
// Can't really recycle various getnext/prior routines because we have
|
||||||
// special needs here. Need to step into inline containers but not block
|
// special needs here. Need to step into inline containers but not block
|
||||||
@@ -1122,7 +1101,8 @@ nsWSRunObject::GetNextWSNodeInner(nsINode* aStartNode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsIContent*
|
nsIContent*
|
||||||
nsWSRunObject::GetNextWSNode(EditorDOMPoint aPoint, nsINode* aBlockParent)
|
WSRunObject::GetNextWSNode(EditorDOMPoint aPoint,
|
||||||
|
nsINode* aBlockParent)
|
||||||
{
|
{
|
||||||
// Can't really recycle various getnext/prior routines because we have
|
// Can't really recycle various getnext/prior routines because we have
|
||||||
// special needs here. Need to step into inline containers but not block
|
// special needs here. Need to step into inline containers but not block
|
||||||
@@ -1166,7 +1146,7 @@ nsWSRunObject::GetNextWSNode(EditorDOMPoint aPoint, nsINode* aBlockParent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject)
|
WSRunObject::PrepareToDeleteRangePriv(WSRunObject* aEndObject)
|
||||||
{
|
{
|
||||||
// this routine adjust whitespace before *this* and after aEndObject
|
// this routine adjust whitespace before *this* and after aEndObject
|
||||||
// in preperation for the two areas to become adjacent after the
|
// in preperation for the two areas to become adjacent after the
|
||||||
@@ -1234,7 +1214,7 @@ nsWSRunObject::PrepareToDeleteRangePriv(nsWSRunObject* aEndObject)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::PrepareToSplitAcrossBlocksPriv()
|
WSRunObject::PrepareToSplitAcrossBlocksPriv()
|
||||||
{
|
{
|
||||||
// used to prepare ws to be split across two blocks. The main issue
|
// used to prepare ws to be split across two blocks. The main issue
|
||||||
// here is make sure normalWS doesn't end up becoming non-significant
|
// here is make sure normalWS doesn't end up becoming non-significant
|
||||||
@@ -1278,9 +1258,11 @@ nsWSRunObject::PrepareToSplitAcrossBlocksPriv()
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::DeleteChars(nsINode* aStartNode, int32_t aStartOffset,
|
WSRunObject::DeleteChars(nsINode* aStartNode,
|
||||||
nsINode* aEndNode, int32_t aEndOffset,
|
int32_t aStartOffset,
|
||||||
AreaRestriction aAR)
|
nsINode* aEndNode,
|
||||||
|
int32_t aEndOffset,
|
||||||
|
AreaRestriction aAR)
|
||||||
{
|
{
|
||||||
// MOOSE: this routine needs to be modified to preserve the integrity of the
|
// MOOSE: this routine needs to be modified to preserve the integrity of the
|
||||||
// wsFragment info.
|
// wsFragment info.
|
||||||
@@ -1367,8 +1349,9 @@ nsWSRunObject::DeleteChars(nsINode* aStartNode, int32_t aStartOffset,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::WSPoint
|
WSRunObject::WSPoint
|
||||||
nsWSRunObject::GetCharAfter(nsINode* aNode, int32_t aOffset)
|
WSRunObject::GetCharAfter(nsINode* aNode,
|
||||||
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aNode);
|
MOZ_ASSERT(aNode);
|
||||||
|
|
||||||
@@ -1382,8 +1365,9 @@ nsWSRunObject::GetCharAfter(nsINode* aNode, int32_t aOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::WSPoint
|
WSRunObject::WSPoint
|
||||||
nsWSRunObject::GetCharBefore(nsINode* aNode, int32_t aOffset)
|
WSRunObject::GetCharBefore(nsINode* aNode,
|
||||||
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aNode);
|
MOZ_ASSERT(aNode);
|
||||||
|
|
||||||
@@ -1397,8 +1381,8 @@ nsWSRunObject::GetCharBefore(nsINode* aNode, int32_t aOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::WSPoint
|
WSRunObject::WSPoint
|
||||||
nsWSRunObject::GetCharAfter(const WSPoint &aPoint)
|
WSRunObject::GetCharAfter(const WSPoint &aPoint)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPoint.mTextNode);
|
MOZ_ASSERT(aPoint.mTextNode);
|
||||||
|
|
||||||
@@ -1427,8 +1411,8 @@ nsWSRunObject::GetCharAfter(const WSPoint &aPoint)
|
|||||||
return outPoint;
|
return outPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::WSPoint
|
WSRunObject::WSPoint
|
||||||
nsWSRunObject::GetCharBefore(const WSPoint &aPoint)
|
WSRunObject::GetCharBefore(const WSPoint &aPoint)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPoint.mTextNode);
|
MOZ_ASSERT(aPoint.mTextNode);
|
||||||
|
|
||||||
@@ -1461,7 +1445,7 @@ nsWSRunObject::GetCharBefore(const WSPoint &aPoint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR)
|
WSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR)
|
||||||
{
|
{
|
||||||
// MOOSE: this routine needs to be modified to preserve the integrity of the
|
// MOOSE: this routine needs to be modified to preserve the integrity of the
|
||||||
// wsFragment info.
|
// wsFragment info.
|
||||||
@@ -1500,9 +1484,13 @@ nsWSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWSRunObject::GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
|
WSRunObject::GetAsciiWSBounds(int16_t aDir,
|
||||||
Text** outStartNode, int32_t* outStartOffset,
|
nsINode* aNode,
|
||||||
Text** outEndNode, int32_t* outEndOffset)
|
int32_t aOffset,
|
||||||
|
Text** outStartNode,
|
||||||
|
int32_t* outStartOffset,
|
||||||
|
Text** outEndNode,
|
||||||
|
int32_t* outEndOffset)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aNode && outStartNode && outStartOffset && outEndNode &&
|
MOZ_ASSERT(aNode && outStartNode && outStartOffset && outEndNode &&
|
||||||
outEndOffset);
|
outEndOffset);
|
||||||
@@ -1559,8 +1547,10 @@ nsWSRunObject::GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
|
|||||||
* needs
|
* needs
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
nsWSRunObject::FindRun(nsINode* aNode, int32_t aOffset, WSFragment** outRun,
|
WSRunObject::FindRun(nsINode* aNode,
|
||||||
bool after)
|
int32_t aOffset,
|
||||||
|
WSFragment** outRun,
|
||||||
|
bool after)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aNode && outRun);
|
MOZ_ASSERT(aNode && outRun);
|
||||||
*outRun = nullptr;
|
*outRun = nullptr;
|
||||||
@@ -1604,7 +1594,8 @@ nsWSRunObject::FindRun(nsINode* aNode, int32_t aOffset, WSFragment** outRun,
|
|||||||
}
|
}
|
||||||
|
|
||||||
char16_t
|
char16_t
|
||||||
nsWSRunObject::GetCharAt(Text* aTextNode, int32_t aOffset)
|
WSRunObject::GetCharAt(Text* aTextNode,
|
||||||
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
// return 0 if we can't get a char, for whatever reason
|
// return 0 if we can't get a char, for whatever reason
|
||||||
NS_ENSURE_TRUE(aTextNode, 0);
|
NS_ENSURE_TRUE(aTextNode, 0);
|
||||||
@@ -1616,8 +1607,9 @@ nsWSRunObject::GetCharAt(Text* aTextNode, int32_t aOffset)
|
|||||||
return aTextNode->GetText()->CharAt(aOffset);
|
return aTextNode->GetText()->CharAt(aOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::WSPoint
|
WSRunObject::WSPoint
|
||||||
nsWSRunObject::GetWSPointAfter(nsINode* aNode, int32_t aOffset)
|
WSRunObject::GetWSPointAfter(nsINode* aNode,
|
||||||
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
// Note: only to be called if aNode is not a ws node.
|
// Note: only to be called if aNode is not a ws node.
|
||||||
|
|
||||||
@@ -1665,8 +1657,9 @@ nsWSRunObject::GetWSPointAfter(nsINode* aNode, int32_t aOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject::WSPoint
|
WSRunObject::WSPoint
|
||||||
nsWSRunObject::GetWSPointBefore(nsINode* aNode, int32_t aOffset)
|
WSRunObject::GetWSPointBefore(nsINode* aNode,
|
||||||
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
// Note: only to be called if aNode is not a ws node.
|
// Note: only to be called if aNode is not a ws node.
|
||||||
|
|
||||||
@@ -1717,7 +1710,7 @@ nsWSRunObject::GetWSPointBefore(nsINode* aNode, int32_t aOffset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
|
WSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
|
||||||
{
|
{
|
||||||
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
// 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
|
// proliferation. Examine what is before and after the trailing nbsp, if
|
||||||
@@ -1833,8 +1826,9 @@ nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::CheckTrailingNBSP(WSFragment* aRun, nsINode* aNode,
|
WSRunObject::CheckTrailingNBSP(WSFragment* aRun,
|
||||||
int32_t aOffset)
|
nsINode* aNode,
|
||||||
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
// 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
|
// proliferation. This routine is called when we are about to make this
|
||||||
@@ -1872,8 +1866,9 @@ nsWSRunObject::CheckTrailingNBSP(WSFragment* aRun, nsINode* aNode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
|
WSRunObject::CheckLeadingNBSP(WSFragment* aRun,
|
||||||
int32_t aOffset)
|
nsINode* aNode,
|
||||||
|
int32_t aOffset)
|
||||||
{
|
{
|
||||||
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
// 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
|
// proliferation This routine is called when we are about to make this point
|
||||||
@@ -1914,7 +1909,7 @@ nsWSRunObject::CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
|
|||||||
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsWSRunObject::Scrub()
|
WSRunObject::Scrub()
|
||||||
{
|
{
|
||||||
WSFragment *run = mStartRun;
|
WSFragment *run = mStartRun;
|
||||||
while (run)
|
while (run)
|
||||||
@@ -1930,8 +1925,10 @@ nsWSRunObject::Scrub()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsWSRunObject::IsBlockNode(nsINode* aNode)
|
WSRunObject::IsBlockNode(nsINode* aNode)
|
||||||
{
|
{
|
||||||
return aNode && aNode->IsElement() &&
|
return aNode && aNode->IsElement() &&
|
||||||
nsHTMLEditor::NodeIsBlockStatic(aNode->AsElement());
|
nsHTMLEditor::NodeIsBlockStatic(aNode->AsElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
411
editor/libeditor/WSRunObject.h
Normal file
411
editor/libeditor/WSRunObject.h
Normal file
@@ -0,0 +1,411 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef WSRunObject_h
|
||||||
|
#define WSRunObject_h
|
||||||
|
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIEditor.h" // for EDirection
|
||||||
|
#include "nsINode.h"
|
||||||
|
#include "nscore.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/dom/Text.h"
|
||||||
|
|
||||||
|
class nsHTMLEditor;
|
||||||
|
class nsHTMLEditRules;
|
||||||
|
class nsIDOMNode;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
struct EditorDOMPoint;
|
||||||
|
|
||||||
|
// class WSRunObject represents the entire whitespace situation
|
||||||
|
// around a given point. It collects up a list of nodes that contain
|
||||||
|
// whitespace and categorizes in up to 3 different WSFragments (detailed
|
||||||
|
// below). Each WSFragment is a collection of whitespace that is
|
||||||
|
// either all insignificant, or that is significant. A WSFragment could
|
||||||
|
// consist of insignificant whitespace because it is after a block
|
||||||
|
// boundary or after a break. Or it could be insignificant because it
|
||||||
|
// is before a block. Or it could be significant because it is
|
||||||
|
// surrounded by text, or starts and ends with nbsps, etc.
|
||||||
|
|
||||||
|
// Throughout I refer to LeadingWS, NormalWS, TrailingWS. LeadingWS & TrailingWS
|
||||||
|
// are runs of ascii ws that are insignificant (do not render) because they
|
||||||
|
// are adjacent to block boundaries, or after a break. NormalWS is ws that
|
||||||
|
// does cause soem rendering. Note that not all the ws in a NormalWS run need
|
||||||
|
// render. For example, two ascii spaces surrounded by text on both sides
|
||||||
|
// will only render as one space (in non-preformatted stlye html), yet both
|
||||||
|
// spaces count as NormalWS. Together, they render as the one visible space.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A type-safe bitfield indicating various types of whitespace or other things.
|
||||||
|
* Used as a member variable in WSRunObject and WSFragment.
|
||||||
|
*
|
||||||
|
* XXX: If this idea is useful in other places, we should generalize it using a
|
||||||
|
* template.
|
||||||
|
*/
|
||||||
|
class WSType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Enum
|
||||||
|
{
|
||||||
|
none = 0,
|
||||||
|
leadingWS = 1, // leading insignificant ws, ie, after block or br
|
||||||
|
trailingWS = 1 << 1, // trailing insignificant ws, ie, before block
|
||||||
|
normalWS = 1 << 2, // normal significant ws, ie, after text, image, ...
|
||||||
|
text = 1 << 3, // indicates regular (non-ws) text
|
||||||
|
special = 1 << 4, // indicates an inline non-container, like image
|
||||||
|
br = 1 << 5, // indicates a br node
|
||||||
|
otherBlock = 1 << 6, // indicates a block other than one ws run is in
|
||||||
|
thisBlock = 1 << 7, // indicates the block ws run is in
|
||||||
|
block = otherBlock | thisBlock // block found
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implicit constructor, because the enums are logically just WSTypes
|
||||||
|
* themselves, and are only a separate type because there's no other obvious
|
||||||
|
* way to name specific WSType values.
|
||||||
|
*/
|
||||||
|
MOZ_IMPLICIT WSType(const Enum& aEnum = none)
|
||||||
|
: mEnum(aEnum)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// operator==, &, and | need to access mEnum
|
||||||
|
friend bool operator==(const WSType& aLeft, const WSType& aRight);
|
||||||
|
friend const WSType operator&(const WSType& aLeft, const WSType& aRight);
|
||||||
|
friend const WSType operator|(const WSType& aLeft, const WSType& aRight);
|
||||||
|
WSType& operator=(const WSType& aOther)
|
||||||
|
{
|
||||||
|
// This handles self-assignment fine
|
||||||
|
mEnum = aOther.mEnum;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WSType& operator&=(const WSType& aOther)
|
||||||
|
{
|
||||||
|
mEnum &= aOther.mEnum;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
WSType& operator|=(const WSType& aOther)
|
||||||
|
{
|
||||||
|
mEnum |= aOther.mEnum;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t mEnum;
|
||||||
|
void bool_conversion_helper() {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Allow boolean conversion with no numeric conversion
|
||||||
|
typedef void (WSType::*bool_type)();
|
||||||
|
operator bool_type() const
|
||||||
|
{
|
||||||
|
return mEnum ? &WSType::bool_conversion_helper : nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are declared as global functions so "WSType::Enum == WSType" et al.
|
||||||
|
* will work using the implicit constructor.
|
||||||
|
*/
|
||||||
|
inline bool operator==(const WSType& aLeft, const WSType& aRight)
|
||||||
|
{
|
||||||
|
return aLeft.mEnum == aRight.mEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const WSType& aLeft, const WSType& aRight)
|
||||||
|
{
|
||||||
|
return !(aLeft == aRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const WSType operator&(const WSType& aLeft, const WSType& aRight)
|
||||||
|
{
|
||||||
|
WSType ret;
|
||||||
|
ret.mEnum = aLeft.mEnum & aRight.mEnum;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const WSType operator|(const WSType& aLeft, const WSType& aRight)
|
||||||
|
{
|
||||||
|
WSType ret;
|
||||||
|
ret.mEnum = aLeft.mEnum | aRight.mEnum;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure that & and | of WSType::Enum creates a WSType instead of an int,
|
||||||
|
* because operators between WSType and int shouldn't work
|
||||||
|
*/
|
||||||
|
inline const WSType operator&(const WSType::Enum& aLeft,
|
||||||
|
const WSType::Enum& aRight)
|
||||||
|
{
|
||||||
|
return WSType(aLeft) & WSType(aRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const WSType operator|(const WSType::Enum& aLeft,
|
||||||
|
const WSType::Enum& aRight)
|
||||||
|
{
|
||||||
|
return WSType(aLeft) | WSType(aRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MOZ_STACK_CLASS WSRunObject final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum BlockBoundary
|
||||||
|
{
|
||||||
|
kBeforeBlock,
|
||||||
|
kBlockStart,
|
||||||
|
kBlockEnd,
|
||||||
|
kAfterBlock
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {eBefore = 1};
|
||||||
|
enum {eAfter = 1 << 1};
|
||||||
|
enum {eBoth = eBefore | eAfter};
|
||||||
|
|
||||||
|
WSRunObject(nsHTMLEditor* aHTMLEditor, nsINode* aNode, int32_t aOffset);
|
||||||
|
WSRunObject(nsHTMLEditor* aHTMLEditor, nsIDOMNode* aNode, int32_t aOffset);
|
||||||
|
~WSRunObject();
|
||||||
|
|
||||||
|
// ScrubBlockBoundary removes any non-visible whitespace at the specified
|
||||||
|
// location relative to a block node.
|
||||||
|
static nsresult ScrubBlockBoundary(nsHTMLEditor* aHTMLEditor,
|
||||||
|
BlockBoundary aBoundary,
|
||||||
|
nsINode* aBlock,
|
||||||
|
int32_t aOffset = -1);
|
||||||
|
|
||||||
|
// PrepareToJoinBlocks fixes up ws at the end of aLeftBlock and the
|
||||||
|
// beginning of aRightBlock in preperation for them to be joined. Example
|
||||||
|
// of fixup: trailingws in aLeftBlock needs to be removed.
|
||||||
|
static nsresult PrepareToJoinBlocks(nsHTMLEditor* aHTMLEditor,
|
||||||
|
dom::Element* aLeftBlock,
|
||||||
|
dom::Element* aRightBlock);
|
||||||
|
|
||||||
|
// PrepareToDeleteRange fixes up ws before {aStartNode,aStartOffset}
|
||||||
|
// and after {aEndNode,aEndOffset} in preperation for content
|
||||||
|
// in that range to be deleted. Note that the nodes and offsets
|
||||||
|
// are adjusted in response to any dom changes we make while
|
||||||
|
// adjusting ws.
|
||||||
|
// example of fixup: trailingws before {aStartNode,aStartOffset}
|
||||||
|
// needs to be removed.
|
||||||
|
static nsresult PrepareToDeleteRange(nsHTMLEditor* aHTMLEditor,
|
||||||
|
nsCOMPtr<nsINode>* aStartNode,
|
||||||
|
int32_t* aStartOffset,
|
||||||
|
nsCOMPtr<nsINode>* aEndNode,
|
||||||
|
int32_t* aEndOffset);
|
||||||
|
|
||||||
|
// PrepareToDeleteNode fixes up ws before and after aContent in preparation
|
||||||
|
// for aContent to be deleted. Example of fixup: trailingws before
|
||||||
|
// aContent needs to be removed.
|
||||||
|
static nsresult PrepareToDeleteNode(nsHTMLEditor* aHTMLEditor,
|
||||||
|
nsIContent* aContent);
|
||||||
|
|
||||||
|
// PrepareToSplitAcrossBlocks fixes up ws before and after
|
||||||
|
// {aSplitNode,aSplitOffset} in preparation for a block parent to be split.
|
||||||
|
// Note that the aSplitNode and aSplitOffset are adjusted in response to
|
||||||
|
// any DOM changes we make while adjusting ws. Example of fixup: normalws
|
||||||
|
// before {aSplitNode,aSplitOffset} needs to end with nbsp.
|
||||||
|
static nsresult PrepareToSplitAcrossBlocks(nsHTMLEditor* aHTMLEditor,
|
||||||
|
nsCOMPtr<nsINode>* aSplitNode,
|
||||||
|
int32_t* aSplitOffset);
|
||||||
|
|
||||||
|
// InsertBreak inserts a br node at {aInOutParent,aInOutOffset}
|
||||||
|
// and makes any needed adjustments to ws around that point.
|
||||||
|
// example of fixup: normalws after {aInOutParent,aInOutOffset}
|
||||||
|
// needs to begin with nbsp.
|
||||||
|
dom::Element* InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
|
||||||
|
int32_t* aInOutOffset,
|
||||||
|
nsIEditor::EDirection aSelect);
|
||||||
|
|
||||||
|
// InsertText inserts a string at {aInOutParent,aInOutOffset} and makes any
|
||||||
|
// needed adjustments to ws around that point. Example of fixup:
|
||||||
|
// trailingws before {aInOutParent,aInOutOffset} needs to be removed.
|
||||||
|
nsresult InsertText(const nsAString& aStringToInsert,
|
||||||
|
nsCOMPtr<nsINode>* aInOutNode,
|
||||||
|
int32_t* aInOutOffset,
|
||||||
|
nsIDocument* aDoc);
|
||||||
|
|
||||||
|
// DeleteWSBackward deletes a single visible piece of ws before the ws
|
||||||
|
// point (the point to create the wsRunObject, passed to its constructor).
|
||||||
|
// It makes any needed conversion to adjacent ws to retain its
|
||||||
|
// significance.
|
||||||
|
nsresult DeleteWSBackward();
|
||||||
|
|
||||||
|
// DeleteWSForward deletes a single visible piece of ws after the ws point
|
||||||
|
// (the point to create the wsRunObject, passed to its constructor). It
|
||||||
|
// makes any needed conversion to adjacent ws to retain its significance.
|
||||||
|
nsresult DeleteWSForward();
|
||||||
|
|
||||||
|
// PriorVisibleNode returns the first piece of visible thing before
|
||||||
|
// {aNode,aOffset}. If there is no visible ws qualifying it returns what
|
||||||
|
// is before the ws run. Note that {outVisNode,outVisOffset} is set to
|
||||||
|
// just AFTER the visible object.
|
||||||
|
void PriorVisibleNode(nsINode* aNode,
|
||||||
|
int32_t aOffset,
|
||||||
|
nsCOMPtr<nsINode>* outVisNode,
|
||||||
|
int32_t* outVisOffset,
|
||||||
|
WSType* outType);
|
||||||
|
|
||||||
|
// NextVisibleNode returns the first piece of visible thing after
|
||||||
|
// {aNode,aOffset}. If there is no visible ws qualifying it returns what
|
||||||
|
// is after the ws run. Note that {outVisNode,outVisOffset} is set to just
|
||||||
|
// BEFORE the visible object.
|
||||||
|
void NextVisibleNode(nsINode* aNode,
|
||||||
|
int32_t aOffset,
|
||||||
|
nsCOMPtr<nsINode>* outVisNode,
|
||||||
|
int32_t* outVisOffset,
|
||||||
|
WSType* outType);
|
||||||
|
|
||||||
|
// AdjustWhitespace examines the ws object for nbsp's that can
|
||||||
|
// be safely converted to regular ascii space and converts them.
|
||||||
|
nsresult AdjustWhitespace();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// WSFragment represents a single run of ws (all leadingws, or all normalws,
|
||||||
|
// or all trailingws, or all leading+trailingws). Note that this single run
|
||||||
|
// may still span multiple nodes.
|
||||||
|
struct WSFragment final
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsINode> mStartNode; // node where ws run starts
|
||||||
|
nsCOMPtr<nsINode> mEndNode; // node where ws run ends
|
||||||
|
int32_t mStartOffset; // offset where ws run starts
|
||||||
|
int32_t mEndOffset; // offset where ws run ends
|
||||||
|
// type of ws, and what is to left and right of it
|
||||||
|
WSType mType, mLeftType, mRightType;
|
||||||
|
// other ws runs to left or right. may be null.
|
||||||
|
WSFragment *mLeft, *mRight;
|
||||||
|
|
||||||
|
WSFragment()
|
||||||
|
: mStartOffset(0)
|
||||||
|
, mEndOffset(0)
|
||||||
|
, mLeft(nullptr)
|
||||||
|
, mRight(nullptr)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A WSPoint struct represents a unique location within the ws run. It is
|
||||||
|
// always within a textnode that is one of the nodes stored in the list
|
||||||
|
// in the wsRunObject. For convenience, the character at that point is also
|
||||||
|
// stored in the struct.
|
||||||
|
struct MOZ_STACK_CLASS WSPoint final
|
||||||
|
{
|
||||||
|
RefPtr<dom::Text> mTextNode;
|
||||||
|
uint32_t mOffset;
|
||||||
|
char16_t mChar;
|
||||||
|
|
||||||
|
WSPoint()
|
||||||
|
: mTextNode(0)
|
||||||
|
, mOffset(0)
|
||||||
|
, mChar(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
WSPoint(dom::Text* aTextNode, int32_t aOffset, char16_t aChar)
|
||||||
|
: mTextNode(aTextNode)
|
||||||
|
, mOffset(aOffset)
|
||||||
|
, mChar(aChar)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AreaRestriction
|
||||||
|
{
|
||||||
|
eAnywhere, eOutsideUserSelectAll
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the node which we will handle white-space under. This is the
|
||||||
|
* closest block within the DOM subtree we're editing, or if none is
|
||||||
|
* found, the (inline) root of the editable subtree.
|
||||||
|
*/
|
||||||
|
nsINode* GetWSBoundingParent();
|
||||||
|
|
||||||
|
nsresult GetWSNodes();
|
||||||
|
void GetRuns();
|
||||||
|
void ClearRuns();
|
||||||
|
void MakeSingleWSRun(WSType aType);
|
||||||
|
nsIContent* GetPreviousWSNodeInner(nsINode* aStartNode,
|
||||||
|
nsINode* aBlockParent);
|
||||||
|
nsIContent* GetPreviousWSNode(EditorDOMPoint aPoint, nsINode* aBlockParent);
|
||||||
|
nsIContent* GetNextWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent);
|
||||||
|
nsIContent* GetNextWSNode(EditorDOMPoint aPoint, nsINode* aBlockParent);
|
||||||
|
nsresult PrepareToDeleteRangePriv(WSRunObject* aEndObject);
|
||||||
|
nsresult PrepareToSplitAcrossBlocksPriv();
|
||||||
|
nsresult DeleteChars(nsINode* aStartNode, int32_t aStartOffset,
|
||||||
|
nsINode* aEndNode, int32_t aEndOffset,
|
||||||
|
AreaRestriction aAR = eAnywhere);
|
||||||
|
WSPoint GetCharAfter(nsINode* aNode, int32_t aOffset);
|
||||||
|
WSPoint GetCharBefore(nsINode* aNode, int32_t aOffset);
|
||||||
|
WSPoint GetCharAfter(const WSPoint& aPoint);
|
||||||
|
WSPoint GetCharBefore(const WSPoint& aPoint);
|
||||||
|
nsresult ConvertToNBSP(WSPoint aPoint,
|
||||||
|
AreaRestriction aAR = eAnywhere);
|
||||||
|
void GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
|
||||||
|
dom::Text** outStartNode, int32_t* outStartOffset,
|
||||||
|
dom::Text** outEndNode, int32_t* outEndOffset);
|
||||||
|
void FindRun(nsINode* aNode, int32_t aOffset, WSFragment** outRun,
|
||||||
|
bool after);
|
||||||
|
char16_t GetCharAt(dom::Text* aTextNode, int32_t aOffset);
|
||||||
|
WSPoint GetWSPointAfter(nsINode* aNode, int32_t aOffset);
|
||||||
|
WSPoint GetWSPointBefore(nsINode* aNode, int32_t aOffset);
|
||||||
|
nsresult CheckTrailingNBSPOfRun(WSFragment *aRun);
|
||||||
|
nsresult CheckTrailingNBSP(WSFragment* aRun, nsINode* aNode,
|
||||||
|
int32_t aOffset);
|
||||||
|
nsresult CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
|
||||||
|
int32_t aOffset);
|
||||||
|
|
||||||
|
nsresult Scrub();
|
||||||
|
bool IsBlockNode(nsINode* aNode);
|
||||||
|
|
||||||
|
// The node passed to our constructor.
|
||||||
|
nsCOMPtr<nsINode> mNode;
|
||||||
|
// The offset passed to our contructor.
|
||||||
|
int32_t mOffset;
|
||||||
|
// Together, the above represent the point at which we are building up ws info.
|
||||||
|
|
||||||
|
// true if we are in preformatted whitespace context.
|
||||||
|
bool mPRE;
|
||||||
|
// Node/offset where ws starts.
|
||||||
|
nsCOMPtr<nsINode> mStartNode;
|
||||||
|
int32_t mStartOffset;
|
||||||
|
// Reason why ws starts (eText, eOtherBlock, etc).
|
||||||
|
WSType mStartReason;
|
||||||
|
// The node that implicated by start reason.
|
||||||
|
nsCOMPtr<nsINode> mStartReasonNode;
|
||||||
|
|
||||||
|
// Node/offset where ws ends.
|
||||||
|
nsCOMPtr<nsINode> mEndNode;
|
||||||
|
int32_t mEndOffset;
|
||||||
|
// Reason why ws ends (eText, eOtherBlock, etc).
|
||||||
|
WSType mEndReason;
|
||||||
|
// The node that implicated by end reason.
|
||||||
|
nsCOMPtr<nsINode> mEndReasonNode;
|
||||||
|
|
||||||
|
// Location of first nbsp in ws run, if any.
|
||||||
|
RefPtr<dom::Text> mFirstNBSPNode;
|
||||||
|
int32_t mFirstNBSPOffset;
|
||||||
|
|
||||||
|
// Location of last nbsp in ws run, if any.
|
||||||
|
RefPtr<dom::Text> mLastNBSPNode;
|
||||||
|
int32_t mLastNBSPOffset;
|
||||||
|
|
||||||
|
// The list of nodes containing ws in this run.
|
||||||
|
nsTArray<RefPtr<dom::Text>> mNodeArray;
|
||||||
|
|
||||||
|
// The first WSFragment in the run.
|
||||||
|
WSFragment* mStartRun;
|
||||||
|
// The last WSFragment in the run, may be same as first.
|
||||||
|
WSFragment* mEndRun;
|
||||||
|
|
||||||
|
// Non-owning.
|
||||||
|
nsHTMLEditor* mHTMLEditor;
|
||||||
|
|
||||||
|
// Opening this class up for pillaging.
|
||||||
|
friend class nsHTMLEditRules;
|
||||||
|
// Opening this class up for more pillaging.
|
||||||
|
friend class nsHTMLEditor;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // #ifndef WSRunObject_h
|
||||||
@@ -53,7 +53,6 @@ UNIFIED_SOURCES += [
|
|||||||
'nsTableEditor.cpp',
|
'nsTableEditor.cpp',
|
||||||
'nsTextEditRules.cpp',
|
'nsTextEditRules.cpp',
|
||||||
'nsTextEditRulesBidi.cpp',
|
'nsTextEditRulesBidi.cpp',
|
||||||
'nsWSRunObject.cpp',
|
|
||||||
'PlaceholderTransaction.cpp',
|
'PlaceholderTransaction.cpp',
|
||||||
'SelectionState.cpp',
|
'SelectionState.cpp',
|
||||||
'SetDocumentTitleTransaction.cpp',
|
'SetDocumentTitleTransaction.cpp',
|
||||||
@@ -62,6 +61,7 @@ UNIFIED_SOURCES += [
|
|||||||
'TextEditorTest.cpp',
|
'TextEditorTest.cpp',
|
||||||
'TextEditUtils.cpp',
|
'TextEditUtils.cpp',
|
||||||
'TypeInState.cpp',
|
'TypeInState.cpp',
|
||||||
|
'WSRunObject.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "HTMLEditUtils.h"
|
#include "HTMLEditUtils.h"
|
||||||
#include "SelectionState.h"
|
#include "SelectionState.h"
|
||||||
#include "TextEditUtils.h"
|
#include "TextEditUtils.h"
|
||||||
|
#include "WSRunObject.h"
|
||||||
#include "mozilla/dom/DataTransfer.h"
|
#include "mozilla/dom/DataTransfer.h"
|
||||||
#include "mozilla/dom/DocumentFragment.h"
|
#include "mozilla/dom/DocumentFragment.h"
|
||||||
#include "mozilla/dom/DOMStringList.h"
|
#include "mozilla/dom/DOMStringList.h"
|
||||||
@@ -81,7 +82,6 @@
|
|||||||
#include "nsSubstringTuple.h"
|
#include "nsSubstringTuple.h"
|
||||||
#include "nsTextEditRules.h"
|
#include "nsTextEditRules.h"
|
||||||
#include "nsTreeSanitizer.h"
|
#include "nsTreeSanitizer.h"
|
||||||
#include "nsWSRunObject.h"
|
|
||||||
#include "nsXPCOM.h"
|
#include "nsXPCOM.h"
|
||||||
#include "nscore.h"
|
#include "nscore.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
@@ -389,7 +389,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
|
|||||||
// if there are any invisible br's after our insertion point, remove them.
|
// if there are any invisible br's after our insertion point, remove them.
|
||||||
// this is because if there is a br at end of what we paste, it will make
|
// this is because if there is a br at end of what we paste, it will make
|
||||||
// the invisible br visible.
|
// the invisible br visible.
|
||||||
nsWSRunObject wsObj(this, parentNode, offsetOfNewNode);
|
WSRunObject wsObj(this, parentNode, offsetOfNewNode);
|
||||||
if (wsObj.mEndReasonNode &&
|
if (wsObj.mEndReasonNode &&
|
||||||
TextEditUtils::IsBreak(wsObj.mEndReasonNode) &&
|
TextEditUtils::IsBreak(wsObj.mEndReasonNode) &&
|
||||||
!IsVisBreak(wsObj.mEndReasonNode)) {
|
!IsVisBreak(wsObj.mEndReasonNode)) {
|
||||||
@@ -647,7 +647,7 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure we don't end up with selection collapsed after an invisible break node
|
// make sure we don't end up with selection collapsed after an invisible break node
|
||||||
nsWSRunObject wsRunObj(this, selNode, selOffset);
|
WSRunObject wsRunObj(this, selNode, selOffset);
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
int32_t outVisOffset=0;
|
int32_t outVisOffset=0;
|
||||||
WSType visType;
|
WSType visType;
|
||||||
@@ -658,14 +658,14 @@ nsHTMLEditor::DoInsertHTMLWithContext(const nsAString & aInputString,
|
|||||||
// we are after a break. Is it visible? Despite the name,
|
// we are after a break. Is it visible? Despite the name,
|
||||||
// PriorVisibleNode does not make that determination for breaks.
|
// PriorVisibleNode does not make that determination for breaks.
|
||||||
// It also may not return the break in visNode. We have to pull it
|
// It also may not return the break in visNode. We have to pull it
|
||||||
// out of the nsWSRunObject's state.
|
// out of the WSRunObject's state.
|
||||||
if (!IsVisBreak(wsRunObj.mStartReasonNode))
|
if (!IsVisBreak(wsRunObj.mStartReasonNode))
|
||||||
{
|
{
|
||||||
// don't leave selection past an invisible break;
|
// don't leave selection past an invisible break;
|
||||||
// reset {selNode,selOffset} to point before break
|
// reset {selNode,selOffset} to point before break
|
||||||
selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset);
|
selNode = GetNodeLocation(GetAsDOMNode(wsRunObj.mStartReasonNode), &selOffset);
|
||||||
// we want to be inside any inline style prior to break
|
// we want to be inside any inline style prior to break
|
||||||
nsWSRunObject wsRunObj(this, selNode, selOffset);
|
WSRunObject wsRunObj(this, selNode, selOffset);
|
||||||
selNode_ = do_QueryInterface(selNode);
|
selNode_ = do_QueryInterface(selNode);
|
||||||
wsRunObj.PriorVisibleNode(selNode_, selOffset, address_of(visNode),
|
wsRunObj.PriorVisibleNode(selNode_, selOffset, address_of(visNode),
|
||||||
&outVisOffset, &visType);
|
&outVisOffset, &visType);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "EditorUtils.h"
|
#include "EditorUtils.h"
|
||||||
#include "HTMLEditUtils.h"
|
#include "HTMLEditUtils.h"
|
||||||
#include "TextEditUtils.h"
|
#include "TextEditUtils.h"
|
||||||
|
#include "WSRunObject.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
@@ -53,7 +54,6 @@
|
|||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsUnicharUtils.h"
|
#include "nsUnicharUtils.h"
|
||||||
#include "nsWSRunObject.h"
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
// Workaround for windows headers
|
// Workaround for windows headers
|
||||||
@@ -514,14 +514,14 @@ nsHTMLEditRules::AfterEditInner(EditAction action,
|
|||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
NS_ENSURE_STATE(mRangeItem->startNode);
|
NS_ENSURE_STATE(mRangeItem->startNode);
|
||||||
NS_ENSURE_STATE(mRangeItem->endNode);
|
NS_ENSURE_STATE(mRangeItem->endNode);
|
||||||
nsWSRunObject(mHTMLEditor, mRangeItem->startNode,
|
WSRunObject(mHTMLEditor, mRangeItem->startNode,
|
||||||
mRangeItem->startOffset).AdjustWhitespace();
|
mRangeItem->startOffset).AdjustWhitespace();
|
||||||
// we only need to handle old selection endpoint if it was different from start
|
// we only need to handle old selection endpoint if it was different from start
|
||||||
if (mRangeItem->startNode != mRangeItem->endNode ||
|
if (mRangeItem->startNode != mRangeItem->endNode ||
|
||||||
mRangeItem->startOffset != mRangeItem->endOffset) {
|
mRangeItem->startOffset != mRangeItem->endOffset) {
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsWSRunObject(mHTMLEditor, mRangeItem->endNode,
|
WSRunObject(mHTMLEditor, mRangeItem->endNode,
|
||||||
mRangeItem->endOffset).AdjustWhitespace();
|
mRangeItem->endOffset).AdjustWhitespace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,7 +1304,7 @@ nsHTMLEditRules::WillInsertText(EditAction aAction,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (aAction == EditAction::insertIMEText) {
|
if (aAction == EditAction::insertIMEText) {
|
||||||
// Right now the nsWSRunObject code bails on empty strings, but IME needs
|
// Right now the WSRunObject code bails on empty strings, but IME needs
|
||||||
// the InsertTextImpl() call to still happen since empty strings are meaningful there.
|
// the InsertTextImpl() call to still happen since empty strings are meaningful there.
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
// If there is one or more IME selections, its minimum offset should be
|
// If there is one or more IME selections, its minimum offset should be
|
||||||
@@ -1321,7 +1321,7 @@ nsHTMLEditRules::WillInsertText(EditAction aAction,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nsWSRunObject wsObj(mHTMLEditor, selNode, selOffset);
|
WSRunObject wsObj(mHTMLEditor, selNode, selOffset);
|
||||||
res = wsObj.InsertText(*inString, address_of(selNode), &selOffset, doc);
|
res = wsObj.InsertText(*inString, address_of(selNode), &selOffset, doc);
|
||||||
}
|
}
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
@@ -1424,7 +1424,7 @@ nsHTMLEditRules::WillInsertText(EditAction aAction,
|
|||||||
|
|
||||||
nsDependentSubstring subStr(tString, oldPos, subStrLen);
|
nsDependentSubstring subStr(tString, oldPos, subStrLen);
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsWSRunObject wsObj(mHTMLEditor, curNode, curOffset);
|
WSRunObject wsObj(mHTMLEditor, curNode, curOffset);
|
||||||
|
|
||||||
// is it a tab?
|
// is it a tab?
|
||||||
if (subStr.Equals(tabStr))
|
if (subStr.Equals(tabStr))
|
||||||
@@ -1604,7 +1604,7 @@ nsHTMLEditRules::StandardBreakImpl(nsINode& aNode, int32_t aOffset,
|
|||||||
brNode = mHTMLEditor->CreateBR(node, aOffset);
|
brNode = mHTMLEditor->CreateBR(node, aOffset);
|
||||||
NS_ENSURE_STATE(brNode);
|
NS_ENSURE_STATE(brNode);
|
||||||
} else {
|
} else {
|
||||||
nsWSRunObject wsObj(mHTMLEditor, node, aOffset);
|
WSRunObject wsObj(mHTMLEditor, node, aOffset);
|
||||||
int32_t visOffset = 0;
|
int32_t visOffset = 0;
|
||||||
WSType wsType;
|
WSType wsType;
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
@@ -1644,7 +1644,7 @@ nsHTMLEditRules::StandardBreakImpl(nsINode& aNode, int32_t aOffset,
|
|||||||
res = aSelection.Collapse(node, offset);
|
res = aSelection.Collapse(node, offset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
} else {
|
} else {
|
||||||
nsWSRunObject wsObj(mHTMLEditor, node, offset + 1);
|
WSRunObject wsObj(mHTMLEditor, node, offset + 1);
|
||||||
nsCOMPtr<nsINode> secondBR;
|
nsCOMPtr<nsINode> secondBR;
|
||||||
int32_t visOffset = 0;
|
int32_t visOffset = 0;
|
||||||
WSType wsType;
|
WSType wsType;
|
||||||
@@ -1714,7 +1714,7 @@ nsHTMLEditRules::SplitMailCites(Selection* aSelection, bool* aHandled)
|
|||||||
// The latter can confuse a user if they click there and start typing,
|
// The latter can confuse a user if they click there and start typing,
|
||||||
// because being in the mailquote may affect wrapping behavior, or font color, etc.
|
// because being in the mailquote may affect wrapping behavior, or font color, etc.
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsWSRunObject wsObj(mHTMLEditor, selNode, selOffset);
|
WSRunObject wsObj(mHTMLEditor, selNode, selOffset);
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
int32_t visOffset=0;
|
int32_t visOffset=0;
|
||||||
WSType wsType;
|
WSType wsType;
|
||||||
@@ -1750,7 +1750,7 @@ nsHTMLEditRules::SplitMailCites(Selection* aSelection, bool* aHandled)
|
|||||||
// then we will need a 2nd br added to achieve blank line that user expects.
|
// then we will need a 2nd br added to achieve blank line that user expects.
|
||||||
if (IsInlineNode(*citeNode)) {
|
if (IsInlineNode(*citeNode)) {
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsWSRunObject wsObj(mHTMLEditor, selNode, newOffset);
|
WSRunObject wsObj(mHTMLEditor, selNode, newOffset);
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
int32_t visOffset=0;
|
int32_t visOffset=0;
|
||||||
WSType wsType;
|
WSType wsType;
|
||||||
@@ -1759,7 +1759,7 @@ nsHTMLEditRules::SplitMailCites(Selection* aSelection, bool* aHandled)
|
|||||||
if (wsType == WSType::normalWS || wsType == WSType::text ||
|
if (wsType == WSType::normalWS || wsType == WSType::text ||
|
||||||
wsType == WSType::special) {
|
wsType == WSType::special) {
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsWSRunObject wsObjAfterBR(mHTMLEditor, selNode, newOffset+1);
|
WSRunObject wsObjAfterBR(mHTMLEditor, selNode, newOffset+1);
|
||||||
wsObjAfterBR.NextVisibleNode(selNode, newOffset + 1,
|
wsObjAfterBR.NextVisibleNode(selNode, newOffset + 1,
|
||||||
address_of(visNode), &visOffset, &wsType);
|
address_of(visNode), &visOffset, &wsType);
|
||||||
if (wsType == WSType::normalWS || wsType == WSType::text ||
|
if (wsType == WSType::normalWS || wsType == WSType::text ||
|
||||||
@@ -1895,7 +1895,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
|||||||
if (bCollapsed) {
|
if (bCollapsed) {
|
||||||
// What's in the direction we are deleting?
|
// What's in the direction we are deleting?
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsWSRunObject wsObj(mHTMLEditor, startNode, startOffset);
|
WSRunObject wsObj(mHTMLEditor, startNode, startOffset);
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
int32_t visOffset;
|
int32_t visOffset;
|
||||||
WSType wsType;
|
WSType wsType;
|
||||||
@@ -1960,7 +1960,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
|||||||
eo = range->EndOffset();
|
eo = range->EndOffset();
|
||||||
}
|
}
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
res = WSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
||||||
address_of(visNode), &so, address_of(visNode), &eo);
|
address_of(visNode), &so, address_of(visNode), &eo);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
@@ -2051,7 +2051,7 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
|||||||
|
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsCOMPtr<nsIContent> otherContent(do_QueryInterface(otherNode));
|
nsCOMPtr<nsIContent> otherContent(do_QueryInterface(otherNode));
|
||||||
res = nsWSRunObject::PrepareToDeleteNode(mHTMLEditor, otherContent);
|
res = WSRunObject::PrepareToDeleteNode(mHTMLEditor, otherContent);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
res = mHTMLEditor->DeleteNode(otherNode);
|
res = mHTMLEditor->DeleteNode(otherNode);
|
||||||
@@ -2066,8 +2066,8 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
|||||||
// Found break or image, or hr.
|
// Found break or image, or hr.
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
NS_ENSURE_STATE(visNode->IsContent());
|
NS_ENSURE_STATE(visNode->IsContent());
|
||||||
res = nsWSRunObject::PrepareToDeleteNode(mHTMLEditor,
|
res = WSRunObject::PrepareToDeleteNode(mHTMLEditor,
|
||||||
visNode->AsContent());
|
visNode->AsContent());
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
// Remember sibling to visnode, if any
|
// Remember sibling to visnode, if any
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
@@ -2254,9 +2254,9 @@ nsHTMLEditRules::WillDeleteSelection(Selection* aSelection,
|
|||||||
if (!IsPlaintextEditor()) {
|
if (!IsPlaintextEditor()) {
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
|
AutoTransactionsConserveSelection dontSpazMySelection(mHTMLEditor);
|
||||||
res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
res = WSRunObject::PrepareToDeleteRange(mHTMLEditor,
|
||||||
address_of(startNode), &startOffset,
|
address_of(startNode), &startOffset,
|
||||||
address_of(endNode), &endOffset);
|
address_of(endNode), &endOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2492,7 +2492,7 @@ nsHTMLEditRules::InsertBRIfNeeded(Selection* aSelection)
|
|||||||
|
|
||||||
// examine selection
|
// examine selection
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsWSRunObject wsObj(mHTMLEditor, node, offset);
|
WSRunObject wsObj(mHTMLEditor, node, offset);
|
||||||
if (((wsObj.mStartReason & WSType::block) ||
|
if (((wsObj.mStartReason & WSType::block) ||
|
||||||
(wsObj.mStartReason & WSType::br)) &&
|
(wsObj.mStartReason & WSType::br)) &&
|
||||||
(wsObj.mEndReason & WSType::block)) {
|
(wsObj.mEndReason & WSType::block)) {
|
||||||
@@ -2629,9 +2629,9 @@ nsHTMLEditRules::JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
|
|||||||
// Tricky case. Left block is inside right block. Do ws adjustment. This
|
// Tricky case. Left block is inside right block. Do ws adjustment. This
|
||||||
// just destroys non-visible ws at boundaries we will be joining.
|
// just destroys non-visible ws at boundaries we will be joining.
|
||||||
rightOffset++;
|
rightOffset++;
|
||||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
res = WSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||||
nsWSRunObject::kBlockEnd,
|
WSRunObject::kBlockEnd,
|
||||||
leftBlock);
|
leftBlock);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -2639,9 +2639,9 @@ nsHTMLEditRules::JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
|
|||||||
nsCOMPtr<nsINode> trackingRightBlock(rightBlock);
|
nsCOMPtr<nsINode> trackingRightBlock(rightBlock);
|
||||||
AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
||||||
address_of(trackingRightBlock), &rightOffset);
|
address_of(trackingRightBlock), &rightOffset);
|
||||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
res = WSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||||
nsWSRunObject::kAfterBlock,
|
WSRunObject::kAfterBlock,
|
||||||
rightBlock, rightOffset);
|
rightBlock, rightOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
if (trackingRightBlock->IsElement()) {
|
if (trackingRightBlock->IsElement()) {
|
||||||
rightBlock = trackingRightBlock->AsElement();
|
rightBlock = trackingRightBlock->AsElement();
|
||||||
@@ -2672,9 +2672,9 @@ nsHTMLEditRules::JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
|
|||||||
} else if (EditorUtils::IsDescendantOf(rightBlock, leftBlock, &leftOffset)) {
|
} else if (EditorUtils::IsDescendantOf(rightBlock, leftBlock, &leftOffset)) {
|
||||||
// Tricky case. Right block is inside left block. Do ws adjustment. This
|
// Tricky case. Right block is inside left block. Do ws adjustment. This
|
||||||
// just destroys non-visible ws at boundaries we will be joining.
|
// just destroys non-visible ws at boundaries we will be joining.
|
||||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
res = WSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||||
nsWSRunObject::kBlockStart,
|
WSRunObject::kBlockStart,
|
||||||
rightBlock);
|
rightBlock);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
{
|
{
|
||||||
// We can't just track leftBlock because it's an Element, so track
|
// We can't just track leftBlock because it's an Element, so track
|
||||||
@@ -2682,9 +2682,9 @@ nsHTMLEditRules::JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
|
|||||||
nsCOMPtr<nsINode> trackingLeftBlock(leftBlock);
|
nsCOMPtr<nsINode> trackingLeftBlock(leftBlock);
|
||||||
AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
|
||||||
address_of(trackingLeftBlock), &leftOffset);
|
address_of(trackingLeftBlock), &leftOffset);
|
||||||
res = nsWSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
res = WSRunObject::ScrubBlockBoundary(mHTMLEditor,
|
||||||
nsWSRunObject::kBeforeBlock,
|
WSRunObject::kBeforeBlock,
|
||||||
leftBlock, leftOffset);
|
leftBlock, leftOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
if (trackingLeftBlock->IsElement()) {
|
if (trackingLeftBlock->IsElement()) {
|
||||||
leftBlock = trackingLeftBlock->AsElement();
|
leftBlock = trackingLeftBlock->AsElement();
|
||||||
@@ -2766,7 +2766,7 @@ nsHTMLEditRules::JoinBlocks(nsIContent& aLeftNode, nsIContent& aRightNode,
|
|||||||
// if you backspace from li into p.
|
// if you backspace from li into p.
|
||||||
|
|
||||||
// Adjust whitespace at block boundaries
|
// Adjust whitespace at block boundaries
|
||||||
res = nsWSRunObject::PrepareToJoinBlocks(mHTMLEditor, leftBlock, rightBlock);
|
res = WSRunObject::PrepareToJoinBlocks(mHTMLEditor, leftBlock, rightBlock);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
// Do br adjustment.
|
// Do br adjustment.
|
||||||
nsCOMPtr<Element> brNode =
|
nsCOMPtr<Element> brNode =
|
||||||
@@ -4893,7 +4893,7 @@ nsHTMLEditRules::CheckForInvisibleBR(Element& aBlock, BRLocation aWhere,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWSRunObject wsTester(mHTMLEditor, testNode, testOffset);
|
WSRunObject wsTester(mHTMLEditor, testNode, testOffset);
|
||||||
if (WSType::br == wsTester.mStartReason) {
|
if (WSType::br == wsTester.mStartReason) {
|
||||||
return wsTester.mStartReasonNode->AsElement();
|
return wsTester.mStartReasonNode->AsElement();
|
||||||
}
|
}
|
||||||
@@ -4972,7 +4972,7 @@ nsHTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
|
|||||||
// Find previous visible thingy before start of selection
|
// Find previous visible thingy before start of selection
|
||||||
if (selStartNode != selCommon && selStartNode != root) {
|
if (selStartNode != selCommon && selStartNode != root) {
|
||||||
while (true) {
|
while (true) {
|
||||||
nsWSRunObject wsObj(mHTMLEditor, selStartNode, selStartOffset);
|
WSRunObject wsObj(mHTMLEditor, selStartNode, selStartOffset);
|
||||||
wsObj.PriorVisibleNode(selStartNode, selStartOffset, address_of(unused),
|
wsObj.PriorVisibleNode(selStartNode, selStartOffset, address_of(unused),
|
||||||
&visOffset, &wsType);
|
&visOffset, &wsType);
|
||||||
if (wsType != WSType::thisBlock) {
|
if (wsType != WSType::thisBlock) {
|
||||||
@@ -4994,7 +4994,7 @@ nsHTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
|
|||||||
// Find next visible thingy after end of selection
|
// Find next visible thingy after end of selection
|
||||||
if (selEndNode != selCommon && selEndNode != root) {
|
if (selEndNode != selCommon && selEndNode != root) {
|
||||||
while (true) {
|
while (true) {
|
||||||
nsWSRunObject wsObj(mHTMLEditor, selEndNode, selEndOffset);
|
WSRunObject wsObj(mHTMLEditor, selEndNode, selEndOffset);
|
||||||
wsObj.NextVisibleNode(selEndNode, selEndOffset, address_of(unused),
|
wsObj.NextVisibleNode(selEndNode, selEndOffset, address_of(unused),
|
||||||
&visOffset, &wsType);
|
&visOffset, &wsType);
|
||||||
if (wsType == WSType::br) {
|
if (wsType == WSType::br) {
|
||||||
@@ -5117,7 +5117,7 @@ nsHTMLEditRules::NormalizeSelection(Selection* inSelection)
|
|||||||
WSType wsType;
|
WSType wsType;
|
||||||
|
|
||||||
// let the whitespace code do the heavy lifting
|
// let the whitespace code do the heavy lifting
|
||||||
nsWSRunObject wsEndObj(mHTMLEditor, endNode, endOffset);
|
WSRunObject wsEndObj(mHTMLEditor, endNode, endOffset);
|
||||||
// is there any intervening visible whitespace? if so we can't push selection past that,
|
// is there any intervening visible whitespace? if so we can't push selection past that,
|
||||||
// it would visibly change maening of users selection
|
// it would visibly change maening of users selection
|
||||||
nsCOMPtr<nsINode> endNode_(do_QueryInterface(endNode));
|
nsCOMPtr<nsINode> endNode_(do_QueryInterface(endNode));
|
||||||
@@ -5157,7 +5157,7 @@ nsHTMLEditRules::NormalizeSelection(Selection* inSelection)
|
|||||||
|
|
||||||
|
|
||||||
// similar dealio for start of range
|
// similar dealio for start of range
|
||||||
nsWSRunObject wsStartObj(mHTMLEditor, startNode, startOffset);
|
WSRunObject wsStartObj(mHTMLEditor, startNode, startOffset);
|
||||||
// is there any intervening visible whitespace? if so we can't push selection past that,
|
// is there any intervening visible whitespace? if so we can't push selection past that,
|
||||||
// it would visibly change maening of users selection
|
// it would visibly change maening of users selection
|
||||||
nsCOMPtr<nsINode> startNode_(do_QueryInterface(startNode));
|
nsCOMPtr<nsINode> startNode_(do_QueryInterface(startNode));
|
||||||
@@ -6143,9 +6143,9 @@ nsHTMLEditRules::ReturnInHeader(Selection& aSelection,
|
|||||||
|
|
||||||
// Get ws code to adjust any ws
|
// Get ws code to adjust any ws
|
||||||
nsCOMPtr<nsINode> node = &aNode;
|
nsCOMPtr<nsINode> node = &aNode;
|
||||||
nsresult res = nsWSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
|
nsresult res = WSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
|
||||||
address_of(node),
|
address_of(node),
|
||||||
&aOffset);
|
&aOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
// Split the header
|
// Split the header
|
||||||
@@ -6340,7 +6340,8 @@ nsHTMLEditRules::SplitParagraph(nsIDOMNode *aPara,
|
|||||||
nsCOMPtr<nsIContent> leftPara, rightPara;
|
nsCOMPtr<nsIContent> leftPara, rightPara;
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
nsCOMPtr<nsINode> selNode(do_QueryInterface(*aSelNode));
|
nsCOMPtr<nsINode> selNode(do_QueryInterface(*aSelNode));
|
||||||
res = nsWSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor, address_of(selNode), aOffset);
|
res = WSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
|
||||||
|
address_of(selNode), aOffset);
|
||||||
*aSelNode = GetAsDOMNode(selNode);
|
*aSelNode = GetAsDOMNode(selNode);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
// split the paragraph
|
// split the paragraph
|
||||||
@@ -6465,9 +6466,9 @@ nsHTMLEditRules::ReturnInListItem(Selection& aSelection,
|
|||||||
// Else we want a new list item at the same list level. Get ws code to
|
// Else we want a new list item at the same list level. Get ws code to
|
||||||
// adjust any ws.
|
// adjust any ws.
|
||||||
nsCOMPtr<nsINode> selNode = &aNode;
|
nsCOMPtr<nsINode> selNode = &aNode;
|
||||||
res = nsWSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
|
res = WSRunObject::PrepareToSplitAcrossBlocks(mHTMLEditor,
|
||||||
address_of(selNode),
|
address_of(selNode),
|
||||||
&aOffset);
|
&aOffset);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
// Now split list item
|
// Now split list item
|
||||||
NS_ENSURE_STATE(selNode->IsContent());
|
NS_ENSURE_STATE(selNode->IsContent());
|
||||||
@@ -6519,7 +6520,7 @@ nsHTMLEditRules::ReturnInListItem(Selection& aSelection,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nsWSRunObject wsObj(mHTMLEditor, &aListItem, 0);
|
WSRunObject wsObj(mHTMLEditor, &aListItem, 0);
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
int32_t visOffset = 0;
|
int32_t visOffset = 0;
|
||||||
WSType wsType;
|
WSType wsType;
|
||||||
@@ -7131,7 +7132,7 @@ nsHTMLEditRules::AdjustWhitespace(Selection* aSelection)
|
|||||||
|
|
||||||
// ask whitespace object to tweak nbsp's
|
// ask whitespace object to tweak nbsp's
|
||||||
NS_ENSURE_STATE(mHTMLEditor);
|
NS_ENSURE_STATE(mHTMLEditor);
|
||||||
return nsWSRunObject(mHTMLEditor, selNode, selOffset).AdjustWhitespace();
|
return WSRunObject(mHTMLEditor, selNode, selOffset).AdjustWhitespace();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
// Misc
|
// Misc
|
||||||
#include "EditorUtils.h"
|
#include "EditorUtils.h"
|
||||||
#include "TextEditorTest.h"
|
#include "TextEditorTest.h"
|
||||||
#include "nsWSRunObject.h"
|
#include "WSRunObject.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
#include "nsIWidget.h"
|
#include "nsIWidget.h"
|
||||||
|
|
||||||
@@ -549,7 +549,7 @@ nsHTMLEditor::BeginningOfDocument()
|
|||||||
nsCOMPtr<nsINode> curNode = rootElement.get(), selNode;
|
nsCOMPtr<nsINode> curNode = rootElement.get(), selNode;
|
||||||
int32_t curOffset = 0, selOffset = 0;
|
int32_t curOffset = 0, selOffset = 0;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
nsWSRunObject wsObj(this, curNode, curOffset);
|
WSRunObject wsObj(this, curNode, curOffset);
|
||||||
int32_t visOffset = 0;
|
int32_t visOffset = 0;
|
||||||
WSType visType;
|
WSType visType;
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
@@ -564,7 +564,7 @@ nsHTMLEditor::BeginningOfDocument()
|
|||||||
selOffset = selNode ? selNode->IndexOf(visNode) : -1;
|
selOffset = selNode ? selNode->IndexOf(visNode) : -1;
|
||||||
done = true;
|
done = true;
|
||||||
} else if (visType == WSType::otherBlock) {
|
} else if (visType == WSType::otherBlock) {
|
||||||
// By definition of nsWSRunObject, a block element terminates a
|
// By definition of WSRunObject, a block element terminates a
|
||||||
// whitespace run. That is, although we are calling a method that is
|
// whitespace run. That is, although we are calling a method that is
|
||||||
// named "NextVisibleNode", the node returned might not be
|
// named "NextVisibleNode", the node returned might not be
|
||||||
// visible/editable!
|
// visible/editable!
|
||||||
@@ -983,7 +983,7 @@ nsHTMLEditor::IsVisBreak(nsINode* aNode)
|
|||||||
nsCOMPtr<nsINode> selNode = GetNodeLocation(aNode, &selOffset);
|
nsCOMPtr<nsINode> selNode = GetNodeLocation(aNode, &selOffset);
|
||||||
// Let's look after the break
|
// Let's look after the break
|
||||||
selOffset++;
|
selOffset++;
|
||||||
nsWSRunObject wsObj(this, selNode, selOffset);
|
WSRunObject wsObj(this, selNode, selOffset);
|
||||||
nsCOMPtr<nsINode> unused;
|
nsCOMPtr<nsINode> unused;
|
||||||
int32_t visOffset = 0;
|
int32_t visOffset = 0;
|
||||||
WSType visType;
|
WSType visType;
|
||||||
@@ -1444,7 +1444,7 @@ nsHTMLEditor::NormalizeEOLInsertPosition(nsINode* firstNodeToInsert,
|
|||||||
if (!IsBlockNode(firstNodeToInsert))
|
if (!IsBlockNode(firstNodeToInsert))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nsWSRunObject wsObj(this, *insertParentNode, *insertOffset);
|
WSRunObject wsObj(this, *insertParentNode, *insertOffset);
|
||||||
nsCOMPtr<nsINode> nextVisNode, prevVisNode;
|
nsCOMPtr<nsINode> nextVisNode, prevVisNode;
|
||||||
int32_t nextVisOffset=0;
|
int32_t nextVisOffset=0;
|
||||||
WSType nextVisType;
|
WSType nextVisType;
|
||||||
@@ -4245,7 +4245,7 @@ nsHTMLEditor::IsVisTextNode(nsIContent* aNode,
|
|||||||
{
|
{
|
||||||
if (aNode->TextIsOnlyWhitespace())
|
if (aNode->TextIsOnlyWhitespace())
|
||||||
{
|
{
|
||||||
nsWSRunObject wsRunObj(this, aNode, 0);
|
WSRunObject wsRunObj(this, aNode, 0);
|
||||||
nsCOMPtr<nsINode> visNode;
|
nsCOMPtr<nsINode> visNode;
|
||||||
int32_t outVisOffset=0;
|
int32_t outVisOffset=0;
|
||||||
WSType visType;
|
WSType visType;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class nsRange;
|
|||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class TypeInState;
|
class TypeInState;
|
||||||
|
class WSRunObject;
|
||||||
struct PropItem;
|
struct PropItem;
|
||||||
template<class T> class OwningNonNull;
|
template<class T> class OwningNonNull;
|
||||||
namespace dom {
|
namespace dom {
|
||||||
@@ -973,9 +974,9 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// friends
|
// friends
|
||||||
|
friend class mozilla::WSRunObject;
|
||||||
friend class nsHTMLEditRules;
|
friend class nsHTMLEditRules;
|
||||||
friend class nsTextEditRules;
|
friend class nsTextEditRules;
|
||||||
friend class nsWSRunObject;
|
|
||||||
friend class nsHTMLEditorEventListener;
|
friend class nsHTMLEditorEventListener;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,388 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#ifndef __wsrunobject_h__
|
|
||||||
#define __wsrunobject_h__
|
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsIEditor.h" // for EDirection
|
|
||||||
#include "nsINode.h"
|
|
||||||
#include "nscore.h"
|
|
||||||
#include "mozilla/Attributes.h"
|
|
||||||
#include "mozilla/dom/Text.h"
|
|
||||||
|
|
||||||
class nsHTMLEditor;
|
|
||||||
class nsIDOMNode;
|
|
||||||
namespace mozilla {
|
|
||||||
struct EditorDOMPoint;
|
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
// class nsWSRunObject represents the entire whitespace situation
|
|
||||||
// around a given point. It collects up a list of nodes that contain
|
|
||||||
// whitespace and categorizes in up to 3 different WSFragments (detailed
|
|
||||||
// below). Each WSFragment is a collection of whitespace that is
|
|
||||||
// either all insignificant, or that is significant. A WSFragment could
|
|
||||||
// consist of insignificant whitespace because it is after a block
|
|
||||||
// boundary or after a break. Or it could be insignificant because it
|
|
||||||
// is before a block. Or it could be significant because it is
|
|
||||||
// surrounded by text, or starts and ends with nbsps, etc.
|
|
||||||
|
|
||||||
// Throughout I refer to LeadingWS, NormalWS, TrailingWS. LeadingWS & TrailingWS
|
|
||||||
// are runs of ascii ws that are insignificant (do not render) because they
|
|
||||||
// are adjacent to block boundaries, or after a break. NormalWS is ws that
|
|
||||||
// does cause soem rendering. Note that not all the ws in a NormalWS run need
|
|
||||||
// render. For example, two ascii spaces surrounded by text on both sides
|
|
||||||
// will only render as one space (in non-preformatted stlye html), yet both
|
|
||||||
// spaces count as NormalWS. Together, they render as the one visible space.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A type-safe bitfield indicating various types of whitespace or other things.
|
|
||||||
* Used as a member variable in nsWSRunObject and WSFragment.
|
|
||||||
*
|
|
||||||
* XXX: If this idea is useful in other places, we should generalize it using a
|
|
||||||
* template.
|
|
||||||
*/
|
|
||||||
class WSType {
|
|
||||||
public:
|
|
||||||
enum Enum {
|
|
||||||
none = 0,
|
|
||||||
leadingWS = 1, // leading insignificant ws, ie, after block or br
|
|
||||||
trailingWS = 1 << 1, // trailing insignificant ws, ie, before block
|
|
||||||
normalWS = 1 << 2, // normal significant ws, ie, after text, image, ...
|
|
||||||
text = 1 << 3, // indicates regular (non-ws) text
|
|
||||||
special = 1 << 4, // indicates an inline non-container, like image
|
|
||||||
br = 1 << 5, // indicates a br node
|
|
||||||
otherBlock = 1 << 6, // indicates a block other than one ws run is in
|
|
||||||
thisBlock = 1 << 7, // indicates the block ws run is in
|
|
||||||
block = otherBlock | thisBlock // block found
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implicit constructor, because the enums are logically just WSTypes
|
|
||||||
* themselves, and are only a separate type because there's no other obvious
|
|
||||||
* way to name specific WSType values.
|
|
||||||
*/
|
|
||||||
MOZ_IMPLICIT WSType(const Enum& aEnum = none) : mEnum(aEnum) {}
|
|
||||||
// operator==, &, and | need to access mEnum
|
|
||||||
friend bool operator==(const WSType& aLeft, const WSType& aRight);
|
|
||||||
friend const WSType operator&(const WSType& aLeft, const WSType& aRight);
|
|
||||||
friend const WSType operator|(const WSType& aLeft, const WSType& aRight);
|
|
||||||
WSType& operator=(const WSType& aOther) {
|
|
||||||
// This handles self-assignment fine
|
|
||||||
mEnum = aOther.mEnum;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
WSType& operator&=(const WSType& aOther) {
|
|
||||||
mEnum &= aOther.mEnum;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
WSType& operator|=(const WSType& aOther) {
|
|
||||||
mEnum |= aOther.mEnum;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
uint16_t mEnum;
|
|
||||||
void bool_conversion_helper() {}
|
|
||||||
public:
|
|
||||||
// Allow boolean conversion with no numeric conversion
|
|
||||||
typedef void (WSType::*bool_type)();
|
|
||||||
operator bool_type() const
|
|
||||||
{
|
|
||||||
return mEnum ? &WSType::bool_conversion_helper : nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are declared as global functions so "WSType::Enum == WSType" et al.
|
|
||||||
* will work using the implicit constructor.
|
|
||||||
*/
|
|
||||||
inline bool operator==(const WSType& aLeft, const WSType& aRight)
|
|
||||||
{
|
|
||||||
return aLeft.mEnum == aRight.mEnum;
|
|
||||||
}
|
|
||||||
inline bool operator!=(const WSType& aLeft, const WSType& aRight)
|
|
||||||
{
|
|
||||||
return !(aLeft == aRight);
|
|
||||||
}
|
|
||||||
inline const WSType operator&(const WSType& aLeft, const WSType& aRight)
|
|
||||||
{
|
|
||||||
WSType ret;
|
|
||||||
ret.mEnum = aLeft.mEnum & aRight.mEnum;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
inline const WSType operator|(const WSType& aLeft, const WSType& aRight)
|
|
||||||
{
|
|
||||||
WSType ret;
|
|
||||||
ret.mEnum = aLeft.mEnum | aRight.mEnum;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure that & and | of WSType::Enum creates a WSType instead of an int,
|
|
||||||
* because operators between WSType and int shouldn't work
|
|
||||||
*/
|
|
||||||
inline const WSType operator&(const WSType::Enum& aLeft,
|
|
||||||
const WSType::Enum& aRight)
|
|
||||||
{
|
|
||||||
return WSType(aLeft) & WSType(aRight);
|
|
||||||
}
|
|
||||||
inline const WSType operator|(const WSType::Enum& aLeft,
|
|
||||||
const WSType::Enum& aRight)
|
|
||||||
{
|
|
||||||
return WSType(aLeft) | WSType(aRight);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class MOZ_STACK_CLASS nsWSRunObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// public enums ---------------------------------------------------------
|
|
||||||
enum BlockBoundary
|
|
||||||
{
|
|
||||||
kBeforeBlock,
|
|
||||||
kBlockStart,
|
|
||||||
kBlockEnd,
|
|
||||||
kAfterBlock
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {eBefore = 1};
|
|
||||||
enum {eAfter = 1 << 1};
|
|
||||||
enum {eBoth = eBefore | eAfter};
|
|
||||||
|
|
||||||
// constructor / destructor -----------------------------------------------
|
|
||||||
nsWSRunObject(nsHTMLEditor* aEd, nsINode* aNode, int32_t aOffset);
|
|
||||||
nsWSRunObject(nsHTMLEditor *aEd, nsIDOMNode *aNode, int32_t aOffset);
|
|
||||||
~nsWSRunObject();
|
|
||||||
|
|
||||||
// public methods ---------------------------------------------------------
|
|
||||||
|
|
||||||
// ScrubBlockBoundary removes any non-visible whitespace at the specified
|
|
||||||
// location relative to a block node.
|
|
||||||
static nsresult ScrubBlockBoundary(nsHTMLEditor* aHTMLEd,
|
|
||||||
BlockBoundary aBoundary,
|
|
||||||
nsINode* aBlock,
|
|
||||||
int32_t aOffset = -1);
|
|
||||||
|
|
||||||
// PrepareToJoinBlocks fixes up ws at the end of aLeftBlock and the
|
|
||||||
// beginning of aRightBlock in preperation for them to be joined. Example
|
|
||||||
// of fixup: trailingws in aLeftBlock needs to be removed.
|
|
||||||
static nsresult PrepareToJoinBlocks(nsHTMLEditor* aEd,
|
|
||||||
mozilla::dom::Element* aLeftBlock,
|
|
||||||
mozilla::dom::Element* aRightBlock);
|
|
||||||
|
|
||||||
// PrepareToDeleteRange fixes up ws before {aStartNode,aStartOffset}
|
|
||||||
// and after {aEndNode,aEndOffset} in preperation for content
|
|
||||||
// in that range to be deleted. Note that the nodes and offsets
|
|
||||||
// are adjusted in response to any dom changes we make while
|
|
||||||
// adjusting ws.
|
|
||||||
// example of fixup: trailingws before {aStartNode,aStartOffset}
|
|
||||||
// needs to be removed.
|
|
||||||
static nsresult PrepareToDeleteRange(nsHTMLEditor* aHTMLEd,
|
|
||||||
nsCOMPtr<nsINode>* aStartNode,
|
|
||||||
int32_t* aStartOffset,
|
|
||||||
nsCOMPtr<nsINode>* aEndNode,
|
|
||||||
int32_t* aEndOffset);
|
|
||||||
|
|
||||||
// PrepareToDeleteNode fixes up ws before and after aContent in preparation
|
|
||||||
// for aContent to be deleted. Example of fixup: trailingws before
|
|
||||||
// aContent needs to be removed.
|
|
||||||
static nsresult PrepareToDeleteNode(nsHTMLEditor *aHTMLEd,
|
|
||||||
nsIContent* aContent);
|
|
||||||
|
|
||||||
// PrepareToSplitAcrossBlocks fixes up ws before and after
|
|
||||||
// {aSplitNode,aSplitOffset} in preparation for a block parent to be split.
|
|
||||||
// Note that the aSplitNode and aSplitOffset are adjusted in response to
|
|
||||||
// any DOM changes we make while adjusting ws. Example of fixup: normalws
|
|
||||||
// before {aSplitNode,aSplitOffset} needs to end with nbsp.
|
|
||||||
static nsresult PrepareToSplitAcrossBlocks(nsHTMLEditor* aHTMLEd,
|
|
||||||
nsCOMPtr<nsINode>* aSplitNode,
|
|
||||||
int32_t* aSplitOffset);
|
|
||||||
|
|
||||||
// InsertBreak inserts a br node at {aInOutParent,aInOutOffset}
|
|
||||||
// and makes any needed adjustments to ws around that point.
|
|
||||||
// example of fixup: normalws after {aInOutParent,aInOutOffset}
|
|
||||||
// needs to begin with nbsp.
|
|
||||||
mozilla::dom::Element* InsertBreak(nsCOMPtr<nsINode>* aInOutParent,
|
|
||||||
int32_t* aInOutOffset,
|
|
||||||
nsIEditor::EDirection aSelect);
|
|
||||||
|
|
||||||
// InsertText inserts a string at {aInOutParent,aInOutOffset} and makes any
|
|
||||||
// needed adjustments to ws around that point. Example of fixup:
|
|
||||||
// trailingws before {aInOutParent,aInOutOffset} needs to be removed.
|
|
||||||
nsresult InsertText(const nsAString& aStringToInsert,
|
|
||||||
nsCOMPtr<nsINode>* aInOutNode,
|
|
||||||
int32_t* aInOutOffset,
|
|
||||||
nsIDocument* aDoc);
|
|
||||||
|
|
||||||
// DeleteWSBackward deletes a single visible piece of ws before the ws
|
|
||||||
// point (the point to create the wsRunObject, passed to its constructor).
|
|
||||||
// It makes any needed conversion to adjacent ws to retain its
|
|
||||||
// significance.
|
|
||||||
nsresult DeleteWSBackward();
|
|
||||||
|
|
||||||
// DeleteWSForward deletes a single visible piece of ws after the ws point
|
|
||||||
// (the point to create the wsRunObject, passed to its constructor). It
|
|
||||||
// makes any needed conversion to adjacent ws to retain its significance.
|
|
||||||
nsresult DeleteWSForward();
|
|
||||||
|
|
||||||
// PriorVisibleNode returns the first piece of visible thing before
|
|
||||||
// {aNode,aOffset}. If there is no visible ws qualifying it returns what
|
|
||||||
// is before the ws run. Note that {outVisNode,outVisOffset} is set to
|
|
||||||
// just AFTER the visible object.
|
|
||||||
void PriorVisibleNode(nsINode* aNode,
|
|
||||||
int32_t aOffset,
|
|
||||||
nsCOMPtr<nsINode>* outVisNode,
|
|
||||||
int32_t* outVisOffset,
|
|
||||||
WSType* outType);
|
|
||||||
|
|
||||||
// NextVisibleNode returns the first piece of visible thing after
|
|
||||||
// {aNode,aOffset}. If there is no visible ws qualifying it returns what
|
|
||||||
// is after the ws run. Note that {outVisNode,outVisOffset} is set to just
|
|
||||||
// BEFORE the visible object.
|
|
||||||
void NextVisibleNode(nsINode* aNode,
|
|
||||||
int32_t aOffset,
|
|
||||||
nsCOMPtr<nsINode>* outVisNode,
|
|
||||||
int32_t* outVisOffset,
|
|
||||||
WSType* outType);
|
|
||||||
|
|
||||||
// AdjustWhitespace examines the ws object for nbsp's that can
|
|
||||||
// be safely converted to regular ascii space and converts them.
|
|
||||||
nsresult AdjustWhitespace();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// WSFragment struct ---------------------------------------------------------
|
|
||||||
// WSFragment represents a single run of ws (all leadingws, or all normalws,
|
|
||||||
// or all trailingws, or all leading+trailingws). Note that this single run may
|
|
||||||
// still span multiple nodes.
|
|
||||||
struct WSFragment
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsINode> mStartNode; // node where ws run starts
|
|
||||||
nsCOMPtr<nsINode> mEndNode; // node where ws run ends
|
|
||||||
int32_t mStartOffset; // offset where ws run starts
|
|
||||||
int32_t mEndOffset; // offset where ws run ends
|
|
||||||
// type of ws, and what is to left and right of it
|
|
||||||
WSType mType, mLeftType, mRightType;
|
|
||||||
// other ws runs to left or right. may be null.
|
|
||||||
WSFragment *mLeft, *mRight;
|
|
||||||
|
|
||||||
WSFragment() : mStartNode(0), mEndNode(0),
|
|
||||||
mStartOffset(0), mEndOffset(0),
|
|
||||||
mType(), mLeftType(), mRightType(),
|
|
||||||
mLeft(0), mRight(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// WSPoint struct ------------------------------------------------------------
|
|
||||||
// A WSPoint struct represents a unique location within the ws run. It is
|
|
||||||
// always within a textnode that is one of the nodes stored in the list
|
|
||||||
// in the wsRunObject. For convenience, the character at that point is also
|
|
||||||
// stored in the struct.
|
|
||||||
struct MOZ_STACK_CLASS WSPoint
|
|
||||||
{
|
|
||||||
RefPtr<mozilla::dom::Text> mTextNode;
|
|
||||||
uint32_t mOffset;
|
|
||||||
char16_t mChar;
|
|
||||||
|
|
||||||
WSPoint() : mTextNode(0),mOffset(0),mChar(0) {}
|
|
||||||
WSPoint(mozilla::dom::Text* aTextNode, int32_t aOffset, char16_t aChar) :
|
|
||||||
mTextNode(aTextNode),mOffset(aOffset),mChar(aChar) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
enum AreaRestriction
|
|
||||||
{
|
|
||||||
eAnywhere, eOutsideUserSelectAll
|
|
||||||
};
|
|
||||||
|
|
||||||
// protected methods ---------------------------------------------------------
|
|
||||||
// tons of utility methods.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the node which we will handle white-space under. This is the
|
|
||||||
* closest block within the DOM subtree we're editing, or if none is
|
|
||||||
* found, the (inline) root of the editable subtree.
|
|
||||||
*/
|
|
||||||
nsINode* GetWSBoundingParent();
|
|
||||||
|
|
||||||
nsresult GetWSNodes();
|
|
||||||
void GetRuns();
|
|
||||||
void ClearRuns();
|
|
||||||
void MakeSingleWSRun(WSType aType);
|
|
||||||
nsIContent* GetPreviousWSNodeInner(nsINode* aStartNode,
|
|
||||||
nsINode* aBlockParent);
|
|
||||||
nsIContent* GetPreviousWSNode(mozilla::EditorDOMPoint aPoint,
|
|
||||||
nsINode* aBlockParent);
|
|
||||||
nsIContent* GetNextWSNodeInner(nsINode* aStartNode, nsINode* aBlockParent);
|
|
||||||
nsIContent* GetNextWSNode(mozilla::EditorDOMPoint aPoint,
|
|
||||||
nsINode* aBlockParent);
|
|
||||||
nsresult PrepareToDeleteRangePriv(nsWSRunObject* aEndObject);
|
|
||||||
nsresult PrepareToSplitAcrossBlocksPriv();
|
|
||||||
nsresult DeleteChars(nsINode* aStartNode, int32_t aStartOffset,
|
|
||||||
nsINode* aEndNode, int32_t aEndOffset,
|
|
||||||
AreaRestriction aAR = eAnywhere);
|
|
||||||
WSPoint GetCharAfter(nsINode* aNode, int32_t aOffset);
|
|
||||||
WSPoint GetCharBefore(nsINode* aNode, int32_t aOffset);
|
|
||||||
WSPoint GetCharAfter(const WSPoint& aPoint);
|
|
||||||
WSPoint GetCharBefore(const WSPoint& aPoint);
|
|
||||||
nsresult ConvertToNBSP(WSPoint aPoint,
|
|
||||||
AreaRestriction aAR = eAnywhere);
|
|
||||||
void GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
|
|
||||||
mozilla::dom::Text** outStartNode,
|
|
||||||
int32_t* outStartOffset,
|
|
||||||
mozilla::dom::Text** outEndNode,
|
|
||||||
int32_t* outEndOffset);
|
|
||||||
void FindRun(nsINode* aNode, int32_t aOffset, WSFragment** outRun,
|
|
||||||
bool after);
|
|
||||||
char16_t GetCharAt(mozilla::dom::Text* aTextNode, int32_t aOffset);
|
|
||||||
WSPoint GetWSPointAfter(nsINode* aNode, int32_t aOffset);
|
|
||||||
WSPoint GetWSPointBefore(nsINode* aNode, int32_t aOffset);
|
|
||||||
nsresult CheckTrailingNBSPOfRun(WSFragment *aRun);
|
|
||||||
nsresult CheckTrailingNBSP(WSFragment* aRun, nsINode* aNode,
|
|
||||||
int32_t aOffset);
|
|
||||||
nsresult CheckLeadingNBSP(WSFragment* aRun, nsINode* aNode,
|
|
||||||
int32_t aOffset);
|
|
||||||
|
|
||||||
nsresult Scrub();
|
|
||||||
bool IsBlockNode(nsINode* aNode);
|
|
||||||
|
|
||||||
// member variables ---------------------------------------------------------
|
|
||||||
|
|
||||||
nsCOMPtr<nsINode> mNode; // the node passed to our constructor
|
|
||||||
int32_t mOffset; // the offset passed to our contructor
|
|
||||||
// together, the above represent the point at which we are building up ws info.
|
|
||||||
|
|
||||||
bool mPRE; // true if we are in preformatted whitespace context
|
|
||||||
nsCOMPtr<nsINode> mStartNode; // node/offset where ws starts
|
|
||||||
int32_t mStartOffset; // ...
|
|
||||||
WSType mStartReason; // reason why ws starts (eText, eOtherBlock, etc)
|
|
||||||
nsCOMPtr<nsINode> mStartReasonNode;// the node that implicated by start reason
|
|
||||||
|
|
||||||
nsCOMPtr<nsINode> mEndNode; // node/offset where ws ends
|
|
||||||
int32_t mEndOffset; // ...
|
|
||||||
WSType mEndReason; // reason why ws ends (eText, eOtherBlock, etc)
|
|
||||||
nsCOMPtr<nsINode> mEndReasonNode; // the node that implicated by end reason
|
|
||||||
|
|
||||||
RefPtr<mozilla::dom::Text> mFirstNBSPNode; // location of first nbsp in ws run, if any
|
|
||||||
int32_t mFirstNBSPOffset; // ...
|
|
||||||
|
|
||||||
RefPtr<mozilla::dom::Text> mLastNBSPNode; // location of last nbsp in ws run, if any
|
|
||||||
int32_t mLastNBSPOffset; // ...
|
|
||||||
|
|
||||||
// the list of nodes containing ws in this run
|
|
||||||
nsTArray<RefPtr<mozilla::dom::Text>> mNodeArray;
|
|
||||||
|
|
||||||
WSFragment *mStartRun; // the first WSFragment in the run
|
|
||||||
WSFragment *mEndRun; // the last WSFragment in the run, may be same as first
|
|
||||||
|
|
||||||
nsHTMLEditor *mHTMLEditor; // non-owning.
|
|
||||||
|
|
||||||
friend class nsHTMLEditRules; // opening this class up for pillaging
|
|
||||||
friend class nsHTMLEditor; // opening this class up for more pillaging
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user