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:
uriber@gmail.com 2008-03-31 10:47:42 -07:00
Родитель 796a83583c
Коммит befef14e75
3 изменённых файлов: 118 добавлений и 32 удалений

Просмотреть файл

@ -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>