mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 12:04:51 +00:00
[KERNEL32] Support Japanese calendar (#1482)
Implement the Japanese calendar in kernel32. Locale info and date formatting. CORE-15920
This commit is contained in:
parent
a008bf8ef2
commit
15537c3bbe
5 changed files with 465 additions and 0 deletions
|
@ -76,6 +76,7 @@ list(APPEND SOURCE
|
||||||
winnls/string/digitmap.c
|
winnls/string/digitmap.c
|
||||||
winnls/string/fold.c
|
winnls/string/fold.c
|
||||||
winnls/string/format_msg.c
|
winnls/string/format_msg.c
|
||||||
|
winnls/string/japanese.c
|
||||||
winnls/string/lang.c
|
winnls/string/lang.c
|
||||||
winnls/string/lcformat.c
|
winnls/string/lcformat.c
|
||||||
winnls/string/lstring.c
|
winnls/string/lstring.c
|
||||||
|
|
229
dll/win32/kernel32/winnls/string/japanese.c
Normal file
229
dll/win32/kernel32/winnls/string/japanese.c
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Japanese era support
|
||||||
|
* COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
|
*/
|
||||||
|
#include <k32.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
#include "japanese.h"
|
||||||
|
|
||||||
|
#define JAPANESE_ERA_MAX 16
|
||||||
|
|
||||||
|
/* #define DONT_USE_REGISTRY */
|
||||||
|
|
||||||
|
static DWORD s_JapaneseEraCount = 0;
|
||||||
|
static JAPANESE_ERA s_JapaneseEraTable[JAPANESE_ERA_MAX]
|
||||||
|
#ifdef DONT_USE_REGISTRY
|
||||||
|
=
|
||||||
|
{
|
||||||
|
{1868, 1, 1, {0x660E, 0x6CBB}, {0x660E, 0}, L"Meiji", L"M"},
|
||||||
|
{1912, 7, 30, {0x5927, 0x6B63}, {0x5927, 0}, L"Taisho", L"T"},
|
||||||
|
{1926, 12, 25, {0x662D, 0x548C}, {0x662D, 0}, L"Showa", L"S"},
|
||||||
|
{1989, 1, 8, {0x5E73, 0x6210}, {0x5E73, 0}, L"Heisei", L"H"},
|
||||||
|
{2019, 5, 1, {0x4EE4, 0x548C}, {0x4EE4, 0}, L"Reiwa", L"R"},
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName);
|
||||||
|
|
||||||
|
BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
|
||||||
|
LPWSTR szValueName, ULONG valueNameSize,
|
||||||
|
LPWSTR szValueData, ULONG valueDataSize);
|
||||||
|
|
||||||
|
static INT JapaneseEra_Compare(const void *e1, const void *e2)
|
||||||
|
{
|
||||||
|
PCJAPANESE_ERA pEra1 = (PCJAPANESE_ERA)e1;
|
||||||
|
PCJAPANESE_ERA pEra2 = (PCJAPANESE_ERA)e2;
|
||||||
|
if (pEra1->wYear < pEra2->wYear)
|
||||||
|
return -1;
|
||||||
|
if (pEra1->wYear > pEra2->wYear)
|
||||||
|
return 1;
|
||||||
|
if (pEra1->wMonth < pEra2->wMonth)
|
||||||
|
return -1;
|
||||||
|
if (pEra1->wMonth > pEra2->wMonth)
|
||||||
|
return 1;
|
||||||
|
if (pEra1->wDay < pEra2->wDay)
|
||||||
|
return -1;
|
||||||
|
if (pEra1->wDay > pEra2->wDay)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SEE ALSO:
|
||||||
|
* https://en.wikipedia.org/wiki/Japanese_era_name
|
||||||
|
* https://docs.microsoft.com/en-us/windows/desktop/Intl/era-handling-for-the-japanese-calendar
|
||||||
|
*/
|
||||||
|
static PCJAPANESE_ERA JapaneseEra_Load(DWORD *pdwCount)
|
||||||
|
{
|
||||||
|
#ifndef DONT_USE_REGISTRY
|
||||||
|
HANDLE KeyHandle = NULL;
|
||||||
|
DWORD dwIndex;
|
||||||
|
WCHAR szName[128], szValue[128];
|
||||||
|
JAPANESE_ERA *pEntry;
|
||||||
|
LPWSTR pch1, pch2, pch3, pch4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ASSERT(pdwCount != NULL);
|
||||||
|
|
||||||
|
/* return cache if any */
|
||||||
|
if (s_JapaneseEraCount != 0)
|
||||||
|
{
|
||||||
|
*pdwCount = s_JapaneseEraCount;
|
||||||
|
return s_JapaneseEraTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DONT_USE_REGISTRY
|
||||||
|
s_JapaneseEraCount = ARRAYSIZE(s_JapaneseEraTable);
|
||||||
|
#else
|
||||||
|
/* init */
|
||||||
|
*pdwCount = 0;
|
||||||
|
RtlZeroMemory(&s_JapaneseEraTable, sizeof(s_JapaneseEraTable));
|
||||||
|
|
||||||
|
/* open registry key */
|
||||||
|
KeyHandle = NLS_RegOpenKey(NULL, L"\\Registry\\Machine\\System\\"
|
||||||
|
L"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese\\Eras");
|
||||||
|
if (!KeyHandle)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* for all values */
|
||||||
|
for (dwIndex = 0; dwIndex < JAPANESE_ERA_MAX; ++dwIndex)
|
||||||
|
{
|
||||||
|
pEntry = &s_JapaneseEraTable[dwIndex];
|
||||||
|
|
||||||
|
/* get name and data */
|
||||||
|
if (!NLS_RegEnumValue(KeyHandle, dwIndex, szName, sizeof(szName),
|
||||||
|
szValue, sizeof(szValue)))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split fields */
|
||||||
|
pch1 = szName;
|
||||||
|
pch2 = wcschr(pch1, L' ');
|
||||||
|
if (pch2 == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pch2++ = UNICODE_NULL;
|
||||||
|
|
||||||
|
pch3 = wcschr(pch2, L' ');
|
||||||
|
if (pch3 == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pch3++ = UNICODE_NULL;
|
||||||
|
|
||||||
|
pEntry->wYear = _wtoi(pch1);
|
||||||
|
pEntry->wMonth = _wtoi(pch2);
|
||||||
|
pEntry->wDay = _wtoi(pch3);
|
||||||
|
if (pEntry->wYear == 0 || pEntry->wMonth == 0 || pEntry->wDay == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split fields */
|
||||||
|
pch1 = szValue;
|
||||||
|
pch2 = wcschr(pch1, L'_');
|
||||||
|
if (pch2 == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pch2++ = UNICODE_NULL;
|
||||||
|
|
||||||
|
pch3 = wcschr(pch2, L'_');
|
||||||
|
if (pch3 == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pch3++ = UNICODE_NULL;
|
||||||
|
|
||||||
|
pch4 = wcschr(pch3, L'_');
|
||||||
|
if (pch4 == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*pch4++ = UNICODE_NULL;
|
||||||
|
|
||||||
|
/* store */
|
||||||
|
RtlStringCbCopyW(pEntry->szEraName, sizeof(pEntry->szEraName), pch1);
|
||||||
|
RtlStringCbCopyW(pEntry->szEraAbbrev, sizeof(pEntry->szEraAbbrev), pch2);
|
||||||
|
RtlStringCbCopyW(pEntry->szEnglishEraName, sizeof(pEntry->szEnglishEraName), pch3);
|
||||||
|
RtlStringCbCopyW(pEntry->szEnglishEraAbbrev, sizeof(pEntry->szEnglishEraAbbrev), pch4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close key */
|
||||||
|
NtClose(KeyHandle);
|
||||||
|
|
||||||
|
/* sort */
|
||||||
|
qsort(s_JapaneseEraTable, s_JapaneseEraCount, sizeof(JAPANESE_ERA),
|
||||||
|
JapaneseEra_Compare);
|
||||||
|
|
||||||
|
/* make cache */
|
||||||
|
s_JapaneseEraCount = dwIndex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*pdwCount = s_JapaneseEraCount;
|
||||||
|
|
||||||
|
return s_JapaneseEraTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL JapaneseEra_ToSystemTime(PCJAPANESE_ERA pEra, LPSYSTEMTIME pst)
|
||||||
|
{
|
||||||
|
ASSERT(pEra != NULL);
|
||||||
|
ASSERT(pst != NULL);
|
||||||
|
|
||||||
|
ZeroMemory(pst, sizeof(*pst));
|
||||||
|
pst->wYear = pEra->wYear;
|
||||||
|
pst->wMonth = pEra->wMonth;
|
||||||
|
pst->wDay = pEra->wDay;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PCJAPANESE_ERA JapaneseEra_Find(const SYSTEMTIME *pst OPTIONAL)
|
||||||
|
{
|
||||||
|
DWORD dwIndex, dwCount = 0;
|
||||||
|
PCJAPANESE_ERA pTable, pEntry, pPrevEntry = NULL;
|
||||||
|
SYSTEMTIME st1, st2;
|
||||||
|
FILETIME ft1, ft2;
|
||||||
|
LONG nCompare;
|
||||||
|
|
||||||
|
/* pst --> ft1 */
|
||||||
|
if (pst == NULL)
|
||||||
|
{
|
||||||
|
GetLocalTime(&st1);
|
||||||
|
pst = &st1;
|
||||||
|
}
|
||||||
|
SystemTimeToFileTime(pst, &ft1);
|
||||||
|
|
||||||
|
/* load era table */
|
||||||
|
pTable = JapaneseEra_Load(&dwCount);
|
||||||
|
if (pTable == NULL || dwCount == 0 || dwCount > JAPANESE_ERA_MAX)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for all eras */
|
||||||
|
for (dwIndex = 0; dwIndex < dwCount; dwIndex++)
|
||||||
|
{
|
||||||
|
pEntry = &pTable[dwIndex];
|
||||||
|
|
||||||
|
/* pEntry --> st2 --> ft2 */
|
||||||
|
JapaneseEra_ToSystemTime(pEntry, &st2);
|
||||||
|
SystemTimeToFileTime(&st2, &ft2);
|
||||||
|
|
||||||
|
/* ft1 <=> ft2 */
|
||||||
|
nCompare = CompareFileTime(&ft1, &ft2);
|
||||||
|
if (nCompare == 0)
|
||||||
|
return pEntry;
|
||||||
|
if (nCompare < 0)
|
||||||
|
return pPrevEntry;
|
||||||
|
pPrevEntry = pEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pPrevEntry;
|
||||||
|
}
|
21
dll/win32/kernel32/winnls/string/japanese.h
Normal file
21
dll/win32/kernel32/winnls/string/japanese.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS system libraries
|
||||||
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||||
|
* PURPOSE: Japanese era support
|
||||||
|
* COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||||
|
*/
|
||||||
|
#define JAPANESE_MAX_TWODIGITYEAR 99
|
||||||
|
|
||||||
|
typedef struct JAPANESE_ERA
|
||||||
|
{
|
||||||
|
WORD wYear;
|
||||||
|
WORD wMonth;
|
||||||
|
WORD wDay;
|
||||||
|
WCHAR szEraName[16];
|
||||||
|
WCHAR szEraAbbrev[5];
|
||||||
|
WCHAR szEnglishEraName[24];
|
||||||
|
WCHAR szEnglishEraAbbrev[5];
|
||||||
|
} JAPANESE_ERA, *PJAPANESE_ERA;
|
||||||
|
typedef const JAPANESE_ERA *PCJAPANESE_ERA;
|
||||||
|
|
||||||
|
PCJAPANESE_ERA JapaneseEra_Find(const SYSTEMTIME *pst OPTIONAL);
|
|
@ -2366,14 +2366,22 @@ INT WINAPI CompareStringA(LCID lcid, DWORD flags,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
|
||||||
|
#else
|
||||||
static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
|
static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
UNICODE_STRING keyName;
|
UNICODE_STRING keyName;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
HANDLE hkey;
|
HANDLE hkey;
|
||||||
|
|
||||||
RtlInitUnicodeString( &keyName, szKeyName );
|
RtlInitUnicodeString( &keyName, szKeyName );
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
InitializeObjectAttributes(&attr, &keyName, OBJ_CASE_INSENSITIVE, hRootKey, NULL);
|
||||||
|
#else
|
||||||
InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL);
|
InitializeObjectAttributes(&attr, &keyName, 0, hRootKey, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS)
|
if (NtOpenKey( &hkey, KEY_READ, &attr ) != STATUS_SUCCESS)
|
||||||
hkey = 0;
|
hkey = 0;
|
||||||
|
@ -2381,9 +2389,15 @@ static HANDLE NLS_RegOpenKey(HANDLE hRootKey, LPCWSTR szKeyName)
|
||||||
return hkey;
|
return hkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
|
||||||
|
LPWSTR szValueName, ULONG valueNameSize,
|
||||||
|
LPWSTR szValueData, ULONG valueDataSize)
|
||||||
|
#else
|
||||||
static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
|
static BOOL NLS_RegEnumValue(HANDLE hKey, UINT ulIndex,
|
||||||
LPWSTR szValueName, ULONG valueNameSize,
|
LPWSTR szValueName, ULONG valueNameSize,
|
||||||
LPWSTR szValueData, ULONG valueDataSize)
|
LPWSTR szValueData, ULONG valueDataSize)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
BYTE buffer[80];
|
BYTE buffer[80];
|
||||||
KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
|
KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
|
|
||||||
#include <k32.h>
|
#include <k32.h>
|
||||||
|
#include "japanese.h" /* Japanese eras */
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
@ -34,6 +35,12 @@ DEBUG_CHANNEL(nls);
|
||||||
#define CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG
|
#define CRITICAL_SECTION_DEBUG RTL_CRITICAL_SECTION_DEBUG
|
||||||
#define CALINFO_MAX_YEAR 2029
|
#define CALINFO_MAX_YEAR 2029
|
||||||
|
|
||||||
|
#define IS_LCID_JAPANESE(lcid) PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_JAPANESE
|
||||||
|
|
||||||
|
#ifndef CAL_SABBREVERASTRING
|
||||||
|
#define CAL_SABBREVERASTRING 0x00000039
|
||||||
|
#endif
|
||||||
|
|
||||||
#else /* __REACTOS__ */
|
#else /* __REACTOS__ */
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -372,7 +379,11 @@ BOOL NLS_IsUnicodeOnlyLcid(LCID lcid)
|
||||||
#define IsTimeFmtChar(p) (p == 'H'||p == 'h'||p == 'm'||p == 's'||p == 't')
|
#define IsTimeFmtChar(p) (p == 'H'||p == 'h'||p == 'm'||p == 's'||p == 't')
|
||||||
|
|
||||||
/* Only the following flags can be given if a date/time format is specified */
|
/* Only the following flags can be given if a date/time format is specified */
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
#define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY | DATE_USE_ALT_CALENDAR)
|
||||||
|
#else
|
||||||
#define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY)
|
#define DATE_FORMAT_FLAGS (DATE_DATEVARSONLY)
|
||||||
|
#endif
|
||||||
#define TIME_FORMAT_FLAGS (TIME_TIMEVARSONLY|TIME_FORCE24HOURFORMAT| \
|
#define TIME_FORMAT_FLAGS (TIME_TIMEVARSONLY|TIME_FORCE24HOURFORMAT| \
|
||||||
TIME_NOMINUTESORSECONDS|TIME_NOSECONDS| \
|
TIME_NOMINUTESORSECONDS|TIME_NOSECONDS| \
|
||||||
TIME_NOTIMEMARKER)
|
TIME_NOTIMEMARKER)
|
||||||
|
@ -604,6 +615,24 @@ static INT NLS_GetDateTimeFormatW(LCID lcid, DWORD dwFlags,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'y':
|
case 'y':
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
if (IS_LCID_JAPANESE(lcid) && (dwFlags & DATE_USE_ALT_CALENDAR))
|
||||||
|
{
|
||||||
|
PCJAPANESE_ERA pEra = JapaneseEra_Find(lpTime);
|
||||||
|
if (pEra)
|
||||||
|
{
|
||||||
|
if (count >= 2)
|
||||||
|
{
|
||||||
|
count = 2;
|
||||||
|
}
|
||||||
|
dwVal = lpTime->wYear - pEra->wYear + 1;
|
||||||
|
szAdd = buff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (count >= 4)
|
if (count >= 4)
|
||||||
{
|
{
|
||||||
count = 4;
|
count = 4;
|
||||||
|
@ -618,6 +647,32 @@ static INT NLS_GetDateTimeFormatW(LCID lcid, DWORD dwFlags,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
if (IS_LCID_JAPANESE(lcid))
|
||||||
|
{
|
||||||
|
if (dwFlags & DATE_USE_ALT_CALENDAR)
|
||||||
|
{
|
||||||
|
PCJAPANESE_ERA pEra = JapaneseEra_Find(lpTime);
|
||||||
|
if (pEra)
|
||||||
|
{
|
||||||
|
RtlStringCbCopyW(buff, sizeof(buff), pEra->szEraName);
|
||||||
|
szAdd = buff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Seireki */
|
||||||
|
buff[0] = 0x897F;
|
||||||
|
buff[1] = 0x66A6;
|
||||||
|
buff[2] = 0;
|
||||||
|
szAdd = buff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (count == 2)
|
if (count == 2)
|
||||||
{
|
{
|
||||||
/* FIXME: Our GetCalendarInfo() does not yet support CAL_SERASTRING.
|
/* FIXME: Our GetCalendarInfo() does not yet support CAL_SERASTRING.
|
||||||
|
@ -2367,6 +2422,26 @@ int WINAPI GetCalendarInfoA(LCID lcid, CALID Calendar, CALTYPE CalType,
|
||||||
{
|
{
|
||||||
int ret, cchDataW = cchData;
|
int ret, cchDataW = cchData;
|
||||||
LPWSTR lpCalDataW = NULL;
|
LPWSTR lpCalDataW = NULL;
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
DWORD cp = CP_ACP;
|
||||||
|
if (!(CalType & CAL_USE_CP_ACP))
|
||||||
|
{
|
||||||
|
DWORD dwFlags = ((CalType & CAL_NOUSEROVERRIDE) ? LOCALE_NOUSEROVERRIDE : 0);
|
||||||
|
const NLS_FORMAT_NODE *node = NLS_GetFormats(lcid, dwFlags);
|
||||||
|
if (!node)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cp = node->dwCodePage;
|
||||||
|
}
|
||||||
|
if ((CalType & 0xFFFF) == CAL_SABBREVERASTRING)
|
||||||
|
{
|
||||||
|
/* NOTE: CAL_SABBREVERASTRING is not supported in GetCalendarInfoA */
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (NLS_IsUnicodeOnlyLcid(lcid))
|
if (NLS_IsUnicodeOnlyLcid(lcid))
|
||||||
{
|
{
|
||||||
|
@ -2381,7 +2456,11 @@ int WINAPI GetCalendarInfoA(LCID lcid, CALID Calendar, CALTYPE CalType,
|
||||||
|
|
||||||
ret = GetCalendarInfoW(lcid, Calendar, CalType, lpCalDataW, cchDataW, lpValue);
|
ret = GetCalendarInfoW(lcid, Calendar, CalType, lpCalDataW, cchDataW, lpValue);
|
||||||
if(ret && lpCalDataW && lpCalData)
|
if(ret && lpCalDataW && lpCalData)
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
ret = WideCharToMultiByte(cp, 0, lpCalDataW, -1, lpCalData, cchData, NULL, NULL);
|
||||||
|
#else
|
||||||
ret = WideCharToMultiByte(CP_ACP, 0, lpCalDataW, -1, lpCalData, cchData, NULL, NULL);
|
ret = WideCharToMultiByte(CP_ACP, 0, lpCalDataW, -1, lpCalData, cchData, NULL, NULL);
|
||||||
|
#endif
|
||||||
else if (CalType & CAL_RETURN_NUMBER)
|
else if (CalType & CAL_RETURN_NUMBER)
|
||||||
ret *= sizeof(WCHAR);
|
ret *= sizeof(WCHAR);
|
||||||
HeapFree(GetProcessHeap(), 0, lpCalDataW);
|
HeapFree(GetProcessHeap(), 0, lpCalDataW);
|
||||||
|
@ -2495,18 +2574,101 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType,
|
||||||
|
|
||||||
switch (calinfo) {
|
switch (calinfo) {
|
||||||
case CAL_ICALINTVALUE:
|
case CAL_ICALINTVALUE:
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
if (IS_LCID_JAPANESE(Locale))
|
||||||
|
{
|
||||||
|
if (CalType & CAL_RETURN_NUMBER)
|
||||||
|
{
|
||||||
|
*lpValue = CAL_JAPAN;
|
||||||
|
return sizeof(DWORD) / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const WCHAR fmtW[] = {'%','u',0};
|
||||||
|
WCHAR buffer[10];
|
||||||
|
int ret = snprintfW( buffer, 10, fmtW, CAL_JAPAN ) + 1;
|
||||||
|
if (!lpCalData) return ret;
|
||||||
|
if (ret <= cchData)
|
||||||
|
{
|
||||||
|
strcpyW( lpCalData, buffer );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (CalType & CAL_RETURN_NUMBER)
|
if (CalType & CAL_RETURN_NUMBER)
|
||||||
return GetLocaleInfoW(Locale, LOCALE_RETURN_NUMBER | LOCALE_ICALENDARTYPE,
|
return GetLocaleInfoW(Locale, LOCALE_RETURN_NUMBER | LOCALE_ICALENDARTYPE,
|
||||||
(LPWSTR)lpValue, 2);
|
(LPWSTR)lpValue, 2);
|
||||||
return GetLocaleInfoW(Locale, LOCALE_ICALENDARTYPE, lpCalData, cchData);
|
return GetLocaleInfoW(Locale, LOCALE_ICALENDARTYPE, lpCalData, cchData);
|
||||||
case CAL_SCALNAME:
|
case CAL_SCALNAME:
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
|
||||||
|
{
|
||||||
|
// Wareki
|
||||||
|
lpCalData[0] = 0x548C;
|
||||||
|
lpCalData[1] = 0x66A6;
|
||||||
|
lpCalData[2] = 0;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
FIXME("Unimplemented caltype %d\n", calinfo);
|
FIXME("Unimplemented caltype %d\n", calinfo);
|
||||||
if (lpCalData) *lpCalData = 0;
|
if (lpCalData) *lpCalData = 0;
|
||||||
return 1;
|
return 1;
|
||||||
case CAL_IYEAROFFSETRANGE:
|
case CAL_IYEAROFFSETRANGE:
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
|
||||||
|
{
|
||||||
|
PCJAPANESE_ERA pEra = JapaneseEra_Find(NULL);
|
||||||
|
if (pEra)
|
||||||
|
{
|
||||||
|
if (CalType & CAL_RETURN_NUMBER)
|
||||||
|
{
|
||||||
|
*lpValue = pEra->wYear;
|
||||||
|
return sizeof(DWORD) / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const WCHAR fmtW[] = {'%','u',0};
|
||||||
|
WCHAR buffer[10];
|
||||||
|
int ret = snprintfW( buffer, 10, fmtW, pEra->wYear ) + 1;
|
||||||
|
if (!lpCalData) return ret;
|
||||||
|
if (ret <= cchData)
|
||||||
|
{
|
||||||
|
strcpyW( lpCalData, buffer );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
FIXME("Unimplemented caltype %d\n", calinfo);
|
FIXME("Unimplemented caltype %d\n", calinfo);
|
||||||
return 0;
|
return 0;
|
||||||
case CAL_SERASTRING:
|
case CAL_SERASTRING:
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
|
||||||
|
{
|
||||||
|
PCJAPANESE_ERA pEra = JapaneseEra_Find(NULL);
|
||||||
|
if (pEra)
|
||||||
|
{
|
||||||
|
RtlStringCchCopyW(lpCalData, cchData, pEra->szEraName);
|
||||||
|
return strlenW(lpCalData) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
FIXME("Unimplemented caltype %d\n", calinfo);
|
FIXME("Unimplemented caltype %d\n", calinfo);
|
||||||
return 0;
|
return 0;
|
||||||
case CAL_SSHORTDATE:
|
case CAL_SSHORTDATE:
|
||||||
|
@ -2554,6 +2716,30 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType,
|
||||||
case CAL_SYEARMONTH:
|
case CAL_SYEARMONTH:
|
||||||
return GetLocaleInfoW(Locale, caltype_lctype_map[calinfo] | localeflags, lpCalData, cchData);
|
return GetLocaleInfoW(Locale, caltype_lctype_map[calinfo] | localeflags, lpCalData, cchData);
|
||||||
case CAL_ITWODIGITYEARMAX:
|
case CAL_ITWODIGITYEARMAX:
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
|
||||||
|
{
|
||||||
|
if (CalType & CAL_RETURN_NUMBER)
|
||||||
|
{
|
||||||
|
*lpValue = JAPANESE_MAX_TWODIGITYEAR;
|
||||||
|
return sizeof(DWORD) / sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const WCHAR fmtW[] = {'%','u',0};
|
||||||
|
WCHAR buffer[10];
|
||||||
|
int ret = snprintfW( buffer, 10, fmtW, JAPANESE_MAX_TWODIGITYEAR ) + 1;
|
||||||
|
if (!lpCalData) return ret;
|
||||||
|
if (ret <= cchData)
|
||||||
|
{
|
||||||
|
strcpyW( lpCalData, buffer );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
SetLastError( ERROR_INSUFFICIENT_BUFFER );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (CalType & CAL_RETURN_NUMBER)
|
if (CalType & CAL_RETURN_NUMBER)
|
||||||
{
|
{
|
||||||
*lpValue = CALINFO_MAX_YEAR;
|
*lpValue = CALINFO_MAX_YEAR;
|
||||||
|
@ -2574,6 +2760,20 @@ int WINAPI GetCalendarInfoW(LCID Locale, CALID Calendar, CALTYPE CalType,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
case CAL_SABBREVERASTRING:
|
||||||
|
if (IS_LCID_JAPANESE(Locale) && Calendar == CAL_JAPAN)
|
||||||
|
{
|
||||||
|
PCJAPANESE_ERA pEra = JapaneseEra_Find(NULL);
|
||||||
|
if (pEra)
|
||||||
|
{
|
||||||
|
RtlStringCchCopyW(lpCalData, cchData, pEra->szEraAbbrev);
|
||||||
|
return strlenW(lpCalData) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
FIXME("Unknown caltype %d\n", calinfo);
|
FIXME("Unknown caltype %d\n", calinfo);
|
||||||
SetLastError(ERROR_INVALID_FLAGS);
|
SetLastError(ERROR_INVALID_FLAGS);
|
||||||
|
|
Loading…
Reference in a new issue