зеркало из https://github.com/mozilla/pjs.git
When adding a range to the selection, set the anchor focus to the added range, rather than the last range in the selection. bug=392746 r+sr=roc a1.9=beltzner. Mochitest (v3) by Martijn Wargers.
This commit is contained in:
Родитель
796a83583c
Коммит
befef14e75
|
@ -221,7 +221,7 @@ public:
|
|||
PRBool aDoFlush,
|
||||
PRInt16 aVPercent = NS_PRESSHELL_SCROLL_ANYWHERE,
|
||||
PRInt16 aHPercent = NS_PRESSHELL_SCROLL_ANYWHERE);
|
||||
nsresult AddItem(nsIDOMRange *aRange);
|
||||
nsresult AddItem(nsIDOMRange *aRange, PRInt32* aOutIndex = nsnull);
|
||||
nsresult RemoveItem(nsIDOMRange *aRange);
|
||||
nsresult Clear(nsPresContext* aPresContext);
|
||||
|
||||
|
@ -307,7 +307,7 @@ private:
|
|||
NS_IMETHOD selectFrames(nsPresContext* aPresContext, nsIContentIterator *aInnerIter, nsIContent *aContent, nsIDOMRange *aRange, nsIPresShell *aPresShell, PRBool aFlags);
|
||||
NS_IMETHOD selectFrames(nsPresContext* aPresContext, nsIDOMRange *aRange, PRBool aSelect);
|
||||
nsresult getTableCellLocationFromRange(nsIDOMRange *aRange, PRInt32 *aSelectionType, PRInt32 *aRow, PRInt32 *aCol);
|
||||
nsresult addTableCellRange(nsIDOMRange *aRange, PRBool *aDidAddRange);
|
||||
nsresult addTableCellRange(nsIDOMRange *aRange, PRBool *aDidAddRange, PRInt32 *aOutIndex);
|
||||
|
||||
#ifdef OLD_SELECTION
|
||||
NS_IMETHOD FixupSelectionPoints(nsIDOMRange *aRange, nsDirection *aDir, PRBool *aFixupState);
|
||||
|
@ -360,9 +360,9 @@ private:
|
|||
PRInt32 aOffset,
|
||||
const nsTArray<PRInt32>* aRemappingArray,
|
||||
PRBool aUseBeginning);
|
||||
PRBool FindRangeGivenPoint(nsIDOMNode* aBeginNode, PRInt32 aBeginOffset,
|
||||
nsIDOMNode* aEndNode, PRInt32 aEndOffset,
|
||||
PRInt32 aStartSearchingHere);
|
||||
PRInt32 FindRangeGivenPoint(nsIDOMNode* aBeginNode, PRInt32 aBeginOffset,
|
||||
nsIDOMNode* aEndNode, PRInt32 aEndOffset,
|
||||
PRInt32 aStartSearchingHere);
|
||||
|
||||
nsTArray<RangeData> mRanges;
|
||||
nsTArray<PRInt32> mRangeEndings; // references info mRanges
|
||||
|
@ -3741,12 +3741,14 @@ nsTypedSelection::getTableCellLocationFromRange(nsIDOMRange *aRange, PRInt32 *aS
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::addTableCellRange(nsIDOMRange *aRange, PRBool *aDidAddRange)
|
||||
{
|
||||
if (!aDidAddRange)
|
||||
nsTypedSelection::addTableCellRange(nsIDOMRange *aRange, PRBool *aDidAddRange,
|
||||
PRInt32 *aOutIndex)
|
||||
{
|
||||
if (!aDidAddRange || !aOutIndex)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*aDidAddRange = PR_FALSE;
|
||||
*aOutIndex = -1;
|
||||
|
||||
if (!mFrameSelection)
|
||||
return NS_OK;
|
||||
|
@ -3774,7 +3776,8 @@ nsTypedSelection::addTableCellRange(nsIDOMRange *aRange, PRBool *aDidAddRange)
|
|||
if (mFrameSelection->mSelectingTableCellMode == TABLESELECTION_NONE)
|
||||
mFrameSelection->mSelectingTableCellMode = tableMode;
|
||||
|
||||
return AddItem(aRange);
|
||||
*aDidAddRange = PR_TRUE;
|
||||
return AddItem(aRange, aOutIndex);
|
||||
}
|
||||
|
||||
//TODO: Figure out TABLESELECTION_COLUMN and TABLESELECTION_ALLCELLS
|
||||
|
@ -4410,12 +4413,14 @@ nsTypedSelection::FindInsertionPoint(
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsTypedSelection::AddItem(nsIDOMRange *aItem)
|
||||
nsTypedSelection::AddItem(nsIDOMRange *aItem, PRInt32 *aOutIndex)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!aItem)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (aOutIndex)
|
||||
*aOutIndex = -1;
|
||||
|
||||
NS_ASSERTION(ValidateRanges(), "Ranges out of sync");
|
||||
|
||||
// a common case is that we have no ranges yet
|
||||
|
@ -4426,6 +4431,8 @@ nsTypedSelection::AddItem(nsIDOMRange *aItem)
|
|||
mRanges.Clear();
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (aOutIndex)
|
||||
*aOutIndex = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4441,6 +4448,9 @@ nsTypedSelection::AddItem(nsIDOMRange *aItem)
|
|||
CompareToRangeStart, &beginInsertionPoint);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (aOutIndex)
|
||||
*aOutIndex = beginInsertionPoint;
|
||||
|
||||
// XXX Performance: 99% of the time, the beginning array and the ending array
|
||||
// will be the same because the ranges do not overlap. We could save a few
|
||||
// compares (which can be expensive) in this common case by special casing
|
||||
|
@ -4454,9 +4464,13 @@ nsTypedSelection::AddItem(nsIDOMRange *aItem)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// make sure that this range is not already in the selection
|
||||
if (FindRangeGivenPoint(beginNode, beginOffset, endNode, endOffset,
|
||||
beginInsertionPoint)) {
|
||||
PRInt32 index = FindRangeGivenPoint(beginNode, beginOffset,
|
||||
endNode, endOffset,
|
||||
beginInsertionPoint);
|
||||
if (index >= 0) {
|
||||
// silently succeed, this range is already in the selection
|
||||
if (aOutIndex)
|
||||
*aOutIndex = index;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -4465,7 +4479,6 @@ nsTypedSelection::AddItem(nsIDOMRange *aItem)
|
|||
CompareToRangeEnd, &endInsertionPoint);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
// insert the range, being careful to revert everything on error to keep
|
||||
// consistency
|
||||
if (! mRanges.InsertElementAt(beginInsertionPoint,
|
||||
|
@ -4863,9 +4876,10 @@ RangeMatchesEndPoint(nsIDOMRange* aRange, nsIDOMNode* aNode, PRInt32 aOffset)
|
|||
//
|
||||
// Therefore, this function searches backwards and forwards from that point
|
||||
// of all matching beginning points, and then compares the ending points to
|
||||
// find a match. Returns true if a match was found, false if not.
|
||||
// find a match. Returns the index of the match if a match was found, -1 if
|
||||
// not.
|
||||
|
||||
PRBool
|
||||
PRInt32
|
||||
nsTypedSelection::FindRangeGivenPoint(
|
||||
nsIDOMNode* aBeginNode, PRInt32 aBeginOffset,
|
||||
nsIDOMNode* aEndNode, PRInt32 aEndOffset,
|
||||
|
@ -4879,7 +4893,7 @@ nsTypedSelection::FindRangeGivenPoint(
|
|||
for (i = aStartSearchingHere; i >= 0 && i < (PRInt32)mRanges.Length(); i --) {
|
||||
if (RangeMatchesBeginPoint(mRanges[i].mRange, aBeginNode, aBeginOffset)) {
|
||||
if (RangeMatchesEndPoint(mRanges[i].mRange, aEndNode, aEndOffset))
|
||||
return PR_TRUE;
|
||||
return i;
|
||||
} else {
|
||||
// done with matches going backwards
|
||||
break;
|
||||
|
@ -4890,7 +4904,7 @@ nsTypedSelection::FindRangeGivenPoint(
|
|||
for (i = aStartSearchingHere + 1; i < (PRInt32)mRanges.Length(); i ++) {
|
||||
if (RangeMatchesBeginPoint(mRanges[i].mRange, aBeginNode, aBeginOffset)) {
|
||||
if (RangeMatchesEndPoint(mRanges[i].mRange, aEndNode, aEndOffset))
|
||||
return PR_TRUE;
|
||||
return i;
|
||||
} else {
|
||||
// done with matches going forwards
|
||||
break;
|
||||
|
@ -4898,7 +4912,7 @@ nsTypedSelection::FindRangeGivenPoint(
|
|||
}
|
||||
|
||||
// match not found
|
||||
return PR_FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//utility method to get the primary frame of node or use the offset to get frame of child node
|
||||
|
@ -5783,25 +5797,18 @@ nsTypedSelection::AddRange(nsIDOMRange* aRange)
|
|||
// This inserts a table cell range in proper document order
|
||||
// and returns NS_OK if range doesn't contain just one table cell
|
||||
PRBool didAddRange;
|
||||
nsresult result = addTableCellRange(aRange, &didAddRange);
|
||||
PRInt32 rangeIndex;
|
||||
nsresult result = addTableCellRange(aRange, &didAddRange, &rangeIndex);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
if (!didAddRange)
|
||||
{
|
||||
result = AddItem(aRange);
|
||||
result = AddItem(aRange, &rangeIndex);
|
||||
if (NS_FAILED(result)) return result;
|
||||
}
|
||||
|
||||
PRInt32 count;
|
||||
result = GetRangeCount(&count);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
NS_ASSERTION(0,"bad count after additem\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
setAnchorFocusRange(count -1);
|
||||
NS_ASSERTION(rangeIndex >= 0, "Range index not returned");
|
||||
setAnchorFocusRange(rangeIndex);
|
||||
|
||||
// Make sure the caret appears on the next line, if at a newline
|
||||
if (mType == nsISelectionController::SELECTION_NORMAL)
|
||||
|
|
|
@ -53,6 +53,7 @@ _TEST_FILES = test_bug288789.html \
|
|||
test_bug385751.html \
|
||||
test_bug389630.html \
|
||||
test_bug391747.html \
|
||||
test_bug392746.html \
|
||||
test_bug392923.html \
|
||||
test_bug394173.html \
|
||||
test_bug394239.html \
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=392746
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 392746</title>
|
||||
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=392746">Mozilla Bug 392746</a>
|
||||
<div id="content">
|
||||
text text text text text text <span id="d">ddd text text </span>text text text text <br>
|
||||
text <span id="c">ccc text</span> text text text <span id="e">eee text</span> text text text text <span id="b">bbb text</span><br>
|
||||
text text text text text text text <span id="a">aaa text</span> text text text <br>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
function ctrlselect(aX,aY, aX2, aY2) {
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
var modifyers = (navigator.platform.indexOf("Mac") >= 0) ? 8 : 2;
|
||||
wu.sendMouseEvent('mousedown', aX, aY, 0, 1, modifyers);
|
||||
wu.sendMouseEvent('mousemove', aX2, aY2, 0, 0, modifyers);
|
||||
wu.sendMouseEvent('mouseup', aY2, aY2, 0, 1, modifyers);
|
||||
}
|
||||
|
||||
function test() {
|
||||
var sel = window.getSelection();
|
||||
sel.removeAllRanges();
|
||||
|
||||
var a=document.getElementById('a').getBoundingClientRect();
|
||||
ctrlselect(a.left+1, a.top+1, a.right-1, a.top+1);
|
||||
var b=document.getElementById('b').getBoundingClientRect();
|
||||
ctrlselect(b.left+1, b.top+1, b.right-1, b.top+1);
|
||||
var c=document.getElementById('c').getBoundingClientRect();
|
||||
ctrlselect(c.left+1, c.top+1, c.right-1, c.top+1);
|
||||
var d=document.getElementById('d').getBoundingClientRect();
|
||||
ctrlselect(d.left+1, d.top+1, d.right-1, d.top+1);
|
||||
var e=document.getElementById('e').getBoundingClientRect();
|
||||
ctrlselect(e.right-1, e.top+1, e.left+1, e.top+1);
|
||||
|
||||
ok(sel.getRangeAt(0).toString() == 'ddd text text ', 'First selection range should be "ddd text text "');
|
||||
ok(sel.getRangeAt(1).toString() == 'ccc text', 'First selection range should be "ccc text"');
|
||||
ok(sel.getRangeAt(2).toString() == 'eee text', 'First selection range should be "eee text"');
|
||||
ok(sel.getRangeAt(3).toString() == 'bbb text', 'First selection range should be "bbb text"');
|
||||
ok(sel.getRangeAt(4).toString() == 'aaa text', 'First selection range should be "aaa text"');
|
||||
|
||||
ok(sel.focusNode == sel.anchorNode, 'focusNode and anchorNode should be the same');
|
||||
ok(sel.focusNode.parentNode == document.getElementById('e'), 'focusNode.parentNode should be the same as the node with id=e');
|
||||
ok(sel.focusOffset == 0, 'focusOffset should be 0');
|
||||
ok(sel.anchorOffset == 8, 'anchorOffset should be 8');
|
||||
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
wu.sendMouseEvent('mousedown', 0, 0, 0, 1, 0);
|
||||
wu.sendMouseEvent('mousemove', 0, 0, 0, 0, 0);
|
||||
wu.sendMouseEvent('mouseup', 0, 0, 0, 1, 0);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.onload=function() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
setTimeout(test, 0);
|
||||
};
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче