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 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
81 static IsValidLanguageGroupFn pIsValidLanguageGroup;
83 static void InitFunctionPointers(void)
85 hKernel32 = GetModuleHandleA("kernel32");
89 pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
90 pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
91 pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
92 pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
93 pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
97 #define eq(received, expected, label, type) \
98 ok((received) == (expected), "%s: got " type " instead of " type "\n", \
99 (label), (received), (expected))
101 #define BUFFER_SIZE 128
102 char GlobalBuffer[BUFFER_SIZE]; /* Buffer used by callback function */
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
105 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (len), ret)
106 #define EXPECT_INVALID ok(GetLastError() == ERROR_INVALID_PARAMETER, \
107 "Expected ERROR_INVALID_PARAMETER, got %ld\n", GetLastError())
108 #define EXPECT_BUFFER ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
109 "Expected ERROR_INSUFFICIENT_BUFFER, got %ld\n", GetLastError())
110 #define EXPECT_FLAGS ok(GetLastError() == ERROR_INVALID_FLAGS, \
111 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
112 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
113 GetLastError() == ERROR_INVALID_PARAMETER, \
114 "Expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError())
115 #define EXPECT_VALID ok(GetLastError() == 0, \
116 "Expected GetLastError() == 0, got %ld\n", GetLastError())
118 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
119 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
120 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
121 "Expected '%s', got '%s'", Expected, buffer)
123 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
124 MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
125 SetLastError(0); buffer[0] = '\0'
126 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
127 #define EXPECT_EQW ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
129 #define NUO LOCALE_NOUSEROVERRIDE
131 static void test_GetLocaleInfoA()
134 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
135 char buffer[BUFFER_SIZE];
137 ok(lcid == 0x409, "wrong LCID calculated - %ld\n", lcid);
139 /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
140 * partially fill the buffer even if it is too short. See bug 637.
142 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
143 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
144 ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
146 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
147 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
148 EXPECT_BUFFER; EXPECT_LEN(0);
149 ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
151 SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
152 ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
153 EXPECT_VALID; EXPECT_LEN(7);
154 ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
157 static void test_GetTimeFormatA()
161 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
162 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
164 memset(&curtime, 2, sizeof(SYSTEMTIME));
165 STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
166 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
167 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
170 curtime.wMinute = 56;
171 curtime.wSecond = 13;
172 curtime.wMilliseconds = 22;
173 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
174 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
175 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
177 STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficent buffer */
178 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
179 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
181 STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
182 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
183 EXPECT_VALID; EXPECT_LENA;
185 STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
186 ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
187 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
189 STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
190 ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
191 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
193 STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
194 ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
195 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
197 STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
198 strcpy(Expected, "8:56 AM");
199 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
200 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
202 STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
203 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
204 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
206 STRINGSA("s1s2s3", ""); /* Duplicate tokens */
207 ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
208 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
210 STRINGSA("t/tt", "A/AM"); /* AM time marker */
211 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
212 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
215 STRINGSA("t/tt", "P/PM"); /* PM time marker */
216 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
217 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
219 STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
220 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
221 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
223 STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
224 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
225 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
227 STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
228 ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
229 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
231 curtime.wHour = 14; /* change this to 14 or 2pm */
234 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 */
235 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
236 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
239 STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
240 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
241 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
243 STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
244 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
245 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
247 /* try to convert formatting strings with more than two letters
248 * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
249 * NOTE: We expect any letter for which there is an upper case value
250 * we should see a replacement. For letters that DO NOT have
251 * upper case values we should see NO REPLACEMENT.
254 curtime.wMinute = 56;
255 curtime.wSecond = 13;
256 curtime.wMilliseconds = 22;
257 STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
258 "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
259 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
260 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
262 STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
263 strcpy(buffer, "text");
264 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
265 EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
267 STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
268 "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
269 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
270 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
272 STRINGSA("'''", "'"); /* invalid quoted string */
273 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
274 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
276 /* test that msdn suggested single quotation usage works as expected */
277 STRINGSA("''''", "'"); /* single quote mark */
278 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
279 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
281 STRINGSA("''HHHHHH", "08"); /* Normal use */
282 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
283 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
285 /* and test for normal use of the single quotation mark */
286 STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
287 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
288 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
290 STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
291 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
292 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
294 STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
295 ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
296 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
299 STRINGSA("'123'tt", ""); /* Invalid time */
300 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
301 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
304 curtime.wMonth = 60; /* Invalid */
305 STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
306 ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
307 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
310 static void test_GetDateFormatA()
314 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
315 char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
317 memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
318 STRINGSA("ddd',' MMM dd yy","");
319 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
320 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
322 curtime.wYear = 2002;
325 curtime.wDayOfWeek = 3;
326 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
327 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
328 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
330 STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
331 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
332 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
334 curtime.wHour = 36; /* Invalid */
335 STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
336 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
337 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
339 STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
340 ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
341 EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
343 STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
344 ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
345 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
347 STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
348 ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
349 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
351 STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
352 ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
353 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
355 /* test for expected DATE_YEARMONTH behavior with null format */
356 /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
357 STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
358 ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
359 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
361 /* Test that using invalid DATE_* flags results in the correct error */
362 /* and return values */
363 STRINGSA("m/d/y", ""); /* Invalid flags */
364 ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
365 &curtime, input, buffer, COUNTOF(buffer));
366 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
369 static void test_GetDateFormatW()
373 WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
374 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
376 STRINGSW("",""); /* If flags is not zero then format must be NULL */
377 ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
378 input, buffer, COUNTOF(buffer));
379 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
381 EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
383 STRINGSW("",""); /* NULL buffer, len > 0 */
384 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
385 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
387 STRINGSW("",""); /* NULL buffer, len == 0 */
388 ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
389 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
391 curtime.wYear = 2002;
394 curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
395 curtime.wHour = 65432; /* Invalid */
396 curtime.wMinute = 34512; /* Invalid */
397 curtime.wSecond = 65535; /* Invalid */
398 curtime.wMilliseconds = 12345;
399 STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
400 ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
401 EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
405 #define CY_POS_LEFT 0
406 #define CY_POS_RIGHT 1
407 #define CY_POS_LEFT_SPACE 2
408 #define CY_POS_RIGHT_SPACE 3
410 static void test_GetCurrencyFormatA()
412 static char szDot[] = { '.', '\0' };
413 static char szComma[] = { ',', '\0' };
414 static char szDollar[] = { '$', '\0' };
416 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
417 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
420 memset(&format, 0, sizeof(format));
422 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
423 ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
424 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
426 STRINGSA("23,53",""); /* Invalid character --> Error */
427 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
428 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
430 STRINGSA("--",""); /* Double '-' --> Error */
431 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
432 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
434 STRINGSA("0-",""); /* Trailing '-' --> Error */
435 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
436 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
438 STRINGSA("0..",""); /* Double '.' --> Error */
439 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
440 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
442 STRINGSA(" 0.1",""); /* Leading space --> Error */
443 ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
444 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
446 STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
447 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
448 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
450 STRINGSA("2353",""); /* Format and flags given --> Error */
451 ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
452 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
454 STRINGSA("2353",""); /* Invalid format --> Error */
455 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
456 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
458 STRINGSA("2353","$2,353.00"); /* Valid number */
459 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
460 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
462 STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
463 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
464 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
466 STRINGSA("2353.1","$2,353.10"); /* Valid real number */
467 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
468 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
470 STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
471 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
472 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
474 STRINGSA("2353.119","$2,353.12"); /* Too many DP --> Rounded */
475 ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
476 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
478 format.NumDigits = 0; /* No decimal separator */
479 format.LeadingZero = 0;
480 format.Grouping = 0; /* No grouping char */
481 format.NegativeOrder = 0;
482 format.PositiveOrder = CY_POS_LEFT;
483 format.lpDecimalSep = szDot;
484 format.lpThousandSep = szComma;
485 format.lpCurrencySymbol = szDollar;
487 STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
488 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
489 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
491 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
492 STRINGSA("2353","$2353.0");
493 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
494 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
496 format.Grouping = 2; /* Group by 100's */
497 STRINGSA("2353","$23,53.0");
498 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
499 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
501 format.LeadingZero = 1; /* Always provide leading zero */
502 STRINGSA(".5","$0.5");
503 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
504 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
506 format.PositiveOrder = CY_POS_RIGHT;
507 STRINGSA("1","1.0$");
508 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
509 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
511 format.PositiveOrder = CY_POS_LEFT_SPACE;
512 STRINGSA("1","$ 1.0");
513 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
514 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
516 format.PositiveOrder = CY_POS_RIGHT_SPACE;
517 STRINGSA("1","1.0 $");
518 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
519 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
521 format.NegativeOrder = 0;
522 STRINGSA("-1","($1.0)");
523 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
524 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
526 format.NegativeOrder = 1;
527 STRINGSA("-1","-$1.0");
528 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
529 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
531 format.NegativeOrder = 2;
532 STRINGSA("-1","$-1.0");
533 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
534 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
536 format.NegativeOrder = 3;
537 STRINGSA("-1","$1.0-");
538 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
539 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
541 format.NegativeOrder = 4;
542 STRINGSA("-1","(1.0$)");
543 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
544 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
546 format.NegativeOrder = 5;
547 STRINGSA("-1","-1.0$");
548 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
549 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
551 format.NegativeOrder = 6;
552 STRINGSA("-1","1.0-$");
553 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
554 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
556 format.NegativeOrder = 7;
557 STRINGSA("-1","1.0$-");
558 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
559 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
561 format.NegativeOrder = 8;
562 STRINGSA("-1","-1.0 $");
563 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
564 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
566 format.NegativeOrder = 9;
567 STRINGSA("-1","-$ 1.0");
568 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
569 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
571 format.NegativeOrder = 10;
572 STRINGSA("-1","1.0 $-");
573 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
574 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
576 format.NegativeOrder = 11;
577 STRINGSA("-1","$ 1.0-");
578 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
579 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
581 format.NegativeOrder = 12;
582 STRINGSA("-1","$ -1.0");
583 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
584 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
586 format.NegativeOrder = 13;
587 STRINGSA("-1","1.0- $");
588 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
589 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
591 format.NegativeOrder = 14;
592 STRINGSA("-1","($ 1.0)");
593 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
594 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
596 format.NegativeOrder = 15;
597 STRINGSA("-1","(1.0 $)");
598 ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
599 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
602 #define NEG_PARENS 0 /* "(1.1)" */
603 #define NEG_LEFT 1 /* "-1.1" */
604 #define NEG_LEFT_SPACE 2 /* "- 1.1" */
605 #define NEG_RIGHT 3 /* "1.1-" */
606 #define NEG_RIGHT_SPACE 4 /* "1.1 -" */
608 static void test_GetNumberFormatA()
610 static char szDot[] = { '.', '\0' };
611 static char szComma[] = { ',', '\0' };
613 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
614 char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
617 memset(&format, 0, sizeof(format));
619 STRINGSA("23",""); /* NULL output, length > 0 --> Error */
620 ret = GetNumberFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
621 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
623 STRINGSA("23,53",""); /* Invalid character --> Error */
624 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
625 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
627 STRINGSA("--",""); /* Double '-' --> Error */
628 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
629 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
631 STRINGSA("0-",""); /* Trailing '-' --> Error */
632 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
633 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
635 STRINGSA("0..",""); /* Double '.' --> Error */
636 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
637 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
639 STRINGSA(" 0.1",""); /* Leading space --> Error */
640 ret = GetNumberFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
641 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
643 STRINGSA("1234","1"); /* Length too small --> Write up to length chars */
644 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, 2);
645 EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
647 STRINGSA("2353",""); /* Format and flags given --> Error */
648 ret = GetNumberFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
649 EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
651 STRINGSA("2353",""); /* Invalid format --> Error */
652 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
653 EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
655 STRINGSA("2353","2,353.00"); /* Valid number */
656 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
657 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
659 STRINGSA("-2353","-2,353.00"); /* Valid negative number */
660 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
661 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
663 STRINGSA("2353.1","2,353.10"); /* Valid real number */
664 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
665 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
667 STRINGSA("2353.111","2,353.11"); /* Too many DP --> Truncated */
668 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
669 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
671 STRINGSA("2353.119","2,353.12"); /* Too many DP --> Rounded */
672 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
673 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
675 format.NumDigits = 0; /* No decimal separator */
676 format.LeadingZero = 0;
677 format.Grouping = 0; /* No grouping char */
678 format.NegativeOrder = 0;
679 format.lpDecimalSep = szDot;
680 format.lpThousandSep = szComma;
682 STRINGSA("2353","2353"); /* No decimal or grouping chars expected */
683 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
684 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
686 format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
687 STRINGSA("2353","2353.0");
688 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
689 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
691 format.Grouping = 2; /* Group by 100's */
692 STRINGSA("2353","23,53.0");
693 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
694 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
696 format.LeadingZero = 1; /* Always provide leading zero */
697 STRINGSA(".5","0.5");
698 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
699 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
701 format.NegativeOrder = NEG_PARENS;
702 STRINGSA("-1","(1.0)");
703 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
704 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
706 format.NegativeOrder = NEG_LEFT;
707 STRINGSA("-1","-1.0");
708 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
709 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
711 format.NegativeOrder = NEG_LEFT_SPACE;
712 STRINGSA("-1","- 1.0");
713 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
714 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
716 format.NegativeOrder = NEG_RIGHT;
717 STRINGSA("-1","1.0-");
718 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
719 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
721 format.NegativeOrder = NEG_RIGHT_SPACE;
722 STRINGSA("-1","1.0 -");
723 ret = GetNumberFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
724 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
726 lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
728 if (IsValidLocale(lcid, 0))
730 STRINGSA("-12345","-12 345,00"); /* Try French formatting */
731 Expected[3] = 160; /* Non breaking space */
732 ret = GetNumberFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
733 EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
738 /* Callback function used by TestEnumTimeFormats */
739 static BOOL CALLBACK EnumTimeFormatsProc(char * lpTimeFormatString)
741 trace("%s\n", lpTimeFormatString);
742 strcpy(GlobalBuffer, lpTimeFormatString);
749 void test_EnumTimeFormats()
752 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
754 GlobalBuffer[0] = '\0';
755 ret = EnumTimeFormatsA(EnumTimeFormatsProc, lcid, 0);
756 ok (ret == 1 && !strcmp(GlobalBuffer,"h:mm:ss tt"), "Expected %d '%s'\n", ret, GlobalBuffer);
759 static void test_CompareStringA()
762 LCID lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
764 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "Salute", -1);
765 ok (ret== 1, "(Salut/Salute) Expected 1, got %d\n", ret);
767 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "SaLuT", -1);
768 ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
770 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", -1, "hola", -1);
771 ok (ret== 3, "(Salut/hola) Expected 3, got %d\n", ret);
773 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
774 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
776 lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
778 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", -1);
779 ok (ret== 1, "(haha/hoho) Expected 1, got %d\n", ret);
781 ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
782 ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
784 ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
785 ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
787 SetLastError(0xdeadbeef);
788 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
789 ok(GetLastError() == ERROR_INVALID_FLAGS,
790 "unexpected error code %ld\n", GetLastError());
791 ok(!ret, "CompareStringA must fail with invalid flag\n");
793 ret = lstrcmpA("", "");
794 ok (!ret, "lstrcmpA(\"\", \"\") should return 0, got %d", ret);
796 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
797 ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d", ret);
799 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
800 ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d", ret);
802 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
803 ok( ret == 3, "r vs \\ ... expected 3, got %d", ret);
805 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
806 ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d", ret);
808 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
809 ok( ret == 3, "AAA vs aaa expected 3, got %d", ret);
811 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
812 ok( ret == 1, "AAA vs aab expected 1, got %d", ret);
814 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
815 ok( ret == 1, "AAA vs Aab expected 1, got %d", ret);
817 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
818 ok( ret == 1, ".AAA vs Aab expected 1, got %d", ret);
820 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
821 ok( ret == 1, ".AAA vs A.ab expected 1, got %d", ret);
823 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
824 ok( ret == 1, "aa vs AB expected 1, got %d", ret);
826 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
827 ok( ret == 1, "aa vs Aab expected 1, got %d", ret);
829 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
830 ok( ret == 3, "aB vs Aab expected 3, got %d", ret);
832 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
833 ok( ret == 1, "Ba vs bab expected 1, got %d", ret);
835 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
836 ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d", ret);
838 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
839 ok( ret == 3, "a vs { expected 3, got %d", ret);
841 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
842 ok( ret == 3, "A vs { expected 3, got %d", ret);
844 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
845 ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d", ret);
847 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
848 ok(ret == 1, "3.5 vs 4.0 expected 1, got %d", ret);
850 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
851 ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d", ret);
853 /* hyphen and apostrophe are treated differently depending on
854 * whether SORT_STRINGSORT specified or not
856 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
857 ok(ret == 3, "-o vs /m expected 3, got %d", ret);
859 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
860 ok(ret == 1, "/m vs -o expected 1, got %d", ret);
862 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
863 ok(ret == 1, "-o vs /m expected 1, got %d", ret);
865 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
866 ok(ret == 3, "/m vs -o expected 3, got %d", ret);
868 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
869 ok(ret == 3, "'o vs /m expected 3, got %d", ret);
871 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
872 ok(ret == 1, "/m vs 'o expected 1, got %d", ret);
874 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
875 ok(ret == 1, "'o vs /m expected 1, got %d", ret);
877 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
878 ok(ret == 3, "/m vs 'o expected 3, got %d", ret);
880 #if 0 /* this requires collation table patch to make it MS compatible */
881 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
882 ok(ret == 1, "'o vs -o expected 1, got %d", ret);
884 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
885 ok(ret == 1, "'o vs -o expected 1, got %d", ret);
887 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
888 ok(ret == 1, "' vs - expected 1, got %d", ret);
890 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
891 ok(ret == 1, "' vs - expected 1, got %d", ret);
893 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
894 ok(ret == 3, "`o vs /m expected 3, got %d", ret);
896 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
897 ok(ret == 1, "/m vs `o expected 1, got %d", ret);
899 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
900 ok(ret == 3, "`o vs /m expected 3, got %d", ret);
902 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
903 ok(ret == 1, "/m vs `o expected 1, got %d", ret);
905 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
906 ok(ret == 1, "`o vs -m expected 1, got %d", ret);
908 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
909 ok(ret == 3, "-m vs `o expected 3, got %d", ret);
911 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
912 ok(ret == 3, "`o vs -m expected 3, got %d", ret);
914 ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
915 ok(ret == 1, "-m vs `o expected 1, got %d", ret);
918 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
919 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d", ret);
921 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
922 ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d", ret);
924 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
925 ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d", ret);
927 ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
928 ok(ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d", ret);
931 void test_LCMapStringA(void)
934 char buf[256], buf2[256];
935 static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
936 static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
937 static const char symbols_stripped[] = "justateststring1";
939 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
940 upper_case, -1, buf, sizeof(buf));
941 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
942 ok(GetLastError() == ERROR_INVALID_FLAGS,
943 "unexpected error code %ld\n", GetLastError());
945 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
946 upper_case, -1, buf, sizeof(buf));
947 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
948 ok(GetLastError() == ERROR_INVALID_FLAGS,
949 "unexpected error code %ld\n", GetLastError());
951 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
953 upper_case, -1, buf, sizeof(buf));
954 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
955 ok(GetLastError() == ERROR_INVALID_FLAGS,
956 "unexpected error code %ld\n", GetLastError());
958 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
959 upper_case, -1, buf, sizeof(buf));
960 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
961 ok(GetLastError() == ERROR_INVALID_FLAGS,
962 "unexpected error code %ld\n", GetLastError());
964 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
965 SetLastError(0xdeadbeef);
966 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
967 upper_case, -1, buf, sizeof(buf));
968 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
969 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
971 /* test LCMAP_LOWERCASE */
972 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
973 upper_case, -1, buf, sizeof(buf));
974 ok(ret == lstrlenA(upper_case) + 1,
975 "ret %d, error %ld, expected value %d\n",
976 ret, GetLastError(), lstrlenA(upper_case) + 1);
977 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
979 /* test LCMAP_UPPERCASE */
980 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
981 lower_case, -1, buf, sizeof(buf));
982 ok(ret == lstrlenA(lower_case) + 1,
983 "ret %d, error %ld, expected value %d\n",
984 ret, GetLastError(), lstrlenA(lower_case) + 1);
985 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
987 /* test buffer overflow */
988 SetLastError(0xdeadbeef);
989 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
990 lower_case, -1, buf, 4);
991 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
992 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
994 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
995 lstrcpyA(buf, lower_case);
996 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
997 buf, -1, buf, sizeof(buf));
998 if (!ret) /* Win9x */
999 trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
1002 ok(ret == lstrlenA(lower_case) + 1,
1003 "ret %d, error %ld, expected value %d\n",
1004 ret, GetLastError(), lstrlenA(lower_case) + 1);
1005 ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
1007 lstrcpyA(buf, upper_case);
1008 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1009 buf, -1, buf, sizeof(buf));
1010 if (!ret) /* Win9x */
1011 trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
1014 ok(ret == lstrlenA(upper_case) + 1,
1015 "ret %d, error %ld, expected value %d\n",
1016 ret, GetLastError(), lstrlenA(lower_case) + 1);
1017 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1020 /* otherwise src == dst should fail */
1021 SetLastError(0xdeadbeef);
1022 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1023 buf, 10, buf, sizeof(buf));
1024 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1025 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1026 "unexpected error code %ld\n", GetLastError());
1027 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1029 /* test whether '\0' is always appended */
1030 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1031 upper_case, -1, buf, sizeof(buf));
1032 ok(ret, "LCMapStringA must succeed\n");
1033 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1034 upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
1035 ok(ret, "LCMapStringA must succeed\n");
1036 ok(ret == ret2, "lengths of sort keys must be equal\n");
1037 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1039 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1040 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1041 upper_case, -1, buf, sizeof(buf));
1042 ok(ret, "LCMapStringA must succeed\n");
1043 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1044 lower_case, -1, buf2, sizeof(buf2));
1045 ok(ret2, "LCMapStringA must succeed\n");
1046 ok(ret == ret2, "lengths of sort keys must be equal\n");
1047 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1049 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1050 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1051 lower_case, -1, buf, sizeof(buf));
1052 ok(ret, "LCMapStringA must succeed\n");
1053 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1054 lower_case, -1, buf2, sizeof(buf2));
1055 ok(ret2, "LCMapStringA must succeed\n");
1056 ok(ret == ret2, "lengths of sort keys must be equal\n");
1057 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1059 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1060 ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1061 lower_case, -1, buf, sizeof(buf));
1062 ok(ret, "LCMapStringA must succeed\n");
1063 ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1064 symbols_stripped, -1, buf2, sizeof(buf2));
1065 ok(ret2, "LCMapStringA must succeed\n");
1066 ok(ret == ret2, "lengths of sort keys must be equal\n");
1067 ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
1069 /* test NORM_IGNORENONSPACE */
1070 lstrcpyA(buf, "foo");
1071 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1072 lower_case, -1, buf, sizeof(buf));
1073 ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
1074 lstrlenA(lower_case) + 1, ret);
1075 ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1077 /* test NORM_IGNORESYMBOLS */
1078 lstrcpyA(buf, "foo");
1079 ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1080 lower_case, -1, buf, sizeof(buf));
1081 ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
1082 lstrlenA(symbols_stripped) + 1, ret);
1083 ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
1085 /* test srclen = 0 */
1086 SetLastError(0xdeadbeef);
1087 ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1088 ok(!ret, "LCMapStringA should fail with srclen = 0");
1089 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1090 "unexpected error code %ld\n", GetLastError());
1093 void test_LCMapStringW(void)
1096 WCHAR buf[256], buf2[256];
1097 char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
1098 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};
1099 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};
1100 static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
1101 static const WCHAR fooW[] = {'f','o','o',0};
1103 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
1104 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1105 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1107 trace("Skipping LCMapStringW tests on Win9x\n");
1110 ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
1111 ok(GetLastError() == ERROR_INVALID_FLAGS,
1112 "unexpected error code %ld\n", GetLastError());
1114 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
1115 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1116 ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
1117 ok(GetLastError() == ERROR_INVALID_FLAGS,
1118 "unexpected error code %ld\n", GetLastError());
1120 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
1121 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1122 ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
1123 ok(GetLastError() == ERROR_INVALID_FLAGS,
1124 "unexpected error code %ld\n", GetLastError());
1126 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
1127 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1128 ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
1129 ok(GetLastError() == ERROR_INVALID_FLAGS,
1130 "unexpected error code %ld\n", GetLastError());
1132 /* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
1133 SetLastError(0xdeadbeef);
1134 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
1135 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1136 ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
1137 ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
1139 /* test LCMAP_LOWERCASE */
1140 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1141 upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1142 ok(ret == lstrlenW(upper_case) + 1,
1143 "ret %d, error %ld, expected value %d\n",
1144 ret, GetLastError(), lstrlenW(upper_case) + 1);
1145 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1147 /* test LCMAP_UPPERCASE */
1148 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1149 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1150 ok(ret == lstrlenW(lower_case) + 1,
1151 "ret %d, error %ld, expected value %d\n",
1152 ret, GetLastError(), lstrlenW(lower_case) + 1);
1153 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1155 /* test buffer overflow */
1156 SetLastError(0xdeadbeef);
1157 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1158 lower_case, -1, buf, 4);
1159 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
1160 "should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
1162 /* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
1163 lstrcpyW(buf, lower_case);
1164 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
1165 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1166 ok(ret == lstrlenW(lower_case) + 1,
1167 "ret %d, error %ld, expected value %d\n",
1168 ret, GetLastError(), lstrlenW(lower_case) + 1);
1169 ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
1171 lstrcpyW(buf, upper_case);
1172 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
1173 buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
1174 ok(ret == lstrlenW(upper_case) + 1,
1175 "ret %d, error %ld, expected value %d\n",
1176 ret, GetLastError(), lstrlenW(lower_case) + 1);
1177 ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
1179 /* otherwise src == dst should fail */
1180 SetLastError(0xdeadbeef);
1181 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
1182 buf, 10, buf, sizeof(buf));
1183 ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
1184 GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
1185 "unexpected error code %ld\n", GetLastError());
1186 ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
1188 /* test whether '\0' is always appended */
1189 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1190 upper_case, -1, buf, sizeof(buf));
1191 ok(ret, "LCMapStringW must succeed\n");
1192 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1193 upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
1194 ok(ret, "LCMapStringW must succeed\n");
1195 ok(ret == ret2, "lengths of sort keys must be equal\n");
1196 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1198 /* test LCMAP_SORTKEY | NORM_IGNORECASE */
1199 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
1200 upper_case, -1, buf, sizeof(buf));
1201 ok(ret, "LCMapStringW must succeed\n");
1202 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1203 lower_case, -1, buf2, sizeof(buf2));
1204 ok(ret2, "LCMapStringW must succeed\n");
1205 ok(ret == ret2, "lengths of sort keys must be equal\n");
1206 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1208 /* test LCMAP_SORTKEY | NORM_IGNORENONSPACE */
1209 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORENONSPACE,
1210 lower_case, -1, buf, sizeof(buf));
1211 ok(ret, "LCMapStringW must succeed\n");
1212 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1213 lower_case, -1, buf2, sizeof(buf2));
1214 ok(ret2, "LCMapStringW must succeed\n");
1215 ok(ret == ret2, "lengths of sort keys must be equal\n");
1216 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1218 /* test LCMAP_SORTKEY | NORM_IGNORESYMBOLS */
1219 ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORESYMBOLS,
1220 lower_case, -1, buf, sizeof(buf));
1221 ok(ret, "LCMapStringW must succeed\n");
1222 ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
1223 symbols_stripped, -1, buf2, sizeof(buf2));
1224 ok(ret2, "LCMapStringW must succeed\n");
1225 ok(ret == ret2, "lengths of sort keys must be equal\n");
1226 ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
1228 /* test NORM_IGNORENONSPACE */
1229 lstrcpyW(buf, fooW);
1230 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
1231 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1232 ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
1233 lstrlenW(lower_case) + 1, ret);
1234 ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
1236 /* test NORM_IGNORESYMBOLS */
1237 lstrcpyW(buf, fooW);
1238 ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
1239 lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
1240 ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
1241 lstrlenW(symbols_stripped) + 1, ret);
1242 ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
1244 /* test srclen = 0 */
1245 SetLastError(0xdeadbeef);
1246 ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
1247 ok(!ret, "LCMapStringW should fail with srclen = 0");
1248 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1249 "unexpected error code %ld\n", GetLastError());
1252 #if 0 /* this requires collation table patch to make it MS compatible */
1253 const char *strings_sorted[] =
1285 const char *strings[] =
1317 static int compare_string1(const void *e1, const void *e2)
1319 const char *s1 = *(const char **)e1;
1320 const char *s2 = *(const char **)e2;
1322 return lstrcmpA(s1, s2);
1325 static int compare_string2(const void *e1, const void *e2)
1327 const char *s1 = *(const char **)e1;
1328 const char *s2 = *(const char **)e2;
1330 return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
1333 static int compare_string3(const void *e1, const void *e2)
1335 const char *s1 = *(const char **)e1;
1336 const char *s2 = *(const char **)e2;
1337 char key1[256], key2[256];
1339 LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
1340 LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
1341 return strcmp(key1, key2);
1344 static void test_sorting(void)
1347 char **str_buf = (char **)buf;
1350 assert(sizeof(buf) >= sizeof(strings));
1352 /* 1. sort using lstrcmpA */
1353 memcpy(buf, strings, sizeof(strings));
1354 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
1355 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1357 ok(!strcmp(strings_sorted[i], str_buf[i]),
1358 "qsort using lstrcmpA failed for element %d\n", i);
1360 /* 2. sort using CompareStringA */
1361 memcpy(buf, strings, sizeof(strings));
1362 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
1363 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1365 ok(!strcmp(strings_sorted[i], str_buf[i]),
1366 "qsort using CompareStringA failed for element %d\n", i);
1368 /* 3. sort using sort keys */
1369 memcpy(buf, strings, sizeof(strings));
1370 qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
1371 for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
1373 ok(!strcmp(strings_sorted[i], str_buf[i]),
1374 "qsort using sort keys failed for element %d\n", i);
1379 static void test_FoldStringA(void)
1382 char src[256], dst[256];
1383 static const char digits_src[] = { 0xB9,0xB2,0xB3,'\0' };
1384 static const char digits_dst[] = { '1','2','3','\0' };
1385 static const char composite_src[] =
1387 0x8a,0x8e,0x9a,0x9e,0x9f,0xc0,0xc1,0xc2,
1388 0xc3,0xc4,0xc5,0xc7,0xc8,0xc9,0xca,0xcb,
1389 0xcc,0xcd,0xce,0xcf,0xd1,0xd2,0xd3,0xd4,
1390 0xd5,0xd6,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,
1391 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe7,0xe8,
1392 0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf1,
1393 0xf2,0xf3,0xf4,0xf5,0xf6,0xf8,0xf9,0xfa,
1394 0xfb,0xfc,0xfd,0xff,'\0'
1396 static const char composite_dst[] =
1398 0x53,0x3f,0x5a,0x3f,0x73,0x3f,0x7a,0x3f,
1399 0x59,0xa8,0x41,0x60,0x41,0xb4,0x41,0x5e,
1400 0x41,0x7e,0x41,0xa8,0x41,0xb0,0x43,0xb8,
1401 0x45,0x60,0x45,0xb4,0x45,0x5e,0x45,0xa8,
1402 0x49,0x60,0x49,0xb4,0x49,0x5e,0x49,0xa8,
1403 0x4e,0x7e,0x4f,0x60,0x4f,0xb4,0x4f,0x5e,
1404 0x4f,0x7e,0x4f,0xa8,0x4f,0x3f,0x55,0x60,
1405 0x55,0xb4,0x55,0x5e,0x55,0xa8,0x59,0xb4,
1406 0x61,0x60,0x61,0xb4,0x61,0x5e,0x61,0x7e,
1407 0x61,0xa8,0x61,0xb0,0x63,0xb8,0x65,0x60,
1408 0x65,0xb4,0x65,0x5e,0x65,0xa8,0x69,0x60,
1409 0x69,0xb4,0x69,0x5e,0x69,0xa8,0x6e,0x7e,
1410 0x6f,0x60,0x6f,0xb4,0x6f,0x5e,0x6f,0x7e,
1411 0x6f,0xa8,0x6f,0x3f,0x75,0x60,0x75,0xb4,
1412 0x75,0x5e,0x75,0xa8,0x79,0xb4,0x79,0xa8,'\0'
1414 static const char ligatures_src[] =
1416 0x8C,0x9C,0xC6,0xDE,0xDF,0xE6,0xFE,'\0'
1418 static const char ligatures_dst[] =
1420 'O','E','o','e','A','E','T','H','s','s','a','e','t','h','\0'
1424 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1426 /* these tests are locale specific */
1427 if (GetACP() != 1252)
1429 trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
1433 /* MAP_FOLDDIGITS */
1435 ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
1436 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1438 EXPECT_LEN(4); EXPECT_VALID;
1439 ok(strcmp(dst, digits_dst) == 0,
1440 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", digits_dst, dst);
1441 for (i = 1; i < 256; i++)
1443 if (!strchr(digits_src, i))
1448 ret = pFoldStringA(MAP_FOLDDIGITS, src, -1, dst, 256);
1449 EXPECT_LEN(2); EXPECT_VALID;
1450 ok(dst[0] == src[0],
1451 "MAP_FOLDDIGITS: Expected '%s', got '%s'\n", src, dst);
1455 /* MAP_EXPAND_LIGATURES */
1457 ret = pFoldStringA(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1458 EXPECT_LEN(sizeof(ligatures_dst)); EXPECT_VALID;
1459 ok(strcmp(dst, ligatures_dst) == 0,
1460 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", ligatures_dst, dst);
1461 for (i = 1; i < 256; i++)
1463 if (!strchr(ligatures_src, i))
1468 ret = pFoldStringA(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1469 EXPECT_LEN(2); EXPECT_VALID;
1470 ok(dst[0] == src[0],
1471 "MAP_EXPAND_LIGATURES: Expected '%s', got '%s'\n", src, dst);
1477 ret = pFoldStringA(MAP_COMPOSITE, composite_src, -1, dst, 256);
1481 /* Wine gets close, but doesn't produce quite the same result as native */
1483 ok(strcmp(dst, composite_dst) == 0,
1484 "MAP_COMPOSITE: Expected '%s', got '%s'\n", composite_dst, dst);
1487 for (i = 1; i < 256; i++)
1489 if (!strchr(composite_src, i))
1494 ret = pFoldStringA(MAP_COMPOSITE, src, -1, dst, 256);
1495 EXPECT_LEN(2); EXPECT_VALID;
1496 ok(dst[0] == src[0],
1497 "0x%02x, 0x%02x,0x%02x,0x%02x,\n", (unsigned char)src[0],
1498 (unsigned char)dst[0],(unsigned char)dst[1],(unsigned char)dst[2]);
1503 for (i = 1; i < 256; i++)
1508 ret = pFoldStringA(MAP_FOLDCZONE, src, -1, dst, 256);
1509 EXPECT_LEN(2); EXPECT_VALID;
1510 ok(src[0] == dst[0],
1511 "MAP_FOLDCZONE: Expected 0x%02x, got 0x%02x\n",
1512 (unsigned char)src[0], (unsigned char)dst[0]);
1515 /* MAP_PRECOMPOSED */
1516 for (i = 1; i < 256; i++)
1521 ret = pFoldStringA(MAP_PRECOMPOSED, src, -1, dst, 256);
1522 EXPECT_LEN(2); EXPECT_VALID;
1523 ok(src[0] == dst[0],
1524 "MAP_PRECOMPOSED: Expected 0x%02x, got 0x%02x\n",
1525 (unsigned char)src[0], (unsigned char)dst[0]);
1529 static void test_FoldStringW(void)
1533 WCHAR src[256], dst[256], ch, prev_ch = 1;
1534 static const DWORD badFlags[] =
1537 MAP_PRECOMPOSED|MAP_COMPOSITE,
1538 MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES,
1539 MAP_COMPOSITE|MAP_EXPAND_LIGATURES
1541 /* Ranges of digits 0-9 : Must be sorted! */
1542 static const WCHAR digitRanges[] =
1544 0x0030, /* '0'-'9' */
1545 0x0660, /* Eastern Arabic */
1546 0x06F0, /* Arabic - Hindu */
1547 0x0966, /* Devengari */
1548 0x09E6, /* Bengalii */
1549 0x0A66, /* Gurmukhi */
1550 0x0AE6, /* Gujarati */
1552 0x0BE6, /* Tamil - No 0 */
1553 0x0C66, /* Telugu */
1554 0x0CE6, /* Kannada */
1555 0x0D66, /* Maylayalam */
1558 0x2070, /* Superscript - 1, 2, 3 are out of sequence */
1559 0x2080, /* Subscript */
1560 0x245F, /* Circled - 0 is out of sequence */
1561 0x2473, /* Bracketed */
1562 0x2487, /* Full stop */
1563 0x2775, /* Inverted circled - No 0 */
1564 0x277F, /* Patterned circled - No 0 */
1565 0x2789, /* Inverted Patterned circled - No 0 */
1566 0xff10, /* Pliene chasse (?) */
1567 0xffff /* Terminator */
1569 /* Digits which are represented, but out of sequence */
1570 static const WCHAR outOfSequenceDigits[] =
1572 0xB9, /* Superscript 1 */
1573 0xB2, /* Superscript 2 */
1574 0xB3, /* Superscript 3 */
1575 0x24EA, /* Circled 0 */
1576 '\0' /* Terminator */
1578 /* Digits in digitRanges for which no representation is available */
1579 static const WCHAR noDigitAvailable[] =
1581 0x0BE6, /* No Tamil 0 */
1582 0x2473, /* No Bracketed 0 */
1583 0x2487, /* No 0 Full stop */
1584 0x2775, /* No inverted circled 0 */
1585 0x277F, /* No patterned circled */
1586 0x2789, /* No inverted Patterned circled */
1587 '\0' /* Terminator */
1589 /* Compatibility conversion results */
1590 static const WCHAR compat_F900_FA2F[256+48] =
1592 0x8c48, 0x66f4, 0x8eca, 0x8cc8, 0x6ed1, 0x4e32, 0x53e5, 0x9f9c,
1593 0x9f9c, 0x5951, 0x91d1, 0x5587, 0x5948, 0x61f6, 0x7669, 0x7f85,
1594 0x863f, 0x87ba, 0x88f8, 0x908f, 0x6a02, 0x6d1b, 0x70d9, 0x73de,
1595 0x843d, 0x916a, 0x99f1, 0x4e82, 0x5375, 0x6b04, 0x721b, 0x862d,
1596 0x9e1e, 0x5d50, 0x6feb, 0x85cd, 0x8964, 0x62c9, 0x81d8, 0x881f,
1597 0x5eca, 0x6717, 0x6d6a, 0x72fc, 0x0000, 0x4f86, 0x51b7, 0x52de,
1598 0x64c4, 0x6ad3, 0x7210, 0x76e7, 0x8001, 0x8606, 0x865c, 0x8def,
1599 0x9732, 0x9b6f, 0x9dfa, 0x788c, 0x797f, 0x7da0, 0x83c9, 0x9304,
1600 0x9e7f, 0x8ad6, 0x58df, 0x5f04, 0x7c60, 0x807e, 0x7262, 0x78ca,
1601 0x8cc2, 0x96f7, 0x58d8, 0x5c62, 0x6a13, 0x6dda, 0x6f0f, 0x7d2f,
1602 0x7e37, 0x964b, 0x52d2, 0x808b, 0x51dc, 0x51cc, 0x7a1c, 0x7dbe,
1603 0x83f1, 0x9675, 0x8b80, 0x62cf, 0x6a02, 0x8afe, 0x4e39, 0x5be7,
1604 0x6012, 0x7387, 0x7570, 0x5317, 0x78fb, 0x4fbf, 0x5fa9, 0x4e0d,
1605 0x6ccc, 0x6578, 0x7d22, 0x53c3, 0x585e, 0x7701, 0x8449, 0x8aaa,
1606 0x6bba, 0x8fb0, 0x6c88, 0x62fe, 0x82e5, 0x63a0, 0x7565, 0x4eae,
1607 0x5169, 0x0000, 0x6881, 0x7ce7, 0x826f, 0x8ad2, 0x91cf, 0x52f5,
1608 0x5442, 0x5973, 0x5eec, 0x65c5, 0x6ffe, 0x792a, 0x95ad, 0x9a6a,
1609 0x9e97, 0x9ece, 0x529b, 0x66c6, 0x6b77, 0x8f62, 0x5e74, 0x6190,
1610 0x6200, 0x649a, 0x6f23, 0x7149, 0x7489, 0x0000, 0x7df4, 0x806f,
1611 0x8f26, 0x84ee, 0x9023, 0x934a, 0x5217, 0x52a3, 0x54bd, 0x70c8,
1612 0x88c2, 0x8aaa, 0x5ec9, 0x5ff5, 0x637b, 0x6bae, 0x7c3e, 0x7375,
1613 0x4ee4, 0x56f9, 0x5be7, 0x5dba, 0x601c, 0x73b2, 0x7469, 0x7f9a,
1614 0x8046, 0x9234, 0x96f6, 0x9748, 0x9818, 0x4f8b, 0x79ae, 0x91b4,
1615 0x96b8, 0x60e1, 0x4e86, 0x50da, 0x5bee, 0x5c3f, 0x6599, 0x6a02,
1616 0x71ce, 0x7642, 0x84fc, 0x907c, 0x9f8d, 0x6688, 0x962e, 0x5289,
1617 0x677b, 0x67f3, 0x6d41, 0x6e9c, 0x7409, 0x7559, 0x786b, 0x7d10,
1618 0x985e, 0x516d, 0x622e, 0x9678, 0x502b, 0x5d19, 0x6dea, 0x8f2a,
1619 0x5f8b, 0x6144, 0x6817, 0x7387, 0x9686, 0x5229, 0x540f, 0x5c65,
1620 0x6613, 0x674e, 0x68a8, 0x6ce5, 0x7406, 0x75e2, 0x7f79, 0x0000,
1621 0x88e1, 0x91cc, 0x96e2, 0x533f, 0x6eba, 0x541d, 0x71d0, 0x7498,
1622 0x85fa, 0x0000, 0x9c57, 0x9e9f, 0x6797, 0x6dcb, 0x81e8, 0x7acb,
1623 0x7b20, 0x7c92, 0x72c0, 0x7099, 0x8b58, 0x4ec0, 0x8336, 0x523a,
1624 0x5207, 0x5ea6, 0x62d3, 0x7cd6, 0x5b85, 0x6d1e, 0x66b4, 0x8f3b,
1625 0x884c, 0x964d, 0x898b, 0x5ed3, 0x0000, 0x0000, 0x0000, 0x0000,
1626 0x585a, 0x0000, 0x6674, 0x0000, 0x0000, 0x51de, 0x8c6c, 0x76ca,
1627 0x0000, 0x795e, 0x7965, 0x798f, 0x9756, 0x7cbe, 0x7fbd, 0x0000,
1628 0x0000, 0x0000, 0x8af8, 0x0000, 0x0000, 0x9038, 0x90fd, 0x0000,
1629 0x0000, 0x0000, 0x98ef, 0x98fc, 0x9928, 0x9db4, 0x0000, 0x0000
1631 static const WCHAR compat_FE30_FEF7[200] =
1633 0x2025, 0x2014, 0x2013, 0x005f, 0x005f, 0x0028, 0x0029, 0x007b,
1634 0x007d, 0x3014, 0x3015, 0x3010, 0x3011, 0x300a, 0x300b, 0x3008,
1635 0x3009, 0x300c, 0x300d, 0x300e, 0x300f, 0x0000, 0x0000, 0x0000,
1636 0x0000, 0x203e, 0x203e, 0x203e, 0x203e, 0x005f, 0x005f, 0x005f,
1637 0x002c, 0x3001, 0x002e, 0x0000, 0x003b, 0x003a, 0x003f, 0x0021,
1638 0x2014, 0x0028, 0x0029, 0x007b, 0x007d, 0x3014, 0x3015, 0x0023,
1639 0x0026, 0x002a, 0x002b, 0x002d, 0x003c, 0x003e, 0x003d, 0x0000,
1640 0x0000, 0x0024, 0x0025, 0x0040, 0x0000, 0x0000, 0x0000, 0x0000,
1641 0x064b, 0x064b, 0x064c, 0x0000, 0x064d, 0x0000, 0x064e, 0x064e,
1642 0x064f, 0x064f, 0x0650, 0x0650, 0x0651, 0x0651, 0x0652, 0x0652,
1643 0x0621, 0x0622, 0x0622, 0x0623, 0x0623, 0x0624, 0x0624, 0x0625,
1644 0x0625, 0x0626, 0x0626, 0x0626, 0x0626, 0x0627, 0x0627, 0x0628,
1645 0x0628, 0x0628, 0x0628, 0x0629, 0x0629, 0x062a, 0x062a, 0x062a,
1646 0x062a, 0x062b, 0x062b, 0x062b, 0x062b, 0x062c, 0x062c, 0x062c,
1647 0x062c, 0x062d, 0x062d, 0x062d, 0x062d, 0x062e, 0x062e, 0x062e,
1648 0x062e, 0x062f, 0x062f, 0x0630, 0x0630, 0x0631, 0x0631, 0x0632,
1649 0x0632, 0x0633, 0x0633, 0x0633, 0x0633, 0x0634, 0x0634, 0x0634,
1650 0x0634, 0x0635, 0x0635, 0x0635, 0x0635, 0x0636, 0x0636, 0x0636,
1651 0x0636, 0x0637, 0x0637, 0x0637, 0x0637, 0x0638, 0x0638, 0x0638,
1652 0x0638, 0x0639, 0x0639, 0x0639, 0x0639, 0x063a, 0x063a, 0x063a,
1653 0x063a, 0x0641, 0x0641, 0x0641, 0x0641, 0x0642, 0x0642, 0x0642,
1654 0x0642, 0x0643, 0x0643, 0x0643, 0x0643, 0x0644, 0x0644, 0x0644,
1655 0x0644, 0x0645, 0x0645, 0x0645, 0x0645, 0x0646, 0x0646, 0x0646,
1656 0x0646, 0x0647, 0x0647, 0x0647, 0x0647, 0x0648, 0x0648, 0x0649,
1657 0x0649, 0x064a, 0x064a, 0x064a, 0x064a, 0x0000, 0x0000, 0x0000
1659 static const WCHAR compat_FF00_FFEF[240] =
1661 0x0000, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
1662 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
1663 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
1664 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
1665 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
1666 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
1667 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
1668 0x0058, 0x0059, 0x005a, 0x005b, 0x0000, 0x005d, 0x005e, 0x005f,
1669 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
1670 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
1671 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
1672 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000,
1673 0x0000, 0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1,
1674 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3,
1675 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad,
1676 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd,
1677 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc,
1678 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de,
1679 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9,
1680 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c,
1681 0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1682 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1683 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1684 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x0000,
1685 0x0000, 0x0000, 0x314f, 0x3150, 0x3151, 0x3152, 0x3153, 0x3154,
1686 0x0000, 0x0000, 0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a,
1687 0x0000, 0x0000, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160,
1688 0x0000, 0x0000, 0x3161, 0x3162, 0x3163, 0x0000, 0x0000, 0x0000,
1689 0x00a2, 0x00a3, 0x00ac, 0x00af, 0x00a6, 0x00a5, 0x20a9, 0x0000,
1690 0x2502, 0x2190, 0x2191, 0x2192, 0x2193, 0x25a0, 0x25cb, 0x0000
1692 static const WCHAR ligatures_src[] =
1694 0x00c6, 0x00de, 0x00df, 0x00e6, 0x00fe, 0x0132, 0x0133, 0x0152,
1695 0x0153, 0x01c4, 0x01c5, 0x01c6, 0x01c7, 0x01c8, 0x01c9, 0x01ca,
1696 0x01cb, 0x01cc, 0x01e2, 0x01e3, 0x01f1, 0x01f2, 0x01f3, 0x01fc,
1697 0x01fd, 0x05f0, 0x05f1, 0x05f2, 0xfb00, 0xfb01, 0xfb02, 0xfb03,
1698 0xfb04, 0xfb05, 0xfb06, '\0'
1700 static const WCHAR ligatures_dst[] =
1702 'A','E','T','H','s','s','a','e','t','h','I','J','i','j','O','E','o','e',
1703 'D',0x017d,'D',0x017e,'d',0x017e,'L','J','L','j','l','j','N','J','N','j',
1704 'n','j',0x0100,0x0112,0x0101,0x0113,'D','Z','D','z','d','z',0x00c1,0x00c9,
1705 0x00e1,0x00e9,0x05d5,0x05d5,0x05d5,0x05d9,0x05d9,0x05d9,'f','f','f','i',
1706 'f','l','f','f','i','f','f','l',0x017f,'t','s','t','\0'
1710 return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
1712 /* Invalid flag combinations */
1713 for (i = 0; i < sizeof(badFlags)/sizeof(badFlags[0]); i++)
1715 src[0] = dst[0] = '\0';
1717 ret = pFoldStringW(badFlags[i], src, 256, dst, 256);
1718 if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
1720 EXPECT_LEN(0); EXPECT_FLAGS;
1723 /* src & dst cannot be the same */
1725 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, src, 256);
1726 EXPECT_LEN(0); EXPECT_INVALID;
1728 /* src can't be NULL */
1730 ret = pFoldStringW(MAP_FOLDCZONE, NULL, -1, dst, 256);
1731 EXPECT_LEN(0); EXPECT_INVALID;
1733 /* srclen can't be 0 */
1735 ret = pFoldStringW(MAP_FOLDCZONE, src, 0, dst, 256);
1736 EXPECT_LEN(0); EXPECT_INVALID;
1738 /* dstlen can't be < 0 */
1740 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, -1);
1741 EXPECT_LEN(0); EXPECT_INVALID;
1743 /* Ret includes terminating NUL which is appended if srclen = -1 */
1748 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1749 EXPECT_LEN(2); EXPECT_VALID;
1750 ok(dst[0] == 'A' && dst[1] == '\0',
1751 "srclen=-1: Expected ret=2 [%d,%d], got ret=%d [%d,%d], err=%ld\n",
1752 'A', '\0', ret, dst[0], dst[1], GetLastError());
1754 /* If size is given, result is not NUL terminated */
1760 ret = pFoldStringW(MAP_FOLDCZONE, src, 1, dst, 256);
1761 EXPECT_LEN(1); EXPECT_VALID;
1762 ok(dst[0] == 'A' && dst[1] == 'X',
1763 "srclen=1: Expected ret=1, [%d,%d], got ret=%d,[%d,%d], err=%ld\n",
1764 'A','X', ret, dst[0], dst[1], GetLastError());
1766 /* MAP_FOLDDIGITS */
1767 for (j = 0; j < sizeof(digitRanges)/sizeof(digitRanges[0]); j++)
1769 /* Check everything before this range */
1770 for (ch = prev_ch; ch < digitRanges[j]; ch++)
1774 src[1] = dst[0] = '\0';
1775 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1776 EXPECT_LEN(2); EXPECT_VALID;
1778 ok(dst[0] == ch || strchrW(outOfSequenceDigits, ch) ||
1779 /* Wine (correctly) maps all Unicode 4.0+ digits */
1780 isdigitW(ch) || (ch >= 0x24F5 && ch <= 0x24FD) || ch == 0x24FF,
1781 "MAP_FOLDDIGITS: ch %d 0x%04x Expected unchanged got %d\n", ch, ch, dst[0]);
1784 if (digitRanges[j] == 0xffff)
1785 break; /* Finished the whole code point space */
1787 for (ch = digitRanges[j]; ch < digitRanges[j] + 10; ch++)
1791 /* Map out of sequence characters */
1792 if (ch == 0x2071) c = 0x00B9; /* Superscript 1 */
1793 else if (ch == 0x2072) c = 0x00B2; /* Superscript 2 */
1794 else if (ch == 0x2073) c = 0x00B3; /* Superscript 3 */
1795 else if (ch == 0x245F) c = 0x24EA; /* Circled 0 */
1799 src[1] = dst[0] = '\0';
1800 ret = pFoldStringW(MAP_FOLDDIGITS, src, -1, dst, 256);
1801 EXPECT_LEN(2); EXPECT_VALID;
1803 ok((dst[0] == '0' + ch - digitRanges[j] && dst[1] == '\0') ||
1804 strchrW(noDigitAvailable, c),
1805 "MAP_FOLDDIGITS: ch %d Expected %d got %d\n",
1806 ch, '0' + digitRanges[j] - ch, dst[0]);
1812 for (ch = 1; ch <0xffff; ch++)
1816 if (ch >= 0xF900 && ch <= 0xFA2F)
1817 expected = compat_F900_FA2F[ch - 0xF900];
1818 else if (ch >= 0xFE30 && ch <= 0xFEF7)
1819 expected = compat_FE30_FEF7[ch - 0xFE30];
1820 else if (ch >= 0xFF00 && ch <= 0xFFEF)
1821 expected = compat_FF00_FFEF[ch - 0xFF00];
1828 src[1] = dst[0] = '\0';
1829 ret = pFoldStringW(MAP_FOLDCZONE, src, -1, dst, 256);
1830 EXPECT_LEN(2); EXPECT_VALID;
1831 ok(dst[0] == expected ||
1832 /* Wine (correctly) uses updated mappings for some Unicode 4.0 chars */
1833 (ch >= 0xFA0D && ch <= 0xFA47) ||
1834 0xf92c || ch == 0xf979 || ch == 0xf995 || ch == 0xf9e7 || ch == 0xf9f1,
1835 "MAP_FOLDCZONE: ch %d 0x%04x Expected 0x%04x got 0x%04x\n",
1836 ch, ch, expected, dst[0]);
1839 /* MAP_EXPAND_LIGATURES */
1841 ret = pFoldStringW(MAP_EXPAND_LIGATURES, ligatures_src, -1, dst, 256);
1842 EXPECT_LEN(sizeof(ligatures_dst)/sizeof(ligatures_dst[0])); EXPECT_VALID;
1843 ok(!memcmp(dst, ligatures_dst, sizeof(ligatures_dst)),
1844 "MAP_EXPAND_LIGATURES: Expanded incorrrectly\n");
1845 for (i = 1; i <= 0xffff; i++)
1847 if (!strchrW(ligatures_src, i))
1852 ret = pFoldStringW(MAP_EXPAND_LIGATURES, src, -1, dst, 256);
1853 EXPECT_LEN(2); EXPECT_VALID;
1854 ok(dst[0] == src[0],
1855 "MAP_EXPAND_LIGATURES: 0x%02x : Expected 0x%02x, got 0x%02x\n",
1860 /* FIXME: MAP_PRECOMPOSED : MAP_COMPOSITE */
1865 #define LCID_OK(l) \
1866 ok(lcid == l, "Expected lcid = %08lx, got %08lx\n", l, lcid)
1867 #define MKLCID(x,y,z) MAKELCID(MAKELANGID(x, y), z)
1868 #define LCID_RES(src, res) lcid = ConvertDefaultLocale(src); LCID_OK(res)
1869 #define TEST_LCIDLANG(a,b) LCID_RES(MAKELCID(a,b), MAKELCID(a,b))
1870 #define TEST_LCID(a,b,c) LCID_RES(MKLCID(a,b,c), MKLCID(a,b,c))
1872 static void test_ConvertDefaultLocale(void)
1876 /* Doesn't change lcid, even if non default sublang/sort used */
1877 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_US, SORT_DEFAULT);
1878 TEST_LCID(LANG_ENGLISH, SUBLANG_ENGLISH_UK, SORT_DEFAULT);
1879 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT);
1880 TEST_LCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE);
1882 /* SUBLANG_NEUTRAL -> SUBLANG_DEFAULT */
1883 LCID_RES(MKLCID(LANG_ENGLISH, SUBLANG_NEUTRAL, SORT_DEFAULT),
1884 MKLCID(LANG_ENGLISH, SUBLANG_DEFAULT, SORT_DEFAULT));
1885 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_DEFAULT),
1886 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_DEFAULT));
1887 LCID_RES(MKLCID(LANG_JAPANESE, SUBLANG_NEUTRAL, SORT_JAPANESE_UNICODE),
1888 MKLCID(LANG_JAPANESE, SUBLANG_DEFAULT, SORT_JAPANESE_UNICODE));
1890 /* Invariant language is not treated specially */
1891 TEST_LCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT);
1892 LCID_RES(MKLCID(LANG_INVARIANT, SUBLANG_NEUTRAL, SORT_DEFAULT),
1893 MKLCID(LANG_INVARIANT, SUBLANG_DEFAULT, SORT_DEFAULT));
1895 /* User/system default languages alone are not mapped */
1896 TEST_LCIDLANG(LANG_SYSTEM_DEFAULT, SORT_JAPANESE_UNICODE);
1897 TEST_LCIDLANG(LANG_USER_DEFAULT, SORT_JAPANESE_UNICODE);
1900 LCID_RES(LOCALE_SYSTEM_DEFAULT, GetSystemDefaultLCID());
1901 LCID_RES(LOCALE_USER_DEFAULT, GetUserDefaultLCID());
1902 LCID_RES(LOCALE_NEUTRAL, GetUserDefaultLCID());
1905 static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
1906 DWORD dwFlags, LONG_PTR lParam)
1908 trace("%08lx, %s, %s, %08lx, %08lx\n",
1909 lgrpid, lpszNum, lpszName, dwFlags, lParam);
1911 ok(pIsValidLanguageGroup(lgrpid, dwFlags) == TRUE,
1912 "Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
1914 /* If lParam is one, we are calling with flags defaulted from 0 */
1915 ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
1916 "Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
1921 static void test_EnumSystemLanguageGroupsA(void)
1923 if (!pEnumSystemLanguageGroupsA || !pIsValidLanguageGroup)
1926 /* No enumeration proc */
1928 pEnumSystemLanguageGroupsA(0, LGRPID_INSTALLED, 0);
1933 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED|LGRPID_SUPPORTED, 0);
1936 /* No flags - defaults to LGRPID_INSTALLED */
1938 pEnumSystemLanguageGroupsA(langgrp_procA, 0, 1);
1941 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_INSTALLED, 0);
1942 pEnumSystemLanguageGroupsA(langgrp_procA, LGRPID_SUPPORTED, 0);
1946 static BOOL CALLBACK lgrplocale_procA(LGRPID lgrpid, LCID lcid, LPSTR lpszNum,
1949 trace("%08lx, %08lx, %s, %08lx\n", lgrpid, lcid, lpszNum, lParam);
1951 ok(pIsValidLanguageGroup(lgrpid, LGRPID_SUPPORTED) == TRUE,
1952 "Enumerated grp %ld not valid\n", lgrpid);
1953 ok(IsValidLocale(lcid, LCID_SUPPORTED) == TRUE,
1954 "Enumerated grp locale %ld not valid\n", lcid);
1958 static void test_EnumLanguageGroupLocalesA(void)
1960 if (!pEnumLanguageGroupLocalesA || !pIsValidLanguageGroup)
1963 /* No enumeration proc */
1965 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0, 0);
1968 /* lgrpid too small */
1970 pEnumLanguageGroupLocalesA(lgrplocale_procA, 0, 0, 0);
1973 /* lgrpid too big */
1975 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_ARMENIAN + 1, 0, 0);
1978 /* dwFlags is reserved */
1980 pEnumLanguageGroupLocalesA(0, LGRPID_WESTERN_EUROPE, 0x1, 0);
1983 pEnumLanguageGroupLocalesA(lgrplocale_procA, LGRPID_WESTERN_EUROPE, 0, 0);
1986 static void test_SetLocaleInfoA(void)
1989 LCID lcid = GetUserDefaultLCID();
1993 bRet = SetLocaleInfoA(lcid, LOCALE_SDATE, 0);
1998 bRet = SetLocaleInfoA(lcid, LOCALE_IDATE, (LPSTR)test_SetLocaleInfoA);
2003 bRet = SetLocaleInfoA(lcid, LOCALE_ILDATE, (LPSTR)test_SetLocaleInfoA);
2009 InitFunctionPointers();
2012 test_EnumTimeFormats();
2014 test_GetLocaleInfoA();
2015 test_GetTimeFormatA();
2016 test_GetDateFormatA();
2017 test_GetDateFormatW();
2018 test_GetCurrencyFormatA(); /* Also tests the W version */
2019 test_GetNumberFormatA(); /* Also tests the W version */
2020 test_CompareStringA();
2021 test_LCMapStringA();
2022 test_LCMapStringW();
2025 test_ConvertDefaultLocale();
2026 test_EnumSystemLanguageGroupsA();
2027 test_EnumLanguageGroupLocalesA();
2028 test_SetLocaleInfoA();
2029 #if 0 /* this requires collation table patch to make it MS compatible */