2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Japanese era support
5 * COPYRIGHT: Copyright 2019 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
13 #define JAPANESE_ERA_MAX 16
15 /* #define DONT_USE_REGISTRY */
17 static DWORD s_JapaneseEraCount
= 0;
18 static JAPANESE_ERA s_JapaneseEraTable
[JAPANESE_ERA_MAX
]
19 #ifdef DONT_USE_REGISTRY
22 {1868, 1, 1, {0x660E, 0x6CBB}, {0x660E, 0}, L
"Meiji", L
"M"},
23 {1912, 7, 30, {0x5927, 0x6B63}, {0x5927, 0}, L
"Taisho", L
"T"},
24 {1926, 12, 25, {0x662D, 0x548C}, {0x662D, 0}, L
"Showa", L
"S"},
25 {1989, 1, 8, {0x5E73, 0x6210}, {0x5E73, 0}, L
"Heisei", L
"H"},
26 {2019, 5, 1, {0x4EE4, 0x548C}, {0x4EE4, 0}, L
"Reiwa", L
"R"},
31 HANDLE
NLS_RegOpenKey(HANDLE hRootKey
, LPCWSTR szKeyName
);
33 BOOL
NLS_RegEnumValue(HANDLE hKey
, UINT ulIndex
,
34 LPWSTR szValueName
, ULONG valueNameSize
,
35 LPWSTR szValueData
, ULONG valueDataSize
);
37 static INT
JapaneseEra_Compare(const void *e1
, const void *e2
)
39 PCJAPANESE_ERA pEra1
= (PCJAPANESE_ERA
)e1
;
40 PCJAPANESE_ERA pEra2
= (PCJAPANESE_ERA
)e2
;
41 if (pEra1
->wYear
< pEra2
->wYear
)
43 if (pEra1
->wYear
> pEra2
->wYear
)
45 if (pEra1
->wMonth
< pEra2
->wMonth
)
47 if (pEra1
->wMonth
> pEra2
->wMonth
)
49 if (pEra1
->wDay
< pEra2
->wDay
)
51 if (pEra1
->wDay
> pEra2
->wDay
)
56 BOOL
JapaneseEra_IsFirstYearGannen(void)
58 #ifdef DONT_USE_REGISTRY
63 WCHAR szName
[32], szValue
[32];
64 static BOOL s_bIsCached
= FALSE
, s_bFirstIsGannen
= TRUE
;
67 return s_bFirstIsGannen
;
69 KeyHandle
= NLS_RegOpenKey(NULL
, L
"\\Registry\\Machine\\System\\"
70 L
"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese");
74 for (dwIndex
= 0; dwIndex
< 16; ++dwIndex
)
76 if (!NLS_RegEnumValue(KeyHandle
, dwIndex
, szName
, sizeof(szName
),
77 szValue
, sizeof(szValue
)))
82 if (lstrcmpiW(szName
, L
"InitialEraYear") == 0)
84 s_bFirstIsGannen
= (szValue
[0] == 0x5143);
93 return s_bFirstIsGannen
;
99 * https://en.wikipedia.org/wiki/Japanese_era_name
100 * https://docs.microsoft.com/en-us/windows/desktop/Intl/era-handling-for-the-japanese-calendar
102 static PCJAPANESE_ERA
JapaneseEra_Load(DWORD
*pdwCount
)
104 #ifndef DONT_USE_REGISTRY
107 WCHAR szName
[128], szValue
[128];
108 JAPANESE_ERA
*pEntry
;
109 LPWSTR pch1
, pch2
, pch3
, pch4
;
112 ASSERT(pdwCount
!= NULL
);
114 /* return cache if any */
115 if (s_JapaneseEraCount
!= 0)
117 *pdwCount
= s_JapaneseEraCount
;
118 return s_JapaneseEraTable
;
121 #ifdef DONT_USE_REGISTRY
122 s_JapaneseEraCount
= ARRAYSIZE(s_JapaneseEraTable
);
126 RtlZeroMemory(&s_JapaneseEraTable
, sizeof(s_JapaneseEraTable
));
128 /* open registry key */
129 KeyHandle
= NLS_RegOpenKey(NULL
, L
"\\Registry\\Machine\\System\\"
130 L
"CurrentControlSet\\Control\\Nls\\Calendars\\Japanese\\Eras");
135 for (dwIndex
= 0; dwIndex
< JAPANESE_ERA_MAX
; ++dwIndex
)
137 pEntry
= &s_JapaneseEraTable
[dwIndex
];
139 /* get name and data */
140 if (!NLS_RegEnumValue(KeyHandle
, dwIndex
, szName
, sizeof(szName
),
141 szValue
, sizeof(szValue
)))
148 pch2
= wcschr(pch1
, L
' ');
153 *pch2
++ = UNICODE_NULL
;
155 pch3
= wcschr(pch2
, L
' ');
160 *pch3
++ = UNICODE_NULL
;
162 pEntry
->wYear
= _wtoi(pch1
);
163 pEntry
->wMonth
= _wtoi(pch2
);
164 pEntry
->wDay
= _wtoi(pch3
);
165 if (pEntry
->wYear
== 0 || pEntry
->wMonth
== 0 || pEntry
->wDay
== 0)
172 pch2
= wcschr(pch1
, L
'_');
177 *pch2
++ = UNICODE_NULL
;
179 pch3
= wcschr(pch2
, L
'_');
184 *pch3
++ = UNICODE_NULL
;
186 pch4
= wcschr(pch3
, L
'_');
191 *pch4
++ = UNICODE_NULL
;
194 RtlStringCbCopyW(pEntry
->szEraName
, sizeof(pEntry
->szEraName
), pch1
);
195 RtlStringCbCopyW(pEntry
->szEraAbbrev
, sizeof(pEntry
->szEraAbbrev
), pch2
);
196 RtlStringCbCopyW(pEntry
->szEnglishEraName
, sizeof(pEntry
->szEnglishEraName
), pch3
);
197 RtlStringCbCopyW(pEntry
->szEnglishEraAbbrev
, sizeof(pEntry
->szEnglishEraAbbrev
), pch4
);
204 qsort(s_JapaneseEraTable
, s_JapaneseEraCount
, sizeof(JAPANESE_ERA
),
205 JapaneseEra_Compare
);
208 s_JapaneseEraCount
= dwIndex
;
211 *pdwCount
= s_JapaneseEraCount
;
213 return s_JapaneseEraTable
;
216 static BOOL
JapaneseEra_ToSystemTime(PCJAPANESE_ERA pEra
, LPSYSTEMTIME pst
)
218 ASSERT(pEra
!= NULL
);
221 ZeroMemory(pst
, sizeof(*pst
));
222 pst
->wYear
= pEra
->wYear
;
223 pst
->wMonth
= pEra
->wMonth
;
224 pst
->wDay
= pEra
->wDay
;
228 PCJAPANESE_ERA
JapaneseEra_Find(const SYSTEMTIME
*pst OPTIONAL
)
230 DWORD dwIndex
, dwCount
= 0;
231 PCJAPANESE_ERA pTable
, pEntry
, pPrevEntry
= NULL
;
242 SystemTimeToFileTime(pst
, &ft1
);
245 pTable
= JapaneseEra_Load(&dwCount
);
246 if (pTable
== NULL
|| dwCount
== 0 || dwCount
> JAPANESE_ERA_MAX
)
252 for (dwIndex
= 0; dwIndex
< dwCount
; dwIndex
++)
254 pEntry
= &pTable
[dwIndex
];
256 /* pEntry --> st2 --> ft2 */
257 JapaneseEra_ToSystemTime(pEntry
, &st2
);
258 SystemTimeToFileTime(&st2
, &ft2
);
261 nCompare
= CompareFileTime(&ft1
, &ft2
);