2 * Unit tests for locale functions
4 * Copyright 2002 YASAR Mehmet
5 * Copyright 2003 Dmitry Timoshkov
6 * Copyright 2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
24 * even when the user has overridden their default i8n settings (e.g. in
25 * the control panel i8n page), we will still get the expected results.
32 #include "wine/test.h"
38 static inline unsigned int strlenW( const WCHAR *str )
45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
48 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
54 for ( ; *str; str++) if (*str == ch) return (WCHAR *)str;
58 inline static int isdigitW( WCHAR wc )
61 GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
62 return type & C1_DIGIT;
65 /* Some functions are only in later versions of kernel32.dll */
66 static HMODULE hKernel32;
68 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
70 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
71 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
72 LGRPID, DWORD, LONG_PTR);
73 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
75 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
76 static FoldStringAFn pFoldStringA;
77 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
78 static FoldStringWFn pFoldStringW;
80 static void InitFunctionPointers(void)
82 hKernel32 = GetModuleHandleA("kernel32");
86 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
87 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
88 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
89 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
93 #define eq(received, expected, label, type) \
94 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
95 (label), (received), (expected))
97 #define BUFFER_SIZE 128
98 char GlobalBuffer[BUFFER_SIZE]; /* Buffer used by callback function */
99 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
101 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (len), ret)
102 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
103 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError())
104 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
105 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError())
106 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
107 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
108 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
109 GetLastError() == ERROR_INVALID_PARAMETER, \
110 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
111 #define EXPECT_VALID ok(GetLastError() == 0, \
112 "Expected GetLastError() == 0, got %ld\n", GetLastError())
114 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
115 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
116 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
117 "Expected '%s', got '%s'", Expected, buffer)
119 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
120 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
121 SetLastError(0); buffer[0] = '\0'
122 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
123 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
125 #define NUO LOCALE_NOUSEROVERRIDE
127 static void test_GetLocaleInfoA()
130 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
131 char buffer[BUFFER_SIZE];
133 ok(lcid == 0x409, "wrong LCID calculated - %ld\n", lcid);
135 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
136 * partially fill the buffer even if it is too short. See bug 637.
138 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
139 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
140 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
142 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
143 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
144 EXPECT_BUFFER; EXPECT_LEN(0);
145 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
147 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
148 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
149 EXPECT_VALID; EXPECT_LEN(7);
150 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
153 static void test_GetTimeFormatA()
157 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
158 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
160 memset(&curtime, 2, sizeof(SYSTEMTIME));
161 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
162 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
163 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
166 curtime.wMinute = 56;
167 curtime.wSecond = 13;
168 curtime.wMilliseconds = 22;
169 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
170 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
171 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
173 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
174 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
175 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
177 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
178 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
179 EXPECT_VALID; EXPECT_LENA;
181 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
182 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
183 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
185 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
186 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
187 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
189 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
190 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
191 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
193 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
194 strcpy(Expected, "8:56 AM");
195 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
196 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
198 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
199 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
200 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
202 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
203 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
204 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
206 STRINGSA("t/tt", "A/AM"); /* AM time marker */
207 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
208 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
211 STRINGSA("t/tt", "P/PM"); /* PM time marker */
212 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
213 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
215 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
216 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
217 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
219 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
220 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
221 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
223 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
224 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
225 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
227 curtime.wHour = 14; /* change this to 14 or 2pm */
230 STRINGSA("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
231 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
232 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
235 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
236 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
237 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
239 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
240 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
241 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
243 /* try to convert formatting strings with more than two letters
244 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
245 * NOTE: We expect any letter for which there is an upper case value
246 * we should see a replacement. For letters that DO NOT have
247 * upper case values we should see NO REPLACEMENT.
250 curtime.wMinute = 56;
251 curtime.wSecond = 13;
252 curtime.wMilliseconds = 22;
253 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
254 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
255 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
256 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
258 STRINGSA("h", "text"); /* Dont write to buffer if len is 0*/
259 strcpy(buffer, "text");
260 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
261 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
263 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
264 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
265 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
266 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
268 STRINGSA("'''", "'"); /* invalid quoted string */
269 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
270 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
272 /* test that msdn suggested single quotation usage works as expected */
273 STRINGSA("''''", "'"); /* single quote mark */
274 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
275 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
277 STRINGSA("''HHHHHH", "08"); /* Normal use */
278 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
279 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
281 /* and test for normal use of the single quotation mark */
282 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
283 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
284 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
286 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
287 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
288 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
290 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
291 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
292 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
295 STRINGSA("'123'tt", ""); /* Invalid time */
296 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
297 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
300 curtime.wMonth = 60; /* Invalid */
301 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
302 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
303 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
306 static void test_GetDateFormatA()
310 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
311 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
313 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
314 STRINGSA("ddd',' MMM dd yy","");
315 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
316 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
318 curtime.wYear = 2002;
321 curtime.wDayOfWeek = 3;
322 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
323 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
324 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
326 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
327 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
328 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
330 curtime.wHour = 36; /* Invalid */
331 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
332 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
333 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
335 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
336 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
337 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
339 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
340 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
341 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
343 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
344 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
345 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
347 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
348 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
349 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
351 /* test for expected DATE_YEARMONTH behavior with null format */
352 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
353 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
354 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
355 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
357 /* Test that using invalid DATE_* flags results in the correct error */
358 /* and return values */
359 STRINGSA("m/d/y", ""); /* Invalid flags */
360 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
361 &curtime, input, buffer, COUNTOF(buffer));
362 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
365 static void test_GetDateFormatW()
369 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
370 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
372 STRINGSW("",""); /* If flags is not zero then format must be NULL */
373 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
374 input, buffer, COUNTOF(buffer));
375 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
377 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
379 STRINGSW("",""); /* NULL buffer, len > 0 */
380 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
381 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
383 STRINGSW("",""); /* NULL buffer, len == 0 */
384 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
385 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
387 curtime.wYear = 2002;
390 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
391 curtime.wHour = 65432; /* Invalid */
392 curtime.wMinute = 34512; /* Invalid */
393 curtime.wSecond = 65535; /* Invalid */
394 curtime.wMilliseconds = 12345;
395 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
396 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
397 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
401 #define CY_POS_LEFT 0
402 #define CY_POS_RIGHT 1
403 #define CY_POS_LEFT_SPACE 2
404 #define CY_POS_RIGHT_SPACE 3
406 static void test_GetCurrencyFormatA()
408 static char szDot[] = { '.', '\0' };
409 static char szComma[] = { ',', '\0' };
410 static char szDollar[] = { '$', '\0' };
412 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
413 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
416 memset(&format, 0, sizeof(format));
418 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
419 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
420 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
422 STRINGSA("23,53",""); /* Invalid character --> Error */
423 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
424 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
426 STRINGSA("--",""); /* Double '-' --> Error */
427 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
428 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
430 STRINGSA("0-",""); /* Trailing '-' --> Error */
431 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
432 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
434 STRINGSA("0..",""); /* Double '.' --> Error */
435 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
436 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
438 STRINGSA(" 0.1",""); /* Leading space --> Error */
439 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
440 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
442 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
443 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
444 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
446 STRINGSA("2353",""); /* Format and flags given --> Error */
447 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
448 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
450 STRINGSA("2353",""); /* Invalid format --> Error */
451 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
452 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
454 STRINGSA("2353","$2,353.00"); /* Valid number */
455 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
456 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
458 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
459 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
460 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
462 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
463 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
464 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
466 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
467 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
468 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
470 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
471 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
472 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
474 format.NumDigits = 0; /* No decimal separator */
475 format.LeadingZero = 0;
476 format.Grouping = 0; /* No grouping char */
477 format.NegativeOrder = 0;
478 format.PositiveOrder = CY_POS_LEFT;
479 format.lpDecimalSep = szDot;
480 format.lpThousandSep = szComma;
481 format.lpCurrencySymbol = szDollar;
483 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
484 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
485 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
487 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
488 STRINGSA("2353","$2353.0");
489 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
490 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
492 format.Grouping = 2; /* Group by 100's */
493 STRINGSA("2353","$23,53.0");
494 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
495 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
497 format.LeadingZero = 1; /* Always provide leading zero */
498 STRINGSA(".5","$0.5");
499 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
500 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
502 format.PositiveOrder = CY_POS_RIGHT;
503 STRINGSA("1","1.0$");
504 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
505 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
507 format.PositiveOrder = CY_POS_LEFT_SPACE;
508 STRINGSA("1","$ 1.0");
509 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
510 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
512 format.PositiveOrder = CY_POS_RIGHT_SPACE;
513 STRINGSA("1","1.0 $");
514 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
515 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
517 format.NegativeOrder = 0;
518 STRINGSA("-1","($1.0)");
519 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
520 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
522 format.NegativeOrder = 1;
523 STRINGSA("-1","-$1.0");
524 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
525 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
527 format.NegativeOrder = 2;
528 STRINGSA("-1","$-1.0");
529 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
530 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
532 format.NegativeOrder = 3;
533 STRINGSA("-1","$1.0-");
534 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
535 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
537 format.NegativeOrder = 4;
538 STRINGSA("-1","(1.0$)");
539 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
540 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
542 format.NegativeOrder = 5;
543 STRINGSA("-1","-1.0$");
544 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
545 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
547 format.NegativeOrder = 6;
548 STRINGSA("-1","1.0-$");
549 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
550 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
552 format.NegativeOrder = 7;
553 STRINGSA("-1","1.0$-");
554 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
555 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
557 format.NegativeOrder = 8;
558 STRINGSA("-1","-1.0 $");
559 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
560 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
562 format.NegativeOrder = 9;
563 STRINGSA("-1","-$ 1.0");
564 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
565 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
567 format.NegativeOrder = 10;
568 STRINGSA("-1","1.0 $-");
569 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
570 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
572 format.NegativeOrder = 11;
573 STRINGSA("-1","$ 1.0-");
574 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
575 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
577 format.NegativeOrder = 12;
578 STRINGSA("-1","$ -1.0");
579 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
580 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
582 format.NegativeOrder = 13;
583 STRINGSA("-1","1.0- $");
584 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
585 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
587 format.NegativeOrder = 14;
588 STRINGSA("-1","($ 1.0)");
589 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
590 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
592 format.NegativeOrder = 15;
593 STRINGSA("-1","(1.0 $)");
594 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
595 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
598 #define NEG_PARENS 0 /* "(1.1)" */
599 #define NEG_LEFT 1 /* "-1.1" */
600 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
601 #define NEG_RIGHT 3 /* "1.1-" */
602 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
604 static void test_GetNumberFormatA()
606 static char szDot[] = { '.', '\0' };
607 static char szComma[] = { ',', '\0' };
609 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
610 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
613 memset(&format, 0, sizeof(format));
615 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
616 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
617 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
619 STRINGSA("23,53",""); /* Invalid character --> Error */
620 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
621 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
623 STRINGSA("--",""); /* Double '-' --> Error */
624 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
625 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
627 STRINGSA("0-",""); /* Trailing '-' --> Error */
628 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
629 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
631 STRINGSA("0..",""); /* Double '.' --> Error */
632 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
633 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
635 STRINGSA(" 0.1",""); /* Leading space --> Error */
636 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
637 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
639 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
640 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
641 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
643 STRINGSA("2353",""); /* Format and flags given --> Error */
644 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
645 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
647 STRINGSA("2353",""); /* Invalid format --> Error */
648 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
649 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
651 STRINGSA("2353","2,353.00"); /* Valid number */
652 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
653 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
655 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
656 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
657 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
659 STRINGSA("2353.1","2,353.10"); /* Valid real number */
660 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
661 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
663 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
664 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
665 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
667 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
668 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
669 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
671 format.NumDigits = 0; /* No decimal separator */
672 format.LeadingZero = 0;
673 format.Grouping = 0; /* No grouping char */
674 format.NegativeOrder = 0;
675 format.lpDecimalSep = szDot;
676 format.lpThousandSep = szComma;
678 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
679 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
680 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
682 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
683 STRINGSA("2353","2353.0");
684 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
685 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
687 format.Grouping = 2; /* Group by 100's */
688 STRINGSA("2353","23,53.0");
689 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
690 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
692 format.LeadingZero = 1; /* Always provide leading zero */
693 STRINGSA(".5","0.5");
694 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
695 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
697 format.NegativeOrder = NEG_PARENS;
698 STRINGSA("-1","(1.0)");
699 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
700 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
702 format.NegativeOrder = NEG_LEFT;
703 STRINGSA("-1","-1.0");
704 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
705 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
707 format.NegativeOrder = NEG_LEFT_SPACE;
708 STRINGSA("-1","- 1.0");
709 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
710 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
712 format.NegativeOrder = NEG_RIGHT;
713 STRINGSA("-1","1.0-");
714 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
715 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
717 format.NegativeOrder = NEG_RIGHT_SPACE;
718 STRINGSA("-1","1.0 -");
719 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
720 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
722 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
724 if (IsValidLocale(lcid, 0))
726 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
727 Expected[3] = 160; /* Non breaking space */
728 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
729 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
734 /* Callback function used by TestEnumTimeFormats */
735 static BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
737 trace("%s\n", lpTimeFormatString);
738 strcpy(GlobalBuffer, lpTimeFormatString);
745 void test_EnumTimeFormats()
748 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
750 GlobalBuffer[0] = '\0';
751 ret = EnumTimeFormatsA(EnumTimeFormatsProc, lcid, 0);
752 ok (ret == 1 && !strcmp(GlobalBuffer,"h:mm:ss tt"), "Expected %d '%s'\n", ret, GlobalBuffer);
755 static void test_CompareStringA()
758 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
760 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
761 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
763 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
764 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
766 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
767 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
769 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
770 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
772 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
774 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
775 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
777 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
778 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
780 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
781 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
783 SetLastError(0xdeadbeef);
784 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
785 ok(GetLastError() == ERROR_INVALID_FLAGS,
786 "unexpected error code %ld\n", GetLastError());
787 ok(!ret, "CompareStringA must fail with invalid flag\n");
789 ret = lstrcmpA("", "");
790 ok (!ret, "lstrcmpA(\"\", \"\") should return 0, got %d", ret);
792 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
793 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d", ret);
795 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
796 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d", ret);
798 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
799 ok( ret == 3, "r vs \\ ... expected 3, got %d", ret);
801 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
802 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d", ret);
804 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
805 ok( ret == 3, "AAA vs aaa expected 3, got %d", ret);
807 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
808 ok( ret == 1, "AAA vs aab expected 1, got %d", ret);
810 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
811 ok( ret == 1, "AAA vs Aab expected 1, got %d", ret);
813 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
814 ok( ret == 1, ".AAA vs Aab expected 1, got %d", ret);
816 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
817 ok( ret == 1, ".AAA vs A.ab expected 1, got %d", ret);
819 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
820 ok( ret == 1, "aa vs AB expected 1, got %d", ret);
822 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
823 ok( ret == 1, "aa vs Aab expected 1, got %d", ret);
825 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
826 ok( ret == 3, "aB vs Aab expected 3, got %d", ret);
828 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
829 ok( ret == 1, "Ba vs bab expected 1, got %d", ret);
831 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
832 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d", ret);
834 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
835 ok( ret == 3, "a vs { expected 3, got %d", ret);
837 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
838 ok( ret == 3, "A vs { expected 3, got %d", ret);
840 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
841 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d", ret);
843 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
844 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d", ret);
846 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
847 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d", ret);
849 /* hyphen and apostrophe are treated differently depending on
850 * whether SORT_STRINGSORT specified or not
852 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
853 ok(ret == 3, "-o vs /m expected 3, got %d", ret);
855 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
856 ok(ret == 1, "/m vs -o expected 1, got %d", ret);
858 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
859 ok(ret == 1, "-o vs /m expected 1, got %d", ret);
861 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
862 ok(ret == 3, "/m vs -o expected 3, got %d", ret);
864 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
865 ok(ret == 3, "'o vs /m expected 3, got %d", ret);
867 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
868 ok(ret == 1, "/m vs 'o expected 1, got %d", ret);
870 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
871 ok(ret == 1, "'o vs /m expected 1, got %d", ret);
873 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
874 ok(ret == 3, "/m vs 'o expected 3, got %d", ret);
876 #if 0 /* this requires collation table patch to make it MS compatible */
877 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
878 ok(ret == 1, "'o vs -o expected 1, got %d", ret);
880 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
881 ok(ret == 1, "'o vs -o expected 1, got %d", ret);
883 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
884 ok(ret == 1, "' vs - expected 1, got %d", ret);
886 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
887 ok(ret == 1, "' vs - expected 1, got %d", ret);
889 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
890 ok(ret == 3, "`o vs /m expected 3, got %d", ret);
892 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
893 ok(ret == 1, "/m vs `o expected 1, got %d", ret);
895 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
896 ok(ret == 3, "`o vs /m expected 3, got %d", ret);
898 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
899 ok(ret == 1, "/m vs `o expected 1, got %d", ret);
901 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
902 ok(ret == 1, "`o vs -m expected 1, got %d", ret);
904 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
905 ok(ret == 3, "-m vs `o expected 3, got %d", ret);
907 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
908 ok(ret == 3, "`o vs -m expected 3, got %d", ret);
910 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
911 ok(ret == 1, "-m vs `o expected 1, got %d", ret);
914 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
915 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d", ret);
917 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
918 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d", ret);
920 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
921 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d", ret);
923 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
924 ok(ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d", ret);
927 void test_LCMapStringA(void)
930 char buf[256], buf2[256];
931 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
932 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
933 static const char symbols_stripped[] = "justateststring1";
935 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
936 upper_case, -1, buf, sizeof(buf));
937 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
938 ok(GetLastError() == ERROR_INVALID_FLAGS,
939 "unexpected error code %ld\n", GetLastError());
941 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
942 upper_case, -1, buf, sizeof(buf));
943 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
944 ok(GetLastError() == ERROR_INVALID_FLAGS,
945 "unexpected error code %ld\n", GetLastError());
947 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
949 upper_case, -1, buf, sizeof(buf));
950 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
951 ok(GetLastError() == ERROR_INVALID_FLAGS,
952 "unexpected error code %ld\n", GetLastError());
954 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
955 upper_case, -1, buf, sizeof(buf));
956 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
957 ok(GetLastError() == ERROR_INVALID_FLAGS,
958 "unexpected error code %ld\n", GetLastError());
960 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
961 SetLastError(0xdeadbeef);
962 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
963 upper_case, -1, buf, sizeof(buf));
964 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
965 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
967 /* test LCMAP_LOWERCASE */
968 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
969 upper_case, -1, buf, sizeof(buf));
970 ok(ret == lstrlenA(upper_case) + 1,
971 "ret %d, error %ld, expected value %d\n",
972 ret, GetLastError(), lstrlenA(upper_case) + 1);
973 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
975 /* test LCMAP_UPPERCASE */
976 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
977 lower_case, -1, buf, sizeof(buf));
978 ok(ret == lstrlenA(lower_case) + 1,
979 "ret %d, error %ld, expected value %d\n",
980 ret, GetLastError(), lstrlenA(lower_case) + 1);
981 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
983 /* test buffer overflow */
984 SetLastError(0xdeadbeef);
985 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
986 lower_case, -1, buf, 4);
987 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
988 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
990 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
991 lstrcpyA(buf, lower_case);
992 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
993 buf, -1, buf, sizeof(buf));
994 if (!ret) /* Win9x */
995 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
998 ok(ret == lstrlenA(lower_case) + 1,
999 "ret %d, error %ld, expected value %d\n",
1000 ret, GetLastError(), lstrlenA(lower_case) + 1);
1001 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1003 lstrcpyA(buf, upper_case);
1004 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1005 buf, -1, buf, sizeof(buf));
1006 if (!ret) /* Win9x */
1007 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1010 ok(ret == lstrlenA(upper_case) + 1,
1011 "ret %d, error %ld, expected value %d\n",
1012 ret, GetLastError(), lstrlenA(lower_case) + 1);
1013 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1016 /* otherwise src == dst should fail */
1017 SetLastError(0xdeadbeef);
1018 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1019 buf, 10, buf, sizeof(buf));
1020 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1021 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1022 "unexpected error code %ld\n", GetLastError());
1023 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1025 /* test whether '\0' is always appended */
1026 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1027 upper_case, -1, buf, sizeof(buf));
1028 ok(ret, "LCMapStringA must succeed\n");
1029 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1030 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1031 ok(ret, "LCMapStringA must succeed\n");
1032 ok(ret == ret2, "lengths of sort keys must be equal\n");
1033 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1035 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1036 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1037 upper_case, -1, buf, sizeof(buf));
1038 ok(ret, "LCMapStringA must succeed\n");
1039 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1040 lower_case, -1, buf2, sizeof(buf2));
1041 ok(ret2, "LCMapStringA must succeed\n");
1042 ok(ret == ret2, "lengths of sort keys must be equal\n");
1043 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1045 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1046 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1047 lower_case, -1, buf, sizeof(buf));
1048 ok(ret, "LCMapStringA must succeed\n");
1049 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1050 lower_case, -1, buf2, sizeof(buf2));
1051 ok(ret2, "LCMapStringA must succeed\n");
1052 ok(ret == ret2, "lengths of sort keys must be equal\n");
1053 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1055 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1056 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1057 lower_case, -1, buf, sizeof(buf));
1058 ok(ret, "LCMapStringA must succeed\n");
1059 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1060 symbols_stripped, -1, buf2, sizeof(buf2));
1061 ok(ret2, "LCMapStringA must succeed\n");
1062 ok(ret == ret2, "lengths of sort keys must be equal\n");
1063 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1065 /* test NORM_IGNORENONSPACE */
1066 lstrcpyA(buf, "foo");
1067 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1068 lower_case, -1, buf, sizeof(buf));
1069 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1070 lstrlenA(lower_case) + 1, ret);
1071 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1073 /* test NORM_IGNORESYMBOLS */
1074 lstrcpyA(buf, "foo");
1075 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1076 lower_case, -1, buf, sizeof(buf));
1077 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1078 lstrlenA(symbols_stripped) + 1, ret);
1079 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1081 /* test srclen = 0 */
1082 SetLastError(0xdeadbeef);
1083 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1084 ok(!ret, "LCMapStringA should fail with srclen = 0");
1085 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1086 "unexpected error code %ld\n", GetLastError());
1089 void test_LCMapStringW(void)
1092 WCHAR buf[256], buf2[256];
1093 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1094 static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
1095 static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
1096 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1097 static const WCHAR fooW[] = {'f','o','o',0};
1099 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1100 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1101 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1103 trace("Skipping LCMapStringW tests on Win9x\n");
1106 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1107 ok(GetLastError() == ERROR_INVALID_FLAGS,
1108 "unexpected error code %ld\n", GetLastError());
1110 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1111 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1112 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1113 ok(GetLastError() == ERROR_INVALID_FLAGS,
1114 "unexpected error code %ld\n", GetLastError());
1116 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1117 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1118 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1119 ok(GetLastError() == ERROR_INVALID_FLAGS,
1120 "unexpected error code %ld\n", GetLastError());
1122 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1123 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1124 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1125 ok(GetLastError() == ERROR_INVALID_FLAGS,
1126 "unexpected error code %ld\n", GetLastError());
1128 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1129 SetLastError(0xdeadbeef);
1130 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1131 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1132 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1133 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1135 /* test LCMAP_LOWERCASE */
1136 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1137 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1138 ok(ret == lstrlenW(upper_case) + 1,
1139 "ret %d, error %ld, expected value %d\n",
1140 ret, GetLastError(), lstrlenW(upper_case) + 1);
1141 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1143 /* test LCMAP_UPPERCASE */
1144 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1145 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1146 ok(ret == lstrlenW(lower_case) + 1,
1147 "ret %d, error %ld, expected value %d\n",
1148 ret, GetLastError(), lstrlenW(lower_case) + 1);
1149 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1151 /* test buffer overflow */
1152 SetLastError(0xdeadbeef);
1153 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1154 lower_case, -1, buf, 4);
1155 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1156 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1158 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1159 lstrcpyW(buf, lower_case);
1160 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1161 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1162 ok(ret == lstrlenW(lower_case) + 1,
1163 "ret %d, error %ld, expected value %d\n",
1164 ret, GetLastError(), lstrlenW(lower_case) + 1);
1165 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1167 lstrcpyW(buf, upper_case);
1168 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1169 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1170 ok(ret == lstrlenW(upper_case) + 1,
1171 "ret %d, error %ld, expected value %d\n",
1172 ret, GetLastError(), lstrlenW(lower_case) + 1);
1173 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1175 /* otherwise src == dst should fail */
1176 SetLastError(0xdeadbeef);
1177 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1178 buf, 10, buf, sizeof(buf));
1179 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1180 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1181 "unexpected error code %ld\n", GetLastError());
1182 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1184 /* test whether '\0' is always appended */
1185 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1186 upper_case, -1, buf, sizeof(buf));
1187 ok(ret, "LCMapStringW must succeed\n");
1188 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1189 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1190 ok(ret, "LCMapStringW must succeed\n");
1191 ok(ret == ret2, "lengths of sort keys must be equal\n");
1192 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1194 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1195 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1196 upper_case, -1, buf, sizeof(buf));
1197 ok(ret, "LCMapStringW must succeed\n");
1198 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1199 lower_case, -1, buf2, sizeof(buf2));
1200 ok(ret2, "LCMapStringW must succeed\n");
1201 ok(ret == ret2, "lengths of sort keys must be equal\n");
1202 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1204 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1205 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1206 lower_case, -1, buf, sizeof(buf));
1207 ok(ret, "LCMapStringW must succeed\n");
1208 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1209 lower_case, -1, buf2, sizeof(buf2));
1210 ok(ret2, "LCMapStringW must succeed\n");
1211 ok(ret == ret2, "lengths of sort keys must be equal\n");
1212 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1214 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1215 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1216 lower_case, -1, buf, sizeof(buf));
1217 ok(ret, "LCMapStringW must succeed\n");
1218 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1219 symbols_stripped, -1, buf2, sizeof(buf2));
1220 ok(ret2, "LCMapStringW must succeed\n");
1221 ok(ret == ret2, "lengths of sort keys must be equal\n");
1222 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1224 /* test NORM_IGNORENONSPACE */
1225 lstrcpyW(buf, fooW);
1226 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1227 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1228 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1229 lstrlenW(lower_case) + 1, ret);
1230 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1232 /* test NORM_IGNORESYMBOLS */
1233 lstrcpyW(buf, fooW);
1234 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1235 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1236 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1237 lstrlenW(symbols_stripped) + 1, ret);
1238 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1240 /* test srclen = 0 */
1241 SetLastError(0xdeadbeef);
1242 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1243 ok(!ret, "LCMapStringW should fail with srclen = 0");
1244 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1245 "unexpected error code %ld\n", GetLastError());
1248 #if 0 /* this requires collation table patch to make it MS compatible */
1249 const char *strings_sorted[] =
1281 const char *strings[] =
1313 static int compare_string1(const void *e1, const void *e2)
1315 const char *s1 = *(const char **)e1;
1316 const char *s2 = *(const char **)e2;
1318 return lstrcmpA(s1, s2);
1321 static int compare_string2(const void *e1, const void *e2)
1323 const char *s1 = *(const char **)e1;
1324 const char *s2 = *(const char **)e2;
1326 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1329 static int compare_string3(const void *e1, const void *e2)
1331 const char *s1 = *(const char **)e1;
1332 const char *s2 = *(const char **)e2;
1333 char key1[256], key2[256];
1335 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1336 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1337 return strcmp(key1, key2);
1340 static void test_sorting(void)
1343 char **str_buf = (char **)buf;
1346 assert(sizeof(buf) >= sizeof(strings));
1348 /* 1. sort using lstrcmpA */
1349 memcpy(buf, strings, sizeof(strings));
1350 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1351 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1353 ok(!strcmp(strings_sorted[i], str_buf[i]),
1354 "qsort using lstrcmpA failed for element %d\n", i);
1356 /* 2. sort using CompareStringA */
1357 memcpy(buf, strings, sizeof(strings));
1358 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1359 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1361 ok(!strcmp(strings_sorted[i], str_buf[i]),
1362 "qsort using CompareStringA failed for element %d\n", i);
1364 /* 3. sort using sort keys */
1365 memcpy(buf, strings, sizeof(strings));
1366 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1367 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1369 ok(!strcmp(strings_sorted[i], str_buf[i]),
1370 "qsort using sort keys failed for element %d\n", i);
1375 static void test_FoldStringA(void)
1378 char src[256], dst[256];
1379 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1380 static const char digits_dst[] = { '1','2','3','\0' };
1381 static const char composite_src[] =
1383 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1384 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1385 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1386 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1387 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1388 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1389 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1390 0xfb,0xfc,0xfd,0xff,'\0'
1392 static const char composite_dst[] =
1394 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1395 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1396 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1397 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1398 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1399 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1400 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1401 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1402 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1403 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1404 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1405 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1406 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1407 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1408 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1410 static const char ligatures_src[] =
1412 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1414 static const char ligatures_dst[] =
1416 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1420 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1422 /* these tests are locale specific */
1423 if (GetACP() != 1252)
1425 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1429 /* MAP_FOLDDIGITS */
1431 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1432 EXPECT_LEN(4); EXPECT_VALID;
1433 ok(strcmp(dst, digits_dst) == 0,
1434 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1435 for (i = 1; i < 256; i++)
1437 if (!strchr(digits_src, i))
1442 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1443 EXPECT_LEN(2); EXPECT_VALID;
1444 ok(dst[0] == src[0],
1445 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1449 /* MAP_EXPAND_LIGATURES */
1451 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1452 EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1453 ok(strcmp(dst, ligatures_dst) == 0,
1454 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1455 for (i = 1; i < 256; i++)
1457 if (!strchr(ligatures_src, i))
1462 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1463 EXPECT_LEN(2); EXPECT_VALID;
1464 ok(dst[0] == src[0],
1465 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1471 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1475 /* Wine gets close, but doesn't produce quite the same result as native */
1477 ok(strcmp(dst, composite_dst) == 0,
1478 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1481 for (i = 1; i < 256; i++)
1483 if (!strchr(composite_src, i))
1488 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1489 EXPECT_LEN(2); EXPECT_VALID;
1490 ok(dst[0] == src[0],
1491 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1492 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1497 for (i = 1; i < 256; i++)
1502 ret = FoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1503 EXPECT_LEN(2); EXPECT_VALID;
1504 ok(src[0] == dst[0],
1505 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1506 (unsigned char)src[0], (unsigned char)dst[0]);
1509 /* MAP_PRECOMPOSED */
1510 for (i = 1; i < 256; i++)
1515 ret = FoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1516 EXPECT_LEN(2); EXPECT_VALID;
1517 ok(src[0] == dst[0],
1518 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1519 (unsigned char)src[0], (unsigned char)dst[0]);
1523 static void test_FoldStringW(void)
1527 WCHAR src[256], dst[256], ch, prev_ch = 1;
1528 static const DWORD badFlags[] =
1531 MAP_PRECOMPOSED|MAP_COMPOSITE,
1532 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1533 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1535 /* Ranges of digits 0-9 : Must be sorted! */
1536 static const WCHAR digitRanges[] =
1538 0x0030, /* '0'-'9' */
1539 0x0660, /* Eastern Arabic */
1540 0x06F0, /* Arabic - Hindu */
1541 0x0966, /* Devengari */
1542 0x09E6, /* Bengalii */
1543 0x0A66, /* Gurmukhi */
1544 0x0AE6, /* Gujarati */
1546 0x0BE6, /* Tamil - No 0 */
1547 0x0C66, /* Telugu */
1548 0x0CE6, /* Kannada */
1549 0x0D66, /* Maylayalam */
1552 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1553 0x2080, /* Subscript */
1554 0x245F, /* Circled - 0 is out of sequence */
1555 0x2473, /* Bracketed */
1556 0x2487, /* Full stop */
1557 0x2775, /* Inverted circled - No 0 */
1558 0x277F, /* Patterned circled - No 0 */
1559 0x2789, /* Inverted Patterned circled - No 0 */
1560 0xff10, /* Pliene chasse (?) */
1561 0xffff /* Terminator */
1563 /* Digits which are represented, but out of sequence */
1564 static const WCHAR outOfSequenceDigits[] =
1566 0xB9, /* Superscript 1 */
1567 0xB2, /* Superscript 2 */
1568 0xB3, /* Superscript 3 */
1569 0x24EA, /* Circled 0 */
1570 '\0' /* Terminator */
1572 /* Digits in digitRanges for which no representation is available */
1573 static const WCHAR noDigitAvailable[] =
1575 0x0BE6, /* No Tamil 0 */
1576 0x2473, /* No Bracketed 0 */
1577 0x2487, /* No 0 Full stop */
1578 0x2775, /* No inverted circled 0 */
1579 0x277F, /* No patterned circled */
1580 0x2789, /* No inverted Patterned circled */
1581 '\0' /* Terminator */
1583 /* Compatibility conversion results */
1584 static const WCHAR compat_F900_FA2F[256+48] =
1586 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1587 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1588 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1589 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1590 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1591 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1592 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1593 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1594 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1595 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1596 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1597 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1598 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1599 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1600 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1601 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1602 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1603 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1604 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1605 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1606 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1607 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1608 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1609 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1610 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1611 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1612 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1613 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1614 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1615 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1616 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1617 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1618 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1619 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1620 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1621 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1622 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1623 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1625 static const WCHAR compat_FE30_FEF7[200] =
1627 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1628 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1629 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1630 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1631 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1632 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1633 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1634 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1635 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1636 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1637 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1638 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1639 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1640 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1641 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1642 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1643 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1644 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1645 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1646 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1647 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1648 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1649 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1650 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1651 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1653 static const WCHAR compat_FF00_FFEF[240] =
1655 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1656 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1657 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1658 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1659 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1660 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1661 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1662 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1663 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1664 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1665 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1666 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1667 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1668 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1669 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1670 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1671 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1672 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1673 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1674 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1675 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1676 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1677 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1678 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1679 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1680 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1681 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1682 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1683 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1684 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1686 static const WCHAR ligatures_src[] =
1688 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1689 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1690 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1691 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1692 0xfb04, 0xfb05, 0xfb06, '\0'
1694 static const WCHAR ligatures_dst[] =
1696 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1697 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1698 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1699 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1700 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1704 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1706 /* Invalid flag combinations */
1707 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1709 src[0] = dst[0] = '\0';
1711 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1712 EXPECT_LEN(0); EXPECT_FLAGS;
1715 /* src & dst cannot be the same */
1717 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1718 EXPECT_LEN(0); EXPECT_INVALID;
1720 /* src can't be NULL */
1722 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1723 EXPECT_LEN(0); EXPECT_INVALID;
1725 /* srclen can't be 0 */
1727 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1728 EXPECT_LEN(0); EXPECT_INVALID;
1730 /* dstlen can't be < 0 */
1732 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1733 EXPECT_LEN(0); EXPECT_INVALID;
1735 /* Ret includes terminating NUL which is appended if srclen = -1 */
1740 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1741 EXPECT_LEN(2); EXPECT_VALID;
1742 ok(dst[0] == 'A' && dst[1] == '\0',
1743 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%ld\n",
1744 'A', '\0', ret, dst[0], dst[1], GetLastError());
1746 /* If size is given, result is not NUL terminated */
1752 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1753 EXPECT_LEN(1); EXPECT_VALID;
1754 ok(dst[0] == 'A' && dst[1] == 'X',
1755 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%ld\n",
1756 'A','X', ret, dst[0], dst[1], GetLastError());
1758 /* MAP_FOLDDIGITS */
1759 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1761 /* Check everything before this range */
1762 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1766 src[1] = dst[0] = '\0';
1767 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1768 EXPECT_LEN(2); EXPECT_VALID;
1770 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1771 /* Wine (correctly) maps all Unicode 4.0+ digits */
1772 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF,
1773 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1776 if (digitRanges[j] == 0xffff)
1777 break; /* Finished the whole code point space */
1779 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1783 /* Map out of sequence characters */
1784 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1785 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1786 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1787 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
1791 src[1] = dst[0] = '\0';
1792 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1793 EXPECT_LEN(2); EXPECT_VALID;
1795 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1796 strchrW(noDigitAvailable, c),
1797 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1798 ch, '0' + digitRanges[j] - ch, dst[0]);
1804 for (ch = 1; ch <0xffff; ch++)
1808 if (ch >= 0xF900 && ch <= 0xFA2F)
1809 expected = compat_F900_FA2F[ch - 0xF900];
1810 else if (ch >= 0xFE30 && ch <= 0xFEF7)
1811 expected = compat_FE30_FEF7[ch - 0xFE30];
1812 else if (ch >= 0xFF00 && ch <= 0xFFEF)
1813 expected = compat_FF00_FFEF[ch - 0xFF00];
1820 src[1] = dst[0] = '\0';
1821 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1822 EXPECT_LEN(2); EXPECT_VALID;
1823 ok(dst[0] == expected ||
1824 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1825 (ch >= 0xFA0D && ch <= 0xFA47) ||
1826 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 || ch == 0xf9f1,
1827 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1828 ch, ch, expected, dst[0]);
1831 /* MAP_EXPAND_LIGATURES */
1833 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1834 EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1835 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1836 "MAP_EXPAND_LIGATURES: Expanded incorrrectly\n");
1837 for (i = 1; i <= 0xffff; i++)
1839 if (!strchrW(ligatures_src, i))
1844 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1845 EXPECT_LEN(2); EXPECT_VALID;
1846 ok(dst[0] == src[0],
1847 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1852 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1857 #define LCID_OK(l) \
1858 ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1859 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1860 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1861 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1862 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1864 static void test_ConvertDefaultLocale(void)
1868 /* Doesn't change lcid, even if non default sublang/sort used */
1869 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1870 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1871 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1872 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1874 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1875 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1876 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1877 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1878 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1879 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1880 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1882 /* Invariant language is not treated specially */
1883 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1884 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1885 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1887 /* User/system default languages alone are not mapped */
1888 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1889 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1892 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1893 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1894 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1897 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1898 DWORD dwFlags, LONG_PTR lParam)
1900 trace("%08lx, %s, %s, %08lx, %08lx\n",
1901 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1903 ok(IsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1904 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1906 /* If lParam is one, we are calling with flags defaulted from 0 */
1907 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1908 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
1913 static void test_EnumSystemLanguageGroupsA(void)
1915 if (!pEnumSystemLanguageGroupsA)
1918 /* No enumeration proc */
1920 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1925 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1928 /* No flags - defaults to LGRPID_INSTALLED */
1930 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1933 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1934 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1938 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1941 trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1943 ok(IsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1944 "Enumerated grp %ld not valid\n", lgrpid);
1945 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1946 "Enumerated grp locale %ld not valid\n", lcid);
1950 static void test_EnumLanguageGroupLocalesA(void)
1952 if (!pEnumLanguageGroupLocalesA)
1955 /* No enumeration proc */
1957 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1960 /* lgrpid too small */
1962 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
1965 /* lgrpid too big */
1967 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
1970 /* dwFlags is reserved */
1972 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
1975 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
1978 static void test_SetLocaleInfoA(void)
1981 LCID lcid = GetUserDefaultLCID();
1985 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
1990 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
1995 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2001 InitFunctionPointers();
2004 test_EnumTimeFormats();
2006 test_GetLocaleInfoA();
2007 test_GetTimeFormatA();
2008 test_GetDateFormatA();
2009 test_GetDateFormatW();
2010 test_GetCurrencyFormatA(); /* Also tests the W version */
2011 test_GetNumberFormatA(); /* Also tests the W version */
2012 test_CompareStringA();
2013 test_LCMapStringA();
2014 test_LCMapStringW();
2017 test_ConvertDefaultLocale();
2018 test_EnumSystemLanguageGroupsA();
2019 test_EnumLanguageGroupLocalesA();
2020 test_SetLocaleInfoA();
2021 #if 0 /* this requires collation table patch to make it MS compatible */