diff --git a/widget/windows/nsIMM32Handler.cpp b/widget/windows/nsIMM32Handler.cpp index 11bb68866a53..275af68b4260 100644 --- a/widget/windows/nsIMM32Handler.cpp +++ b/widget/windows/nsIMM32Handler.cpp @@ -1610,15 +1610,10 @@ nsIMM32Handler::DispatchTextEvent(nsWindow* aWindow, aWindow->InitEvent(event, &point); - nsAutoTArray textRanges; - if (aCheckAttr) { - SetTextRangeList(textRanges); + event.mRanges = CreateTextRangeArray(); } - event.rangeCount = textRanges.Length(); - event.rangeArray = textRanges.Elements(); - event.theText = mCompositionString.get(); aWindow->DispatchWindowEvent(&event); @@ -1628,15 +1623,17 @@ nsIMM32Handler::DispatchTextEvent(nsWindow* aWindow, // it will call SetIMERelatedWindowsPos. } -void -nsIMM32Handler::SetTextRangeList(nsTArray &aTextRangeList) +already_AddRefed +nsIMM32Handler::CreateTextRangeArray() { // Sogou (Simplified Chinese IME) returns contradictory values: The cursor // position is actual cursor position. However, other values (composition // string and attributes) are empty. So, if you want to remove following // assertion, be careful. NS_ASSERTION(ShouldDrawCompositionStringOurselves(), - "SetTextRangeList is called when we don't need to fire text event"); + "CreateTextRangeArray is called when we don't need to fire text event"); + + nsRefPtr textRangeArray = new TextRangeArray(); TextRange range; if (mClauseArray.Length() == 0) { @@ -1645,10 +1642,10 @@ nsIMM32Handler::SetTextRangeList(nsTArray &aTextRangeList) range.mStartOffset = 0; range.mEndOffset = mCompositionString.Length(); range.mRangeType = NS_TEXTRANGE_RAWINPUT; - aTextRangeList.AppendElement(range); + textRangeArray->AppendElement(range); PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: SetTextRangeList, mClauseLength=0\n")); + ("IMM32: CreateTextRangeArray, mClauseLength=0\n")); } else { // iterate over the attributes uint32_t lastOffset = 0; @@ -1656,7 +1653,8 @@ nsIMM32Handler::SetTextRangeList(nsTArray &aTextRangeList) uint32_t current = mClauseArray[i + 1]; if (current > mCompositionString.Length()) { PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: SetTextRangeList, mClauseArray[%ld]=%lu. This is larger than mCompositionString.Length()=%lu\n", + ("IMM32: CreateTextRangeArray, mClauseArray[%ld]=%lu. " + "This is larger than mCompositionString.Length()=%lu\n", i + 1, current, mCompositionString.Length())); current = int32_t(mCompositionString.Length()); } @@ -1664,12 +1662,12 @@ nsIMM32Handler::SetTextRangeList(nsTArray &aTextRangeList) range.mRangeType = PlatformToNSAttr(mAttributeArray[lastOffset]); range.mStartOffset = lastOffset; range.mEndOffset = current; - aTextRangeList.AppendElement(range); + textRangeArray->AppendElement(range); lastOffset = current; PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: SetTextRangeList, index=%ld, rangeType=%s, range=[%lu-%lu]\n", + ("IMM32: CreateTextRangeArray, index=%ld, rangeType=%s, range=[%lu-%lu]\n", i, GetRangeTypeName(range.mRangeType), range.mStartOffset, range.mEndOffset)); } @@ -1677,25 +1675,28 @@ nsIMM32Handler::SetTextRangeList(nsTArray &aTextRangeList) if (mCursorPosition == NO_IME_CARET) { PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: GetTextRangeList, no caret\n")); - return; + ("IMM32: CreateTextRangeArray, no caret\n")); + return textRangeArray.forget(); } int32_t cursor = mCursorPosition; if (uint32_t(cursor) > mCompositionString.Length()) { PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: SetTextRangeList, mCursorPosition=%ld. This is larger than mCompositionString.Length()=%lu\n", + ("IMM32: CreateTextRangeArray, mCursorPosition=%ld. " + "This is larger than mCompositionString.Length()=%lu\n", mCursorPosition, mCompositionString.Length())); cursor = mCompositionString.Length(); } range.mStartOffset = range.mEndOffset = cursor; range.mRangeType = NS_TEXTRANGE_CARETPOSITION; - aTextRangeList.AppendElement(range); + textRangeArray->AppendElement(range); PR_LOG(gIMM32Log, PR_LOG_ALWAYS, - ("IMM32: SetTextRangeList, caret position=%ld\n", + ("IMM32: CreateTextRangeArray, caret position=%ld\n", range.mStartOffset)); + + return textRangeArray.forget(); } void diff --git a/widget/windows/nsIMM32Handler.h b/widget/windows/nsIMM32Handler.h index a0688c79e1d5..107c2b1bfa6b 100644 --- a/widget/windows/nsIMM32Handler.h +++ b/widget/windows/nsIMM32Handler.h @@ -8,6 +8,7 @@ #include "nscore.h" #include +#include "nsCOMPtr.h" #include "nsString.h" #include "nsTArray.h" #include "mozilla/EventForwards.h" @@ -285,7 +286,7 @@ protected: bool GetTargetClauseRange(uint32_t *aOffset, uint32_t *aLength = nullptr); void DispatchTextEvent(nsWindow* aWindow, const nsIMEContext &aIMEContext, bool aCheckAttr = true); - void SetTextRangeList(nsTArray& aTextRangeList); + already_AddRefed CreateTextRangeArray(); nsresult EnsureClauseArray(int32_t aCount); nsresult EnsureAttributeArray(int32_t aCount); diff --git a/widget/windows/nsTextStore.cpp b/widget/windows/nsTextStore.cpp index be70dd8013da..afc0d0b039d9 100644 --- a/widget/windows/nsTextStore.cpp +++ b/widget/windows/nsTextStore.cpp @@ -1049,41 +1049,38 @@ nsTextStore::FlushPendingActions() PR_LOG(sTextStoreLog, PR_LOG_DEBUG, ("TSF: 0x%p nsTextStore::FlushPendingActions() " "flushing COMPOSITION_UPDATE={ mData=\"%s\", " - "mRanges.Length()=%d }", - this, NS_ConvertUTF16toUTF8(action.mData).get(), - action.mRanges.Length())); + "mRanges=0x%p, mRanges->Length()=%d }", + this, NS_ConvertUTF16toUTF8(action.mData).get(), action.mRanges, + action.mRanges ? action.mRanges->Length() : 0)); - if (action.mRanges.IsEmpty()) { - TextRange wholeRange; - wholeRange.mStartOffset = 0; - wholeRange.mEndOffset = action.mData.Length(); - wholeRange.mRangeType = NS_TEXTRANGE_RAWINPUT; - action.mRanges.AppendElement(wholeRange); - } else { - // Adjust offsets in the ranges for XP linefeed character (only \n). - // XXX Following code is the safest approach. However, it wastes - // a little performance. For ensuring the clauses do not - // overlap each other, we should redesign TextRange later. - for (uint32_t i = 0; i < action.mRanges.Length(); ++i) { - TextRange& range = action.mRanges[i]; - TextRange nativeRange = range; - if (nativeRange.mStartOffset > 0) { - nsAutoString preText( - Substring(action.mData, 0, nativeRange.mStartOffset)); - preText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"), - NS_LITERAL_STRING("\n")); - range.mStartOffset = preText.Length(); - } - if (nativeRange.Length() == 0) { - range.mEndOffset = range.mStartOffset; - } else { - nsAutoString clause( - Substring(action.mData, - nativeRange.mStartOffset, nativeRange.Length())); - clause.ReplaceSubstring(NS_LITERAL_STRING("\r\n"), - NS_LITERAL_STRING("\n")); - range.mEndOffset = range.mStartOffset + clause.Length(); - } + if (!action.mRanges) { + NS_WARNING("How does this case occur?"); + action.mRanges = new TextRangeArray(); + } + + // Adjust offsets in the ranges for XP linefeed character (only \n). + // XXX Following code is the safest approach. However, it wastes + // a little performance. For ensuring the clauses do not + // overlap each other, we should redesign TextRange later. + for (uint32_t i = 0; i < action.mRanges->Length(); ++i) { + TextRange& range = action.mRanges->ElementAt(i); + TextRange nativeRange = range; + if (nativeRange.mStartOffset > 0) { + nsAutoString preText( + Substring(action.mData, 0, nativeRange.mStartOffset)); + preText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"), + NS_LITERAL_STRING("\n")); + range.mStartOffset = preText.Length(); + } + if (nativeRange.Length() == 0) { + range.mEndOffset = range.mStartOffset; + } else { + nsAutoString clause( + Substring(action.mData, + nativeRange.mStartOffset, nativeRange.Length())); + clause.ReplaceSubstring(NS_LITERAL_STRING("\r\n"), + NS_LITERAL_STRING("\n")); + range.mEndOffset = range.mStartOffset + clause.Length(); } } @@ -1113,15 +1110,14 @@ nsTextStore::FlushPendingActions() WidgetTextEvent textEvent(true, NS_TEXT_TEXT, mWidget); mWidget->InitEvent(textEvent); textEvent.theText = mComposition.mLastData; - if (action.mRanges.IsEmpty()) { + if (action.mRanges->IsEmpty()) { TextRange wholeRange; wholeRange.mStartOffset = 0; wholeRange.mEndOffset = textEvent.theText.Length(); wholeRange.mRangeType = NS_TEXTRANGE_RAWINPUT; - action.mRanges.AppendElement(wholeRange); + action.mRanges->AppendElement(wholeRange); } - textEvent.rangeArray = action.mRanges.Elements(); - textEvent.rangeCount = action.mRanges.Length(); + textEvent.mRanges = action.mRanges; mWidget->DispatchWindowEvent(&textEvent); // Be aware, the mWidget might already have been destroyed. break; @@ -1648,11 +1644,10 @@ nsTextStore::RecordCompositionUpdateAction() PendingAction* action = GetPendingCompositionUpdate(); action->mData = mComposition.mString; - nsTArray& textRanges = action->mRanges; - // The ranges might already have been initialized already, however, if this - // is called again, that means we need to overwrite the ranges with current + // The ranges might already have been initialized, however, if this is + // called again, that means we need to overwrite the ranges with current // information. - textRanges.Clear(); + action->mRanges->Clear(); TextRange newRange; // No matter if we have display attribute info or not, @@ -1660,7 +1655,7 @@ nsTextStore::RecordCompositionUpdateAction() newRange.mStartOffset = 0; newRange.mEndOffset = action->mData.Length(); newRange.mRangeType = NS_TEXTRANGE_RAWINPUT; - textRanges.AppendElement(newRange); + action->mRanges->AppendElement(newRange); nsRefPtr range; while (S_OK == enumRanges->Next(1, getter_AddRefs(range), nullptr) && range) { @@ -1700,14 +1695,14 @@ nsTextStore::RecordCompositionUpdateAction() } } - TextRange& lastRange = textRanges[textRanges.Length() - 1]; + TextRange& lastRange = action->mRanges->LastElement(); if (lastRange.mStartOffset == newRange.mStartOffset) { // Replace range if last range is the same as this one // So that ranges don't overlap and confuse the editor lastRange = newRange; } else { lastRange.mEndOffset = newRange.mStartOffset; - textRanges.AppendElement(newRange); + action->mRanges->AppendElement(newRange); } } @@ -1719,8 +1714,8 @@ nsTextStore::RecordCompositionUpdateAction() // string, however, Gecko doesn't support the wide caret drawing now (Gecko // doesn't support XOR drawing), unfortunately. For now, we should change // the range style to undefined. - if (!currentSel.IsCollapsed() && textRanges.Length() == 1) { - TextRange& range = textRanges[0]; + if (!currentSel.IsCollapsed() && action->mRanges->Length() == 1) { + TextRange& range = action->mRanges->ElementAt(0); LONG start = currentSel.MinOffset(); LONG end = currentSel.MaxOffset(); if ((LONG)range.mStartOffset == start - mComposition.mStart && @@ -1738,7 +1733,7 @@ nsTextStore::RecordCompositionUpdateAction() TextRange caretRange; caretRange.mStartOffset = caretRange.mEndOffset = uint32_t(caretPosition); caretRange.mRangeType = NS_TEXTRANGE_CARETPOSITION; - textRanges.AppendElement(caretRange); + action->mRanges->AppendElement(caretRange); PR_LOG(sTextStoreLog, PR_LOG_ALWAYS, ("TSF: 0x%p nsTextStore::RecordCompositionUpdateAction() " diff --git a/widget/windows/nsTextStore.h b/widget/windows/nsTextStore.h index a50b1f6e0ca6..a71f92b6178e 100644 --- a/widget/windows/nsTextStore.h +++ b/widget/windows/nsTextStore.h @@ -501,7 +501,7 @@ protected: // For compositionupdate and compositionend nsString mData; // For compositionupdate - nsTArray mRanges; + nsRefPtr mRanges; // For selectionset bool mSelectionReversed; }; @@ -521,9 +521,7 @@ protected: } PendingAction* newAction = mPendingActions.AppendElement(); newAction->mType = PendingAction::COMPOSITION_UPDATE; - // We think that 4 ranges (3 clauses and caret position) are enough for - // most cases. - newAction->mRanges.SetCapacity(4); + newAction->mRanges = new mozilla::TextRangeArray(); return newAction; }