mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1003894 part 2 - Clean up nsWSRunObject::CheckTrailingNBSPOfRun; r=ehsan
This commit is contained in:
parent
e1d12854be
commit
c995efe830
@ -31,6 +31,7 @@
|
||||
#include "mozilla/TextComposition.h" // for TextComposition
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/Element.h" // for Element, nsINode::AsElement
|
||||
#include "mozilla/dom/Text.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new, etc
|
||||
#include "nsAString.h" // for nsAString_internal::Length, etc
|
||||
#include "nsCCUncollectableMarker.h" // for nsCCUncollectableMarker
|
||||
@ -2442,6 +2443,16 @@ nsEditor::InsertTextImpl(const nsAString& aStringToInsert,
|
||||
}
|
||||
|
||||
|
||||
nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
Text* aTextNode,
|
||||
int32_t aOffset,
|
||||
bool aSuppressIME)
|
||||
{
|
||||
return InsertTextIntoTextNodeImpl(aStringToInsert,
|
||||
static_cast<nsIDOMCharacterData*>(GetAsDOMNode(aTextNode)),
|
||||
aOffset, aSuppressIME);
|
||||
}
|
||||
|
||||
nsresult nsEditor::InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
nsIDOMCharacterData *aTextNode,
|
||||
int32_t aOffset,
|
||||
|
@ -75,6 +75,7 @@ class DataTransfer;
|
||||
class Element;
|
||||
class EventTarget;
|
||||
class Selection;
|
||||
class Text;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@ -196,6 +197,10 @@ public:
|
||||
nsCOMPtr<nsIDOMNode> *aInOutNode,
|
||||
int32_t *aInOutOffset,
|
||||
nsIDOMDocument *aDoc);
|
||||
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
mozilla::dom::Text* aTextNode,
|
||||
int32_t aOffset,
|
||||
bool aSuppressIME = false);
|
||||
nsresult InsertTextIntoTextNodeImpl(const nsAString& aStringToInsert,
|
||||
nsIDOMCharacterData *aTextNode,
|
||||
int32_t aOffset,
|
||||
|
@ -1125,6 +1125,18 @@ nsHTMLEditor::TabInTable(bool inIsShift, bool* outHandled)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<Element>
|
||||
nsHTMLEditor::CreateBR(nsINode* aNode, int32_t aOffset, EDirection aSelect)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> parent = GetAsDOMNode(aNode);
|
||||
int32_t offset = aOffset;
|
||||
nsCOMPtr<nsIDOMNode> outBRNode;
|
||||
// We assume everything is fine if the br is not null, irrespective of retval
|
||||
CreateBRImpl(address_of(parent), &offset, address_of(outBRNode), aSelect);
|
||||
nsCOMPtr<Element> ret = do_QueryInterface(outBRNode);
|
||||
return ret.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::CreateBR(nsIDOMNode *aNode, int32_t aOffset, nsCOMPtr<nsIDOMNode> *outBRNode, EDirection aSelect)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> parent = aNode;
|
||||
|
@ -420,6 +420,8 @@ protected:
|
||||
|
||||
// key event helpers
|
||||
NS_IMETHOD TabInTable(bool inIsShift, bool *outHandled);
|
||||
already_AddRefed<mozilla::dom::Element> CreateBR(nsINode* aNode,
|
||||
int32_t aOffset, EDirection aSelect = eNone);
|
||||
NS_IMETHOD CreateBR(nsIDOMNode *aNode, int32_t aOffset,
|
||||
nsCOMPtr<nsIDOMNode> *outBRNode, nsIEditor::EDirection aSelect = nsIEditor::eNone);
|
||||
|
||||
|
@ -25,6 +25,9 @@
|
||||
#include "nsTextFragment.h"
|
||||
#include "nsWSRunObject.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
const char16_t nbsp = 160;
|
||||
|
||||
static bool IsBlockNode(nsINode* node)
|
||||
@ -655,7 +658,7 @@ nsWSRunObject::GetWSNodes()
|
||||
// block boundary.
|
||||
nsresult res = NS_OK;
|
||||
|
||||
DOMPoint start(mNode, mOffset), end(mNode, mOffset);
|
||||
::DOMPoint start(mNode, mOffset), end(mNode, mOffset);
|
||||
nsCOMPtr<nsINode> wsBoundingParent = GetWSBoundingParent();
|
||||
|
||||
// first look backwards to find preceding ws nodes
|
||||
@ -1110,7 +1113,7 @@ nsWSRunObject::GetPreviousWSNodeInner(nsINode* aStartNode,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWSRunObject::GetPreviousWSNode(DOMPoint aPoint,
|
||||
nsWSRunObject::GetPreviousWSNode(::DOMPoint aPoint,
|
||||
nsINode* aBlockParent,
|
||||
nsCOMPtr<nsINode>* aPriorNode)
|
||||
{
|
||||
@ -1202,7 +1205,7 @@ nsWSRunObject::GetNextWSNodeInner(nsINode* aStartNode,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWSRunObject::GetNextWSNode(DOMPoint aPoint,
|
||||
nsWSRunObject::GetNextWSNode(::DOMPoint aPoint,
|
||||
nsINode* aBlockParent,
|
||||
nsCOMPtr<nsINode>* aNextNode)
|
||||
{
|
||||
@ -1621,6 +1624,21 @@ nsWSRunObject::ConvertToNBSP(WSPoint aPoint, AreaRestriction aAR)
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
nsWSRunObject::GetAsciiWSBounds(int16_t aDir, nsINode* aNode, int32_t aOffset,
|
||||
Text** outStartNode, int32_t* outStartOffset,
|
||||
Text** outEndNode, int32_t* outEndOffset)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> outStartDOMNode, outEndDOMNode;
|
||||
GetAsciiWSBounds(aDir, GetAsDOMNode(aNode), aOffset,
|
||||
address_of(outStartDOMNode), outStartOffset,
|
||||
address_of(outEndDOMNode), outEndOffset);
|
||||
nsCOMPtr<Text> start(do_QueryInterface(outStartDOMNode));
|
||||
nsCOMPtr<Text> end(do_QueryInterface(outEndDOMNode));
|
||||
start.forget(outStartNode);
|
||||
end.forget(outEndNode);
|
||||
}
|
||||
|
||||
void
|
||||
nsWSRunObject::GetAsciiWSBounds(int16_t aDir, nsIDOMNode *aNode, int32_t aOffset,
|
||||
nsCOMPtr<nsIDOMNode> *outStartNode, int32_t *outStartOffset,
|
||||
@ -1869,114 +1887,114 @@ nsWSRunObject::GetWSPointBefore(nsIDOMNode *aNode, int32_t aOffset)
|
||||
|
||||
nsresult
|
||||
nsWSRunObject::CheckTrailingNBSPOfRun(WSFragment *aRun)
|
||||
{
|
||||
// try to change an nbsp to a space, if possible, just to prevent nbsp proliferation.
|
||||
// examine what is before and after the trailing nbsp, if any.
|
||||
{
|
||||
// Try to change an nbsp to a space, if possible, just to prevent nbsp
|
||||
// proliferation. Examine what is before and after the trailing nbsp, if
|
||||
// any.
|
||||
NS_ENSURE_TRUE(aRun, NS_ERROR_NULL_POINTER);
|
||||
nsresult res;
|
||||
bool leftCheck = false;
|
||||
bool spaceNBSP = false;
|
||||
bool rightCheck = false;
|
||||
|
||||
|
||||
// confirm run is normalWS
|
||||
if (aRun->mType != WSType::normalWS) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// first check for trailing nbsp
|
||||
WSPoint thePoint = GetCharBefore(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset);
|
||||
if (thePoint.mTextNode && thePoint.mChar == nbsp) {
|
||||
// now check that what is to the left of it is compatible with replacing nbsp with space
|
||||
WSPoint prevPoint = GetCharBefore(thePoint);
|
||||
if (prevPoint.mTextNode) {
|
||||
if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) leftCheck = true;
|
||||
else spaceNBSP = true;
|
||||
} else if (aRun->mLeftType == WSType::text) {
|
||||
leftCheck = true;
|
||||
} else if (aRun->mLeftType == WSType::special) {
|
||||
if (!nsCRT::IsAsciiSpace(prevPoint.mChar)) {
|
||||
leftCheck = true;
|
||||
} else {
|
||||
spaceNBSP = true;
|
||||
}
|
||||
} else if (aRun->mLeftType == WSType::text ||
|
||||
aRun->mLeftType == WSType::special) {
|
||||
leftCheck = true;
|
||||
}
|
||||
if (leftCheck || spaceNBSP)
|
||||
{
|
||||
// now check that what is to the right of it is compatible with replacing nbsp with space
|
||||
if (aRun->mRightType == WSType::text) {
|
||||
rightCheck = true;
|
||||
}
|
||||
if (aRun->mRightType == WSType::special) {
|
||||
rightCheck = true;
|
||||
}
|
||||
if (aRun->mRightType == WSType::br) {
|
||||
if (leftCheck || spaceNBSP) {
|
||||
// now check that what is to the right of it is compatible with replacing
|
||||
// nbsp with space
|
||||
if (aRun->mRightType == WSType::text ||
|
||||
aRun->mRightType == WSType::special ||
|
||||
aRun->mRightType == WSType::br) {
|
||||
rightCheck = true;
|
||||
}
|
||||
if ((aRun->mRightType & WSType::block) &&
|
||||
IsBlockNode(nsCOMPtr<nsINode>(GetWSBoundingParent()))) {
|
||||
// we are at a block boundary. Insert a <br>. Why? Well, first note that
|
||||
// the br will have no visible effect since it is up against a block boundary.
|
||||
// |foo<br><p>bar| renders like |foo<p>bar| and similarly
|
||||
// |<p>foo<br></p>bar| renders like |<p>foo</p>bar|. What this <br> addition
|
||||
// gets us is the ability to convert a trailing nbsp to a space. Consider:
|
||||
// |<body>foo. '</body>|, where ' represents selection. User types space attempting
|
||||
// to put 2 spaces after the end of their sentence. We used to do this as:
|
||||
// |<body>foo.  </body>| This caused problems with soft wrapping: the nbsp
|
||||
// would wrap to the next line, which looked attrocious. If you try to do:
|
||||
// |<body>foo.  </body>| instead, the trailing space is invisible because it
|
||||
// is against a block boundary. If you do: |<body>foo.  </body>| then
|
||||
// you get an even uglier soft wrapping problem, where foo is on one line until
|
||||
// you type the final space, and then "foo " jumps down to the next line. Ugh.
|
||||
// The best way I can find out of this is to throw in a harmless <br>
|
||||
// here, which allows us to do: |<body>foo.  <br></body>|, which doesn't
|
||||
// cause foo to jump lines, doesn't cause spaces to show up at the beginning of
|
||||
// soft wrapped lines, and lets the user see 2 spaces when they type 2 spaces.
|
||||
// We are at a block boundary. Insert a <br>. Why? Well, first note
|
||||
// that the br will have no visible effect since it is up against a
|
||||
// block boundary. |foo<br><p>bar| renders like |foo<p>bar| and
|
||||
// similarly |<p>foo<br></p>bar| renders like |<p>foo</p>bar|. What
|
||||
// this <br> addition gets us is the ability to convert a trailing nbsp
|
||||
// to a space. Consider: |<body>foo. '</body>|, where ' represents
|
||||
// selection. User types space attempting to put 2 spaces after the
|
||||
// end of their sentence. We used to do this as: |<body>foo.
|
||||
//  </body>| This caused problems with soft wrapping: the nbsp
|
||||
// would wrap to the next line, which looked attrocious. If you try to
|
||||
// do: |<body>foo.  </body>| instead, the trailing space is
|
||||
// invisible because it is against a block boundary. If you do:
|
||||
// |<body>foo.  </body>| then you get an even uglier soft
|
||||
// wrapping problem, where foo is on one line until you type the final
|
||||
// space, and then "foo " jumps down to the next line. Ugh. The best
|
||||
// way I can find out of this is to throw in a harmless <br> here,
|
||||
// which allows us to do: |<body>foo.  <br></body>|, which doesn't
|
||||
// cause foo to jump lines, doesn't cause spaces to show up at the
|
||||
// beginning of soft wrapped lines, and lets the user see 2 spaces when
|
||||
// they type 2 spaces.
|
||||
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = mHTMLEditor->CreateBR(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset, address_of(brNode));
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
nsCOMPtr<Element> brNode =
|
||||
mHTMLEditor->CreateBR(aRun->mEndNode, aRun->mEndOffset);
|
||||
NS_ENSURE_TRUE(brNode, NS_ERROR_FAILURE);
|
||||
|
||||
// refresh thePoint, prevPoint
|
||||
// Refresh thePoint, prevPoint
|
||||
thePoint = GetCharBefore(GetAsDOMNode(aRun->mEndNode), aRun->mEndOffset);
|
||||
prevPoint = GetCharBefore(thePoint);
|
||||
rightCheck = true;
|
||||
}
|
||||
}
|
||||
if (leftCheck && rightCheck)
|
||||
{
|
||||
// now replace nbsp with space
|
||||
// first, insert a space
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode(do_QueryInterface(thePoint.mTextNode));
|
||||
NS_ENSURE_TRUE(textNode, NS_ERROR_NULL_POINTER);
|
||||
if (leftCheck && rightCheck) {
|
||||
// Now replace nbsp with space. First, insert a space
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
|
||||
nsAutoString spaceStr(char16_t(32));
|
||||
res = mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr, textNode, thePoint.mOffset, true);
|
||||
res = mHTMLEditor->InsertTextIntoTextNodeImpl(spaceStr,
|
||||
thePoint.mTextNode,
|
||||
thePoint.mOffset, true);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// finally, delete that nbsp
|
||||
nsCOMPtr<nsIDOMNode> delNode(do_QueryInterface(thePoint.mTextNode));
|
||||
res = DeleteChars(delNode, thePoint.mOffset+1, delNode, thePoint.mOffset+2);
|
||||
|
||||
// Finally, delete that nbsp
|
||||
res = DeleteChars(GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset + 1,
|
||||
GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset + 2);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
else if (!mPRE && spaceNBSP && rightCheck) // don't mess with this preformatted for now.
|
||||
{
|
||||
// we have a run of ascii whitespace (which will render as one space)
|
||||
// followed by an nbsp (which is at the end of the whitespace run). Let's
|
||||
// switch their order. This will insure that if someone types two spaces
|
||||
// after a sentence, and the editor softwraps at this point, the spaces wont
|
||||
// be split across lines, which looks ugly and is bad for the moose.
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startNode, endNode, thenode(do_QueryInterface(prevPoint.mTextNode));
|
||||
} else if (!mPRE && spaceNBSP && rightCheck) {
|
||||
// Don't mess with this preformatted for now. We have a run of ASCII
|
||||
// whitespace (which will render as one space) followed by an nbsp (which
|
||||
// is at the end of the whitespace run). Let's switch their order. This
|
||||
// will ensure that if someone types two spaces after a sentence, and the
|
||||
// editor softwraps at this point, the spaces won't be split across lines,
|
||||
// which looks ugly and is bad for the moose.
|
||||
|
||||
nsCOMPtr<Text> startNode, endNode;
|
||||
int32_t startOffset, endOffset;
|
||||
GetAsciiWSBounds(eBoth, thenode, prevPoint.mOffset+1, address_of(startNode),
|
||||
&startOffset, address_of(endNode), &endOffset);
|
||||
|
||||
// delete that nbsp
|
||||
nsCOMPtr<nsIDOMNode> delNode(do_QueryInterface(thePoint.mTextNode));
|
||||
res = DeleteChars(delNode, thePoint.mOffset, delNode, thePoint.mOffset+1);
|
||||
GetAsciiWSBounds(eBoth, prevPoint.mTextNode, prevPoint.mOffset + 1,
|
||||
getter_AddRefs(startNode), &startOffset,
|
||||
getter_AddRefs(endNode), &endOffset);
|
||||
|
||||
// Delete that nbsp
|
||||
res = DeleteChars(GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset,
|
||||
GetAsDOMNode(thePoint.mTextNode), thePoint.mOffset + 1);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
// finally, insert that nbsp before the ascii ws run
|
||||
|
||||
// Finally, insert that nbsp before the ASCII ws run
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor);
|
||||
nsAutoString nbspStr(nbsp);
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode(do_QueryInterface(startNode));
|
||||
res = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, textNode, startOffset, true);
|
||||
res = mHTMLEditor->InsertTextIntoTextNodeImpl(nbspStr, startNode,
|
||||
startOffset, true);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +343,11 @@ class MOZ_STACK_CLASS nsWSRunObject
|
||||
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 GetAsciiWSBounds(int16_t aDir, nsIDOMNode *aNode, int32_t aOffset,
|
||||
nsCOMPtr<nsIDOMNode> *outStartNode, int32_t *outStartOffset,
|
||||
nsCOMPtr<nsIDOMNode> *outEndNode, int32_t *outEndOffset);
|
||||
|
Loading…
Reference in New Issue
Block a user