Skip to content
Snippets Groups Projects
Select Git revision
  • 688d2c9fa17bbd61d5855eac9bf92e57a18f2f05
  • tor-browser-115.2.0esr-13.0-1 default
  • bug_44027_PBM_lockscreen
  • bug_43976_remove_default_browser_prompt
  • bug_44021_44047_fix_first_launch_theme
  • bug_44098_disable_bookmark_sync
  • bug_44081_swipe_notification_restart_fix
  • bug_43699_properly_clear_dummy-about-pages
  • bug_44080_Further-remove-Analytics-data-collection-and-usage
  • bug_44036_Better_fix_for_Crash-on-opening-Search-Settings-on-android
  • bug_43179_make_persistent_private_tabs_notification_distinct
  • bug_43576_add_FrequentRegions_UI
  • bug_43576_add_FrequentRegions
  • bug_44042_Debug-crash-when-opening-settings-too-quickly-after-launching-app
  • bug_44042_clean_up_commented_code
  • meek-name-tb44069
  • bug_43645_-Swiping-away-doesn't-always-disconnect-from-tor-
  • bug_44036_Crash-on-opening-Search-Settings-on-android
  • bug_44029_search-url-bar-doesn't-work-on-android-after-ESR-140
  • bug_43977_crash_on_debug_launch
  • tor-browser-140.0a1-15.0-2
  • bug_43786
  • tor-browser-115.2.0esr-13.0-1-build2
  • base-browser-115.2.0esr-13.0-1-build1
  • tor-browser-115.2.0esr-13.0-1-build1
  • FIREFOX_102_15_0esr_BUILD1
  • FIREFOX_115_2_0esr_BUILD1
  • base-browser-115.1.0esr-13.0-1-build1
  • tor-browser-115.1.0esr-13.0-1-build4
  • tor-browser-115.1.0esr-13.0-1-build3
  • base-browser-115.1.0esr-13.0-1-build2
  • tor-browser-115.1.0esr-13.0-1-build2
  • base-browser-102.14.0esr-12.5-1-build2
  • tor-browser-102.14.0esr-12.5-1-build2
  • tor-browser-115.1.0esr-13.0-1-build1
  • tor-browser-102.14.0esr-12.5-1-build1
  • base-browser-102.14.0esr-12.5-1-build1
  • FIREFOX_102_14_0esr_BUILD1
  • FIREFOX_115_1_0esr_BUILD1
  • base-browser-115.0.2esr-13.0-1-build2
  • tor-browser-115.0.2esr-13.0-1-build3
  • tor-browser-115.0.2esr-13.0-1-build2
42 results

IMEData.cpp

