mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1216427 - part 1 - Ensure a character+VS sequence or a ligated Regional-Indicator flag symbol is deleted as a single unit when backspacing. r=emk
This commit is contained in:
parent
4fb932dfc3
commit
898bd67059
@ -5,6 +5,7 @@
|
||||
|
||||
#include "nsPlaintextEditor.h"
|
||||
|
||||
#include "gfxFontUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
@ -600,7 +601,8 @@ nsPlaintextEditor::ExtendSelectionForDelete(Selection* aSelection,
|
||||
break;
|
||||
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
|
||||
// surrogate pair or a variation selector.
|
||||
// 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;
|
||||
@ -616,9 +618,11 @@ nsPlaintextEditor::ExtendSelectionForDelete(Selection* aSelection,
|
||||
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])) {
|
||||
if ((offset > 1 &&
|
||||
NS_IS_LOW_SURROGATE(data[offset - 1]) &&
|
||||
NS_IS_HIGH_SURROGATE(data[offset - 2])) ||
|
||||
(offset > 0 &&
|
||||
gfxFontUtils::IsVarSelector(data[offset - 1]))) {
|
||||
result = selCont->CharacterExtendForBackspace();
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ function test(edit, bsCount) {
|
||||
for (i = 0; i < bsCount; ++i) {
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
}
|
||||
todo_is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
|
||||
is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
|
||||
}
|
||||
|
||||
function testWithMove(edit, offset, bsCount) {
|
||||
@ -70,7 +70,7 @@ function testWithMove(edit, offset, bsCount) {
|
||||
for (i = 0; i < bsCount; ++i) {
|
||||
synthesizeKey("VK_BACK_SPACE", {});
|
||||
}
|
||||
todo_is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
|
||||
is(edit.textContent, "ab", "The backspace key should delete the characters correctly");
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
|
@ -573,9 +573,6 @@ gfxShapedText::SetupClusterBoundaries(uint32_t aOffset,
|
||||
// mark all the rest as cluster-continuations
|
||||
while (aString < iter) {
|
||||
*glyphs = extendCluster;
|
||||
if (NS_IS_LOW_SURROGATE(*aString)) {
|
||||
glyphs->SetIsLowSurrogate();
|
||||
}
|
||||
glyphs++;
|
||||
aString++;
|
||||
}
|
||||
|
@ -741,8 +741,7 @@ public:
|
||||
|
||||
FLAG_CHAR_IS_TAB = 0x08,
|
||||
FLAG_CHAR_IS_NEWLINE = 0x10,
|
||||
FLAG_CHAR_IS_LOW_SURROGATE = 0x20,
|
||||
CHAR_IDENTITY_FLAGS_MASK = 0x38,
|
||||
CHAR_IDENTITY_FLAGS_MASK = 0x18,
|
||||
|
||||
GLYPH_COUNT_MASK = 0x00FFFF00U,
|
||||
GLYPH_COUNT_SHIFT = 8
|
||||
@ -793,9 +792,6 @@ public:
|
||||
bool CharIsNewline() const {
|
||||
return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_NEWLINE) != 0;
|
||||
}
|
||||
bool CharIsLowSurrogate() const {
|
||||
return !IsSimpleGlyph() && (mValue & FLAG_CHAR_IS_LOW_SURROGATE) != 0;
|
||||
}
|
||||
|
||||
uint32_t CharIdentityFlags() const {
|
||||
return IsSimpleGlyph() ? 0 : (mValue & CHAR_IDENTITY_FLAGS_MASK);
|
||||
@ -870,10 +866,6 @@ public:
|
||||
NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
|
||||
mValue |= FLAG_CHAR_IS_NEWLINE;
|
||||
}
|
||||
void SetIsLowSurrogate() {
|
||||
NS_ASSERTION(!IsSimpleGlyph(), "Expected non-simple-glyph");
|
||||
mValue |= FLAG_CHAR_IS_LOW_SURROGATE;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t mValue;
|
||||
@ -908,11 +900,6 @@ public:
|
||||
GetCharacterGlyphs()[aIndex].SetIsSpace();
|
||||
}
|
||||
|
||||
void SetIsLowSurrogate(uint32_t aIndex) {
|
||||
SetGlyphs(aIndex, CompressedGlyph().SetComplex(false, false, 0), nullptr);
|
||||
GetCharacterGlyphs()[aIndex].SetIsLowSurrogate();
|
||||
}
|
||||
|
||||
bool HasDetailedGlyphs() const {
|
||||
return mDetailedGlyphs != nullptr;
|
||||
}
|
||||
|
@ -903,6 +903,16 @@ public:
|
||||
(ch >= kUnicodeVS17 && ch <= kUnicodeVS256);
|
||||
}
|
||||
|
||||
enum {
|
||||
kUnicodeRegionalIndicatorA = 0x1F1E6,
|
||||
kUnicodeRegionalIndicatorZ = 0x1F1FF
|
||||
};
|
||||
|
||||
static inline bool IsRegionalIndicator(uint32_t aCh) {
|
||||
return aCh >= kUnicodeRegionalIndicatorA &&
|
||||
aCh <= kUnicodeRegionalIndicatorZ;
|
||||
}
|
||||
|
||||
static inline bool IsInvalid(uint32_t ch) {
|
||||
return (ch == 0xFFFD);
|
||||
}
|
||||
|
@ -128,10 +128,6 @@ public:
|
||||
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
|
||||
return mCharacterGlyphs[aPos].CharIsNewline();
|
||||
}
|
||||
bool CharIsLowSurrogate(uint32_t aPos) const {
|
||||
NS_ASSERTION(aPos < GetLength(), "aPos out of range");
|
||||
return mCharacterGlyphs[aPos].CharIsLowSurrogate();
|
||||
}
|
||||
|
||||
// All uint32_t aStart, uint32_t aLength ranges below are restricted to
|
||||
// grapheme cluster boundaries! All offsets are in terms of the string
|
||||
@ -535,10 +531,6 @@ public:
|
||||
}
|
||||
g->SetIsNewline();
|
||||
}
|
||||
void SetIsLowSurrogate(uint32_t aIndex) {
|
||||
SetGlyphs(aIndex, CompressedGlyph().SetComplex(false, false, 0), nullptr);
|
||||
mCharacterGlyphs[aIndex].SetIsLowSurrogate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch all the glyph extents needed to ensure that Measure calls
|
||||
|
@ -7026,13 +7026,37 @@ IsAcceptableCaretPosition(const gfxSkipCharsIterator& aIter,
|
||||
return false;
|
||||
if (index > 0) {
|
||||
// Check whether the proposed position is in between the two halves of a
|
||||
// surrogate pair; if so, this is not a valid character boundary.
|
||||
// surrogate pair, or before a Variation Selector character;
|
||||
// if so, this is not a valid character boundary.
|
||||
// (In the case where we are respecting clusters, we won't actually get
|
||||
// this far because the low surrogate is also marked as non-clusterStart
|
||||
// so we'll return FALSE above.)
|
||||
if (aTextRun->CharIsLowSurrogate(index)) {
|
||||
uint32_t offs = aIter.GetOriginalOffset();
|
||||
const nsTextFragment* frag = aFrame->GetContent()->GetText();
|
||||
uint32_t ch = frag->CharAt(offs);
|
||||
|
||||
if (gfxFontUtils::IsVarSelector(ch) ||
|
||||
(NS_IS_LOW_SURROGATE(ch) && offs > 0 &&
|
||||
NS_IS_HIGH_SURROGATE(frag->CharAt(offs - 1)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the proposed position is before a high surrogate, we need to decode
|
||||
// the surrogate pair (if valid) and check the resulting character.
|
||||
if (NS_IS_HIGH_SURROGATE(ch) && offs + 1 < frag->GetLength()) {
|
||||
uint32_t ch2 = frag->CharAt(offs + 1);
|
||||
if (NS_IS_LOW_SURROGATE(ch2)) {
|
||||
ch = SURROGATE_TO_UCS4(ch, ch2);
|
||||
// If the character is a (Plane-14) variation selector,
|
||||
// or a Regional Indicator character that is ligated with the previous
|
||||
// character, this is not a valid boundary.
|
||||
if (gfxFontUtils::IsVarSelector(ch) ||
|
||||
(gfxFontUtils::IsRegionalIndicator(ch) &&
|
||||
!aTextRun->IsLigatureGroupStart(index))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user