From 7bfb25e88de694b9e382de96aee42fb9d286ff04 Mon Sep 17 00:00:00 2001 From: the_r3dacted Date: Thu, 21 May 2026 12:26:10 -0700 Subject: [PATCH 1/2] funny stuff --- dom/performance/Performance.cpp | 20 +- dom/performance/Performance.h | 13 +- dom/performance/PerformanceMainThread.h | 5 - dom/performance/PerformanceMark.cpp | 5 + dom/performance/PerformanceMark.h | 4 + dom/performance/PerformanceMeasure.cpp | 1 + dom/performance/PerformanceTiming.h | 4 +- dom/performance/PerformanceWorker.h | 5 - intl/icu/source/common/locmap.cpp | 56 +- intl/icu/source/common/locmap.h | 2 +- intl/icu/source/common/putil.cpp | 62 +- intl/icu/source/common/uloc.cpp | 4 +- intl/icu/source/common/unicode/localpointer.h | 2 + intl/icu/source/common/wintz.cpp | 614 ++++++++++-------- intl/icu/source/data/locales/en.txt | 2 +- intl/icu/source/i18n/windtfmt.cpp | 134 +--- intl/icu/source/i18n/windtfmt.h | 3 +- intl/icu/source/i18n/winnmfmt.cpp | 188 ++---- intl/icu/source/i18n/winnmfmt.h | 2 - .../python/icutools/databuilder/filtration.py | 4 +- .../icutools/databuilder/request_types.py | 6 +- .../python/icutools/databuilder/utils.py | 8 +- 22 files changed, 496 insertions(+), 648 deletions(-) diff --git a/dom/performance/Performance.cpp b/dom/performance/Performance.cpp index 49f70e28d7..67276d9517 100755 --- a/dom/performance/Performance.cpp +++ b/dom/performance/Performance.cpp @@ -262,12 +262,6 @@ already_AddRefed Performance::Mark( const PerformanceMarkOptions& aMarkOptions, ErrorResult& aRv) { - // Clear the buffer if it is full and throw an error informing the web dev. - if (mUserEntries.Length() >= mResourceTimingBufferSize) { - aRv.Throw(NS_ERROR_DOM_UT_QUOTA_ERR); - mUserEntries.Clear(); - } - nsCOMPtr parent = GetParentObject(); if (!parent || parent->IsDying() || !parent->GetGlobalJSObject()) { aRv.Throw(NS_ERROR_DOM_UT_UNAVAILABLE_GLOBAL_OBJECT); @@ -496,12 +490,6 @@ Performance::Measure(JSContext* aCx, return nullptr; } - // Clear the buffer if it is full and throw an error informing the web dev. - if (mUserEntries.Length() >= mResourceTimingBufferSize) { - aRv.Throw(NS_ERROR_DOM_UT_QUOTA_ERR); - mUserEntries.Clear(); - } - // Maybe is more readable than using the union type directly. Maybe options; if (aStartOrMeasureOptions.IsPerformanceMeasureOptions()) { @@ -561,7 +549,7 @@ Performance::Measure(JSContext* aCx, } RefPtr performanceMeasure = new PerformanceMeasure( - GetAsISupports(), aName, startTime, endTime, detail); + GetParentObject(), aName, startTime, endTime, detail); InsertUserEntry(performanceMeasure); return performanceMeasure.forget(); @@ -779,5 +767,11 @@ Performance::IsObserverEnabled(JSContext* aCx, JSObject* aGlobal) return runnable->Dispatch() && runnable->IsEnabled(); } +void +Performance::MemoryPressure() +{ + mUserEntries.Clear(); +} + } // dom namespace } // mozilla namespace diff --git a/dom/performance/Performance.h b/dom/performance/Performance.h index 2e1b63c45b..ad63d1ebd1 100644 --- a/dom/performance/Performance.h +++ b/dom/performance/Performance.h @@ -124,6 +124,8 @@ class Performance : public DOMEventTargetHelper return false; } + void MemoryPressure(); + virtual void QueueNavigationTimingEntry() = 0; protected: @@ -138,8 +140,6 @@ class Performance : public DOMEventTargetHelper void ClearUserEntries(const Optional& aEntryName, const nsAString& aEntryType); - virtual nsISupports* GetAsISupports() = 0; - virtual void DispatchBufferFullEvent() = 0; virtual TimeStamp CreationTimeStamp() const = 0; @@ -169,11 +169,14 @@ class Performance : public DOMEventTargetHelper nsTObserverArray mObservers; protected: - nsTArray> mUserEntries; - nsTArray> mResourceEntries; + static const uint64_t kDefaultResourceTimingBufferSize = 1500; + + // When kDefaultResourceTimingBufferSize is increased or removed, these should + // be changed to use SegmentedVector + AutoTArray, kDefaultResourceTimingBufferSize> mUserEntries; + AutoTArray, kDefaultResourceTimingBufferSize> mResourceEntries; uint64_t mResourceTimingBufferSize; - static const uint64_t kDefaultResourceTimingBufferSize = 16384; bool mPendingNotificationObserversTask; RefPtr mPerformanceService; diff --git a/dom/performance/PerformanceMainThread.h b/dom/performance/PerformanceMainThread.h index fc81c94e2a..feb70e1c92 100644 --- a/dom/performance/PerformanceMainThread.h +++ b/dom/performance/PerformanceMainThread.h @@ -69,11 +69,6 @@ class PerformanceMainThread final : public Performance void CreateNavigationTimingEntry(); - nsISupports* GetAsISupports() override - { - return this; - } - void InsertUserEntry(PerformanceEntry* aEntry) override; DOMHighResTimeStamp diff --git a/dom/performance/PerformanceMark.cpp b/dom/performance/PerformanceMark.cpp index ddafe0e0ef..7469fdf385 100644 --- a/dom/performance/PerformanceMark.cpp +++ b/dom/performance/PerformanceMark.cpp @@ -3,12 +3,17 @@ * 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 "Performance.h" #include "PerformanceMark.h" #include "MainThreadUtils.h" +#include "mozilla/HoldDropJSObjects.h" +#include "mozilla/dom/PerformanceBinding.h" #include "mozilla/dom/PerformanceMarkBinding.h" #include "mozilla/dom/MessagePortBinding.h" #include "mozilla/ErrorResult.h" +#include "nsContentUtils.h" +using mozilla::ErrorResult; using mozilla::dom::StructuredSerializeOptions; using namespace mozilla::dom; diff --git a/dom/performance/PerformanceMark.h b/dom/performance/PerformanceMark.h index 4e98bfaa92..9ac640fcf9 100644 --- a/dom/performance/PerformanceMark.h +++ b/dom/performance/PerformanceMark.h @@ -8,9 +8,13 @@ #include "mozilla/dom/PerformanceEntry.h" +class nsIGlobalObject; namespace mozilla { + +class ErrorResult; namespace dom { +class GlobalObject; struct PerformanceMarkOptions; // http://www.w3.org/TR/user-timing/#performancemark diff --git a/dom/performance/PerformanceMeasure.cpp b/dom/performance/PerformanceMeasure.cpp index 3c6e73230f..64da3dbcd9 100644 --- a/dom/performance/PerformanceMeasure.cpp +++ b/dom/performance/PerformanceMeasure.cpp @@ -5,6 +5,7 @@ #include "PerformanceMeasure.h" #include "MainThreadUtils.h" +#include "mozilla/HoldDropJSObjects.h" #include "mozilla/dom/PerformanceMeasureBinding.h" using namespace mozilla::dom; diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h index 91bd14f0d7..5787d3efc7 100755 --- a/dom/performance/PerformanceTiming.h +++ b/dom/performance/PerformanceTiming.h @@ -260,7 +260,7 @@ class PerformanceTiming final : public nsWrapperCache DOMTimeMilliSec UnloadEventStart() { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { + if (!nsContentUtils::IsPerformanceTimingEnabled() || !mTimingData->AllRedirectsSameOrigin()) { return 0; } return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventStart()); @@ -268,7 +268,7 @@ class PerformanceTiming final : public nsWrapperCache DOMTimeMilliSec UnloadEventEnd() { - if (!nsContentUtils::IsPerformanceTimingEnabled()) { + if (!nsContentUtils::IsPerformanceTimingEnabled() || !mTimingData->AllRedirectsSameOrigin()) { return 0; } return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventEnd()); diff --git a/dom/performance/PerformanceWorker.h b/dom/performance/PerformanceWorker.h index cdd3a521dd..301fb59db7 100644 --- a/dom/performance/PerformanceWorker.h +++ b/dom/performance/PerformanceWorker.h @@ -70,11 +70,6 @@ class PerformanceWorker final : public Performance protected: ~PerformanceWorker(); - nsISupports* GetAsISupports() override - { - return nullptr; - } - void InsertUserEntry(PerformanceEntry* aEntry) override; void DispatchBufferFullEvent() override diff --git a/intl/icu/source/common/locmap.cpp b/intl/icu/source/common/locmap.cpp index da78c7716a..ba3cb6b241 100644 --- a/intl/icu/source/common/locmap.cpp +++ b/intl/icu/source/common/locmap.cpp @@ -1074,39 +1074,29 @@ uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UEr char16_t windowsLocaleName[LOCALE_NAME_MAX_LENGTH] = {}; // Note: LOCALE_ALLOW_NEUTRAL_NAMES was enabled in Windows7+, prior versions did not handle neutral (no-region) locale names. - tmpLen = LCIDToLocaleName(hostid, (PWSTR)windowsLocaleName, UPRV_LENGTHOF(windowsLocaleName), LOCALE_ALLOW_NEUTRAL_NAMES); + tmpLen = GetLocaleInfoA(hostid, LOCALE_SNAME, (LPSTR)locName, UPRV_LENGTHOF(locName)); if (tmpLen > 1) { - int32_t i = 0; - // Only need to look up in table if have _, eg for de-de_phoneb type alternate sort. - bLookup = false; - for (i = 0; i < UPRV_LENGTHOF(locName); i++) - { - locName[i] = (char)(windowsLocaleName[i]); - - // Windows locale name may contain sorting variant, such as "es-ES_tradnl". - // In such cases, we need special mapping data found in the hardcoded table - // in this source file. - if (windowsLocaleName[i] == L'_') - { - // Keep the base locale, without variant - // TODO: Should these be mapped from _phoneb to @collation=phonebook, etc.? - locName[i] = '\0'; - tmpLen = i; - bLookup = true; - break; - } - else if (windowsLocaleName[i] == L'-') - { - // Windows names use -, ICU uses _ - locName[i] = '_'; - } - else if (windowsLocaleName[i] == L'\0') - { - // No point in doing more work than necessary - break; - } + /* Windows locale name may contain sorting variant, such as "es-ES_tradnl". + In such case, we need special mapping data found in the hardcoded table + in this source file. */ + char *p = uprv_strchr(locName, '_'); + if (p) { + /* Keep the base locale, without variant */ + *p = 0; + tmpLen = uprv_strlen(locName); + } + else { + /* No hardcoded table lookup necessary */ + bLookup = FALSE; } - // TODO: Need to understand this better, why isn't it an alias? + /* Change the tag separator from '-' to '_' */ + p = locName; + while (*p) { + if (*p == '-') { + *p = '_'; + } + p++; + } FIX_LANGUAGE_ID_TAG(locName, tmpLen); pPosixID = locName; } @@ -1163,7 +1153,7 @@ uprv_convertToPosix(uint32_t hostid, char *posixID, int32_t posixIDCapacity, UEr // ///////////////////////////////////// */ -U_CAPI uint32_t +/*U_CAPI uint32_t uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status) { if (U_FAILURE(*status)) { @@ -1241,7 +1231,7 @@ uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status) // Nothing found, or not implemented. return 0; -} +}*/ U_CAPI uint32_t uprv_convertToLCID(const char *langID, const char* posixID, UErrorCode* status) diff --git a/intl/icu/source/common/locmap.h b/intl/icu/source/common/locmap.h index e669873a14..a250419d15 100644 --- a/intl/icu/source/common/locmap.h +++ b/intl/icu/source/common/locmap.h @@ -33,7 +33,7 @@ U_CAPI int32_t uprv_convertToPosix(uint32_t hostid, char* posixID, int32_t posixIDCapacity, UErrorCode* status); /* Don't call these functions directly. Use uloc_getLCID instead. */ -U_CAPI uint32_t uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status); // Leverage platform conversion if possible +//U_CAPI uint32_t uprv_convertToLCIDPlatform(const char* localeID, UErrorCode* status); // Leverage platform conversion if possible U_CAPI uint32_t uprv_convertToLCID(const char* langID, const char* posixID, UErrorCode* status); #endif /* LOCMAP_H */ diff --git a/intl/icu/source/common/putil.cpp b/intl/icu/source/common/putil.cpp index ea15fdff0b..482be991aa 100644 --- a/intl/icu/source/common/putil.cpp +++ b/intl/icu/source/common/putil.cpp @@ -1803,58 +1803,16 @@ The leftmost codepage (.xxx) wins. return gCorrectedPOSIXLocale; } - // No cached value, need to determine the current value - static WCHAR windowsLocale[LOCALE_NAME_MAX_LENGTH] = {}; - int length = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, windowsLocale, LOCALE_NAME_MAX_LENGTH); - - // Now we should have a Windows locale name that needs converted to the POSIX style. - if (length > 0) // If length is 0, then the GetLocaleInfoEx failed. - { - // First we need to go from UTF-16 to char (and also convert from _ to - while we're at it.) - char modifiedWindowsLocale[LOCALE_NAME_MAX_LENGTH] = {}; - - int32_t i; - for (i = 0; i < UPRV_LENGTHOF(modifiedWindowsLocale); i++) - { - if (windowsLocale[i] == '_') - { - modifiedWindowsLocale[i] = '-'; - } - else - { - modifiedWindowsLocale[i] = static_cast(windowsLocale[i]); - } - - if (modifiedWindowsLocale[i] == '\0') - { - break; - } - } - - if (i >= UPRV_LENGTHOF(modifiedWindowsLocale)) - { - // Ran out of room, can't really happen, maybe we'll be lucky about a matching - // locale when tags are dropped - modifiedWindowsLocale[UPRV_LENGTHOF(modifiedWindowsLocale) - 1] = '\0'; - } - - // Now normalize the resulting name - correctedPOSIXLocale = static_cast(uprv_malloc(POSIX_LOCALE_CAPACITY + 1)); - /* TODO: Should we just exit on memory allocation failure? */ - if (correctedPOSIXLocale) - { - int32_t posixLen = uloc_canonicalize(modifiedWindowsLocale, correctedPOSIXLocale, POSIX_LOCALE_CAPACITY, &status); - if (U_SUCCESS(status)) - { - *(correctedPOSIXLocale + posixLen) = 0; - gCorrectedPOSIXLocale = correctedPOSIXLocale; - gCorrectedPOSIXLocaleHeapAllocated = true; - ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); - } - else - { - uprv_free(correctedPOSIXLocale); - } + LCID id = GetThreadLocale(); + correctedPOSIXLocale = static_cast(uprv_malloc(POSIX_LOCALE_CAPACITY + 1)); + if (correctedPOSIXLocale) { + int32_t posixLen = uprv_convertToPosix(id, correctedPOSIXLocale, POSIX_LOCALE_CAPACITY, &status); + if (U_SUCCESS(status)) { + *(correctedPOSIXLocale + posixLen) = 0; + gCorrectedPOSIXLocale = correctedPOSIXLocale; + ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); + } else { + uprv_free(correctedPOSIXLocale); } } diff --git a/intl/icu/source/common/uloc.cpp b/intl/icu/source/common/uloc.cpp index 7467f1cb33..42a4391e14 100644 --- a/intl/icu/source/common/uloc.cpp +++ b/intl/icu/source/common/uloc.cpp @@ -2289,14 +2289,14 @@ uloc_getLCID(const char* localeID) // First, attempt Windows platform lookup if available, but fall // through to catch any special cases (ICU vs Windows name differences). - lcid = uprv_convertToLCIDPlatform(localeID, &status); + /*lcid = uprv_convertToLCIDPlatform(localeID, &status); if (U_FAILURE(status)) { return 0; } if (lcid > 0) { // Windows found an LCID, return that return lcid; - } + }*/ CharString langID = ulocimp_getLanguage(localeID, status); if (U_FAILURE(status)) { diff --git a/intl/icu/source/common/unicode/localpointer.h b/intl/icu/source/common/unicode/localpointer.h index 1803222d8d..adcda899f6 100644 --- a/intl/icu/source/common/unicode/localpointer.h +++ b/intl/icu/source/common/unicode/localpointer.h @@ -223,6 +223,8 @@ class LocalPointer : public LocalPointerBase { src.ptr=nullptr; } + LocalPointer(const LocalPointer &src) noexcept : LocalPointerBase(src.ptr) {} + /** * Constructs a LocalPointer from a C++11 std::unique_ptr. * The LocalPointer steals the object owned by the std::unique_ptr. diff --git a/intl/icu/source/common/wintz.cpp b/intl/icu/source/common/wintz.cpp index ef9cd68019..c4d5327274 100644 --- a/intl/icu/source/common/wintz.cpp +++ b/intl/icu/source/common/wintz.cpp @@ -13,16 +13,16 @@ #include "unicode/utypes.h" -#if U_PLATFORM_USES_ONLY_WIN32_API +// This file contains only desktop Windows behavior +// Windows UWP calls Windows::Globalization directly, so this isn't needed there. +#if U_PLATFORM_USES_ONLY_WIN32_API && (U_PLATFORM_HAS_WINUWP_API == 0) #include "wintz.h" -#include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "unicode/ures.h" -#include "unicode/unistr.h" -#include "uresimp.h" +#include "unicode/ustring.h" #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN @@ -34,298 +34,386 @@ # define NOMCX #include -U_NAMESPACE_BEGIN +#define MAX_LENGTH_ID 40 -// Note these constants and the struct are only used when dealing with the fallback path for RDP sessions. +/* The layout of the Tzi value in the registry */ +typedef struct +{ + int32_t bias; + int32_t standardBias; + int32_t daylightBias; + SYSTEMTIME standardDate; + SYSTEMTIME daylightDate; +} TZI; -// This is the location of the time zones in the registry on Vista+ systems. -// See: https://docs.microsoft.com/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information -#define WINDOWS_TIMEZONES_REG_KEY_PATH L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones" +/** + * Various registry keys and key fragments. + */ +static const wchar_t CURRENT_ZONE_REGKEY[] = L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation\\"; +static const char TZI_REGKEY[] = "TZI"; +static const char STD_REGKEY[] = "Std"; -// Max length for a registry key is 255. +1 for null. -// See: https://docs.microsoft.com/windows/win32/sysinfo/registry-element-size-limits -#define WINDOWS_MAX_REG_KEY_LENGTH 256 +/** + * The time zone root keys (under HKLM) for Win7+ + */ +static const char TZ_REGKEY[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\"; -#if U_PLATFORM_HAS_WINUWP_API == 0 +static LONG openTZRegKey(HKEY *hkey, const char *winid) +{ + char subKeyName[110]; /* TODO: why 110?? */ + char *name; + LONG result; + + uprv_strcpy(subKeyName, TZ_REGKEY); + name = &subKeyName[strlen(subKeyName)]; + uprv_strcat(subKeyName, winid); + + result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + subKeyName, + 0, + KEY_QUERY_VALUE, + hkey); + return result; +} -// This is the layout of the TZI binary value in the registry. -// See: https://docs.microsoft.com/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information -typedef struct _REG_TZI_FORMAT { - LONG Bias; - LONG StandardBias; - LONG DaylightBias; - SYSTEMTIME StandardDate; - SYSTEMTIME DaylightDate; -} REG_TZI_FORMAT; +static LONG getTZI(const char *winid, TZI *tzi) +{ + DWORD cbData = sizeof(TZI); + LONG result; + HKEY hkey; -#endif // U_PLATFORM_HAS_WINUWP_API + result = openTZRegKey(&hkey, winid); -/** -* This is main Windows time zone detection function. -* -* It returns the Windows time zone converted to an ICU time zone as a heap-allocated buffer, or nullptr upon failure. -* -* We use the Win32 API GetDynamicTimeZoneInformation (which is available since Vista) to get the current time zone info, -* as this API returns a non-localized time zone name which can be then mapped to an ICU time zone. -* -* However, in some RDP/terminal services situations, this struct isn't always fully complete, and the TimeZoneKeyName -* field of the struct might be nullptr. This can happen with some 3rd party RDP clients, and also when using older versions -* of the RDP protocol, which don't send the newer TimeZoneKeyNamei information and only send the StandardName and DaylightName. -* -* Since these 3rd party clients and older RDP clients only send the pre-Vista time zone information to the server, this means that we -* need to fallback on using the pre-Vista methods to determine the time zone. This unfortunately requires examining the registry directly -* in order to try and determine the current time zone. -* -* Note that this can however still fail in some cases though if the client and server are using different languages, as the StandardName -* that is sent by client is localized in the client's language. However, we must compare this to the names that are on the server, which -* are localized in registry using the server's language. Despite that, this is the best we can do. -* -* Note: This fallback method won't work for the UWP version though, as we can't use the registry APIs in UWP. -* -* Once we have the current Windows time zone, then we can then map it to an ICU time zone ID (~ Olsen ID). -*/ -U_CAPI const char* U_EXPORT2 -uprv_detectWindowsTimeZone() -{ - // We first try to obtain the time zone directly by using the TimeZoneKeyName field of the DYNAMIC_TIME_ZONE_INFORMATION struct. - DYNAMIC_TIME_ZONE_INFORMATION dynamicTZI; - uprv_memset(&dynamicTZI, 0, sizeof(dynamicTZI)); - SYSTEMTIME systemTimeAllZero; - uprv_memset(&systemTimeAllZero, 0, sizeof(systemTimeAllZero)); - - if (GetDynamicTimeZoneInformation(&dynamicTZI) == TIME_ZONE_ID_INVALID) { - return nullptr; + if (result == ERROR_SUCCESS) + { + result = RegQueryValueExA(hkey, + TZI_REGKEY, + NULL, + NULL, + (LPBYTE)tzi, + &cbData); + RegCloseKey(hkey); } - // If the DST setting has been turned off in the Control Panel, then return "Etc/GMT". - // - // Note: This logic is based on how the Control Panel itself determines if DST is 'off' on Windows. - // The code is somewhat convoluted; in a sort of pseudo-code it looks like this: - // - // IF (GetDynamicTimeZoneInformation != TIME_ZONE_ID_INVALID) && (DynamicDaylightTimeDisabled != 0) && - // (StandardDate == DaylightDate) && - // ( - // (TimeZoneKeyName != Empty && StandardDate == 0) || - // (TimeZoneKeyName == Empty && StandardDate != 0) - // ) - // THEN - // DST setting is "Disabled". - // - if (dynamicTZI.DynamicDaylightTimeDisabled != 0 && - uprv_memcmp(&dynamicTZI.StandardDate, &dynamicTZI.DaylightDate, sizeof(dynamicTZI.StandardDate)) == 0 && - ((dynamicTZI.TimeZoneKeyName[0] != L'\0' && uprv_memcmp(&dynamicTZI.StandardDate, &systemTimeAllZero, sizeof(systemTimeAllZero)) == 0) || - (dynamicTZI.TimeZoneKeyName[0] == L'\0' && uprv_memcmp(&dynamicTZI.StandardDate, &systemTimeAllZero, sizeof(systemTimeAllZero)) != 0))) + return result; +} + +static LONG getSTDName(const char *winid, char *regStdName, int32_t length) +{ + DWORD cbData = length; + LONG result; + HKEY hkey; + + result = openTZRegKey(&hkey, winid); + + if (result == ERROR_SUCCESS) { - LONG utcOffsetMins = dynamicTZI.Bias; - if (utcOffsetMins == 0) { - return uprv_strdup("Etc/UTC"); - } + result = RegQueryValueExA(hkey, + STD_REGKEY, + NULL, + NULL, + (LPBYTE)regStdName, + &cbData); + RegCloseKey(hkey); + } - // No way to support when DST is turned off and the offset in minutes is not a multiple of 60. - if (utcOffsetMins % 60 == 0) { - char gmtOffsetTz[11] = {}; // "Etc/GMT+dd" is 11-char long with a terminal null. - // Important note on the sign convention for zones: - // - // From https://en.wikipedia.org/wiki/Tz_database#Area - // "In order to conform with the POSIX style, those zone names beginning with "Etc/GMT" have their sign reversed - // from the standard ISO 8601 convention. In the "Etc" area, zones west of GMT have a positive sign and those - // east have a negative sign in their name (e.g "Etc/GMT-14" is 14 hours ahead of GMT)." - // - // Regarding the POSIX style, from https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html - // "The offset specifies the time value you must add to the local time to get a Coordinated Universal Time value." - // - // However, the Bias value in DYNAMIC_TIME_ZONE_INFORMATION *already* follows the POSIX convention. - // - // From https://docs.microsoft.com/en-us/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information - // "The bias is the difference, in minutes, between Coordinated Universal Time (UTC) and - // local time. All translations between UTC and local time are based on the following formula: - // UTC = local time + bias" - // - // For example, a time zone that is 3 hours ahead of UTC (UTC+03:00) would have a Bias value of -180, and the - // corresponding time zone ID would be "Etc/GMT-3". (So there is no need to negate utcOffsetMins below.) - int ret = snprintf(gmtOffsetTz, sizeof(gmtOffsetTz), "Etc/GMT%+ld", utcOffsetMins / 60); - if (ret > 0 && ret < UPRV_LENGTHOF(gmtOffsetTz)) { - return uprv_strdup(gmtOffsetTz); + return result; +} + +static LONG getTZKeyName(char* tzKeyName, int32_t tzKeyNamelength) +{ + HKEY hkey; + LONG result = FALSE; + WCHAR timeZoneKeyNameData[128]; + DWORD timeZoneKeyNameLength = static_cast(sizeof(timeZoneKeyNameData)); + + if(ERROR_SUCCESS == RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + CURRENT_ZONE_REGKEY, + 0, + KEY_QUERY_VALUE, + &hkey)) + { + if (ERROR_SUCCESS == RegQueryValueExW( + hkey, + L"TimeZoneKeyName", + NULL, + NULL, + (LPBYTE)timeZoneKeyNameData, + &timeZoneKeyNameLength)) + { + // Ensure null termination. + timeZoneKeyNameData[UPRV_LENGTHOF(timeZoneKeyNameData) - 1] = L'\0'; + + // Convert the UTF-16 string to UTF-8. + UErrorCode status = U_ZERO_ERROR; + u_strToUTF8(tzKeyName, tzKeyNamelength, NULL, reinterpret_cast(timeZoneKeyNameData), -1, &status); + if (U_ZERO_ERROR == status) + { + result = ERROR_SUCCESS; } } + RegCloseKey(hkey); } - // If DST is NOT disabled, but the TimeZoneKeyName field of the struct is nullptr, then we may be dealing with a - // RDP/terminal services session where the 'Time Zone Redirection' feature is enabled. However, either the RDP - // client sent the server incomplete info (some 3rd party RDP clients only send the StandardName and DaylightName, - // but do not send the important TimeZoneKeyName), or if the RDP server has not appropriately populated the struct correctly. - // - // In this case we unfortunately have no choice but to fallback to using the pre-Vista method of determining the - // time zone, which requires examining the registry directly. - // - // Note that this can however still fail though if the client and server are using different languages, as the StandardName - // that is sent by client is *localized* in the client's language. However, we must compare this to the names that are - // on the server, which are *localized* in registry using the server's language. - // - // One other note is that this fallback method doesn't work for the UWP version, as we can't use the registry APIs. - - // windowsTimeZoneName will point at timezoneSubKeyName if we had to fallback to using the registry, and we found a match. - WCHAR timezoneSubKeyName[WINDOWS_MAX_REG_KEY_LENGTH]; - WCHAR *windowsTimeZoneName = dynamicTZI.TimeZoneKeyName; - - if (dynamicTZI.TimeZoneKeyName[0] == 0) { - -// We can't use the registry APIs in the UWP version. -#if U_PLATFORM_HAS_WINUWP_API == 1 - (void)timezoneSubKeyName; // suppress unused variable warnings. - return nullptr; -#else - // Open the path to the time zones in the Windows registry. - LONG ret; - HKEY hKeyAllTimeZones = nullptr; - ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, WINDOWS_TIMEZONES_REG_KEY_PATH, 0, KEY_READ, - reinterpret_cast(&hKeyAllTimeZones)); - - if (ret != ERROR_SUCCESS) { - // If we can't open the key, then we can't do much, so fail. - return nullptr; - } - - // Read the number of subkeys under the time zone registry path. - DWORD numTimeZoneSubKeys; - ret = RegQueryInfoKeyW(hKeyAllTimeZones, nullptr, nullptr, nullptr, &numTimeZoneSubKeys, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); - - if (ret != ERROR_SUCCESS) { - RegCloseKey(hKeyAllTimeZones); - return nullptr; - } + return result; +} - // Examine each of the subkeys to try and find a match for the localized standard name ("Std"). - // - // Note: The name of the time zone subkey itself is not localized, but the "Std" name is localized. This means - // that we could fail to find a match if the RDP client and RDP server are using different languages, but unfortunately - // there isn't much we can do about it. - HKEY hKeyTimeZoneSubKey = nullptr; - ULONG registryValueType; - WCHAR registryStandardName[WINDOWS_MAX_REG_KEY_LENGTH]; - - for (DWORD i = 0; i < numTimeZoneSubKeys; i++) { - // Note: RegEnumKeyExW wants the size of the buffer in characters. - DWORD size = UPRV_LENGTHOF(timezoneSubKeyName); - ret = RegEnumKeyExW(hKeyAllTimeZones, i, timezoneSubKeyName, &size, nullptr, nullptr, nullptr, nullptr); - - if (ret != ERROR_SUCCESS) { - RegCloseKey(hKeyAllTimeZones); - return nullptr; - } - - ret = RegOpenKeyExW(hKeyAllTimeZones, timezoneSubKeyName, 0, KEY_READ, - reinterpret_cast(&hKeyTimeZoneSubKey)); - - if (ret != ERROR_SUCCESS) { - RegCloseKey(hKeyAllTimeZones); - return nullptr; - } +/* + This code attempts to detect the Windows time zone directly, + as set in the Windows Date and Time control panel. It attempts + to work on versions greater than Windows Vista and on localized + installs. It works by directly interrogating the registry and + comparing the data there with the data returned by the + GetTimeZoneInformation API, along with some other strategies. The + registry contains time zone data under this key: + + HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\ + + Under this key are several subkeys, one for each time zone. For + example these subkeys are named "Pacific Standard Time" on Vista+. + There are some other wrinkles; see the code for + details. The subkey name is NOT LOCALIZED, allowing us to support + localized installs. + + Under the subkey are data values. We care about: + + Std Standard time display name, localized + TZI Binary block of data + + The TZI data is of particular interest. It contains the offset, two + more offsets for standard and daylight time, and the start and end + rules. This is the same data returned by the GetTimeZoneInformation + API. The API may modify the data on the way out, so we have to be + careful, but essentially we do a binary comparison against the TZI + blocks of various registry keys. When we find a match, we know what + time zone Windows is set to. Since the registry key is not + localized, we can then translate the key through a simple table + lookup into the corresponding ICU time zone. + + This strategy doesn't always work because there are zones which + share an offset and rules, so more than one TZI block will match. + For example, both Tokyo and Seoul are at GMT+9 with no DST rules; + their TZI blocks are identical. For these cases, we fall back to a + name lookup. We attempt to match the display name as stored in the + registry for the current zone to the display name stored in the + registry for various Windows zones. By comparing the registry data + directly we avoid conversion complications. + + Author: Alan Liu + Since: ICU 2.6 + Based on original code by Carl Brown +*/ - // Note: RegQueryValueExW wants the size of the buffer in bytes. - size = sizeof(registryStandardName); - ret = RegQueryValueExW(hKeyTimeZoneSubKey, L"Std", nullptr, ®istryValueType, - reinterpret_cast(registryStandardName), &size); - - if (ret != ERROR_SUCCESS || registryValueType != REG_SZ) { - RegCloseKey(hKeyTimeZoneSubKey); - RegCloseKey(hKeyAllTimeZones); - return nullptr; - } +/** + * Main Windows time zone detection function. Returns the Windows + * time zone, translated to an ICU time zone, or NULL upon failure. + */ +U_CFUNC const char* U_EXPORT2 +uprv_detectWindowsTimeZone() +{ + UErrorCode status = U_ZERO_ERROR; + UResourceBundle* bundle = NULL; + char* icuid = NULL; + char apiStdName[MAX_LENGTH_ID]; + char regStdName[MAX_LENGTH_ID]; + char tmpid[MAX_LENGTH_ID]; + int32_t len; + int id; + int errorCode; + wchar_t ISOcodeW[3]; /* 2 letter iso code in UTF-16*/ + char ISOcodeA[3]; /* 2 letter iso code in ansi */ + + LONG result; + TZI tziKey; + TZI tziReg; + TIME_ZONE_INFORMATION apiTZI; + + BOOL isVistaOrHigher; + BOOL tryPreVistaFallback; + OSVERSIONINFO osVerInfo; + + /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it + to TZI. We could also interrogate the registry directly; we do + this below if needed. */ + uprv_memset(&apiTZI, 0, sizeof(apiTZI)); + uprv_memset(&tziKey, 0, sizeof(tziKey)); + uprv_memset(&tziReg, 0, sizeof(tziReg)); + GetTimeZoneInformation(&apiTZI); + tziKey.bias = apiTZI.Bias; + uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate, + sizeof(apiTZI.StandardDate)); + uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate, + sizeof(apiTZI.DaylightDate)); + + /* Convert the wchar_t* standard name to char* */ + uprv_memset(apiStdName, 0, sizeof(apiStdName)); + wcstombs(apiStdName, apiTZI.StandardName, MAX_LENGTH_ID); + + tmpid[0] = 0; + + id = GetUserGeoID(GEOCLASS_NATION); + errorCode = GetGeoInfoW(id, GEO_ISO2, ISOcodeW, sizeof(ISOcodeW), 0); + u_strToUTF8(ISOcodeA, sizeof(ISOcodeA), NULL, (const UChar *)ISOcodeW, sizeof(ISOcodeW), &status); + + status = U_ZERO_ERROR; + bundle = ures_openDirect(NULL, "windowsZones", &status); + ures_getByKey(bundle, "mapTimezones", bundle, &status); + + /* + Windows Vista+ provides us with a "TimeZoneKeyName" that is not localized + and can be used to directly map a name in our bundle. Try to use that first + if we're on Vista or higher + */ + uprv_memset(&osVerInfo, 0, sizeof(osVerInfo)); + osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); + isVistaOrHigher = osVerInfo.dwMajorVersion >= 6; + + tryPreVistaFallback = TRUE; + + if(isVistaOrHigher) { + result = getTZKeyName(regStdName, sizeof(regStdName)); + if(ERROR_SUCCESS == result) + { + UResourceBundle* winTZ = ures_getByKey(bundle, regStdName, NULL, &status); + if(U_SUCCESS(status)) + { + const UChar* icuTZ = NULL; + if (errorCode != 0) + { + icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &status); + } + if (errorCode==0 || icuTZ==NULL) + { + /* fallback to default "001" and reset status */ + status = U_ZERO_ERROR; + icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); + } - // Note: wcscmp does an ordinal (byte) comparison. - if (wcscmp(reinterpret_cast(registryStandardName), dynamicTZI.StandardName) == 0) { - // Since we are comparing the *localized* time zone name, it's possible that some languages might use - // the same string for more than one time zone. Thus we need to examine the TZI data in the registry to - // compare the GMT offset (the bias), and the DST transition dates, to ensure it's the same time zone - // as the currently reported one. - REG_TZI_FORMAT registryTziValue; - uprv_memset(®istryTziValue, 0, sizeof(registryTziValue)); - - // Note: RegQueryValueExW wants the size of the buffer in bytes. - DWORD timezoneTziValueSize = sizeof(registryTziValue); - ret = RegQueryValueExW(hKeyTimeZoneSubKey, L"TZI", nullptr, ®istryValueType, - reinterpret_cast(®istryTziValue), &timezoneTziValueSize); - - if (ret == ERROR_SUCCESS) { - if ((dynamicTZI.Bias == registryTziValue.Bias) && - (memcmp((const void *)&dynamicTZI.StandardDate, (const void *)®istryTziValue.StandardDate, sizeof(SYSTEMTIME)) == 0) && - (memcmp((const void *)&dynamicTZI.DaylightDate, (const void *)®istryTziValue.DaylightDate, sizeof(SYSTEMTIME)) == 0)) + if(U_SUCCESS(status)) + { + int index=0; + while (! (*icuTZ == '\0' || *icuTZ ==' ')) { - // We found a matching time zone. - windowsTimeZoneName = timezoneSubKeyName; - break; + tmpid[index++]=(char)(*icuTZ++); /* safe to assume 'char' is ASCII compatible on windows */ } + tmpid[index]='\0'; + tryPreVistaFallback = FALSE; } } - RegCloseKey(hKeyTimeZoneSubKey); - hKeyTimeZoneSubKey = nullptr; + ures_close(winTZ); } + } - if (hKeyTimeZoneSubKey != nullptr) { - RegCloseKey(hKeyTimeZoneSubKey); - } - if (hKeyAllTimeZones != nullptr) { - RegCloseKey(hKeyAllTimeZones); + if(tryPreVistaFallback) + { + HKEY hZonesKey; + DWORD dwIndex; + DWORD dwNameSize; + CHAR szKeyName[MAX_LENGTH_ID]; + CHAR tmp[256]; + UBool idFound = FALSE; + + /* Open the registry key containing the list of time zones */ + result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, + TZ_REGKEY, + 0, + KEY_ENUMERATE_SUB_KEYS, + &hZonesKey); + if (result != ERROR_SUCCESS) + { + return icuid; } -#endif // U_PLATFORM_HAS_WINUWP_API - } - CharString winTZ; - UErrorCode status = U_ZERO_ERROR; - winTZ.appendInvariantChars(UnicodeString(true, windowsTimeZoneName, -1), status); + /* Enumerate it */ + for (dwIndex = 0;; dwIndex++) + { + dwNameSize = sizeof(szKeyName); + result = RegEnumKeyExA(hZonesKey, + dwIndex, + szKeyName, + &dwNameSize, + NULL, + NULL, + NULL, + NULL); + // if (lError != ERROR_SUCCESS && lError != ERROR_MORE_DATA) + if (result == ERROR_NO_MORE_ITEMS) + { + break; + } - // Map Windows Timezone name (non-localized) to ICU timezone ID (~ Olson timezone id). - StackUResourceBundle winTZBundle; - ures_openDirectFillIn(winTZBundle.getAlias(), nullptr, "windowsZones", &status); - ures_getByKey(winTZBundle.getAlias(), "mapTimezones", winTZBundle.getAlias(), &status); - ures_getByKey(winTZBundle.getAlias(), winTZ.data(), winTZBundle.getAlias(), &status); + result = getTZI(szKeyName, &tziReg); + + if (result == ERROR_SUCCESS) + { + /* Windows alters the DaylightBias in some situations. + Using the bias and the rules suffices, so overwrite + these unreliable fields. */ + tziKey.standardBias = tziReg.standardBias; + tziKey.daylightBias = tziReg.daylightBias; + + if (uprv_memcmp((char*)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) + { + const UChar* icuTZ = NULL; + UResourceBundle* winTZ = ures_getByKey(bundle, szKeyName, NULL, &status); + if (errorCode != 0) + { + icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &status); + } + if (errorCode==0 || icuTZ==NULL) + { + /* fallback to default "001" and reset status */ + status = U_ZERO_ERROR; + icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); + } - if (U_FAILURE(status)) { - return nullptr; - } - - // Note: Since the ISO 3166 country/region codes are all invariant ASCII chars, we can - // directly downcast from wchar_t to do the conversion. - // We could call the A version of the GetGeoInfo API, but that would be slightly slower than calling the W API, - // as the A version of the API will end up calling MultiByteToWideChar anyways internally. - wchar_t regionCodeW[3] = {}; - char regionCode[3] = {}; // 2 letter ISO 3166 country/region code made entirely of invariant chars. - int geoId = GetUserGeoID(GEOCLASS_NATION); - int regionCodeLen = GetGeoInfoW(geoId, GEO_ISO2, regionCodeW, UPRV_LENGTHOF(regionCodeW), 0); - - const char16_t *icuTZ16 = nullptr; - int32_t tzListLen = 0; - - if (regionCodeLen != 0) { - for (int i = 0; i < UPRV_LENGTHOF(regionCodeW); i++) { - regionCode[i] = static_cast(regionCodeW[i]); + if (U_SUCCESS(status)) + { + idFound = TRUE; + + /* tmpid buffer holds the ICU timezone ID corresponding to the timezone ID from Windows. + * If none is found, tmpid buffer will contain a fallback ID (i.e. the time zone ID matching + * the current time zone information) + */ + if (idFound || tmpid[0] == 0) + { + /* if icuTZ has more than one city, take only the first (i.e. terminate icuTZ at first space) */ + int index=0; + while (! (*icuTZ == '\0' || *icuTZ ==' ')) + { + tmpid[index++]=(char)(*icuTZ++); /* safe to assume 'char' is ASCII compatible on windows */ + } + tmpid[index]='\0'; + } + } + ures_close(winTZ); + } + } + if (idFound) + { + break; + } } - icuTZ16 = ures_getStringByKey(winTZBundle.getAlias(), regionCode, &tzListLen, &status); - } - if (regionCodeLen == 0 || U_FAILURE(status)) { - // fallback to default "001" (world) - status = U_ZERO_ERROR; - icuTZ16 = ures_getStringByKey(winTZBundle.getAlias(), "001", &tzListLen, &status); + RegCloseKey(hZonesKey); } - // Note: We want the first entry in the string returned by ures_getStringByKey. - // However this string can be a space delimited list of timezones: - // Ex: "America/New_York America/Detroit America/Indiana/Petersburg ..." - // We need to stop at the first space, so we pass tzLen (instead of tzListLen) to appendInvariantChars below. - int32_t tzLen = 0; - if (tzListLen > 0) { - while (!(icuTZ16[tzLen] == u'\0' || icuTZ16[tzLen] == u' ')) { - tzLen++; + /* + * Copy the timezone ID to icuid to be returned. + */ + if (tmpid[0] != 0) + { + len = uprv_strlen(tmpid); + icuid = (char*)uprv_calloc(len + 1, sizeof(char)); + if (icuid != NULL) + { + uprv_strcpy(icuid, tmpid); } } - // Note: cloneData returns nullptr if the status is a failure, so this - // will return nullptr if the above look-up fails. - CharString icuTZStr; - return icuTZStr.appendInvariantChars(icuTZ16, tzLen, status).cloneData(status); + ures_close(bundle); + + return icuid; } -U_NAMESPACE_END -#endif /* U_PLATFORM_USES_ONLY_WIN32_API */ +#endif /* U_PLATFORM_USES_ONLY_WIN32_API && (U_PLATFORM_HAS_WINUWP_API == 0) */ diff --git a/intl/icu/source/data/locales/en.txt b/intl/icu/source/data/locales/en.txt index 5d7c9d5a80..3748344f6d 100644 --- a/intl/icu/source/data/locales/en.txt +++ b/intl/icu/source/data/locales/en.txt @@ -913,7 +913,7 @@ en{ Hms{"HH:mm:ss"} Hmsv{"HH:mm:ss v"} Hmv{"HH:mm v"} - Hv{"HH'h' v"} + Hv{"HH v"} M{"L"} MEd{"E, M/d"} MMM{"LLL"} diff --git a/intl/icu/source/i18n/windtfmt.cpp b/intl/icu/source/i18n/windtfmt.cpp index f1d5c25f3e..7dbf7a7852 100644 --- a/intl/icu/source/i18n/windtfmt.cpp +++ b/intl/icu/source/i18n/windtfmt.cpp @@ -30,9 +30,7 @@ #include "unicode/timezone.h" #include "unicode/utmscale.h" -#include "charstr.h" #include "cmemory.h" -#include "ulocimp.h" #include "uresimp.h" #include "windtfmt.h" #include "wintzimpl.h" @@ -46,7 +44,6 @@ # define NOIME # define NOMCX #include -#include U_NAMESPACE_BEGIN @@ -59,13 +56,13 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Win32DateFormat) UnicodeString* Win32DateFormat::getTimeDateFormat(const Calendar *cal, const Locale *locale, UErrorCode &status) const { - UnicodeString *result = nullptr; + UnicodeString *result = NULL; const char *type = cal->getType(); const char *base = locale->getBaseName(); UResourceBundle *topBundle = ures_open((char *) 0, base, &status); - UResourceBundle *calBundle = ures_getByKey(topBundle, "calendar", nullptr, &status); - UResourceBundle *typBundle = ures_getByKeyWithFallback(calBundle, type, nullptr, &status); - UResourceBundle *patBundle = ures_getByKeyWithFallback(typBundle, "DateTimePatterns", nullptr, &status); + UResourceBundle *calBundle = ures_getByKey(topBundle, "calendar", NULL, &status); + UResourceBundle *typBundle = ures_getByKeyWithFallback(calBundle, type, NULL, &status); + UResourceBundle *patBundle = ures_getByKeyWithFallback(typBundle, "DateTimePatterns", NULL, &status); if (status == U_MISSING_RESOURCE_ERROR) { status = U_ZERO_ERROR; @@ -74,7 +71,7 @@ UnicodeString* Win32DateFormat::getTimeDateFormat(const Calendar *cal, const Loc } if (U_FAILURE(status)) { - static const char16_t defaultPattern[] = {0x007B, 0x0031, 0x007D, 0x0020, 0x007B, 0x0030, 0x007D, 0x0000}; // "{1} {0}" + static const UChar defaultPattern[] = {0x007B, 0x0031, 0x007D, 0x0020, 0x007B, 0x0030, 0x007D, 0x0000}; // "{1} {0}" return new UnicodeString(defaultPattern, UPRV_LENGTHOF(defaultPattern)); } @@ -85,9 +82,9 @@ UnicodeString* Win32DateFormat::getTimeDateFormat(const Calendar *cal, const Loc // Get proper date time format glueIndex = (int32_t)(DateFormat::kDateTimeOffset + (fDateStyle - DateFormat::kDateOffset)); } - const char16_t *resStr = ures_getStringByIndex(patBundle, glueIndex, &resStrLen, &status); + const UChar *resStr = ures_getStringByIndex(patBundle, glueIndex, &resStrLen, &status); - result = new UnicodeString(true, resStr, resStrLen); + result = new UnicodeString(TRUE, resStr, resStrLen); ures_close(patBundle); ures_close(typBundle); @@ -97,82 +94,12 @@ UnicodeString* Win32DateFormat::getTimeDateFormat(const Calendar *cal, const Loc return result; } -// TODO: This is copied in both winnmfmt.cpp and windtfmt.cpp, but really should -// be factored out into a common helper for both. -static UErrorCode GetEquivalentWindowsLocaleName(const Locale& locale, UnicodeString** buffer) -{ - UErrorCode status = U_ZERO_ERROR; - - // Convert from names like "en_CA" and "de_DE@collation=phonebook" to "en-CA" and "de-DE-u-co-phonebk". - CharString asciiBCP47Tag = ulocimp_toLanguageTag(locale.getName(), false, status); - - if (U_SUCCESS(status)) - { - // Need it to be UTF-16, not 8-bit - // TODO: This seems like a good thing for a helper - wchar_t bcp47Tag[LOCALE_NAME_MAX_LENGTH] = {}; - int32_t i; - for (i = 0; i < UPRV_LENGTHOF(bcp47Tag); i++) - { - if (asciiBCP47Tag[i] == '\0') - { - break; - } - else - { - // normally just copy the character - bcp47Tag[i] = static_cast(asciiBCP47Tag[i]); - } - } - - // Ensure it's null terminated - if (i < (UPRV_LENGTHOF(bcp47Tag) - 1)) - { - bcp47Tag[i] = L'\0'; - } - else - { - // Ran out of room. - bcp47Tag[UPRV_LENGTHOF(bcp47Tag) - 1] = L'\0'; - } - - - wchar_t windowsLocaleName[LOCALE_NAME_MAX_LENGTH] = {}; - - // Note: On Windows versions below 10, there is no support for locale name aliases. - // This means that it will fail for locales where ICU has a completely different - // name (like ku vs ckb), and it will also not work for alternate sort locale - // names like "de-DE-u-co-phonebk". - - // TODO: We could add some sort of exception table for cases like ku vs ckb. - - int length = ResolveLocaleName(bcp47Tag, windowsLocaleName, UPRV_LENGTHOF(windowsLocaleName)); - - if (length > 0) - { - *buffer = new UnicodeString(windowsLocaleName); - } - else - { - status = U_UNSUPPORTED_ERROR; - } - } - return status; -} - // TODO: Range-check timeStyle, dateStyle Win32DateFormat::Win32DateFormat(DateFormat::EStyle timeStyle, DateFormat::EStyle dateStyle, const Locale &locale, UErrorCode &status) - : DateFormat(), fDateTimeMsg(nullptr), fTimeStyle(timeStyle), fDateStyle(dateStyle), fLocale(locale), fZoneID(), fWindowsLocaleName(nullptr) + : DateFormat(), fDateTimeMsg(NULL), fTimeStyle(timeStyle), fDateStyle(dateStyle), fLocale(locale), fZoneID() { if (U_SUCCESS(status)) { - GetEquivalentWindowsLocaleName(locale, &fWindowsLocaleName); - // Note: In the previous code, it would look up the LCID for the locale, and if - // the locale was not recognized then it would get an LCID of 0, which is a - // synonym for LOCALE_USER_DEFAULT on Windows. - // If the above method fails, then fWindowsLocaleName will remain as nullptr, and - // then we will pass nullptr to API GetLocaleInfoEx, which is the same as passing - // LOCALE_USER_DEFAULT. - + fLCID = locale.getLCID(); fTZI = NEW_ARRAY(TIME_ZONE_INFORMATION, 1); uprv_memset(fTZI, 0, sizeof(TIME_ZONE_INFORMATION)); adoptCalendar(Calendar::createInstance(locale, status)); @@ -190,18 +117,16 @@ Win32DateFormat::~Win32DateFormat() // delete fCalendar; uprv_free(fTZI); delete fDateTimeMsg; - delete fWindowsLocaleName; } Win32DateFormat &Win32DateFormat::operator=(const Win32DateFormat &other) { - if (this == &other) { return *this; } // self-assignment: no-op // The following handles fCalendar DateFormat::operator=(other); // delete fCalendar; - this->fDateTimeMsg = other.fDateTimeMsg == nullptr ? nullptr : new UnicodeString(*other.fDateTimeMsg); + this->fDateTimeMsg = other.fDateTimeMsg == NULL ? NULL : new UnicodeString(*other.fDateTimeMsg); this->fTimeStyle = other.fTimeStyle; this->fDateStyle = other.fDateStyle; this->fLocale = other.fLocale; @@ -211,12 +136,10 @@ Win32DateFormat &Win32DateFormat::operator=(const Win32DateFormat &other) this->fTZI = NEW_ARRAY(TIME_ZONE_INFORMATION, 1); *this->fTZI = *other.fTZI; - this->fWindowsLocaleName = other.fWindowsLocaleName == nullptr ? nullptr : new UnicodeString(*other.fWindowsLocaleName); - return *this; } -Win32DateFormat *Win32DateFormat::clone() const +Win32DateFormat *Win32DateFormat::clone(void) const { return new Win32DateFormat(*this); } @@ -252,7 +175,7 @@ UnicodeString &Win32DateFormat::format(Calendar &cal, UnicodeString &appendTo, F formatDate(&st_local, date); formatTime(&st_local, time); - if (typeid(cal) != typeid(*fCalendar)) { + if (strcmp(fCalendar->getType(), cal.getType()) != 0) { pattern = getTimeDateFormat(&cal, &fLocale, status); } @@ -273,7 +196,7 @@ void Win32DateFormat::parse(const UnicodeString& /* text */, Calendar& /* cal */ void Win32DateFormat::adoptCalendar(Calendar *newCalendar) { - if (fCalendar == nullptr || typeid(*fCalendar) != typeid(*newCalendar)) { + if (fCalendar == NULL || strcmp(fCalendar->getType(), newCalendar->getType()) != 0) { UErrorCode status = U_ZERO_ERROR; if (fDateStyle != DateFormat::kNone && fTimeStyle != DateFormat::kNone) { @@ -312,26 +235,20 @@ void Win32DateFormat::formatDate(const SYSTEMTIME *st, UnicodeString &appendTo) int result=0; wchar_t stackBuffer[STACK_BUFFER_SIZE]; wchar_t *buffer = stackBuffer; - const wchar_t *localeName = nullptr; - - if (fWindowsLocaleName != nullptr) - { - localeName = reinterpret_cast(toOldUCharPtr(fWindowsLocaleName->getTerminatedBuffer())); - } - result = GetDateFormatEx(localeName, dfFlags[fDateStyle - kDateOffset], st, nullptr, buffer, STACK_BUFFER_SIZE, nullptr); + result = GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, buffer, STACK_BUFFER_SIZE); if (result == 0) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - int newLength = GetDateFormatEx(localeName, dfFlags[fDateStyle - kDateOffset], st, nullptr, nullptr, 0, nullptr); + int newLength = GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, NULL, 0); buffer = NEW_ARRAY(wchar_t, newLength); - GetDateFormatEx(localeName, dfFlags[fDateStyle - kDateOffset], st, nullptr, buffer, newLength, nullptr); + GetDateFormatW(fLCID, dfFlags[fDateStyle - kDateOffset], st, NULL, buffer, newLength); } } - appendTo.append((const char16_t *)buffer, (int32_t) wcslen(buffer)); + appendTo.append((const UChar *)buffer, (int32_t) wcslen(buffer)); if (buffer != stackBuffer) { DELETE_ARRAY(buffer); @@ -345,26 +262,20 @@ void Win32DateFormat::formatTime(const SYSTEMTIME *st, UnicodeString &appendTo) int result; wchar_t stackBuffer[STACK_BUFFER_SIZE]; wchar_t *buffer = stackBuffer; - const wchar_t *localeName = nullptr; - if (fWindowsLocaleName != nullptr) - { - localeName = reinterpret_cast(toOldUCharPtr(fWindowsLocaleName->getTerminatedBuffer())); - } - - result = GetTimeFormatEx(localeName, tfFlags[fTimeStyle], st, nullptr, buffer, STACK_BUFFER_SIZE); + result = GetTimeFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, buffer, STACK_BUFFER_SIZE); if (result == 0) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - int newLength = GetTimeFormatEx(localeName, tfFlags[fTimeStyle], st, nullptr, nullptr, 0); + int newLength = GetTimeFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, NULL, 0); buffer = NEW_ARRAY(wchar_t, newLength); - GetTimeFormatEx(localeName, tfFlags[fTimeStyle], st, nullptr, buffer, newLength); + GetDateFormatW(fLCID, tfFlags[fTimeStyle], st, NULL, buffer, newLength); } } - appendTo.append((const char16_t *)buffer, (int32_t) wcslen(buffer)); + appendTo.append((const UChar *)buffer, (int32_t) wcslen(buffer)); if (buffer != stackBuffer) { DELETE_ARRAY(buffer); @@ -382,7 +293,7 @@ UnicodeString Win32DateFormat::setTimeZoneInfo(TIME_ZONE_INFORMATION *tzi, const zone.getID(icuid); if (! uprv_getWindowsTimeZoneInfo(tzi, icuid.getBuffer(), icuid.length())) { - UBool found = false; + UBool found = FALSE; int32_t ec = TimeZone::countEquivalentIDs(icuid); for (int z = 0; z < ec; z += 1) { @@ -408,3 +319,4 @@ U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */ #endif // U_PLATFORM_USES_ONLY_WIN32_API + diff --git a/intl/icu/source/i18n/windtfmt.h b/intl/icu/source/i18n/windtfmt.h index 0c3f542785..1a8bc1f9e4 100644 --- a/intl/icu/source/i18n/windtfmt.h +++ b/intl/icu/source/i18n/windtfmt.h @@ -124,10 +124,9 @@ class Win32DateFormat : public DateFormat DateFormat::EStyle fTimeStyle; DateFormat::EStyle fDateStyle; Locale fLocale; + int32_t fLCID; UnicodeString fZoneID; TIME_ZONE_INFORMATION *fTZI; - - UnicodeString* fWindowsLocaleName; // Stores the equivalent Windows locale name. }; U_NAMESPACE_END diff --git a/intl/icu/source/i18n/winnmfmt.cpp b/intl/icu/source/i18n/winnmfmt.cpp index a23e3eb8c5..fc1f92fbb0 100644 --- a/intl/icu/source/i18n/winnmfmt.cpp +++ b/intl/icu/source/i18n/winnmfmt.cpp @@ -24,10 +24,8 @@ #include "unicode/locid.h" #include "unicode/ustring.h" -#include "charstr.h" #include "cmemory.h" #include "uassert.h" -#include "ulocimp.h" #include "locmap.h" #ifndef WIN32_LEAN_AND_MEAN @@ -62,161 +60,91 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Win32NumberFormat) * end in ";0" then the return value should be multiplied by 10. * (e.g. "3" => 30, "3;2" => 320) */ -static UINT getGrouping(const wchar_t *grouping) +static UINT getGrouping(const char *grouping) { UINT g = 0; - const wchar_t *s; + const char *s; - for (s = grouping; *s != L'\0'; s += 1) { - if (*s > L'0' && *s < L'9') { - g = g * 10 + (*s - L'0'); - } else if (*s != L';') { + for (s = grouping; *s != '\0'; s += 1) { + if (*s > '0' && *s < '9') { + g = g * 10 + (*s - '0'); + } else if (*s != ';') { break; } } - if (*s != L'0') { + if (*s != '0') { g *= 10; } return g; } -static void getNumberFormat(NUMBERFMTW *fmt, const wchar_t *windowsLocaleName) +static void getNumberFormat(NUMBERFMTW *fmt, int32_t lcid) { - wchar_t buf[10]; + char buf[10]; - GetLocaleInfoEx(windowsLocaleName, LOCALE_RETURN_NUMBER|LOCALE_IDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT)); - GetLocaleInfoEx(windowsLocaleName, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR) &fmt->LeadingZero, sizeof(UINT)); + GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_IDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT)); + GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR) &fmt->LeadingZero, sizeof(UINT)); - GetLocaleInfoEx(windowsLocaleName, LOCALE_SGROUPING, (LPWSTR)buf, 10); + GetLocaleInfoA(lcid, LOCALE_SGROUPING, buf, 10); fmt->Grouping = getGrouping(buf); fmt->lpDecimalSep = NEW_ARRAY(wchar_t, 6); - GetLocaleInfoEx(windowsLocaleName, LOCALE_SDECIMAL, fmt->lpDecimalSep, 6); + GetLocaleInfoW(lcid, LOCALE_SDECIMAL, fmt->lpDecimalSep, 6); fmt->lpThousandSep = NEW_ARRAY(wchar_t, 6); - GetLocaleInfoEx(windowsLocaleName, LOCALE_STHOUSAND, fmt->lpThousandSep, 6); + GetLocaleInfoW(lcid, LOCALE_STHOUSAND, fmt->lpThousandSep, 6); - GetLocaleInfoEx(windowsLocaleName, LOCALE_RETURN_NUMBER|LOCALE_INEGNUMBER, (LPWSTR) &fmt->NegativeOrder, sizeof(UINT)); + GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGNUMBER, (LPWSTR) &fmt->NegativeOrder, sizeof(UINT)); } static void freeNumberFormat(NUMBERFMTW *fmt) { - if (fmt != nullptr) { + if (fmt != NULL) { DELETE_ARRAY(fmt->lpThousandSep); DELETE_ARRAY(fmt->lpDecimalSep); } } -static void getCurrencyFormat(CURRENCYFMTW *fmt, const wchar_t *windowsLocaleName) +static void getCurrencyFormat(CURRENCYFMTW *fmt, int32_t lcid) { - wchar_t buf[10]; + char buf[10]; - GetLocaleInfoEx(windowsLocaleName, LOCALE_RETURN_NUMBER|LOCALE_ICURRDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT)); - GetLocaleInfoEx(windowsLocaleName, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR) &fmt->LeadingZero, sizeof(UINT)); + GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ICURRDIGITS, (LPWSTR) &fmt->NumDigits, sizeof(UINT)); + GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ILZERO, (LPWSTR) &fmt->LeadingZero, sizeof(UINT)); - GetLocaleInfoEx(windowsLocaleName, LOCALE_SMONGROUPING, (LPWSTR)buf, sizeof(buf)); + GetLocaleInfoA(lcid, LOCALE_SMONGROUPING, buf, sizeof(buf)); fmt->Grouping = getGrouping(buf); fmt->lpDecimalSep = NEW_ARRAY(wchar_t, 6); - GetLocaleInfoEx(windowsLocaleName, LOCALE_SMONDECIMALSEP, fmt->lpDecimalSep, 6); + GetLocaleInfoW(lcid, LOCALE_SMONDECIMALSEP, fmt->lpDecimalSep, 6); fmt->lpThousandSep = NEW_ARRAY(wchar_t, 6); - GetLocaleInfoEx(windowsLocaleName, LOCALE_SMONTHOUSANDSEP, fmt->lpThousandSep, 6); + GetLocaleInfoW(lcid, LOCALE_SMONTHOUSANDSEP, fmt->lpThousandSep, 6); - GetLocaleInfoEx(windowsLocaleName, LOCALE_RETURN_NUMBER|LOCALE_INEGCURR, (LPWSTR) &fmt->NegativeOrder, sizeof(UINT)); - GetLocaleInfoEx(windowsLocaleName, LOCALE_RETURN_NUMBER|LOCALE_ICURRENCY, (LPWSTR) &fmt->PositiveOrder, sizeof(UINT)); + GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_INEGCURR, (LPWSTR) &fmt->NegativeOrder, sizeof(UINT)); + GetLocaleInfoW(lcid, LOCALE_RETURN_NUMBER|LOCALE_ICURRENCY, (LPWSTR) &fmt->PositiveOrder, sizeof(UINT)); fmt->lpCurrencySymbol = NEW_ARRAY(wchar_t, 8); - GetLocaleInfoEx(windowsLocaleName, LOCALE_SCURRENCY, (LPWSTR) fmt->lpCurrencySymbol, 8); + GetLocaleInfoW(lcid, LOCALE_SCURRENCY, (LPWSTR) fmt->lpCurrencySymbol, 8); } static void freeCurrencyFormat(CURRENCYFMTW *fmt) { - if (fmt != nullptr) { + if (fmt != NULL) { DELETE_ARRAY(fmt->lpCurrencySymbol); DELETE_ARRAY(fmt->lpThousandSep); DELETE_ARRAY(fmt->lpDecimalSep); } } -// TODO: This is copied in both winnmfmt.cpp and windtfmt.cpp, but really should -// be factored out into a common helper for both. -static UErrorCode GetEquivalentWindowsLocaleName(const Locale& locale, UnicodeString** buffer) -{ - UErrorCode status = U_ZERO_ERROR; - - // Convert from names like "en_CA" and "de_DE@collation=phonebook" to "en-CA" and "de-DE-u-co-phonebk". - CharString asciiBCP47Tag = ulocimp_toLanguageTag(locale.getName(), false, status); - - if (U_SUCCESS(status)) - { - // Need it to be UTF-16, not 8-bit - // TODO: This seems like a good thing for a helper - wchar_t bcp47Tag[LOCALE_NAME_MAX_LENGTH] = {}; - int32_t i; - for (i = 0; i < UPRV_LENGTHOF(bcp47Tag); i++) - { - if (asciiBCP47Tag[i] == '\0') - { - break; - } - else - { - // normally just copy the character - bcp47Tag[i] = static_cast(asciiBCP47Tag[i]); - } - } - - // Ensure it's null terminated - if (i < (UPRV_LENGTHOF(bcp47Tag) - 1)) - { - bcp47Tag[i] = L'\0'; - } - else - { - // Ran out of room. - bcp47Tag[UPRV_LENGTHOF(bcp47Tag) - 1] = L'\0'; - } - - - wchar_t windowsLocaleName[LOCALE_NAME_MAX_LENGTH] = {}; - - // Note: On Windows versions below 10, there is no support for locale name aliases. - // This means that it will fail for locales where ICU has a completely different - // name (like ku vs ckb), and it will also not work for alternate sort locale - // names like "de-DE-u-co-phonebk". - - // TODO: We could add some sort of exception table for cases like ku vs ckb. - - int length = ResolveLocaleName(bcp47Tag, windowsLocaleName, UPRV_LENGTHOF(windowsLocaleName)); - - if (length > 0) - { - *buffer = new UnicodeString(windowsLocaleName); - } - else - { - status = U_UNSUPPORTED_ERROR; - } - } - return status; -} - Win32NumberFormat::Win32NumberFormat(const Locale &locale, UBool currency, UErrorCode &status) - : NumberFormat(), fCurrency(currency), fFormatInfo(nullptr), fFractionDigitsSet(false), fWindowsLocaleName(nullptr) + : NumberFormat(), fCurrency(currency), fFormatInfo(NULL), fFractionDigitsSet(FALSE) { if (!U_FAILURE(status)) { fLCID = locale.getLCID(); - GetEquivalentWindowsLocaleName(locale, &fWindowsLocaleName); - // Note: In the previous code, it would look up the LCID for the locale, and if - // the locale was not recognized then it would get an LCID of 0, which is a - // synonym for LOCALE_USER_DEFAULT on Windows. - // If the above method fails, then fWindowsLocaleName will remain as nullptr, and - // then we will pass nullptr to API GetLocaleInfoEx, which is the same as passing - // LOCALE_USER_DEFAULT. // Resolve actual locale to be used later UErrorCode tmpsts = U_ZERO_ERROR; @@ -227,19 +155,12 @@ Win32NumberFormat::Win32NumberFormat(const Locale &locale, UBool currency, UErro fLocale = Locale((const char*)tmpLocID); } - const wchar_t *localeName = nullptr; - - if (fWindowsLocaleName != nullptr) - { - localeName = reinterpret_cast(toOldUCharPtr(fWindowsLocaleName->getTerminatedBuffer())); - } - fFormatInfo = (FormatInfo*)uprv_malloc(sizeof(FormatInfo)); if (fCurrency) { - getCurrencyFormat(&fFormatInfo->currency, localeName); + getCurrencyFormat(&fFormatInfo->currency, fLCID); } else { - getNumberFormat(&fFormatInfo->number, localeName); + getNumberFormat(&fFormatInfo->number, fLCID); } } } @@ -247,7 +168,7 @@ Win32NumberFormat::Win32NumberFormat(const Locale &locale, UBool currency, UErro Win32NumberFormat::Win32NumberFormat(const Win32NumberFormat &other) : NumberFormat(other), fFormatInfo((FormatInfo*)uprv_malloc(sizeof(FormatInfo))) { - if (fFormatInfo != nullptr) { + if (fFormatInfo != NULL) { uprv_memset(fFormatInfo, 0, sizeof(*fFormatInfo)); } *this = other; @@ -255,7 +176,7 @@ Win32NumberFormat::Win32NumberFormat(const Win32NumberFormat &other) Win32NumberFormat::~Win32NumberFormat() { - if (fFormatInfo != nullptr) { + if (fFormatInfo != NULL) { if (fCurrency) { freeCurrencyFormat(&fFormatInfo->currency); } else { @@ -264,39 +185,29 @@ Win32NumberFormat::~Win32NumberFormat() uprv_free(fFormatInfo); } - delete fWindowsLocaleName; } Win32NumberFormat &Win32NumberFormat::operator=(const Win32NumberFormat &other) { - if (this == &other) { return *this; } // self-assignment: no-op NumberFormat::operator=(other); this->fCurrency = other.fCurrency; this->fLocale = other.fLocale; this->fLCID = other.fLCID; this->fFractionDigitsSet = other.fFractionDigitsSet; - this->fWindowsLocaleName = other.fWindowsLocaleName == nullptr ? nullptr : new UnicodeString(*other.fWindowsLocaleName); - const wchar_t *localeName = nullptr; - - if (fWindowsLocaleName != nullptr) - { - localeName = reinterpret_cast(toOldUCharPtr(fWindowsLocaleName->getTerminatedBuffer())); - } - if (fCurrency) { freeCurrencyFormat(&fFormatInfo->currency); - getCurrencyFormat(&fFormatInfo->currency, localeName); + getCurrencyFormat(&fFormatInfo->currency, fLCID); } else { freeNumberFormat(&fFormatInfo->number); - getNumberFormat(&fFormatInfo->number, localeName); + getNumberFormat(&fFormatInfo->number, fLCID); } return *this; } -Win32NumberFormat *Win32NumberFormat::clone() const +Win32NumberFormat *Win32NumberFormat::clone(void) const { return new Win32NumberFormat(*this); } @@ -326,13 +237,13 @@ void Win32NumberFormat::parse(const UnicodeString& text, Formattable& result, Pa } void Win32NumberFormat::setMaximumFractionDigits(int32_t newValue) { - fFractionDigitsSet = true; + fFractionDigitsSet = TRUE; NumberFormat::setMaximumFractionDigits(newValue); } void Win32NumberFormat::setMinimumFractionDigits(int32_t newValue) { - fFractionDigitsSet = true; + fFractionDigitsSet = TRUE; NumberFormat::setMinimumFractionDigits(newValue); } @@ -345,7 +256,7 @@ UnicodeString &Win32NumberFormat::format(int32_t numDigits, UnicodeString &appen nBuffer[0] = 0x0000; - /* Due to the arguments causing a result to be <= 23 characters (+2 for nullptr and minus), + /* Due to the arguments causing a result to be <= 23 characters (+2 for NULL and minus), we don't need to reallocate the buffer. */ va_start(args, fmt); result = _vsnwprintf(nBuffer, STACK_BUFFER_SIZE, fmt, args); @@ -361,7 +272,7 @@ UnicodeString &Win32NumberFormat::format(int32_t numDigits, UnicodeString &appen newLength = _vscwprintf(fmt, args); va_end(args); - nBuffer = NEW_ARRAY(char16_t, newLength + 1); + nBuffer = NEW_ARRAY(UChar, newLength + 1); va_start(args, fmt); result = _vsnwprintf(nBuffer, newLength + 1, fmt, args); @@ -391,13 +302,6 @@ UnicodeString &Win32NumberFormat::format(int32_t numDigits, UnicodeString &appen formatInfo = *fFormatInfo; buffer[0] = 0x0000; - const wchar_t *localeName = nullptr; - - if (fWindowsLocaleName != nullptr) - { - localeName = reinterpret_cast(toOldUCharPtr(fWindowsLocaleName->getTerminatedBuffer())); - } - if (fCurrency) { if (fFractionDigitsSet) { formatInfo.currency.NumDigits = (UINT) numDigits; @@ -407,17 +311,17 @@ UnicodeString &Win32NumberFormat::format(int32_t numDigits, UnicodeString &appen formatInfo.currency.Grouping = 0; } - result = GetCurrencyFormatEx(localeName, 0, nBuffer, &formatInfo.currency, buffer, STACK_BUFFER_SIZE); + result = GetCurrencyFormatW(fLCID, 0, nBuffer, &formatInfo.currency, buffer, STACK_BUFFER_SIZE); if (result == 0) { DWORD lastError = GetLastError(); if (lastError == ERROR_INSUFFICIENT_BUFFER) { - int newLength = GetCurrencyFormatEx(localeName, 0, nBuffer, &formatInfo.currency, nullptr, 0); + int newLength = GetCurrencyFormatW(fLCID, 0, nBuffer, &formatInfo.currency, NULL, 0); buffer = NEW_ARRAY(wchar_t, newLength); buffer[0] = 0x0000; - GetCurrencyFormatEx(localeName, 0, nBuffer, &formatInfo.currency, buffer, newLength); + GetCurrencyFormatW(fLCID, 0, nBuffer, &formatInfo.currency, buffer, newLength); } } } else { @@ -429,20 +333,20 @@ UnicodeString &Win32NumberFormat::format(int32_t numDigits, UnicodeString &appen formatInfo.number.Grouping = 0; } - result = GetNumberFormatEx(localeName, 0, nBuffer, &formatInfo.number, buffer, STACK_BUFFER_SIZE); + result = GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, buffer, STACK_BUFFER_SIZE); if (result == 0) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - int newLength = GetNumberFormatEx(localeName, 0, nBuffer, &formatInfo.number, nullptr, 0); + int newLength = GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, NULL, 0); buffer = NEW_ARRAY(wchar_t, newLength); buffer[0] = 0x0000; - GetNumberFormatEx(localeName, 0, nBuffer, &formatInfo.number, buffer, newLength); + GetNumberFormatW(fLCID, 0, nBuffer, &formatInfo.number, buffer, newLength); } } } - appendTo.append((char16_t *)buffer, (int32_t) wcslen(buffer)); + appendTo.append((UChar *)buffer, (int32_t) wcslen(buffer)); if (buffer != stackBuffer) { DELETE_ARRAY(buffer); diff --git a/intl/icu/source/i18n/winnmfmt.h b/intl/icu/source/i18n/winnmfmt.h index 1cf87f4d2c..71ccfff0be 100644 --- a/intl/icu/source/i18n/winnmfmt.h +++ b/intl/icu/source/i18n/winnmfmt.h @@ -154,8 +154,6 @@ class Win32NumberFormat : public NumberFormat int32_t fLCID; FormatInfo *fFormatInfo; UBool fFractionDigitsSet; - - UnicodeString* fWindowsLocaleName; // Stores the equivalent Windows locale name. }; U_NAMESPACE_END diff --git a/intl/icu/source/python/icutools/databuilder/filtration.py b/intl/icu/source/python/icutools/databuilder/filtration.py index 66e6d637e3..08b69a7dd1 100644 --- a/intl/icu/source/python/icutools/databuilder/filtration.py +++ b/intl/icu/source/python/icutools/databuilder/filtration.py @@ -398,7 +398,7 @@ def make_requests(self): new_requests = [] i = 0 - for rules, filter_files in list(unique_rules.items()): + for rules, filter_files in unique_rules.items(): base_filter_file = filter_files[0] new_requests += [ PrintFileRequest( @@ -451,7 +451,7 @@ def _apply_resource_filters(all_requests, config, io): # Add the filter generation requests to the beginning so that by default # they are made before genrb gets run (order is required by windirect) new_requests = [] - for filter_info in list(collected.values()): + for filter_info in collected.values(): new_requests += filter_info.make_requests() new_requests += all_requests return new_requests diff --git a/intl/icu/source/python/icutools/databuilder/request_types.py b/intl/icu/source/python/icutools/databuilder/request_types.py index c3a804ba2b..55fcb2564d 100644 --- a/intl/icu/source/python/icutools/databuilder/request_types.py +++ b/intl/icu/source/python/icutools/databuilder/request_types.py @@ -106,7 +106,7 @@ def apply_file_filter(self, filter): def _del_at(self, i): del self.input_files[i] - for _, v in list(self.format_with.items()): + for _, v in self.format_with.items(): if isinstance(v, list): assert len(v) == len(self.input_files) + 1 del v[i] @@ -177,7 +177,7 @@ def _del_at(self, i): super(RepeatedExecutionRequest, self)._del_at(i) del self.output_files[i] del self.specific_dep_files[i] - for _, v in list(self.repeat_with.items()): + for _, v in self.repeat_with.items(): if isinstance(v, list): del v[i] @@ -222,7 +222,7 @@ def flatten(self, config, all_requests, common_vars): def _del_at(self, i): super(RepeatedOrSingleExecutionRequest, self)._del_at(i) del self.output_files[i] - for _, v in list(self.repeat_with.items()): + for _, v in self.repeat_with.items(): if isinstance(v, list): del v[i] diff --git a/intl/icu/source/python/icutools/databuilder/utils.py b/intl/icu/source/python/icutools/databuilder/utils.py index dcbb5df116..3d53d18fae 100644 --- a/intl/icu/source/python/icutools/databuilder/utils.py +++ b/intl/icu/source/python/icutools/databuilder/utils.py @@ -46,7 +46,7 @@ def get_local_dirname(dirname): return LOCAL_DIRNAME_SUBSTITUTIONS[variable] + dirname[sep_idx:] print( "Error: Local directory must be absolute, or relative to one of: " + - (", ".join("$%s" % v for v in list(LOCAL_DIRNAME_SUBSTITUTIONS.keys()))), + (", ".join("$%s" % v for v in LOCAL_DIRNAME_SUBSTITUTIONS.keys())), file=sys.stderr ) exit(1) @@ -76,13 +76,13 @@ def concat_dicts(*dicts): def repeated_execution_request_looper(request): # dictionary of lists to list of dictionaries: ld = [ - dict(list(zip(request.repeat_with, t))) - for t in zip(*list(request.repeat_with.values())) + dict(zip(request.repeat_with, t)) + for t in zip(*request.repeat_with.values()) ] if not ld: # No special options given in repeat_with ld = [{} for _ in range(len(request.input_files))] - return list(zip(ld, request.specific_dep_files, request.input_files, request.output_files)) + return zip(ld, request.specific_dep_files, request.input_files, request.output_files) def format_single_request_command(request, cmd_template, common_vars): From 29ff1d2daa2e18091c6fed00e671f60fda125e0a Mon Sep 17 00:00:00 2001 From: wuggy Date: Thu, 21 May 2026 12:48:28 -0700 Subject: [PATCH 2/2] ffmpreg vc2017 fix? --- media/ffvpx/config.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/media/ffvpx/config.h b/media/ffvpx/config.h index 91853a31f4..2f61ec4788 100644 --- a/media/ffvpx/config.h +++ b/media/ffvpx/config.h @@ -30,6 +30,10 @@ #undef HAVE_LIBC_MSVCRT #define HAVE_LIBC_MSVCRT 0 #endif +#if defined(_MSC_VER) +#undef av_restrict +#define av_restrict __restrict +#endif #elif defined(XP_DARWIN) #if defined(__aarch64__) #include "config_darwin_aarch64.h"