This source file includes following definitions.
- GetLocaleString
 
- GetCharacterDirection
 
- GetConfiguredLocale
 
- GetCanonicalLocale
 
- ICULocaleName
 
- SetICUDefaultLocale
 
- IsRTL
 
- ICUIsRTL
 
- GetTextDirectionForLocale
 
- GetFirstStrongCharacterDirection
 
- GetLastStrongCharacterDirection
 
- GetStringDirection
 
- AdjustStringForLocaleDirection
 
- UnadjustStringForLocaleDirection
 
- AdjustStringForLocaleDirection
 
- UnadjustStringForLocaleDirection
 
- StringContainsStrongRTLChars
 
- WrapStringWithLTRFormatting
 
- WrapStringWithRTLFormatting
 
- WrapPathWithLTRFormatting
 
- GetDisplayStringInLTRDirectionality
 
- StripWrappingBidiControlCharacters
 
#include "base/i18n/rtl.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/icu/source/common/unicode/locid.h"
#include "third_party/icu/source/common/unicode/uchar.h"
#include "third_party/icu/source/common/unicode/uscript.h"
#include "third_party/icu/source/i18n/unicode/coll.h"
#if defined(TOOLKIT_GTK)
#include <gtk/gtk.h>
#endif
namespace {
std::string GetLocaleString(const icu::Locale& locale) {
  const char* language = locale.getLanguage();
  const char* country = locale.getCountry();
  const char* variant = locale.getVariant();
  std::string result =
      (language != NULL && *language != '\0') ? language : "und";
  if (country != NULL && *country != '\0') {
    result += '-';
    result += country;
  }
  if (variant != NULL && *variant != '\0') {
    std::string variant_str(variant);
    StringToLowerASCII(&variant_str);
    result += '@' + variant_str;
  }
  return result;
}
base::i18n::TextDirection GetCharacterDirection(UChar32 character) {
  
  
  int32_t property = u_getIntPropertyValue(character, UCHAR_BIDI_CLASS);
  if ((property == U_RIGHT_TO_LEFT) ||
      (property == U_RIGHT_TO_LEFT_ARABIC) ||
      (property == U_RIGHT_TO_LEFT_EMBEDDING) ||
      (property == U_RIGHT_TO_LEFT_OVERRIDE)) {
    return base::i18n::RIGHT_TO_LEFT;
  } else if ((property == U_LEFT_TO_RIGHT) ||
             (property == U_LEFT_TO_RIGHT_EMBEDDING) ||
             (property == U_LEFT_TO_RIGHT_OVERRIDE)) {
    return base::i18n::LEFT_TO_RIGHT;
  }
  return base::i18n::UNKNOWN_DIRECTION;
}
}  
namespace base {
namespace i18n {
static TextDirection g_icu_text_direction = UNKNOWN_DIRECTION;
std::string GetConfiguredLocale() {
  return GetLocaleString(icu::Locale::getDefault());
}
std::string GetCanonicalLocale(const char* locale) {
  return GetLocaleString(icu::Locale::createCanonical(locale));
}
std::string ICULocaleName(const std::string& locale_string) {
  
  if (locale_string.substr(0, 2) != "es")
    return locale_string;
  
  if (LowerCaseEqualsASCII(locale_string, "es"))
    return "es-ES";
  
  
  
  if (LowerCaseEqualsASCII(locale_string, "es-419")) {
    const icu::Locale& locale = icu::Locale::getDefault();
    std::string language = locale.getLanguage();
    const char* country = locale.getCountry();
    if (LowerCaseEqualsASCII(language, "es") &&
      !LowerCaseEqualsASCII(country, "es")) {
        language += '-';
        language += country;
        return language;
    }
    return "es-MX";
  }
  
  
  return locale_string;
}
void SetICUDefaultLocale(const std::string& locale_string) {
  icu::Locale locale(ICULocaleName(locale_string).c_str());
  UErrorCode error_code = U_ZERO_ERROR;
  icu::Locale::setDefault(locale, error_code);
  
  
  
  
  DCHECK(U_SUCCESS(error_code));
  g_icu_text_direction = UNKNOWN_DIRECTION;
}
bool IsRTL() {
#if defined(TOOLKIT_GTK)
  GtkTextDirection gtk_dir = gtk_widget_get_default_direction();
  return gtk_dir == GTK_TEXT_DIR_RTL;
#else
  return ICUIsRTL();
#endif
}
bool ICUIsRTL() {
  if (g_icu_text_direction == UNKNOWN_DIRECTION) {
    const icu::Locale& locale = icu::Locale::getDefault();
    g_icu_text_direction = GetTextDirectionForLocale(locale.getName());
  }
  return g_icu_text_direction == RIGHT_TO_LEFT;
}
TextDirection GetTextDirectionForLocale(const char* locale_name) {
  UErrorCode status = U_ZERO_ERROR;
  ULayoutType layout_dir = uloc_getCharacterOrientation(locale_name, &status);
  DCHECK(U_SUCCESS(status));
  
  return (layout_dir != ULOC_LAYOUT_RTL) ? LEFT_TO_RIGHT : RIGHT_TO_LEFT;
}
TextDirection GetFirstStrongCharacterDirection(const string16& text) {
  const UChar* string = text.c_str();
  size_t length = text.length();
  size_t position = 0;
  while (position < length) {
    UChar32 character;
    size_t next_position = position;
    U16_NEXT(string, next_position, length, character);
    TextDirection direction = GetCharacterDirection(character);
    if (direction != UNKNOWN_DIRECTION)
      return direction;
    position = next_position;
  }
  return LEFT_TO_RIGHT;
}
TextDirection GetLastStrongCharacterDirection(const string16& text) {
  const UChar* string = text.c_str();
  size_t position = text.length();
  while (position > 0) {
    UChar32 character;
    size_t prev_position = position;
    U16_PREV(string, 0, prev_position, character);
    TextDirection direction = GetCharacterDirection(character);
    if (direction != UNKNOWN_DIRECTION)
      return direction;
    position = prev_position;
  }
  return LEFT_TO_RIGHT;
}
TextDirection GetStringDirection(const string16& text) {
  const UChar* string = text.c_str();
  size_t length = text.length();
  size_t position = 0;
  TextDirection result(UNKNOWN_DIRECTION);
  while (position < length) {
    UChar32 character;
    size_t next_position = position;
    U16_NEXT(string, next_position, length, character);
    TextDirection direction = GetCharacterDirection(character);
    if (direction != UNKNOWN_DIRECTION) {
      if (result != UNKNOWN_DIRECTION && result != direction)
        return UNKNOWN_DIRECTION;
      result = direction;
    }
    position = next_position;
  }
  
  
  if (result == UNKNOWN_DIRECTION)
    return LEFT_TO_RIGHT;
  return result;
}
#if defined(OS_WIN)
bool AdjustStringForLocaleDirection(string16* text) {
  if (!IsRTL() || text->empty())
    return false;
  
  
  bool has_rtl_chars = StringContainsStrongRTLChars(*text);
  if (!has_rtl_chars)
    WrapStringWithLTRFormatting(text);
  else
    WrapStringWithRTLFormatting(text);
  return true;
}
bool UnadjustStringForLocaleDirection(string16* text) {
  if (!IsRTL() || text->empty())
    return false;
  *text = StripWrappingBidiControlCharacters(*text);
  return true;
}
#else
bool AdjustStringForLocaleDirection(string16* text) {
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  if (text->empty())
    return false;
  bool ui_direction_is_rtl = IsRTL();
  bool has_rtl_chars = StringContainsStrongRTLChars(*text);
  if (!ui_direction_is_rtl && has_rtl_chars) {
    WrapStringWithRTLFormatting(text);
    text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
                 kLeftToRightMark);
    text->push_back(kLeftToRightMark);
  } else if (ui_direction_is_rtl && has_rtl_chars) {
    WrapStringWithRTLFormatting(text);
    text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
                 kRightToLeftMark);
    text->push_back(kRightToLeftMark);
  } else if (ui_direction_is_rtl) {
    WrapStringWithLTRFormatting(text);
    text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
                 kRightToLeftMark);
    text->push_back(kRightToLeftMark);
  } else {
    return false;
  }
  return true;
}
bool UnadjustStringForLocaleDirection(string16* text) {
  if (text->empty())
    return false;
  size_t begin_index = 0;
  char16 begin = text->at(begin_index);
  if (begin == kLeftToRightMark ||
      begin == kRightToLeftMark) {
    ++begin_index;
  }
  size_t end_index = text->length() - 1;
  char16 end = text->at(end_index);
  if (end == kLeftToRightMark ||
      end == kRightToLeftMark) {
    --end_index;
  }
  string16 unmarked_text =
      text->substr(begin_index, end_index - begin_index + 1);
  *text = StripWrappingBidiControlCharacters(unmarked_text);
  return true;
}
#endif  
bool StringContainsStrongRTLChars(const string16& text) {
  const UChar* string = text.c_str();
  size_t length = text.length();
  size_t position = 0;
  while (position < length) {
    UChar32 character;
    size_t next_position = position;
    U16_NEXT(string, next_position, length, character);
    
    
    int32_t property = u_getIntPropertyValue(character, UCHAR_BIDI_CLASS);
    if ((property == U_RIGHT_TO_LEFT) || (property == U_RIGHT_TO_LEFT_ARABIC))
      return true;
    position = next_position;
  }
  return false;
}
void WrapStringWithLTRFormatting(string16* text) {
  if (text->empty())
    return;
  
  text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
               kLeftToRightEmbeddingMark);
  
  text->push_back(kPopDirectionalFormatting);
}
void WrapStringWithRTLFormatting(string16* text) {
  if (text->empty())
    return;
  
  text->insert(static_cast<size_t>(0), static_cast<size_t>(1),
               kRightToLeftEmbeddingMark);
  
  text->push_back(kPopDirectionalFormatting);
}
void WrapPathWithLTRFormatting(const FilePath& path,
                               string16* rtl_safe_path) {
  
  
  
  rtl_safe_path->push_back(kLeftToRightEmbeddingMark);
#if defined(OS_MACOSX)
    rtl_safe_path->append(UTF8ToUTF16(path.value()));
#elif defined(OS_WIN)
    rtl_safe_path->append(path.value());
#else  
    std::wstring wide_path = base::SysNativeMBToWide(path.value());
    rtl_safe_path->append(WideToUTF16(wide_path));
#endif
  
  rtl_safe_path->push_back(kPopDirectionalFormatting);
}
string16 GetDisplayStringInLTRDirectionality(const string16& text) {
  
  
  if (IsRTL() || GetFirstStrongCharacterDirection(text) == RIGHT_TO_LEFT) {
    string16 text_mutable(text);
    WrapStringWithLTRFormatting(&text_mutable);
    return text_mutable;
  }
  return text;
}
string16 StripWrappingBidiControlCharacters(const string16& text) {
  if (text.empty())
    return text;
  size_t begin_index = 0;
  char16 begin = text[begin_index];
  if (begin == kLeftToRightEmbeddingMark ||
      begin == kRightToLeftEmbeddingMark ||
      begin == kLeftToRightOverride ||
      begin == kRightToLeftOverride)
    ++begin_index;
  size_t end_index = text.length() - 1;
  if (text[end_index] == kPopDirectionalFormatting)
    --end_index;
  return text.substr(begin_index, end_index - begin_index + 1);
}
}  
}