Blame
  • user avatar
    Masayuki Nakano authored
    For managing the state of text content cache independent from selection, it
    should be wrapped with `Maybe`.
    
    Differential Revision: https://phabricator.services.mozilla.com/D137429
    55bc376f
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    IMEData.cpp 13.37 KiB
    /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
    /* This Source Code Form is subject to the terms of the Mozilla Public
     * License, v. 2.0. If a copy of the MPL was not distributed with this
     * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    #include "IMEData.h"
    
    #include <sstream>
    
    #include "ContentData.h"
    #include "gfxFontUtils.h"
    #include "TextEvents.h"
    
    #include "mozilla/Maybe.h"
    #include "mozilla/ToString.h"
    #include "mozilla/WritingModes.h"
    
    #include "nsPrintfCString.h"
    #include "nsString.h"
    
    namespace mozilla {
    
    template PrintStringDetail::PrintStringDetail(
        const Maybe<nsString>& aMaybeString, uint32_t aMaxLength);
    
    template <typename StringType>
    PrintStringDetail::PrintStringDetail(const Maybe<StringType>& aMaybeString,
                                         uint32_t aMaxLength /* = UINT32_MAX */)
        : PrintStringDetail(aMaybeString.refOr(EmptyString()), aMaxLength) {
      if (aMaybeString.isNothing()) {
        AssignASCII(ToString(aMaybeString).c_str());
      }
    }
    
    PrintStringDetail::PrintStringDetail(const nsAString& aString,
                                         uint32_t aMaxLength /* = UINT32_MAX */) {
      Assign("\"");
      const uint32_t kFirstHalf =
          aString.Length() <= aMaxLength ? UINT32_MAX : (aMaxLength + 1) / 2;
      const uint32_t kSecondHalf =
          aString.Length() <= aMaxLength ? 0 : aMaxLength / 2;
      for (uint32_t i = 0; i < aString.Length(); i++) {
        if (i > 0) {
          AppendLiteral(" ");
        }
        char32_t ch = aString.CharAt(i);
        if (NS_IS_HIGH_SURROGATE(ch) && i + 1 < aString.Length() &&
            NS_IS_LOW_SURROGATE(aString.CharAt(i + 1))) {
          ch = SURROGATE_TO_UCS4(ch, aString.CharAt(i + 1));
        }
        Append(PrintCharData(ch));
        if (i + 1 == kFirstHalf) {
          AppendLiteral(" ...");
          i = aString.Length() - kSecondHalf - 1;
          if (NS_IS_LOW_SURROGATE(aString.CharAt(i)) &&
              NS_IS_HIGH_SURROGATE(aString.CharAt(i - 1))) {
            if (i - 1 <= kFirstHalf) {
              i++;
            } else {
              i--;
            }
          }
        } else if (!IS_IN_BMP(ch)) {
          i++;
        }
      }
      AppendLiteral("\" (Length()=");
      AppendInt(static_cast<uint32_t>(aString.Length()));
      AppendLiteral(")");
    }
    
    // static
    nsCString PrintStringDetail::PrintCharData(char32_t aChar) {
      switch (aChar) {
        case 0x0000:
          return "NULL (0x0000)"_ns;
        case 0x0008:
          return "BACKSPACE (0x0008)"_ns;
        case 0x0009:
          return "CHARACTER TABULATION (0x0009)"_ns;
        case 0x000A:
          return "LINE FEED (0x000A)"_ns;
        case 0x000B:
          return "LINE TABULATION (0x000B)"_ns;
        case 0x000C:
          return "FORM FEED (0x000C)"_ns;
        case 0x000D:
          return "CARRIAGE RETURN (0x000D)"_ns;
        case 0x0018:
          return "CANCEL (0x0018)"_ns;
        case 0x001B:
          return "ESCAPE (0x001B)"_ns;
        case 0x0020:
          return "SPACE (0x0020)"_ns;
        case 0x007F:
          return "DELETE (0x007F)"_ns;
        case 0x00A0:
          return "NO-BREAK SPACE (0x00A0)"_ns;
        case 0x00AD:
          return "SOFT HYPHEN (0x00AD)"_ns;
        case 0x2000:
          return "EN QUAD (0x2000)"_ns;
        case 0x2001:
          return "EM QUAD (0x2001)"_ns;
        case 0x2002:
          return "EN SPACE (0x2002)"_ns;
        case 0x2003:
          return "EM SPACE (0x2003)"_ns;
        case 0x2004:
          return "THREE-PER-EM SPACE (0x2004)"_ns;
        case 0x2005:
          return "FOUR-PER-EM SPACE (0x2005)"_ns;
        case 0x2006:
          return "SIX-PER-EM SPACE (0x2006)"_ns;
        case 0x2007:
          return "FIGURE SPACE (0x2007)"_ns;
        case 0x2008:
          return "PUNCTUATION SPACE (0x2008)"_ns;
        case 0x2009:
          return "THIN SPACE (0x2009)"_ns;
        case 0x200A:
          return "HAIR SPACE (0x200A)"_ns;
        case 0x200B:
          return "ZERO WIDTH SPACE (0x200B)"_ns;
        case 0x200C:
          return "ZERO WIDTH NON-JOINER (0x200C)"_ns;
        case 0x200D:
          return "ZERO WIDTH JOINER (0x200D)"_ns;
        case 0x200E:
          return "LEFT-TO-RIGHT MARK (0x200E)"_ns;
        case 0x200F:
          return "RIGHT-TO-LEFT MARK (0x200F)"_ns;
        case 0x2029:
          return "PARAGRAPH SEPARATOR (0x2029)"_ns;
        case 0x202A:
          return "LEFT-TO-RIGHT EMBEDDING (0x202A)"_ns;
        case 0x202B:
          return "RIGHT-TO-LEFT EMBEDDING (0x202B)"_ns;
        case 0x202D:
          return "LEFT-TO-RIGHT OVERRIDE (0x202D)"_ns;
        case 0x202E:
          return "RIGHT-TO-LEFT OVERRIDE (0x202E)"_ns;
        case 0x202F:
          return "NARROW NO-BREAK SPACE (0x202F)"_ns;
        case 0x205F:
          return "MEDIUM MATHEMATICAL SPACE (0x205F)"_ns;
        case 0x2060:
          return "WORD JOINER (0x2060)"_ns;
        case 0x2066:
          return "LEFT-TO-RIGHT ISOLATE (0x2066)"_ns;
        case 0x2067:
          return "RIGHT-TO-LEFT ISOLATE (0x2067)"_ns;
        case 0x3000:
          return "IDEOGRAPHIC SPACE (0x3000)"_ns;
        case 0xFEFF:
          return "ZERO WIDTH NO-BREAK SPACE (0xFEFF)"_ns;
        default: {
          if (aChar < ' ' || (aChar >= 0x80 && aChar < 0xA0)) {
            return nsPrintfCString("Control (0x%04X)", aChar);
          }
          if (NS_IS_HIGH_SURROGATE(aChar)) {
            return nsPrintfCString("High Surrogate (0x%04X)", aChar);
          }
          if (NS_IS_LOW_SURROGATE(aChar)) {
            return nsPrintfCString("Low Surrogate (0x%04X)", aChar);
          }
          if (gfxFontUtils::IsVarSelector(aChar)) {
            return IS_IN_BMP(aChar)
                       ? nsPrintfCString("Variant Selector (0x%04X)", aChar)
                       : nsPrintfCString("Variant Selector (0x%08X)", aChar);
          }
          nsAutoString utf16Str;
          AppendUCS4ToUTF16(aChar, utf16Str);
          return IS_IN_BMP(aChar)
                     ? nsPrintfCString("'%s' (0x%04X)",
                                       NS_ConvertUTF16toUTF8(utf16Str).get(), aChar)
                     : nsPrintfCString("'%s' (0x%08X)",
                                       NS_ConvertUTF16toUTF8(utf16Str).get(),
                                       aChar);
        }
      }
    }
    
    namespace widget {
    
    std::ostream& operator<<(std::ostream& aStream, const IMEEnabled& aEnabled) {
      switch (aEnabled) {
        case IMEEnabled::Disabled:
          return aStream << "DISABLED";
        case IMEEnabled::Enabled:
          return aStream << "ENABLED";
        case IMEEnabled::Password:
          return aStream << "PASSWORD";
        case IMEEnabled::Unknown:
          return aStream << "illegal value";
      }
      MOZ_ASSERT_UNREACHABLE("Add a case to handle your new IMEEnabled value");
      return aStream;
    }
    
    std::ostream& operator<<(std::ostream& aStream, const IMEState::Open& aOpen) {
      switch (aOpen) {
        case IMEState::DONT_CHANGE_OPEN_STATE:
          aStream << "DONT_CHANGE_OPEN_STATE";
          break;
        case IMEState::OPEN:
          aStream << "OPEN";
          break;
        case IMEState::CLOSED:
          aStream << "CLOSED";
          break;
        default:
          aStream << "illegal value";
          break;
      }
      return aStream;
    }
    
    std::ostream& operator<<(std::ostream& aStream, const IMEState& aState) {
      aStream << "{ mEnabled=" << aState.mEnabled << ", mOpen=" << aState.mOpen
              << " }";
      return aStream;
    }
    
    std::ostream& operator<<(std::ostream& aStream,
                             const InputContext::Origin& aOrigin) {
      switch (aOrigin) {
        case InputContext::ORIGIN_MAIN:
          aStream << "ORIGIN_MAIN";
          break;
        case InputContext::ORIGIN_CONTENT:
          aStream << "ORIGIN_CONTENT";
          break;
        default:
          aStream << "illegal value";
          break;
      }
      return aStream;
    }
    
    std::ostream& operator<<(std::ostream& aStream, const InputContext& aContext) {
      aStream << "{ mIMEState=" << aContext.mIMEState
              << ", mOrigin=" << aContext.mOrigin << ", mHTMLInputType=\""
              << aContext.mHTMLInputType << "\", mHTMLInputInputmode=\""
              << aContext.mHTMLInputInputmode << "\", mActionHint=\""
              << aContext.mActionHint << "\", mAutocapitalize=\""
              << aContext.mAutocapitalize << "\", mMayBeIMEUnaware="
              << (aContext.mMayBeIMEUnaware ? "true" : "false")
              << ", mIsPrivateBrowsing="
              << (aContext.mInPrivateBrowsing ? "true" : "false") << " }";
      return aStream;
    }
    
    std::ostream& operator<<(std::ostream& aStream,
                             const InputContextAction::Cause& aCause) {
      switch (aCause) {
        case InputContextAction::CAUSE_UNKNOWN:
          aStream << "CAUSE_UNKNOWN";
          break;
        case InputContextAction::CAUSE_UNKNOWN_CHROME:
          aStream << "CAUSE_UNKNOWN_CHROME";
          break;
        case InputContextAction::CAUSE_KEY:
          aStream << "CAUSE_KEY";
          break;
        case InputContextAction::CAUSE_MOUSE:
          aStream << "CAUSE_MOUSE";
          break;
        case InputContextAction::CAUSE_TOUCH:
          aStream << "CAUSE_TOUCH";
          break;
        case InputContextAction::CAUSE_LONGPRESS:
          aStream << "CAUSE_LONGPRESS";
          break;
        case InputContextAction::CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT:
          aStream << "CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT";
          break;
        case InputContextAction::CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT:
          aStream << "CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT";
          break;
        default:
          aStream << "illegal value";
          break;
      }
      return aStream;
    }
    
    std::ostream& operator<<(std::ostream& aStream,
                             const InputContextAction::FocusChange& aFocusChange) {
      switch (aFocusChange) {
        case InputContextAction::FOCUS_NOT_CHANGED:
          aStream << "FOCUS_NOT_CHANGED";
          break;
        case InputContextAction::GOT_FOCUS:
          aStream << "GOT_FOCUS";
          break;
        case InputContextAction::LOST_FOCUS:
          aStream << "LOST_FOCUS";
          break;
        case InputContextAction::MENU_GOT_PSEUDO_FOCUS:
          aStream << "MENU_GOT_PSEUDO_FOCUS";
          break;
        case InputContextAction::MENU_LOST_PSEUDO_FOCUS:
          aStream << "MENU_LOST_PSEUDO_FOCUS";
          break;
        case InputContextAction::WIDGET_CREATED:
          aStream << "WIDGET_CREATED";
          break;
        default:
          aStream << "illegal value";
          break;
      }
      return aStream;
    }
    
    std::ostream& operator<<(
        std::ostream& aStream,
        const IMENotification::SelectionChangeDataBase& aData) {
      if (!aData.IsInitialized()) {
        aStream << "{ IsInitialized()=false }";
        return aStream;
      }
      if (!aData.HasRange()) {
        aStream << "{ HasRange()=false }";
        return aStream;
      }
      aStream << "{ mOffset=" << aData.mOffset;
      if (aData.mString->Length() > 20) {
        aStream << ", mString.Length()=" << aData.mString->Length();
      } else {
        aStream << ", mString=\"" << NS_ConvertUTF16toUTF8(*aData.mString)
                << "\" (Length()=" << aData.mString->Length() << ")";
      }
    
      aStream << ", GetWritingMode()=" << aData.GetWritingMode()
              << ", mReversed=" << (aData.mReversed ? "true" : "false")
              << ", mCausedByComposition="
              << (aData.mCausedByComposition ? "true" : "false")
              << ", mCausedBySelectionEvent="
              << (aData.mCausedBySelectionEvent ? "true" : "false")
              << ", mOccurredDuringComposition="
              << (aData.mOccurredDuringComposition ? "true" : "false") << " }";
      return aStream;
    }
    
    std::ostream& operator<<(std::ostream& aStream,
                             const IMENotification::TextChangeDataBase& aData) {
      if (!aData.IsValid()) {
        aStream << "{ IsValid()=false }";
        return aStream;
      }
      aStream << "{ mStartOffset=" << aData.mStartOffset
              << ", mRemoveEndOffset=" << aData.mRemovedEndOffset
              << ", mAddedEndOffset=" << aData.mAddedEndOffset
              << ", mCausedOnlyByComposition="
              << (aData.mCausedOnlyByComposition ? "true" : "false")
              << ", mIncludingChangesDuringComposition="
              << (aData.mIncludingChangesDuringComposition ? "true" : "false")
              << ", mIncludingChangesWithoutComposition="
              << (aData.mIncludingChangesWithoutComposition ? "true" : "false")
              << " }";
      return aStream;
    }
    
    /******************************************************************************
     * IMENotification::SelectionChangeDataBase
     ******************************************************************************/
    
    void IMENotification::SelectionChangeDataBase::Assign(
        const WidgetQueryContentEvent& aQuerySelectedTextEvent) {
      MOZ_ASSERT(aQuerySelectedTextEvent.mMessage == eQuerySelectedText);
      MOZ_ASSERT(aQuerySelectedTextEvent.Succeeded());
    
      if (!(mIsInitialized = aQuerySelectedTextEvent.Succeeded())) {
        ClearSelectionData();
        return;
      }
      if ((mHasRange = aQuerySelectedTextEvent.FoundSelection())) {
        mOffset = aQuerySelectedTextEvent.mReply->StartOffset();
        *mString = aQuerySelectedTextEvent.mReply->DataRef();
        mReversed = aQuerySelectedTextEvent.mReply->mReversed;
        SetWritingMode(aQuerySelectedTextEvent.mReply->WritingModeRef());
      } else {
        mOffset = UINT32_MAX;
        mString->Truncate();
        mReversed = false;
        // Let's keep the writing mode for avoiding temporarily changing the
        // writing mode at no selection range.
      }
    }
    
    void IMENotification::SelectionChangeDataBase::SetWritingMode(
        const WritingMode& aWritingMode) {
      mWritingModeBits = aWritingMode.GetBits();
    }
    
    WritingMode IMENotification::SelectionChangeDataBase::GetWritingMode() const {
      return WritingMode(mWritingModeBits);
    }
    
    bool IMENotification::SelectionChangeDataBase::EqualsRange(
        const ContentSelection& aContentSelection) const {
      if (aContentSelection.HasRange() != HasRange()) {
        return false;
      }
      if (!HasRange()) {
        return true;
      }
      return mOffset == aContentSelection.OffsetAndDataRef().StartOffset() &&
             *mString == aContentSelection.OffsetAndDataRef().DataRef();
    }
    
    bool IMENotification::SelectionChangeDataBase::EqualsRangeAndWritingMode(
        const ContentSelection& aContentSelection) const {
      return EqualsRange(aContentSelection) &&
             mWritingModeBits == aContentSelection.WritingModeRef().GetBits();
    }
    
    }  // namespace widget
    }  // namespace mozilla