mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1176954 part.7 IMENotification::TextChangeData should have a method to merge with another instance and IMENotification::MergeWith() should use it r=smaug
This commit is contained in:
parent
2d7ddd1c22
commit
f63fe84824
@ -99,7 +99,7 @@ IMEContentObserver::IMEContentObserver()
|
||||
, mIsFlushingPendingNotifications(false)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
TestMergingTextChangeData();
|
||||
mTextChangeData.Test();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -523,195 +523,6 @@ IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void
|
||||
IMEContentObserver::StoreTextChangeData(
|
||||
const TextChangeDataBase& aTextChangeData)
|
||||
{
|
||||
MOZ_ASSERT(aTextChangeData.mStartOffset <= aTextChangeData.mRemovedEndOffset,
|
||||
"end of removed text must be same or larger than start");
|
||||
MOZ_ASSERT(aTextChangeData.mStartOffset <= aTextChangeData.mAddedEndOffset,
|
||||
"end of added text must be same or larger than start");
|
||||
|
||||
if (!mTextChangeData.IsValid()) {
|
||||
// XXX This becomes safe in next patch.
|
||||
static_assert(sizeof(TextChangeData) == sizeof(TextChangeDataBase),
|
||||
"TextChangeData shouldn't have specific members");
|
||||
static_cast<TextChangeDataBase>(mTextChangeData) = aTextChangeData;
|
||||
MOZ_ASSERT(mTextChangeData.IsValid(), "Why mStored is false?");
|
||||
return;
|
||||
}
|
||||
|
||||
// |mTextChangeData| should represent all modified text ranges and all
|
||||
// inserted text ranges.
|
||||
// |mStartOffset| and |mRemovedEndOffset| represent all replaced or removed
|
||||
// text ranges. I.e., mStartOffset should be the smallest offset of all
|
||||
// modified text ranges in old text. |mRemovedEndOffset| should be the
|
||||
// largest end offset in old text of all modified text ranges.
|
||||
// |mAddedEndOffset| represents the end offset of all inserted text ranges.
|
||||
// I.e., only this is an offset in new text.
|
||||
// In other words, between mStartOffset and |mRemovedEndOffset| of the
|
||||
// premodified text was already removed. And some text whose length is
|
||||
// |mAddedEndOffset - mStartOffset| is inserted to |mStartOffset|. I.e.,
|
||||
// this allows IME to mark dirty the modified text range with |mStartOffset|
|
||||
// and |mRemovedEndOffset| if IME stores all text of the focused editor and
|
||||
// to compute new text length with |mAddedEndOffset| and |mRemovedEndOffset|.
|
||||
// Additionally, IME can retrieve only the text between |mStartOffset| and
|
||||
// |mAddedEndOffset| for updating stored text.
|
||||
|
||||
// For comparing new and old |mStartOffset|/|mRemovedEndOffset| values, they
|
||||
// should be adjusted to be in same text. The |newData.mStartOffset| and
|
||||
// |newData.mRemovedEndOffset| should be computed as in old text because
|
||||
// |mStartOffset| and |mRemovedEndOffset| represent the modified text range
|
||||
// in the old text but even if some text before the values of the newData
|
||||
// has already been modified, the values don't include the changes.
|
||||
|
||||
// For comparing new and old |mAddedEndOffset| values, they should be
|
||||
// adjusted to be in same text. The |oldData.mAddedEndOffset| should be
|
||||
// computed as in the new text because |mAddedEndOffset| indicates the end
|
||||
// offset of inserted text in the new text but |oldData.mAddedEndOffset|
|
||||
// doesn't include any changes of the text before |newData.mAddedEndOffset|.
|
||||
|
||||
const TextChangeDataBase& newData = aTextChangeData;
|
||||
const TextChangeDataBase oldData = mTextChangeData;
|
||||
|
||||
mTextChangeData.mCausedByComposition =
|
||||
newData.mCausedByComposition && oldData.mCausedByComposition;
|
||||
|
||||
if (newData.mStartOffset >= oldData.mAddedEndOffset) {
|
||||
// Case 1:
|
||||
// If new start is after old end offset of added text, it means that text
|
||||
// after the modified range is modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
// So, the old start offset is always the smaller offset.
|
||||
mTextChangeData.mStartOffset = oldData.mStartOffset;
|
||||
// The new end offset of removed text is moved by the old change and we
|
||||
// need to cancel the move of the old change for comparing the offsets in
|
||||
// same text because it doesn't make sensce to compare offsets in different
|
||||
// text.
|
||||
uint32_t newRemovedEndOffsetInOldText =
|
||||
newData.mRemovedEndOffset - oldData.Difference();
|
||||
mTextChangeData.mRemovedEndOffset =
|
||||
std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
|
||||
// The new end offset of added text is always the larger offset.
|
||||
mTextChangeData.mAddedEndOffset = newData.mAddedEndOffset;
|
||||
return;
|
||||
}
|
||||
|
||||
if (newData.mStartOffset >= oldData.mStartOffset) {
|
||||
// If new start is in the modified range, it means that new data changes
|
||||
// a part or all of the range.
|
||||
mTextChangeData.mStartOffset = oldData.mStartOffset;
|
||||
if (newData.mRemovedEndOffset >= oldData.mAddedEndOffset) {
|
||||
// Case 2:
|
||||
// If new end of removed text is greater than old end of added text, it
|
||||
// means that all or a part of modified range modified again and text
|
||||
// after the modified range is also modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
// So, the new removed end offset is moved by the old change and we need
|
||||
// to cancel the move of the old change for comparing the offsets in the
|
||||
// same text because it doesn't make sense to compare the offsets in
|
||||
// different text.
|
||||
uint32_t newRemovedEndOffsetInOldText =
|
||||
newData.mRemovedEndOffset - oldData.Difference();
|
||||
mTextChangeData.mRemovedEndOffset =
|
||||
std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
|
||||
// The old end of added text is replaced by new change. So, it should be
|
||||
// same as the new start. On the other hand, the new added end offset is
|
||||
// always same or larger. Therefore, the merged end offset of added
|
||||
// text should be the new end offset of added text.
|
||||
mTextChangeData.mAddedEndOffset = newData.mAddedEndOffset;
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 3:
|
||||
// If new end of removed text is less than old end of added text, it means
|
||||
// that only a part of the modified range is modified again. Like:
|
||||
// added range of old change: +------------+
|
||||
// removed range of new change: +-----+
|
||||
// So, the new end offset of removed text should be same as the old end
|
||||
// offset of removed text. Therefore, the merged end offset of removed
|
||||
// text should be the old text change's |mRemovedEndOffset|.
|
||||
mTextChangeData.mRemovedEndOffset = oldData.mRemovedEndOffset;
|
||||
// The old end of added text is moved by new change. So, we need to cancel
|
||||
// the move of the new change for comparing the offsets in same text.
|
||||
uint32_t oldAddedEndOffsetInNewText =
|
||||
oldData.mAddedEndOffset + newData.Difference();
|
||||
mTextChangeData.mAddedEndOffset =
|
||||
std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newData.mRemovedEndOffset >= oldData.mStartOffset) {
|
||||
// If new end of removed text is greater than old start (and new start is
|
||||
// less than old start), it means that a part of modified range is modified
|
||||
// again and some new text before the modified range is also modified.
|
||||
MOZ_ASSERT(newData.mStartOffset < oldData.mStartOffset,
|
||||
"new start offset should be less than old one here");
|
||||
mTextChangeData.mStartOffset = newData.mStartOffset;
|
||||
if (newData.mRemovedEndOffset >= oldData.mAddedEndOffset) {
|
||||
// Case 4:
|
||||
// If new end of removed text is greater than old end of added text, it
|
||||
// means that all modified text and text after the modified range is
|
||||
// modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +------------------+
|
||||
// So, the new end of removed text is moved by the old change. Therefore,
|
||||
// we need to cancel the move of the old change for comparing the offsets
|
||||
// in same text because it doesn't make sense to compare the offsets in
|
||||
// different text.
|
||||
uint32_t newRemovedEndOffsetInOldText =
|
||||
newData.mRemovedEndOffset - oldData.Difference();
|
||||
mTextChangeData.mRemovedEndOffset =
|
||||
std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
|
||||
// The old end of added text is replaced by new change. So, the old end
|
||||
// offset of added text is same as new text change's start offset. Then,
|
||||
// new change's end offset of added text is always same or larger than
|
||||
// it. Therefore, merged end offset of added text is always the new end
|
||||
// offset of added text.
|
||||
mTextChangeData.mAddedEndOffset = newData.mAddedEndOffset;
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 5:
|
||||
// If new end of removed text is less than old end of added text, it
|
||||
// means that only a part of the modified range is modified again. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
// So, the new end of removed text should be same as old end of removed
|
||||
// text for preventing end of removed text to be modified. Therefore,
|
||||
// merged end offset of removed text is always the old end offset of removed
|
||||
// text.
|
||||
mTextChangeData.mRemovedEndOffset = oldData.mRemovedEndOffset;
|
||||
// The old end of added text is moved by this change. So, we need to
|
||||
// cancel the move of the new change for comparing the offsets in same text
|
||||
// because it doesn't make sense to compare the offsets in different text.
|
||||
uint32_t oldAddedEndOffsetInNewText =
|
||||
oldData.mAddedEndOffset + newData.Difference();
|
||||
mTextChangeData.mAddedEndOffset =
|
||||
std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 6:
|
||||
// Otherwise, i.e., both new end of added text and new start are less than
|
||||
// old start, text before the modified range is modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
MOZ_ASSERT(newData.mStartOffset < oldData.mStartOffset,
|
||||
"new start offset should be less than old one here");
|
||||
mTextChangeData.mStartOffset = newData.mStartOffset;
|
||||
MOZ_ASSERT(newData.mRemovedEndOffset < oldData.mRemovedEndOffset,
|
||||
"new removed end offset should be less than old one here");
|
||||
mTextChangeData.mRemovedEndOffset = oldData.mRemovedEndOffset;
|
||||
// The end of added text should be adjusted with the new difference.
|
||||
uint32_t oldAddedEndOffsetInNewText =
|
||||
oldData.mAddedEndOffset + newData.Difference();
|
||||
mTextChangeData.mAddedEndOffset =
|
||||
std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
|
||||
}
|
||||
|
||||
void
|
||||
IMEContentObserver::CharacterDataWillChange(nsIDocument* aDocument,
|
||||
nsIContent* aContent,
|
||||
@ -1011,7 +822,7 @@ void
|
||||
IMEContentObserver::PostTextChangeNotification(
|
||||
const TextChangeDataBase& aTextChangeData)
|
||||
{
|
||||
StoreTextChangeData(aTextChangeData);
|
||||
mTextChangeData += aTextChangeData;
|
||||
MOZ_ASSERT(mTextChangeData.IsValid(),
|
||||
"mTextChangeData must have text change data");
|
||||
}
|
||||
@ -1146,457 +957,6 @@ IMEContentObserver::FlushMergeableNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// Let's test the code of merging multiple text change data in debug build
|
||||
// and crash if one of them fails because this feature is very complex but
|
||||
// cannot be tested with mochitest.
|
||||
void
|
||||
IMEContentObserver::TestMergingTextChangeData()
|
||||
{
|
||||
static bool gTestTextChangeEvent = true;
|
||||
if (!gTestTextChangeEvent) {
|
||||
return;
|
||||
}
|
||||
gTestTextChangeEvent = false;
|
||||
|
||||
/****************************************************************************
|
||||
* Case 1
|
||||
****************************************************************************/
|
||||
|
||||
// Appending text
|
||||
StoreTextChangeData(TextChangeData(10, 10, 20, false));
|
||||
StoreTextChangeData(TextChangeData(20, 20, 35, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 1-1-1: mStartOffset should be the first offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 10, // 20 - (20 - 10)
|
||||
"Test 1-1-2: mRemovedEndOffset should be the first end of removed text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 35,
|
||||
"Test 1-1-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Removing text (longer line -> shorter line)
|
||||
StoreTextChangeData(TextChangeData(10, 20, 10, false));
|
||||
StoreTextChangeData(TextChangeData(10, 30, 10, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 1-2-1: mStartOffset should be the first offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 40, // 30 + (10 - 20)
|
||||
"Test 1-2-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"with already removed length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 10,
|
||||
"Test 1-2-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Removing text (shorter line -> longer line)
|
||||
StoreTextChangeData(TextChangeData(10, 20, 10, false));
|
||||
StoreTextChangeData(TextChangeData(10, 15, 10, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 1-3-1: mStartOffset should be the first offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 25, // 15 + (10 - 20)
|
||||
"Test 1-3-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"with already removed length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 10,
|
||||
"Test 1-3-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Appending text at different point (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(10, 10, 20, false));
|
||||
StoreTextChangeData(TextChangeData(55, 55, 60, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 1-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 45, // 55 - (10 - 20)
|
||||
"Test 1-4-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text without already added length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 60,
|
||||
"Test 1-4-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Removing text at different point (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(10, 20, 10, false));
|
||||
StoreTextChangeData(TextChangeData(55, 68, 55, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 1-5-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 78, // 68 - (10 - 20)
|
||||
"Test 1-5-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text with already removed length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 55,
|
||||
"Test 1-5-3: mAddedEndOffset should be the largest end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text and append text (becomes longer)
|
||||
StoreTextChangeData(TextChangeData(30, 35, 32, false));
|
||||
StoreTextChangeData(TextChangeData(32, 32, 40, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 30,
|
||||
"Test 1-6-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 35, // 32 - (32 - 35)
|
||||
"Test 1-6-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 40,
|
||||
"Test 1-6-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text and append text (becomes shorter)
|
||||
StoreTextChangeData(TextChangeData(30, 35, 32, false));
|
||||
StoreTextChangeData(TextChangeData(32, 32, 33, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 30,
|
||||
"Test 1-7-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 35, // 32 - (32 - 35)
|
||||
"Test 1-7-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 33,
|
||||
"Test 1-7-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Removing text and replacing text after first range (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(30, 35, 30, false));
|
||||
StoreTextChangeData(TextChangeData(32, 34, 48, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 30,
|
||||
"Test 1-8-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 39, // 34 - (30 - 35)
|
||||
"Test 1-8-2: mRemovedEndOffset should be the the first end of removed text "
|
||||
"without already removed text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 48,
|
||||
"Test 1-8-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Removing text and replacing text after first range (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(30, 35, 30, false));
|
||||
StoreTextChangeData(TextChangeData(32, 38, 36, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 30,
|
||||
"Test 1-9-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 43, // 38 - (30 - 35)
|
||||
"Test 1-9-2: mRemovedEndOffset should be the the first end of removed text "
|
||||
"without already removed text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 36,
|
||||
"Test 1-9-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 2
|
||||
****************************************************************************/
|
||||
|
||||
// Replacing text in around end of added text (becomes shorter) (not sure
|
||||
// if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 50, 55, false));
|
||||
StoreTextChangeData(TextChangeData(53, 60, 54, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 50,
|
||||
"Test 2-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 55, // 60 - (55 - 50)
|
||||
"Test 2-1-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 54,
|
||||
"Test 2-1-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around end of added text (becomes longer) (not sure
|
||||
// if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 50, 55, false));
|
||||
StoreTextChangeData(TextChangeData(54, 62, 68, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 50,
|
||||
"Test 2-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 57, // 62 - (55 - 50)
|
||||
"Test 2-2-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 68,
|
||||
"Test 2-2-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around end of replaced text (became shorter) (not sure if
|
||||
// actually occurs)
|
||||
StoreTextChangeData(TextChangeData(36, 48, 45, false));
|
||||
StoreTextChangeData(TextChangeData(43, 50, 49, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 36,
|
||||
"Test 2-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 53, // 50 - (45 - 48)
|
||||
"Test 2-3-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already removed text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 49,
|
||||
"Test 2-3-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around end of replaced text (became longer) (not sure if
|
||||
// actually occurs)
|
||||
StoreTextChangeData(TextChangeData(36, 52, 53, false));
|
||||
StoreTextChangeData(TextChangeData(43, 68, 61, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 36,
|
||||
"Test 2-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 67, // 68 - (53 - 52)
|
||||
"Test 2-4-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 61,
|
||||
"Test 2-4-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 3
|
||||
****************************************************************************/
|
||||
|
||||
// Appending text in already added text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(10, 10, 20, false));
|
||||
StoreTextChangeData(TextChangeData(15, 15, 30, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 3-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 10,
|
||||
"Test 3-1-2: mRemovedEndOffset should be the the first end of removed text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 35, // 20 + (30 - 15)
|
||||
"Test 3-1-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text in added text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 50, 55, false));
|
||||
StoreTextChangeData(TextChangeData(52, 53, 56, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 50,
|
||||
"Test 3-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 50,
|
||||
"Test 3-2-2: mRemovedEndOffset should be the the first end of removed text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 58, // 55 + (56 - 53)
|
||||
"Test 3-2-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text in replaced text (became shorter) (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(36, 48, 45, false));
|
||||
StoreTextChangeData(TextChangeData(37, 38, 50, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 36,
|
||||
"Test 3-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 48,
|
||||
"Test 3-3-2: mRemovedEndOffset should be the the first end of removed text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 57, // 45 + (50 - 38)
|
||||
"Test 3-3-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text in replaced text (became longer) (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(32, 48, 53, false));
|
||||
StoreTextChangeData(TextChangeData(43, 50, 52, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 32,
|
||||
"Test 3-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 48,
|
||||
"Test 3-4-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 55, // 53 + (52 - 50)
|
||||
"Test 3-4-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text in replaced text (became shorter) (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(36, 48, 50, false));
|
||||
StoreTextChangeData(TextChangeData(37, 49, 47, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 36,
|
||||
"Test 3-5-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 48,
|
||||
"Test 3-5-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 48, // 50 + (47 - 49)
|
||||
"Test 3-5-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text in replaced text (became longer) (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(32, 48, 53, false));
|
||||
StoreTextChangeData(TextChangeData(43, 50, 47, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 32,
|
||||
"Test 3-6-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 48,
|
||||
"Test 3-6-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 50, // 53 + (47 - 50)
|
||||
"Test 3-6-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 4
|
||||
****************************************************************************/
|
||||
|
||||
// Replacing text all of already append text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 50, 55, false));
|
||||
StoreTextChangeData(TextChangeData(44, 66, 68, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 44,
|
||||
"Test 4-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 61, // 66 - (55 - 50)
|
||||
"Test 4-1-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 68,
|
||||
"Test 4-1-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around a point in which text was removed (not sure if
|
||||
// actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 62, 50, false));
|
||||
StoreTextChangeData(TextChangeData(44, 66, 68, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 44,
|
||||
"Test 4-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 78, // 66 - (50 - 62)
|
||||
"Test 4-2-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already removed text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 68,
|
||||
"Test 4-2-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text all replaced text (became shorter) (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 62, 60, false));
|
||||
StoreTextChangeData(TextChangeData(49, 128, 130, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 49,
|
||||
"Test 4-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 130, // 128 - (60 - 62)
|
||||
"Test 4-3-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already removed text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 130,
|
||||
"Test 4-3-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text all replaced text (became longer) (not sure if actually
|
||||
// occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 61, 73, false));
|
||||
StoreTextChangeData(TextChangeData(44, 100, 50, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 44,
|
||||
"Test 4-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 88, // 100 - (73 - 61)
|
||||
"Test 4-4-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"with already added text length");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 50,
|
||||
"Test 4-4-3: mAddedEndOffset should be the last end of added text");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 5
|
||||
****************************************************************************/
|
||||
|
||||
// Replacing text around start of added text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 50, 55, false));
|
||||
StoreTextChangeData(TextChangeData(48, 52, 49, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 48,
|
||||
"Test 5-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 50,
|
||||
"Test 5-1-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 52, // 55 + (52 - 49)
|
||||
"Test 5-1-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became shorter) (not sure if
|
||||
// actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 60, 58, false));
|
||||
StoreTextChangeData(TextChangeData(43, 50, 48, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 43,
|
||||
"Test 5-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 60,
|
||||
"Test 5-2-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 56, // 58 + (48 - 50)
|
||||
"Test 5-2-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became longer) (not sure if
|
||||
// actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 60, 68, false));
|
||||
StoreTextChangeData(TextChangeData(43, 55, 53, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 43,
|
||||
"Test 5-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 60,
|
||||
"Test 5-3-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 66, // 68 + (53 - 55)
|
||||
"Test 5-3-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became shorter) (not sure if
|
||||
// actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 60, 58, false));
|
||||
StoreTextChangeData(TextChangeData(43, 50, 128, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 43,
|
||||
"Test 5-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 60,
|
||||
"Test 5-4-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 136, // 58 + (128 - 50)
|
||||
"Test 5-4-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became longer) (not sure if
|
||||
// actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 60, 68, false));
|
||||
StoreTextChangeData(TextChangeData(43, 55, 65, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 43,
|
||||
"Test 5-5-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 60,
|
||||
"Test 5-5-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 78, // 68 + (65 - 55)
|
||||
"Test 5-5-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 6
|
||||
****************************************************************************/
|
||||
|
||||
// Appending text before already added text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(30, 30, 45, false));
|
||||
StoreTextChangeData(TextChangeData(10, 10, 20, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 6-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 30,
|
||||
"Test 6-1-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 55, // 45 + (20 - 10)
|
||||
"Test 6-1-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Removing text before already removed text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(30, 35, 30, false));
|
||||
StoreTextChangeData(TextChangeData(10, 25, 10, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 10,
|
||||
"Test 6-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 35,
|
||||
"Test 6-2-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 15, // 30 - (25 - 10)
|
||||
"Test 6-2-3: mAddedEndOffset should be the first end of added text with "
|
||||
"removed text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text before already replaced text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 65, 70, false));
|
||||
StoreTextChangeData(TextChangeData(13, 24, 15, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 13,
|
||||
"Test 6-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 65,
|
||||
"Test 6-3-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 61, // 70 + (15 - 24)
|
||||
"Test 6-3-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
|
||||
// Replacing text before already replaced text (not sure if actually occurs)
|
||||
StoreTextChangeData(TextChangeData(50, 65, 70, false));
|
||||
StoreTextChangeData(TextChangeData(13, 24, 36, false));
|
||||
MOZ_ASSERT(mTextChangeData.mStartOffset == 13,
|
||||
"Test 6-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mTextChangeData.mRemovedEndOffset == 65,
|
||||
"Test 6-4-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mTextChangeData.mAddedEndOffset == 82, // 70 + (36 - 24)
|
||||
"Test 6-4-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
mTextChangeData.Clear();
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::IMEContentObserver::AChangeEvent
|
||||
******************************************************************************/
|
||||
|
@ -155,7 +155,6 @@ private:
|
||||
* UnregisterObservers() unregisters all listeners and observers.
|
||||
*/
|
||||
void UnregisterObservers();
|
||||
void StoreTextChangeData(const TextChangeDataBase& aTextChangeData);
|
||||
void FlushMergeableNotifications();
|
||||
void ClearPendingNotifications()
|
||||
{
|
||||
@ -165,10 +164,6 @@ private:
|
||||
mTextChangeData.Clear();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void TestMergingTextChangeData();
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsCOMPtr<nsISelection> mSelection;
|
||||
nsCOMPtr<nsIContent> mRootContent;
|
||||
|
@ -2025,6 +2025,650 @@ nsIWidget::SnapshotWidgetOnScreen()
|
||||
return dt->Snapshot();
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
void
|
||||
IMENotification::TextChangeDataBase::MergeWith(
|
||||
const IMENotification::TextChangeDataBase& aOther)
|
||||
{
|
||||
MOZ_ASSERT(aOther.IsValid(),
|
||||
"Merging data must store valid data");
|
||||
MOZ_ASSERT(aOther.mStartOffset <= aOther.mRemovedEndOffset,
|
||||
"end of removed text must be same or larger than start");
|
||||
MOZ_ASSERT(aOther.mStartOffset <= aOther.mAddedEndOffset,
|
||||
"end of added text must be same or larger than start");
|
||||
|
||||
if (!IsValid()) {
|
||||
*this = aOther;
|
||||
return;
|
||||
}
|
||||
|
||||
// |mStartOffset| and |mRemovedEndOffset| represent all replaced or removed
|
||||
// text ranges. I.e., mStartOffset should be the smallest offset of all
|
||||
// modified text ranges in old text. |mRemovedEndOffset| should be the
|
||||
// largest end offset in old text of all modified text ranges.
|
||||
// |mAddedEndOffset| represents the end offset of all inserted text ranges.
|
||||
// I.e., only this is an offset in new text.
|
||||
// In other words, between mStartOffset and |mRemovedEndOffset| of the
|
||||
// premodified text was already removed. And some text whose length is
|
||||
// |mAddedEndOffset - mStartOffset| is inserted to |mStartOffset|. I.e.,
|
||||
// this allows IME to mark dirty the modified text range with |mStartOffset|
|
||||
// and |mRemovedEndOffset| if IME stores all text of the focused editor and
|
||||
// to compute new text length with |mAddedEndOffset| and |mRemovedEndOffset|.
|
||||
// Additionally, IME can retrieve only the text between |mStartOffset| and
|
||||
// |mAddedEndOffset| for updating stored text.
|
||||
|
||||
// For comparing new and old |mStartOffset|/|mRemovedEndOffset| values, they
|
||||
// should be adjusted to be in same text. The |newData.mStartOffset| and
|
||||
// |newData.mRemovedEndOffset| should be computed as in old text because
|
||||
// |mStartOffset| and |mRemovedEndOffset| represent the modified text range
|
||||
// in the old text but even if some text before the values of the newData
|
||||
// has already been modified, the values don't include the changes.
|
||||
|
||||
// For comparing new and old |mAddedEndOffset| values, they should be
|
||||
// adjusted to be in same text. The |oldData.mAddedEndOffset| should be
|
||||
// computed as in the new text because |mAddedEndOffset| indicates the end
|
||||
// offset of inserted text in the new text but |oldData.mAddedEndOffset|
|
||||
// doesn't include any changes of the text before |newData.mAddedEndOffset|.
|
||||
|
||||
const TextChangeDataBase& newData = aOther;
|
||||
const TextChangeDataBase oldData = *this;
|
||||
|
||||
mCausedByComposition =
|
||||
newData.mCausedByComposition && oldData.mCausedByComposition;
|
||||
|
||||
if (newData.mStartOffset >= oldData.mAddedEndOffset) {
|
||||
// Case 1:
|
||||
// If new start is after old end offset of added text, it means that text
|
||||
// after the modified range is modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
// So, the old start offset is always the smaller offset.
|
||||
mStartOffset = oldData.mStartOffset;
|
||||
// The new end offset of removed text is moved by the old change and we
|
||||
// need to cancel the move of the old change for comparing the offsets in
|
||||
// same text because it doesn't make sensce to compare offsets in different
|
||||
// text.
|
||||
uint32_t newRemovedEndOffsetInOldText =
|
||||
newData.mRemovedEndOffset - oldData.Difference();
|
||||
mRemovedEndOffset =
|
||||
std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
|
||||
// The new end offset of added text is always the larger offset.
|
||||
mAddedEndOffset = newData.mAddedEndOffset;
|
||||
return;
|
||||
}
|
||||
|
||||
if (newData.mStartOffset >= oldData.mStartOffset) {
|
||||
// If new start is in the modified range, it means that new data changes
|
||||
// a part or all of the range.
|
||||
mStartOffset = oldData.mStartOffset;
|
||||
if (newData.mRemovedEndOffset >= oldData.mAddedEndOffset) {
|
||||
// Case 2:
|
||||
// If new end of removed text is greater than old end of added text, it
|
||||
// means that all or a part of modified range modified again and text
|
||||
// after the modified range is also modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
// So, the new removed end offset is moved by the old change and we need
|
||||
// to cancel the move of the old change for comparing the offsets in the
|
||||
// same text because it doesn't make sense to compare the offsets in
|
||||
// different text.
|
||||
uint32_t newRemovedEndOffsetInOldText =
|
||||
newData.mRemovedEndOffset - oldData.Difference();
|
||||
mRemovedEndOffset =
|
||||
std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
|
||||
// The old end of added text is replaced by new change. So, it should be
|
||||
// same as the new start. On the other hand, the new added end offset is
|
||||
// always same or larger. Therefore, the merged end offset of added
|
||||
// text should be the new end offset of added text.
|
||||
mAddedEndOffset = newData.mAddedEndOffset;
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 3:
|
||||
// If new end of removed text is less than old end of added text, it means
|
||||
// that only a part of the modified range is modified again. Like:
|
||||
// added range of old change: +------------+
|
||||
// removed range of new change: +-----+
|
||||
// So, the new end offset of removed text should be same as the old end
|
||||
// offset of removed text. Therefore, the merged end offset of removed
|
||||
// text should be the old text change's |mRemovedEndOffset|.
|
||||
mRemovedEndOffset = oldData.mRemovedEndOffset;
|
||||
// The old end of added text is moved by new change. So, we need to cancel
|
||||
// the move of the new change for comparing the offsets in same text.
|
||||
uint32_t oldAddedEndOffsetInNewText =
|
||||
oldData.mAddedEndOffset + newData.Difference();
|
||||
mAddedEndOffset =
|
||||
std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newData.mRemovedEndOffset >= oldData.mStartOffset) {
|
||||
// If new end of removed text is greater than old start (and new start is
|
||||
// less than old start), it means that a part of modified range is modified
|
||||
// again and some new text before the modified range is also modified.
|
||||
MOZ_ASSERT(newData.mStartOffset < oldData.mStartOffset,
|
||||
"new start offset should be less than old one here");
|
||||
mStartOffset = newData.mStartOffset;
|
||||
if (newData.mRemovedEndOffset >= oldData.mAddedEndOffset) {
|
||||
// Case 4:
|
||||
// If new end of removed text is greater than old end of added text, it
|
||||
// means that all modified text and text after the modified range is
|
||||
// modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +------------------+
|
||||
// So, the new end of removed text is moved by the old change. Therefore,
|
||||
// we need to cancel the move of the old change for comparing the offsets
|
||||
// in same text because it doesn't make sense to compare the offsets in
|
||||
// different text.
|
||||
uint32_t newRemovedEndOffsetInOldText =
|
||||
newData.mRemovedEndOffset - oldData.Difference();
|
||||
mRemovedEndOffset =
|
||||
std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
|
||||
// The old end of added text is replaced by new change. So, the old end
|
||||
// offset of added text is same as new text change's start offset. Then,
|
||||
// new change's end offset of added text is always same or larger than
|
||||
// it. Therefore, merged end offset of added text is always the new end
|
||||
// offset of added text.
|
||||
mAddedEndOffset = newData.mAddedEndOffset;
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 5:
|
||||
// If new end of removed text is less than old end of added text, it
|
||||
// means that only a part of the modified range is modified again. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
// So, the new end of removed text should be same as old end of removed
|
||||
// text for preventing end of removed text to be modified. Therefore,
|
||||
// merged end offset of removed text is always the old end offset of removed
|
||||
// text.
|
||||
mRemovedEndOffset = oldData.mRemovedEndOffset;
|
||||
// The old end of added text is moved by this change. So, we need to
|
||||
// cancel the move of the new change for comparing the offsets in same text
|
||||
// because it doesn't make sense to compare the offsets in different text.
|
||||
uint32_t oldAddedEndOffsetInNewText =
|
||||
oldData.mAddedEndOffset + newData.Difference();
|
||||
mAddedEndOffset =
|
||||
std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 6:
|
||||
// Otherwise, i.e., both new end of added text and new start are less than
|
||||
// old start, text before the modified range is modified. Like:
|
||||
// added range of old change: +----------+
|
||||
// removed range of new change: +----------+
|
||||
MOZ_ASSERT(newData.mStartOffset < oldData.mStartOffset,
|
||||
"new start offset should be less than old one here");
|
||||
mStartOffset = newData.mStartOffset;
|
||||
MOZ_ASSERT(newData.mRemovedEndOffset < oldData.mRemovedEndOffset,
|
||||
"new removed end offset should be less than old one here");
|
||||
mRemovedEndOffset = oldData.mRemovedEndOffset;
|
||||
// The end of added text should be adjusted with the new difference.
|
||||
uint32_t oldAddedEndOffsetInNewText =
|
||||
oldData.mAddedEndOffset + newData.Difference();
|
||||
mAddedEndOffset =
|
||||
std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
// Let's test the code of merging multiple text change data in debug build
|
||||
// and crash if one of them fails because this feature is very complex but
|
||||
// cannot be tested with mochitest.
|
||||
void
|
||||
IMENotification::TextChangeDataBase::Test()
|
||||
{
|
||||
static bool gTestTextChangeEvent = true;
|
||||
if (!gTestTextChangeEvent) {
|
||||
return;
|
||||
}
|
||||
gTestTextChangeEvent = false;
|
||||
|
||||
/****************************************************************************
|
||||
* Case 1
|
||||
****************************************************************************/
|
||||
|
||||
// Appending text
|
||||
MergeWith(TextChangeData(10, 10, 20, false));
|
||||
MergeWith(TextChangeData(20, 20, 35, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 1-1-1: mStartOffset should be the first offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 10, // 20 - (20 - 10)
|
||||
"Test 1-1-2: mRemovedEndOffset should be the first end of removed text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 35,
|
||||
"Test 1-1-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Removing text (longer line -> shorter line)
|
||||
MergeWith(TextChangeData(10, 20, 10, false));
|
||||
MergeWith(TextChangeData(10, 30, 10, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 1-2-1: mStartOffset should be the first offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 40, // 30 + (10 - 20)
|
||||
"Test 1-2-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"with already removed length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 10,
|
||||
"Test 1-2-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Removing text (shorter line -> longer line)
|
||||
MergeWith(TextChangeData(10, 20, 10, false));
|
||||
MergeWith(TextChangeData(10, 15, 10, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 1-3-1: mStartOffset should be the first offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 25, // 15 + (10 - 20)
|
||||
"Test 1-3-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"with already removed length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 10,
|
||||
"Test 1-3-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Appending text at different point (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(10, 10, 20, false));
|
||||
MergeWith(TextChangeData(55, 55, 60, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 1-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 45, // 55 - (10 - 20)
|
||||
"Test 1-4-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text without already added length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 60,
|
||||
"Test 1-4-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Removing text at different point (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(10, 20, 10, false));
|
||||
MergeWith(TextChangeData(55, 68, 55, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 1-5-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 78, // 68 - (10 - 20)
|
||||
"Test 1-5-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text with already removed length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 55,
|
||||
"Test 1-5-3: mAddedEndOffset should be the largest end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text and append text (becomes longer)
|
||||
MergeWith(TextChangeData(30, 35, 32, false));
|
||||
MergeWith(TextChangeData(32, 32, 40, false));
|
||||
MOZ_ASSERT(mStartOffset == 30,
|
||||
"Test 1-6-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 35, // 32 - (32 - 35)
|
||||
"Test 1-6-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 40,
|
||||
"Test 1-6-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text and append text (becomes shorter)
|
||||
MergeWith(TextChangeData(30, 35, 32, false));
|
||||
MergeWith(TextChangeData(32, 32, 33, false));
|
||||
MOZ_ASSERT(mStartOffset == 30,
|
||||
"Test 1-7-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 35, // 32 - (32 - 35)
|
||||
"Test 1-7-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 33,
|
||||
"Test 1-7-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Removing text and replacing text after first range (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(30, 35, 30, false));
|
||||
MergeWith(TextChangeData(32, 34, 48, false));
|
||||
MOZ_ASSERT(mStartOffset == 30,
|
||||
"Test 1-8-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 39, // 34 - (30 - 35)
|
||||
"Test 1-8-2: mRemovedEndOffset should be the the first end of removed text "
|
||||
"without already removed text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 48,
|
||||
"Test 1-8-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Removing text and replacing text after first range (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(30, 35, 30, false));
|
||||
MergeWith(TextChangeData(32, 38, 36, false));
|
||||
MOZ_ASSERT(mStartOffset == 30,
|
||||
"Test 1-9-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 43, // 38 - (30 - 35)
|
||||
"Test 1-9-2: mRemovedEndOffset should be the the first end of removed text "
|
||||
"without already removed text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 36,
|
||||
"Test 1-9-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 2
|
||||
****************************************************************************/
|
||||
|
||||
// Replacing text in around end of added text (becomes shorter) (not sure
|
||||
// if actually occurs)
|
||||
MergeWith(TextChangeData(50, 50, 55, false));
|
||||
MergeWith(TextChangeData(53, 60, 54, false));
|
||||
MOZ_ASSERT(mStartOffset == 50,
|
||||
"Test 2-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 55, // 60 - (55 - 50)
|
||||
"Test 2-1-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 54,
|
||||
"Test 2-1-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text around end of added text (becomes longer) (not sure
|
||||
// if actually occurs)
|
||||
MergeWith(TextChangeData(50, 50, 55, false));
|
||||
MergeWith(TextChangeData(54, 62, 68, false));
|
||||
MOZ_ASSERT(mStartOffset == 50,
|
||||
"Test 2-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 57, // 62 - (55 - 50)
|
||||
"Test 2-2-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 68,
|
||||
"Test 2-2-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text around end of replaced text (became shorter) (not sure if
|
||||
// actually occurs)
|
||||
MergeWith(TextChangeData(36, 48, 45, false));
|
||||
MergeWith(TextChangeData(43, 50, 49, false));
|
||||
MOZ_ASSERT(mStartOffset == 36,
|
||||
"Test 2-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 53, // 50 - (45 - 48)
|
||||
"Test 2-3-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already removed text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 49,
|
||||
"Test 2-3-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text around end of replaced text (became longer) (not sure if
|
||||
// actually occurs)
|
||||
MergeWith(TextChangeData(36, 52, 53, false));
|
||||
MergeWith(TextChangeData(43, 68, 61, false));
|
||||
MOZ_ASSERT(mStartOffset == 36,
|
||||
"Test 2-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 67, // 68 - (53 - 52)
|
||||
"Test 2-4-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 61,
|
||||
"Test 2-4-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 3
|
||||
****************************************************************************/
|
||||
|
||||
// Appending text in already added text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(10, 10, 20, false));
|
||||
MergeWith(TextChangeData(15, 15, 30, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 3-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 10,
|
||||
"Test 3-1-2: mRemovedEndOffset should be the the first end of removed text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 35, // 20 + (30 - 15)
|
||||
"Test 3-1-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text in added text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(50, 50, 55, false));
|
||||
MergeWith(TextChangeData(52, 53, 56, false));
|
||||
MOZ_ASSERT(mStartOffset == 50,
|
||||
"Test 3-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 50,
|
||||
"Test 3-2-2: mRemovedEndOffset should be the the first end of removed text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 58, // 55 + (56 - 53)
|
||||
"Test 3-2-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text in replaced text (became shorter) (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(36, 48, 45, false));
|
||||
MergeWith(TextChangeData(37, 38, 50, false));
|
||||
MOZ_ASSERT(mStartOffset == 36,
|
||||
"Test 3-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 48,
|
||||
"Test 3-3-2: mRemovedEndOffset should be the the first end of removed text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 57, // 45 + (50 - 38)
|
||||
"Test 3-3-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text in replaced text (became longer) (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(32, 48, 53, false));
|
||||
MergeWith(TextChangeData(43, 50, 52, false));
|
||||
MOZ_ASSERT(mStartOffset == 32,
|
||||
"Test 3-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 48,
|
||||
"Test 3-4-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 55, // 53 + (52 - 50)
|
||||
"Test 3-4-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text in replaced text (became shorter) (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(36, 48, 50, false));
|
||||
MergeWith(TextChangeData(37, 49, 47, false));
|
||||
MOZ_ASSERT(mStartOffset == 36,
|
||||
"Test 3-5-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 48,
|
||||
"Test 3-5-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 48, // 50 + (47 - 49)
|
||||
"Test 3-5-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text in replaced text (became longer) (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(32, 48, 53, false));
|
||||
MergeWith(TextChangeData(43, 50, 47, false));
|
||||
MOZ_ASSERT(mStartOffset == 32,
|
||||
"Test 3-6-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 48,
|
||||
"Test 3-6-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 50, // 53 + (47 - 50)
|
||||
"Test 3-6-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 4
|
||||
****************************************************************************/
|
||||
|
||||
// Replacing text all of already append text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(50, 50, 55, false));
|
||||
MergeWith(TextChangeData(44, 66, 68, false));
|
||||
MOZ_ASSERT(mStartOffset == 44,
|
||||
"Test 4-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 61, // 66 - (55 - 50)
|
||||
"Test 4-1-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already added text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 68,
|
||||
"Test 4-1-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text around a point in which text was removed (not sure if
|
||||
// actually occurs)
|
||||
MergeWith(TextChangeData(50, 62, 50, false));
|
||||
MergeWith(TextChangeData(44, 66, 68, false));
|
||||
MOZ_ASSERT(mStartOffset == 44,
|
||||
"Test 4-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 78, // 66 - (50 - 62)
|
||||
"Test 4-2-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already removed text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 68,
|
||||
"Test 4-2-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text all replaced text (became shorter) (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(50, 62, 60, false));
|
||||
MergeWith(TextChangeData(49, 128, 130, false));
|
||||
MOZ_ASSERT(mStartOffset == 49,
|
||||
"Test 4-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 130, // 128 - (60 - 62)
|
||||
"Test 4-3-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"without already removed text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 130,
|
||||
"Test 4-3-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
// Replacing text all replaced text (became longer) (not sure if actually
|
||||
// occurs)
|
||||
MergeWith(TextChangeData(50, 61, 73, false));
|
||||
MergeWith(TextChangeData(44, 100, 50, false));
|
||||
MOZ_ASSERT(mStartOffset == 44,
|
||||
"Test 4-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 88, // 100 - (73 - 61)
|
||||
"Test 4-4-2: mRemovedEndOffset should be the the last end of removed text "
|
||||
"with already added text length");
|
||||
MOZ_ASSERT(mAddedEndOffset == 50,
|
||||
"Test 4-4-3: mAddedEndOffset should be the last end of added text");
|
||||
Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 5
|
||||
****************************************************************************/
|
||||
|
||||
// Replacing text around start of added text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(50, 50, 55, false));
|
||||
MergeWith(TextChangeData(48, 52, 49, false));
|
||||
MOZ_ASSERT(mStartOffset == 48,
|
||||
"Test 5-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 50,
|
||||
"Test 5-1-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 52, // 55 + (52 - 49)
|
||||
"Test 5-1-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became shorter) (not sure if
|
||||
// actually occurs)
|
||||
MergeWith(TextChangeData(50, 60, 58, false));
|
||||
MergeWith(TextChangeData(43, 50, 48, false));
|
||||
MOZ_ASSERT(mStartOffset == 43,
|
||||
"Test 5-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 60,
|
||||
"Test 5-2-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 56, // 58 + (48 - 50)
|
||||
"Test 5-2-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became longer) (not sure if
|
||||
// actually occurs)
|
||||
MergeWith(TextChangeData(50, 60, 68, false));
|
||||
MergeWith(TextChangeData(43, 55, 53, false));
|
||||
MOZ_ASSERT(mStartOffset == 43,
|
||||
"Test 5-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 60,
|
||||
"Test 5-3-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 66, // 68 + (53 - 55)
|
||||
"Test 5-3-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became shorter) (not sure if
|
||||
// actually occurs)
|
||||
MergeWith(TextChangeData(50, 60, 58, false));
|
||||
MergeWith(TextChangeData(43, 50, 128, false));
|
||||
MOZ_ASSERT(mStartOffset == 43,
|
||||
"Test 5-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 60,
|
||||
"Test 5-4-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 136, // 58 + (128 - 50)
|
||||
"Test 5-4-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text around start of replaced text (became longer) (not sure if
|
||||
// actually occurs)
|
||||
MergeWith(TextChangeData(50, 60, 68, false));
|
||||
MergeWith(TextChangeData(43, 55, 65, false));
|
||||
MOZ_ASSERT(mStartOffset == 43,
|
||||
"Test 5-5-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 60,
|
||||
"Test 5-5-2: mRemovedEndOffset should be the the first end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 78, // 68 + (65 - 55)
|
||||
"Test 5-5-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
/****************************************************************************
|
||||
* Case 6
|
||||
****************************************************************************/
|
||||
|
||||
// Appending text before already added text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(30, 30, 45, false));
|
||||
MergeWith(TextChangeData(10, 10, 20, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 6-1-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 30,
|
||||
"Test 6-1-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 55, // 45 + (20 - 10)
|
||||
"Test 6-1-3: mAddedEndOffset should be the first end of added text with "
|
||||
"added text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Removing text before already removed text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(30, 35, 30, false));
|
||||
MergeWith(TextChangeData(10, 25, 10, false));
|
||||
MOZ_ASSERT(mStartOffset == 10,
|
||||
"Test 6-2-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 35,
|
||||
"Test 6-2-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 15, // 30 - (25 - 10)
|
||||
"Test 6-2-3: mAddedEndOffset should be the first end of added text with "
|
||||
"removed text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text before already replaced text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(50, 65, 70, false));
|
||||
MergeWith(TextChangeData(13, 24, 15, false));
|
||||
MOZ_ASSERT(mStartOffset == 13,
|
||||
"Test 6-3-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 65,
|
||||
"Test 6-3-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 61, // 70 + (15 - 24)
|
||||
"Test 6-3-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
Clear();
|
||||
|
||||
// Replacing text before already replaced text (not sure if actually occurs)
|
||||
MergeWith(TextChangeData(50, 65, 70, false));
|
||||
MergeWith(TextChangeData(13, 24, 36, false));
|
||||
MOZ_ASSERT(mStartOffset == 13,
|
||||
"Test 6-4-1: mStartOffset should be the smallest offset");
|
||||
MOZ_ASSERT(mRemovedEndOffset == 65,
|
||||
"Test 6-4-2: mRemovedEndOffset should be the the largest end of removed "
|
||||
"text");
|
||||
MOZ_ASSERT(mAddedEndOffset == 82, // 70 + (36 - 24)
|
||||
"Test 6-4-3: mAddedEndOffset should be the first end of added text without "
|
||||
"removed text length by the new change");
|
||||
Clear();
|
||||
}
|
||||
|
||||
#endif // #ifdef DEBUG
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
#ifdef DEBUG
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -664,16 +664,7 @@ struct IMENotification
|
||||
break;
|
||||
case NOTIFY_IME_OF_TEXT_CHANGE:
|
||||
MOZ_ASSERT(aNotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE);
|
||||
// TODO: Needs to merge the ranges rather than overwriting.
|
||||
mTextChangeData.mStartOffset =
|
||||
aNotification.mTextChangeData.mStartOffset;
|
||||
mTextChangeData.mRemovedEndOffset =
|
||||
aNotification.mTextChangeData.mRemovedEndOffset;
|
||||
mTextChangeData.mAddedEndOffset =
|
||||
aNotification.mTextChangeData.mAddedEndOffset;
|
||||
mTextChangeData.mCausedByComposition =
|
||||
mTextChangeData.mCausedByComposition &&
|
||||
aNotification.mTextChangeData.mCausedByComposition;
|
||||
mTextChangeData += aNotification.mTextChangeData;
|
||||
break;
|
||||
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
|
||||
MOZ_ASSERT(aNotification.mMessage == NOTIFY_IME_OF_COMPOSITION_UPDATE);
|
||||
@ -767,6 +758,17 @@ struct IMENotification
|
||||
mStartOffset = UINT32_MAX;
|
||||
mRemovedEndOffset = mAddedEndOffset = 0;
|
||||
}
|
||||
|
||||
void MergeWith(const TextChangeDataBase& aOther);
|
||||
TextChangeDataBase& operator+=(const TextChangeDataBase& aOther)
|
||||
{
|
||||
MergeWith(aOther);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void Test();
|
||||
#endif // #ifdef DEBUG
|
||||
};
|
||||
|
||||
// TextChangeDataBase cannot have constructors because they are used in union.
|
||||
|
Loading…
Reference in New Issue
Block a user