Bug 332636 - Handle backspace for Unicode plane 1 characters correctly; r=roc

--HG--
extra : rebase_source : a343610b06983d3328f3ddb2e7025193ab275094
This commit is contained in:
Ehsan Akhgari 2010-06-04 13:28:19 -04:00
Родитель 0d39cb2346
Коммит d16570fb74
9 изменённых файлов: 113 добавлений и 6 удалений

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

@ -51,7 +51,7 @@ interface nsIDOMNode;
interface nsISelection;
interface nsISelectionDisplay;
[scriptable, uuid(b5c3ffc4-f48a-4f25-86e1-4cf79db1bcbb)]
[scriptable, uuid(bc5795ab-bcb5-448b-b3c7-a111bead7c26)]
interface nsISelectionController : nsISelectionDisplay
{
const short SELECTION_NONE=0;
@ -172,6 +172,14 @@ interface nsISelectionController : nsISelectionDisplay
*/
[noscript] void characterExtendForDelete();
/**
* CharacterExtendForBackspace will extend the selection one character cell
* backward in the document.
* this method is used internally for handling backspace key only when we're
* after UTF-16 surrogates.
*/
[noscript] void characterExtendForBackspace();
/** WordMove will move the selection one word forward/backward in the document.
* this will also have the effect of collapsing the selection if the aExtend = PR_FALSE
* the "point" of selection that is extended is considered the "focus" point.

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

@ -165,6 +165,7 @@ public:
NS_IMETHOD SetCaretVisibilityDuringSelection(PRBool aVisibility);
NS_IMETHOD CharacterMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD CharacterExtendForDelete();
NS_IMETHOD CharacterExtendForBackspace();
NS_IMETHOD WordMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD WordExtendForDelete(PRBool aForward);
NS_IMETHOD LineMove(PRBool aForward, PRBool aExtend);
@ -397,6 +398,14 @@ nsTextInputSelectionImpl::CharacterExtendForDelete()
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsTextInputSelectionImpl::CharacterExtendForBackspace()
{
if (mFrameSelection)
return mFrameSelection->CharacterExtendForBackspace();
return NS_ERROR_NULL_POINTER;
}
NS_IMETHODIMP
nsTextInputSelectionImpl::WordMove(PRBool aForward, PRBool aExtend)
{

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

@ -45,6 +45,8 @@ include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = \
test_bug332636.html \
test_bug332636.html^headers^ \
test_bug366682.html \
test_bug432225.html \
test_bug455992.html \

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

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=332636
-->
<head>
<title>Test for Bug 332636</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332636">Mozilla Bug 332636</a>
<p id="display"></p>
<div id="content">
<div id="edit" contenteditable="true">a𐐀b</div>
<div id="edit2" contenteditable="true">a&#x10a0f;b</div>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 332636 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(runTest);
function test(edit) {
edit.focus();
var sel = window.getSelection();
sel.collapse(edit.childNodes[0], edit.textContent.length - 1);
synthesizeKey("VK_BACK_SPACE", {});
is(edit.textContent, "ab", "The backspace key should delete the UTF-16 surrogate pair correctly");
}
function runTest() {
test(document.getElementById("edit"));
test(document.getElementById("edit2"));
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

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

@ -0,0 +1 @@
Content-Type: text/html; charset=UTF-8

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

@ -78,6 +78,7 @@
#include "nsInternetCiter.h"
#include "nsEventDispatcher.h"
#include "nsGkAtoms.h"
#include "nsDebug.h"
// Drag & Drop, Clipboard
#include "nsIClipboard.h"
@ -636,6 +637,7 @@ nsPlaintextEditor::ExtendSelectionForDelete(nsISelection *aSelection,
if (*aAction == eNextWord || *aAction == ePreviousWord
|| (*aAction == eNext && bCollapsed)
|| (*aAction == ePrevious && bCollapsed)
|| *aAction == eToBeginningOfLine || *aAction == eToEndOfLine)
{
nsCOMPtr<nsISelectionController> selCont (do_QueryReferent(mSelConWeak));
@ -658,12 +660,33 @@ nsPlaintextEditor::ExtendSelectionForDelete(nsISelection *aSelection,
result = selCont->CharacterExtendForDelete();
// Don't set aAction to eNone (see Bug 502259)
break;
case ePrevious:
/* FIXME: extend selection over UTF-16 surrogates for Bug #332636
* and set *aAction = eNone
*/
result = NS_OK;
case ePrevious: {
// Only extend the selection where the selection is after a UTF-16
// surrogate pair. For other cases we don't want to do that, in order
// to make sure that pressing backspace will only delete the last
// typed character.
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
result = GetStartNodeAndOffset(aSelection, address_of(node), &offset);
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (IsTextNode(node)) {
nsCOMPtr<nsIDOMCharacterData> charData = do_QueryInterface(node);
if (charData) {
nsAutoString data;
result = charData->GetData(data);
NS_ENSURE_SUCCESS(result, result);
if (offset > 1 &&
NS_IS_LOW_SURROGATE(data[offset - 1]) &&
NS_IS_HIGH_SURROGATE(data[offset - 2])) {
result = selCont->CharacterExtendForBackspace();
}
}
}
break;
}
case eToBeginningOfLine:
selCont->IntraLineMove(PR_TRUE, PR_FALSE); // try to move to end
result = selCont->IntraLineMove(PR_FALSE, PR_TRUE); // select to beginning

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

@ -850,6 +850,7 @@ public:
NS_IMETHOD CharacterMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD CharacterExtendForDelete();
NS_IMETHOD CharacterExtendForBackspace();
NS_IMETHOD WordMove(PRBool aForward, PRBool aExtend);
NS_IMETHOD WordExtendForDelete(PRBool aForward);
NS_IMETHOD LineMove(PRBool aForward, PRBool aExtend);
@ -2983,6 +2984,12 @@ PresShell::CharacterExtendForDelete()
return mSelection->CharacterExtendForDelete();
}
NS_IMETHODIMP
PresShell::CharacterExtendForBackspace()
{
return mSelection->CharacterExtendForBackspace();
}
NS_IMETHODIMP
PresShell::WordMove(PRBool aForward, PRBool aExtend)
{

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

@ -463,6 +463,12 @@ public:
/*unsafe*/
nsresult CharacterExtendForDelete();
/** CharacterExtendForBackspace extends the selection backward (logically) to
* the previous character cell, so that the selected cell can be deleted.
*/
/*unsafe*/
nsresult CharacterExtendForBackspace();
/** WordMove will generally be called from the nsiselectioncontroller implementations.
* the effect being the selection will move one word left or right.
* @param aForward move forward in document.

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

@ -2160,6 +2160,12 @@ nsFrameSelection::CharacterExtendForDelete()
return MoveCaret(nsIDOMKeyEvent::DOM_VK_DELETE, PR_TRUE, eSelectCharacter);
}
nsresult
nsFrameSelection::CharacterExtendForBackspace()
{
return MoveCaret(nsIDOMKeyEvent::DOM_VK_BACK_SPACE, PR_TRUE, eSelectCharacter);
}
nsresult
nsFrameSelection::WordMove(PRBool aForward, PRBool aExtend)
{