Bug 240933 - Part 3: Correct the caret movement throughout textareas (and pre elements with caret browsing turned on as well); r=roc a=dbaron

--HG--
extra : rebase_source : 198f679bb5cea82b710c921576fa44c59f77aa23
This commit is contained in:
Ehsan Akhgari 2010-07-13 21:49:16 -04:00
Родитель 9bfb381743
Коммит da0113546a
4 изменённых файлов: 88 добавлений и 22 удалений

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

@ -5219,6 +5219,7 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos)
{
PRBool eatingNonRenderableWS = PR_FALSE;
PRBool done = PR_FALSE;
PRBool jumpedLine = PR_FALSE;
while (!done) {
PRBool movingInFrameDirection =
@ -5230,7 +5231,6 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos)
done = current->PeekOffsetCharacter(movingInFrameDirection, &offset);
if (!done) {
PRBool jumpedLine;
result =
current->GetFrameFromDirection(aPos->mDirection, aPos->mVisual,
aPos->mJumpLines, aPos->mScrollViewStop,
@ -5251,6 +5251,15 @@ nsIFrame::PeekOffset(nsPeekOffsetStruct* aPos)
aPos->mResultContent = range.content;
// Output offset is relative to content, not frame
aPos->mContentOffset = offset < 0 ? range.end : range.start + offset;
// If we're dealing with a text frame and moving backward positions us at
// the end of that line, decrease the offset by one to make sure that
// we're placed before the linefeed character on the previous line.
if (offset < 0 && jumpedLine &&
aPos->mDirection == eDirPrevious &&
current->GetStyleText()->NewlineIsSignificant() &&
current->HasTerminalNewline()) {
--aPos->mContentOffset;
}
break;
}

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

@ -5425,8 +5425,7 @@ IsAcceptableCaretPosition(const gfxSkipCharsIterator& aIter, gfxTextRun* aTextRu
PRUint32 index = aIter.GetSkippedOffset();
if (!aTextRun->IsClusterStart(index))
return PR_FALSE;
return !(aFrame->GetStyleText()->NewlineIsSignificant() &&
aTextRun->GetChar(index) == '\n');
return PR_TRUE;
}
PRBool
@ -5451,8 +5450,8 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
PRInt32 startOffset = GetContentOffset() + (*aOffset < 0 ? contentLength : *aOffset);
if (!aForward) {
PRInt32 i;
for (i = NS_MIN(trimmed.GetEnd(), startOffset) - 1;
// If at the beginning of the line, look at the previous continuation
for (PRInt32 i = NS_MIN(trimmed.GetEnd(), startOffset) - 1;
i >= trimmed.mStart; --i) {
iter.SetOriginalOffset(i);
if (IsAcceptableCaretPosition(iter, mTextRun, this)) {
@ -5462,16 +5461,19 @@ nsTextFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset)
}
*aOffset = 0;
} else {
PRInt32 i;
for (i = startOffset + 1; i <= trimmed.GetEnd(); ++i) {
iter.SetOriginalOffset(i);
// XXX we can't necessarily stop at the end of this frame,
// but we really have no choice right now. We need to do a deeper
// fix/restructuring of PeekOffsetCharacter
if (i == trimmed.GetEnd() ||
IsAcceptableCaretPosition(iter, mTextRun, this)) {
*aOffset = i - mContentOffset;
return PR_TRUE;
// If we're at the end of a line, look at the next continuation
iter.SetOriginalOffset(startOffset);
if (iter.GetSkippedOffset() <= PRUint32(trimmed.GetEnd()) &&
!(iter.GetSkippedOffset() < PRUint32(trimmed.GetEnd()) &&
GetStyleText()->NewlineIsSignificant() &&
mTextRun->GetChar(iter.GetSkippedOffset()) == '\n')) {
for (PRInt32 i = startOffset + 1; i <= trimmed.GetEnd(); ++i) {
iter.SetOriginalOffset(i);
if (i == trimmed.GetEnd() ||
IsAcceptableCaretPosition(iter, mTextRun, this)) {
*aOffset = i - mContentOffset;
return PR_TRUE;
}
}
}
*aOffset = contentLength;

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

@ -18,6 +18,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=288789
&#x05d0;a&#x05d1;
</textarea>
<textarea id="tb">
abc
</textarea>
</div>
<pre id="test">
@ -50,9 +55,59 @@ function test() {
textarea.focus();
collapse(0);
testLeft(1);
collapse(5);
testRight(4);
ok(true, "Testing forward movement in RTL mode");
for (var i = 0; i < textarea.textContent.length; ++i) {
if (i == 0) {
testRight(i);
}
if (textarea.textContent[i] == 'a') {
testLeft(i);
} else {
testLeft(i + 1);
}
if (i == textarea.textContent.length - 1) {
testLeft(i + 1);
}
}
ok(true, "Testing backward movement in RTL mode");
for (var i = textarea.textContent.length; i > 0; --i) {
if (i == textarea.textContent.length) {
testLeft(i);
}
if (i > 0 && textarea.textContent[i - 1] == 'a') {
testRight(i);
} else {
testRight(i - 1);
}
if (i == 1) {
testRight(i - 1);
}
}
textarea = $("tb");
textarea.focus();
collapse(0);
ok(true, "Testing forward movement in LTR mode");
for (var i = 0; i < textarea.textContent.length; ++i) {
if (i == 0) {
testLeft(i);
}
testRight(i + 1);
if (i == textarea.textContent.length - 1) {
testRight(i + 1);
}
}
ok(true, "Testing backward movement in LTR mode");
for (var i = textarea.textContent.length; i > 0; --i) {
if (i == textarea.textContent.length) {
testRight(i);
}
testLeft(i - 1);
if (i == 1) {
testLeft(i - 1);
}
}
SimpleTest.finish();
}

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

@ -68,13 +68,13 @@ function test() {
editor.innerHTML = "<pre>aa\nbb</pre>";
sel.collapse(editor.firstChild.firstChild, 0);
testRight(editor.firstChild.firstChild, 1);
// at the 'bb' but HINTLEFT so appears at the end of the first line
testRight(editor.firstChild.firstChild, 3);
// at the end of the first line, before the \n
testRight(editor.firstChild.firstChild, 2);
testRight(editor.firstChild.firstChild, 3);
testRight(editor.firstChild.firstChild, 4);
testLeft(editor.firstChild.firstChild, 3);
// at the 'bb' but HINTLEFT so appears at the end of the first line
testLeft(editor.firstChild.firstChild, 3);
// at the end of the first line, before the \n
testLeft(editor.firstChild.firstChild, 2);
testLeft(editor.firstChild.firstChild, 1);
testLeft(editor.firstChild.firstChild, 0);