4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 David Lee Lambert
6 * Copyright 2000 Julio César Gázquez
22 #include "debugtools.h"
26 DEFAULT_DEBUG_CHANNEL(ole);
27 DECLARE_DEBUG_CHANNEL(string);
28 DECLARE_DEBUG_CHANNEL(win32);
30 struct NLS_langlocale {
32 struct NLS_localevar {
38 static LPVOID lpNLSInfo = NULL;
40 #define LANG_BEGIN(l,s) { MAKELANGID(l,s), {
42 #define LOCVAL(type,value) {type,value},
46 static const struct NLS_langlocale langlocales[] = {
47 /* add languages in numerical order of main language (last two digits)
48 * it is much easier to find the missing holes that way */
50 LANG_BEGIN (LANG_CATALAN, SUBLANG_DEFAULT) /*0x0403*/
51 #include "nls/cat.nls"
54 LANG_BEGIN (LANG_CZECH, SUBLANG_DEFAULT) /*0x0405*/
55 #include "nls/cze.nls"
58 LANG_BEGIN (LANG_DANISH, SUBLANG_DEFAULT) /*0x0406*/
59 #include "nls/dan.nls"
62 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN) /*0x0407*/
63 #include "nls/deu.nls"
65 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_SWISS) /*0x0807*/
66 #include "nls/des.nls"
68 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN) /*0x0C07*/
69 #include "nls/dea.nls"
71 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG) /*0x1007*/
72 #include "nls/del.nls"
74 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LIECHTENSTEIN) /*0x1407*/
75 #include "nls/dec.nls"
78 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_US) /*0x0409*/
79 #include "nls/enu.nls"
81 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_UK) /*0x0809*/
82 #include "nls/eng.nls"
84 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_AUS) /*0x0C09*/
85 #include "nls/ena.nls"
87 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CAN) /*0x1009*/
88 #include "nls/enc.nls"
90 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_NZ) /*0x1409*/
91 #include "nls/enz.nls"
93 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_EIRE) /*0x1809*/
94 #include "nls/irl.nls"
96 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_SAFRICA) /*0x1C09*/
97 #include "nls/ens.nls"
99 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_JAMAICA) /*0x2009*/
100 #include "nls/enj.nls"
102 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CARRIBEAN) /*0x2409*/
103 #include "nls/enb.nls"
105 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_BELIZE) /*0x2809*/
106 #include "nls/enl.nls"
108 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_TRINIDAD) /*0x2C09*/
109 #include "nls/ent.nls"
112 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH) /*0x040a*/
113 #include "nls/esp.nls"
115 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MEXICAN) /*0x080a*/
116 #include "nls/esm.nls"
118 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MODERN) /*0x0C0a*/
119 #include "nls/esn.nls"
121 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_GUATEMALA) /*0x100a*/
122 #include "nls/esg.nls"
124 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COSTARICA) /*0x140a*/
125 #include "nls/esc.nls"
127 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PANAMA) /*0x180a*/
128 #include "nls/esa.nls"
130 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_DOMINICAN) /*0x1C0A*/
131 #include "nls/esd.nls"
133 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_VENEZUELA) /*0x200a*/
134 #include "nls/esv.nls"
136 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COLOMBIA) /*0x240a*/
137 #include "nls/eso.nls"
139 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PERU) /*0x280a*/
140 #include "nls/esr.nls"
142 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA) /*0x2c0a*/
143 #include "nls/ess.nls"
145 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ECUADOR) /*0x300a*/
146 #include "nls/esf.nls"
148 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_CHILE) /*0x340a*/
149 #include "nls/esl.nls"
151 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_URUGUAY) /*0x380a*/
152 #include "nls/esy.nls"
154 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PARAGUAY) /*0x3c0a*/
155 #include "nls/esz.nls"
157 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_BOLIVIA) /*0x400a*/
158 #include "nls/esb.nls"
160 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_EL_SALVADOR) /*0x440a*/
161 #include "nls/ese.nls"
163 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_HONDURAS) /*0x480a*/
164 #include "nls/esh.nls"
166 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_NICARAGUA) /*0x4c0a*/
167 #include "nls/esi.nls"
169 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PUERTO_RICO) /*0x500a*/
170 #include "nls/esu.nls"
173 LANG_BEGIN (LANG_FINNISH, SUBLANG_DEFAULT) /*0x040B*/
174 #include "nls/fin.nls"
177 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH) /*0x040C*/
178 #include "nls/fra.nls"
180 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_BELGIAN) /*0x080C*/
181 #include "nls/frb.nls"
183 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_CANADIAN) /*0x0C0C*/
184 #include "nls/frc.nls"
186 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_SWISS) /*0x100C*/
187 #include "nls/frs.nls"
189 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_LUXEMBOURG) /*0x140C*/
190 #include "nls/frl.nls"
193 LANG_BEGIN (LANG_HUNGARIAN, SUBLANG_DEFAULT) /*0x040e*/
194 #include "nls/hun.nls"
197 LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN) /*0x0410*/
198 #include "nls/ita.nls"
200 LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN_SWISS) /*0x0810*/
201 #include "nls/its.nls"
204 LANG_BEGIN (LANG_KOREAN, SUBLANG_KOREAN) /*0x0412*/
205 #include "nls/kor.nls"
208 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH) /*0x0413*/
209 #include "nls/nld.nls"
211 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH_BELGIAN) /*0x0813*/
212 #include "nls/nlb.nls"
214 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH_SURINAM) /*0x0C13*/
215 #include "nls/nls.nls"
218 LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL) /*0x0414*/
219 #include "nls/nor.nls"
221 LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK) /*0x0814*/
222 #include "nls/non.nls"
225 LANG_BEGIN (LANG_POLISH, SUBLANG_DEFAULT) /*0x0415*/
226 #include "nls/plk.nls"
229 LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE_BRAZILIAN) /*0x0416*/
230 #include "nls/ptb.nls"
232 LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE) /*0x0816*/
233 #include "nls/ptg.nls"
236 LANG_BEGIN (LANG_RUSSIAN, SUBLANG_DEFAULT) /*0x419*/
237 #include "nls/rus.nls"
240 LANG_BEGIN (LANG_SLOVAK, SUBLANG_DEFAULT) /*0x041b*/
241 #include "nls/sky.nls"
244 LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH) /*0x041d*/
245 #include "nls/sve.nls"
247 LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH_FINLAND) /*0x081d*/
248 #include "nls/svf.nls"
251 LANG_BEGIN (LANG_THAI, SUBLANG_DEFAULT) /*0x41e*/
252 #include "nls/tha.nls"
255 LANG_BEGIN (LANG_ESPERANTO, SUBLANG_DEFAULT) /*0x048f*/
256 #include "nls/esperanto.nls"
259 LANG_BEGIN (LANG_WALON, SUBLANG_DEFAULT) /*0x0490*/
260 #include "nls/wal.nls"
265 /* Locale name to id map. used by EnumSystemLocales, GetLocaleInfoA
266 * MUST contain all #defines from winnls.h
267 * last entry has NULL name, 0 id.
269 #define LOCALE_ENTRY(x) {#x,LOCALE_##x}
270 static struct tagLOCALE_NAME2ID {
273 } locale_name2id[]= {
274 LOCALE_ENTRY(ILANGUAGE),
275 LOCALE_ENTRY(SLANGUAGE),
276 LOCALE_ENTRY(SENGLANGUAGE),
277 LOCALE_ENTRY(SABBREVLANGNAME),
278 LOCALE_ENTRY(SNATIVELANGNAME),
279 LOCALE_ENTRY(ICOUNTRY),
280 LOCALE_ENTRY(SCOUNTRY),
281 LOCALE_ENTRY(SENGCOUNTRY),
282 LOCALE_ENTRY(SABBREVCTRYNAME),
283 LOCALE_ENTRY(SNATIVECTRYNAME),
284 LOCALE_ENTRY(IDEFAULTLANGUAGE),
285 LOCALE_ENTRY(IDEFAULTCOUNTRY),
286 LOCALE_ENTRY(IDEFAULTCODEPAGE),
287 LOCALE_ENTRY(IDEFAULTANSICODEPAGE),
288 LOCALE_ENTRY(IDEFAULTMACCODEPAGE),
290 LOCALE_ENTRY(IMEASURE),
291 LOCALE_ENTRY(SDECIMAL),
292 LOCALE_ENTRY(STHOUSAND),
293 LOCALE_ENTRY(SGROUPING),
294 LOCALE_ENTRY(IDIGITS),
295 LOCALE_ENTRY(ILZERO),
296 LOCALE_ENTRY(INEGNUMBER),
297 LOCALE_ENTRY(SNATIVEDIGITS),
298 LOCALE_ENTRY(SCURRENCY),
299 LOCALE_ENTRY(SINTLSYMBOL),
300 LOCALE_ENTRY(SMONDECIMALSEP),
301 LOCALE_ENTRY(SMONTHOUSANDSEP),
302 LOCALE_ENTRY(SMONGROUPING),
303 LOCALE_ENTRY(ICURRDIGITS),
304 LOCALE_ENTRY(IINTLCURRDIGITS),
305 LOCALE_ENTRY(ICURRENCY),
306 LOCALE_ENTRY(INEGCURR),
309 LOCALE_ENTRY(SSHORTDATE),
310 LOCALE_ENTRY(SLONGDATE),
311 LOCALE_ENTRY(STIMEFORMAT),
313 LOCALE_ENTRY(ILDATE),
315 LOCALE_ENTRY(ITIMEMARKPOSN),
316 LOCALE_ENTRY(ICENTURY),
317 LOCALE_ENTRY(ITLZERO),
318 LOCALE_ENTRY(IDAYLZERO),
319 LOCALE_ENTRY(IMONLZERO),
322 LOCALE_ENTRY(ICALENDARTYPE),
323 LOCALE_ENTRY(IOPTIONALCALENDAR),
324 LOCALE_ENTRY(IFIRSTDAYOFWEEK),
325 LOCALE_ENTRY(IFIRSTWEEKOFYEAR),
326 LOCALE_ENTRY(SDAYNAME1),
327 LOCALE_ENTRY(SDAYNAME2),
328 LOCALE_ENTRY(SDAYNAME3),
329 LOCALE_ENTRY(SDAYNAME4),
330 LOCALE_ENTRY(SDAYNAME5),
331 LOCALE_ENTRY(SDAYNAME6),
332 LOCALE_ENTRY(SDAYNAME7),
333 LOCALE_ENTRY(SABBREVDAYNAME1),
334 LOCALE_ENTRY(SABBREVDAYNAME2),
335 LOCALE_ENTRY(SABBREVDAYNAME3),
336 LOCALE_ENTRY(SABBREVDAYNAME4),
337 LOCALE_ENTRY(SABBREVDAYNAME5),
338 LOCALE_ENTRY(SABBREVDAYNAME6),
339 LOCALE_ENTRY(SABBREVDAYNAME7),
340 LOCALE_ENTRY(SMONTHNAME1),
341 LOCALE_ENTRY(SMONTHNAME2),
342 LOCALE_ENTRY(SMONTHNAME3),
343 LOCALE_ENTRY(SMONTHNAME4),
344 LOCALE_ENTRY(SMONTHNAME5),
345 LOCALE_ENTRY(SMONTHNAME6),
346 LOCALE_ENTRY(SMONTHNAME7),
347 LOCALE_ENTRY(SMONTHNAME8),
348 LOCALE_ENTRY(SMONTHNAME9),
349 LOCALE_ENTRY(SMONTHNAME10),
350 LOCALE_ENTRY(SMONTHNAME11),
351 LOCALE_ENTRY(SMONTHNAME12),
352 LOCALE_ENTRY(SMONTHNAME13),
353 LOCALE_ENTRY(SABBREVMONTHNAME1),
354 LOCALE_ENTRY(SABBREVMONTHNAME2),
355 LOCALE_ENTRY(SABBREVMONTHNAME3),
356 LOCALE_ENTRY(SABBREVMONTHNAME4),
357 LOCALE_ENTRY(SABBREVMONTHNAME5),
358 LOCALE_ENTRY(SABBREVMONTHNAME6),
359 LOCALE_ENTRY(SABBREVMONTHNAME7),
360 LOCALE_ENTRY(SABBREVMONTHNAME8),
361 LOCALE_ENTRY(SABBREVMONTHNAME9),
362 LOCALE_ENTRY(SABBREVMONTHNAME10),
363 LOCALE_ENTRY(SABBREVMONTHNAME11),
364 LOCALE_ENTRY(SABBREVMONTHNAME12),
365 LOCALE_ENTRY(SABBREVMONTHNAME13),
366 LOCALE_ENTRY(SPOSITIVESIGN),
367 LOCALE_ENTRY(SNEGATIVESIGN),
368 LOCALE_ENTRY(IPOSSIGNPOSN),
369 LOCALE_ENTRY(INEGSIGNPOSN),
370 LOCALE_ENTRY(IPOSSYMPRECEDES),
371 LOCALE_ENTRY(IPOSSEPBYSPACE),
372 LOCALE_ENTRY(INEGSYMPRECEDES),
373 LOCALE_ENTRY(INEGSEPBYSPACE),
374 LOCALE_ENTRY(FONTSIGNATURE),
375 LOCALE_ENTRY(SISO639LANGNAME),
376 LOCALE_ENTRY(SISO3166CTRYNAME),
380 const struct map_lcid2str {
382 const char *langname;
384 {0x0401,"Arabic (Saudi Arabia)"},
385 {0x0801,"Arabic (Iraq)"},
386 {0x0c01,"Arabic (Egypt)"},
387 {0x1001,"Arabic (Libya)"},
388 {0x1401,"Arabic (Algeria)"},
389 {0x1801,"Arabic (Morocco)"},
390 {0x1c01,"Arabic (Tunisia)"},
391 {0x2001,"Arabic (Oman)"},
392 {0x2401,"Arabic (Yemen)"},
393 {0x2801,"Arabic (Syria)"},
394 {0x2c01,"Arabic (Jordan)"},
395 {0x3001,"Arabic (Lebanon)"},
396 {0x3401,"Arabic (Kuwait)"},
397 {0x3801,"Arabic (United Arab Emirates)"},
398 {0x3c01,"Arabic (Bahrain)"},
399 {0x4001,"Arabic (Qatar)"},
400 {0x0402,"Bulgarian"},
402 {0x0404,"Chinese (Taiwan)"},
403 {0x0804,"Chinese (People's Republic of China)"},
404 {0x0c04,"Chinese (Hong Kong)"},
405 {0x1004,"Chinese (Singapore)"},
406 {0x1404,"Chinese (Macau)"},
409 {0x0407,"German (Germany)"},
410 {0x0807,"German (Switzerland)"},
411 {0x0c07,"German (Austria)"},
412 {0x1007,"German (Luxembourg)"},
413 {0x1407,"German (Liechtenstein)"},
415 {0x0409,"English (United States)"},
416 {0x0809,"English (United Kingdom)"},
417 {0x0c09,"English (Australia)"},
418 {0x1009,"English (Canada)"},
419 {0x1409,"English (New Zealand)"},
420 {0x1809,"English (Ireland)"},
421 {0x1c09,"English (South Africa)"},
422 {0x2009,"English (Jamaica)"},
423 {0x2409,"English (Caribbean)"},
424 {0x2809,"English (Belize)"},
425 {0x2c09,"English (Trinidad)"},
426 {0x3009,"English (Zimbabwe)"},
427 {0x3409,"English (Philippines)"},
428 {0x040a,"Spanish (Spain, traditional sorting)"},
429 {0x080a,"Spanish (Mexico)"},
430 {0x0c0a,"Spanish (Spain, international sorting)"},
431 {0x100a,"Spanish (Guatemala)"},
432 {0x140a,"Spanish (Costa Rica)"},
433 {0x180a,"Spanish (Panama)"},
434 {0x1c0a,"Spanish (Dominican Republic)"},
435 {0x200a,"Spanish (Venezuela)"},
436 {0x240a,"Spanish (Colombia)"},
437 {0x280a,"Spanish (Peru)"},
438 {0x2c0a,"Spanish (Argentina)"},
439 {0x300a,"Spanish (Ecuador)"},
440 {0x340a,"Spanish (Chile)"},
441 {0x380a,"Spanish (Uruguay)"},
442 {0x3c0a,"Spanish (Paraguay)"},
443 {0x400a,"Spanish (Bolivia)"},
444 {0x440a,"Spanish (El Salvador)"},
445 {0x480a,"Spanish (Honduras)"},
446 {0x4c0a,"Spanish (Nicaragua)"},
447 {0x500a,"Spanish (Puerto Rico)"},
449 {0x040c,"French (France)"},
450 {0x080c,"French (Belgium)"},
451 {0x0c0c,"French (Canada)"},
452 {0x100c,"French (Switzerland)"},
453 {0x140c,"French (Luxembourg)"},
454 {0x180c,"French (Monaco)"},
456 {0x040e,"Hungarian"},
457 {0x040f,"Icelandic"},
458 {0x0410,"Italian (Italy)"},
459 {0x0810,"Italian (Switzerland)"},
461 {0x0412,"Korean (Wansung)"},
462 {0x0812,"Korean (Johab)"},
463 {0x0413,"Dutch (Netherlands)"},
464 {0x0813,"Dutch (Belgium)"},
465 {0x0414,"Norwegian (Bokmal)"},
466 {0x0814,"Norwegian (Nynorsk)"},
468 {0x0416,"Portuguese (Brazil)"},
469 {0x0816,"Portuguese (Portugal)"},
470 {0x0417,"Rhaeto Romanic"},
472 {0x0818,"Moldavian"},
473 {0x0419,"Russian (Russia)"},
474 {0x0819,"Russian (Moldavia)"},
476 {0x081a,"Serbian (latin)"},
477 {0x0c1a,"Serbian (cyrillic)"},
480 {0x041d,"Swedish (Sweden)"},
481 {0x081d,"Swedish (Finland)"},
485 {0x0421,"Indonesian"},
486 {0x0422,"Ukrainian"},
487 {0x0423,"Belarusian"},
491 {0x0427,"Lithuanian (modern)"},
492 {0x0827,"Lithuanian (classic)"},
495 {0x042a,"Vietnamese"},
497 {0x042c,"Azeri (latin)"},
498 {0x082c,"Azeri (cyrillic)"},
501 {0x042f,"Macedonian"},
508 {0x0436,"Afrikaans"},
514 {0x043c,"Irish gaelic"},
515 {0x083c,"Scottish gaelic"},
516 {0x043e,"Malay (Malaysia)"},
517 {0x083e,"Malay (Brunei Darussalam)"},
520 {0x0443,"Uzbek (latin)"},
521 {0x0843,"Uzbek (cyrillic)"},
530 {0x044c,"Malayalam"},
535 {0x048f,"Esperanto"}, /* Non official */
536 {0x0490,"Walon"}, /* Non official */
540 {0x0402,"Bulgarisch"},
541 {0x0403,"Katalanisch"},
542 {0x0404,"Traditionales Chinesisch"},
543 {0x0405,"Tschecisch"},
546 {0x0408,"Griechisch"},
547 {0x0409,"Amerikanisches Englisch"},
548 {0x040A,"Kastilisches Spanisch"},
550 {0x040C,"Franzvsisch"},
551 {0x040D,"Hebrdisch"},
552 {0x040E,"Ungarisch"},
553 {0x040F,"Isldndisch"},
554 {0x0410,"Italienisch"},
555 {0x0411,"Japanisch"},
556 {0x0412,"Koreanisch"},
557 {0x0413,"Niederldndisch"},
558 {0x0414,"Norwegisch-Bokmal"},
560 {0x0416,"Brasilianisches Portugiesisch"},
561 {0x0417,"Rdtoromanisch"},
562 {0x0418,"Rumdnisch"},
564 {0x041A,"Kroatoserbisch (lateinisch)"},
565 {0x041B,"Slowenisch"},
566 {0x041C,"Albanisch"},
567 {0x041D,"Schwedisch"},
572 {0x0804,"Vereinfachtes Chinesisch"},
573 {0x0807,"Schweizerdeutsch"},
574 {0x0809,"Britisches Englisch"},
575 {0x080A,"Mexikanisches Spanisch"},
576 {0x080C,"Belgisches Franzvsisch"},
577 {0x0810,"Schweizerisches Italienisch"},
578 {0x0813,"Belgisches Niederldndisch"},
579 {0x0814,"Norgwegisch-Nynorsk"},
580 {0x0816,"Portugiesisch"},
581 {0x081A,"Serbokratisch (kyrillisch)"},
582 {0x0C1C,"Kanadisches Franzvsisch"},
583 {0x100C,"Schweizerisches Franzvsisch"},
584 {0x0000,"Unbekannt"},
587 /***********************************************************************
588 * GetUserDefaultLCID (OLE2NLS.1)
590 LCID WINAPI GetUserDefaultLCID()
592 return MAKELCID( GetUserDefaultLangID() , SORT_DEFAULT );
595 /***********************************************************************
596 * GetSystemDefaultLCID (OLE2NLS.2)
598 LCID WINAPI GetSystemDefaultLCID()
600 return GetUserDefaultLCID();
603 /***********************************************************************
604 * GetUserDefaultLangID (OLE2NLS.3)
606 LANGID WINAPI GetUserDefaultLangID()
608 /* caching result, if defined from environment, which should (?) not change during a WINE session */
609 static LANGID userLCID = 0;
610 if (Options.language) {
611 return Languages[Options.language].langid;
616 char *lang,*country,*charset,*dialect,*next;
619 buf=getenv("LANGUAGE");
620 if (!buf) buf=getenv("LANG");
621 if (!buf) buf=getenv("LC_ALL");
622 if (!buf) buf=getenv("LC_MESSAGES");
623 if (!buf) buf=getenv("LC_CTYPE");
624 if (!buf) return userLCID = MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT );
626 if (!strcmp(buf,"POSIX") || !strcmp(buf,"C")) {
627 return MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT );
633 next=strchr(lang,':'); if (next) *next++='\0';
634 dialect=strchr(lang,'@'); if (dialect) *dialect++='\0';
635 charset=strchr(lang,'.'); if (charset) *charset++='\0';
636 country=strchr(lang,'_'); if (country) *country++='\0';
638 ret=MAIN_GetLanguageID(lang, country, charset, dialect);
642 } while (lang && !ret);
644 /* FIXME : are strings returned by getenv() to be free()'ed ? */
645 userLCID = (LANGID)ret;
650 /***********************************************************************
651 * GetSystemDefaultLangID (OLE2NLS.4)
653 LANGID WINAPI GetSystemDefaultLangID()
655 return GetUserDefaultLangID();
658 /******************************************************************************
659 * GetLocaleInfo16 [OLE2NLS.5]
660 * Is the last parameter really WORD for Win16?
662 INT16 WINAPI GetLocaleInfo16(LCID lcid,LCTYPE LCType,LPSTR buf,INT16 len)
664 return GetLocaleInfoA(lcid,LCType,buf,len);
666 /******************************************************************************
667 * ConvertDefaultLocale32 [KERNEL32.147]
669 LCID WINAPI ConvertDefaultLocale32 (LCID lcid)
671 { case LOCALE_SYSTEM_DEFAULT:
672 return GetSystemDefaultLCID();
673 case LOCALE_USER_DEFAULT:
674 return GetUserDefaultLCID();
676 return MAKELCID (LANG_NEUTRAL, SUBLANG_NEUTRAL);
678 return MAKELANGID( PRIMARYLANGID(lcid), SUBLANG_NEUTRAL);
680 /******************************************************************************
681 * GetLocaleInfo32A [KERNEL32.342]
684 * LANG_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
686 * MS online documentation states that the string returned is NULL terminated
687 * except for LOCALE_FONTSIGNATURE which "will return a non-NULL
688 * terminated string".
690 INT WINAPI GetLocaleInfoA(LCID lcid,LCTYPE LCType,LPSTR buf,INT len)
696 TRACE("(lcid=0x%lx,lctype=0x%lx,%p,%x)\n",lcid,LCType,buf,len);
698 if (len && (! buf) ) {
699 SetLastError(ERROR_INSUFFICIENT_BUFFER);
703 if (lcid ==0 || lcid == LANG_SYSTEM_DEFAULT || (LCType & LOCALE_NOUSEROVERRIDE) ) /* 0x00, 0x400 */
705 lcid = GetSystemDefaultLCID();
707 else if (lcid == LANG_USER_DEFAULT) /*0x800*/
709 lcid = GetUserDefaultLCID();
711 LCType &= ~(LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP);
713 /* As an option, we could obtain the value from win.ini.
714 This would not match the Wine compile-time option.
715 Also, not all identifiers are available from win.ini */
717 /* If we are through all of this, retLen should not be zero anymore.
718 If it is, the value is not supported */
720 while (locale_name2id[i].name!=NULL) {
721 if (LCType == locale_name2id[i].id) {
722 retString = locale_name2id[i].name;
728 FIXME("Unkown LC type %lX\n",LCType);
733 for (i=0;(i<3 && !found);i++) {
736 for (j=0;j<sizeof(langlocales)/sizeof(langlocales[0]);j++) {
737 if (langlocales[j].lang == lang) {
740 for (k=0;k<sizeof(langlocales[j].locvars)/sizeof(langlocales[j].locvars[0]) && (langlocales[j].locvars[k].type);k++) {
741 if (langlocales[j].locvars[k].type == LCType) {
743 retString = langlocales[j].locvars[k].val;
751 /* language not found, try without a sublanguage*/
752 if (i==1) lang=MAKELANGID( PRIMARYLANGID(lang), SUBLANG_DEFAULT);
753 /* mask the LC Value */
754 if (i==2) LCType &= 0xfff;
758 ERR("'%s' not supported for your language (%04X).\n",
759 retString,(WORD)lcid);
760 SetLastError(ERROR_INVALID_PARAMETER);
763 /* a FONTSIGNATURE is not a string, just 6 DWORDs */
764 if (LCType == LOCALE_FONTSIGNATURE) {
766 memcpy(buf, retString, (len<=sizeof(FONTSIGNATURE))?len:sizeof(FONTSIGNATURE));
767 return sizeof(FONTSIGNATURE);
769 /* if len=0 return only the length, don't touch the buffer*/
770 if (len) lstrcpynA(buf,retString,len);
771 return strlen(retString)+1;
774 /******************************************************************************
775 * GetLocaleInfo32W [KERNEL32.343]
778 * MS documentation states that len "specifies the size, in bytes (ANSI version)
779 * or characters (Unicode version), of" wbuf. Thus the number returned is
780 * the same between GetLocaleInfo32W and GetLocaleInfo32A.
782 INT WINAPI GetLocaleInfoW(LCID lcid,LCTYPE LCType,LPWSTR wbuf,INT len)
786 if (len && (! wbuf) )
787 { SetLastError(ERROR_INSUFFICIENT_BUFFER);
791 abuf = (LPSTR)HeapAlloc(GetProcessHeap(),0,len);
792 wlen = GetLocaleInfoA(lcid, LCType, abuf, len);
794 if (wlen && len) /* if len=0 return only the length*/
795 lstrcpynAtoW(wbuf,abuf,len);
797 HeapFree(GetProcessHeap(),0,abuf);
801 /******************************************************************************
802 * SetLocaleInfoA [KERNEL32.656]
804 BOOL16 WINAPI SetLocaleInfoA(DWORD lcid, DWORD lctype, LPCSTR data)
806 FIXME("(%ld,%ld,%s): stub\n",lcid,lctype,data);
810 /******************************************************************************
811 * IsValidLocale [KERNEL32.489]
813 BOOL WINAPI IsValidLocale(LCID lcid,DWORD flags)
815 /* we support ANY language. Well, at least say that...*/
819 /******************************************************************************
820 * EnumSystemLocales32W [KERNEL32.209]
822 BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum,
830 TRACE_(win32)("(%p,%08lx)\n",lpfnLocaleEnum,flags );
831 /* see if we can reuse the Win95 registry entries.... */
832 if (ERROR_SUCCESS==RegOpenKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\control\\Nls\\Locale\\",&xhkey)) {
835 if (ERROR_SUCCESS!=RegEnumKeyW(xhkey,i,buffer,sizeof(buffer)))
837 if (!lpfnLocaleEnum(buffer))
846 while (languages[i].langid!=0)
851 sprintf(xbuffer,"%08lx",(DWORD)languages[i].langid);
853 cp = HEAP_strdupAtoW( GetProcessHeap(), 0, xbuffer );
854 ret = lpfnLocaleEnum(cp);
855 HeapFree( GetProcessHeap(), 0, cp );
862 /******************************************************************************
863 * EnumSystemLocales32A [KERNEL32.208]
865 BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum,
872 TRACE_(win32)("(%p,%08lx)\n",
876 if ( ERROR_SUCCESS==RegOpenKeyA(HKEY_LOCAL_MACHINE,
877 "System\\CurrentControlSet\\Control\\Nls\\Locale\\",
881 DWORD size=sizeof(buffer);
882 if (ERROR_SUCCESS!=RegEnumValueA(xhkey,i,buffer,&size,NULL,
885 if (size && !lpfnLocaleEnum(buffer))
893 while (languages[i].langid!=0) {
894 sprintf(buffer,"%08lx",(DWORD)languages[i].langid);
895 if (!lpfnLocaleEnum(buffer))
902 static const unsigned char CT_CType2_LUT[] = {
903 C2_NOTAPPLICABLE, /* - 0 */
904 C2_NOTAPPLICABLE, /* - 1 */
905 C2_NOTAPPLICABLE, /* - 2 */
906 C2_NOTAPPLICABLE, /* - 3 */
907 C2_NOTAPPLICABLE, /* - 4 */
908 C2_NOTAPPLICABLE, /* - 5 */
909 C2_NOTAPPLICABLE, /* - 6 */
910 C2_NOTAPPLICABLE, /* - 7 */
911 C2_NOTAPPLICABLE, /* - 8 */
912 C2_SEGMENTSEPARATOR, /* - 9 */
913 C2_NOTAPPLICABLE, /* - 10 */
914 C2_NOTAPPLICABLE, /* - 11 */
915 C2_NOTAPPLICABLE, /* - 12 */
916 C2_NOTAPPLICABLE, /* - 13 */
917 C2_NOTAPPLICABLE, /* - 14 */
918 C2_NOTAPPLICABLE, /* - 15 */
919 C2_NOTAPPLICABLE, /* - 16 */
920 C2_NOTAPPLICABLE, /* - 17 */
921 C2_NOTAPPLICABLE, /* - 18 */
922 C2_NOTAPPLICABLE, /* - 19 */
923 C2_NOTAPPLICABLE, /* - 20 */
924 C2_NOTAPPLICABLE, /* - 21 */
925 C2_NOTAPPLICABLE, /* - 22 */
926 C2_NOTAPPLICABLE, /* - 23 */
927 C2_NOTAPPLICABLE, /* - 24 */
928 C2_NOTAPPLICABLE, /* - 25 */
929 C2_NOTAPPLICABLE, /* - 26 */
930 C2_NOTAPPLICABLE, /* - 27 */
931 C2_NOTAPPLICABLE, /* - 28 */
932 C2_NOTAPPLICABLE, /* - 29 */
933 C2_NOTAPPLICABLE, /* - 30 */
934 C2_NOTAPPLICABLE, /* - 31 */
935 C2_WHITESPACE, /* - 32 */
936 C2_OTHERNEUTRAL, /* ! - 33 */
937 C2_OTHERNEUTRAL, /* " - 34 */ /* " */
938 C2_EUROPETERMINATOR, /* # - 35 */
939 C2_EUROPETERMINATOR, /* $ - 36 */
940 C2_EUROPETERMINATOR, /* % - 37 */
941 C2_LEFTTORIGHT, /* & - 38 */
942 C2_OTHERNEUTRAL, /* ' - 39 */
943 C2_OTHERNEUTRAL, /* ( - 40 */
944 C2_OTHERNEUTRAL, /* ) - 41 */
945 C2_OTHERNEUTRAL, /* * - 42 */
946 C2_EUROPETERMINATOR, /* + - 43 */
947 C2_COMMONSEPARATOR, /* , - 44 */
948 C2_EUROPETERMINATOR, /* - - 45 */
949 C2_EUROPESEPARATOR, /* . - 46 */
950 C2_EUROPESEPARATOR, /* / - 47 */
951 C2_EUROPENUMBER, /* 0 - 48 */
952 C2_EUROPENUMBER, /* 1 - 49 */
953 C2_EUROPENUMBER, /* 2 - 50 */
954 C2_EUROPENUMBER, /* 3 - 51 */
955 C2_EUROPENUMBER, /* 4 - 52 */
956 C2_EUROPENUMBER, /* 5 - 53 */
957 C2_EUROPENUMBER, /* 6 - 54 */
958 C2_EUROPENUMBER, /* 7 - 55 */
959 C2_EUROPENUMBER, /* 8 - 56 */
960 C2_EUROPENUMBER, /* 9 - 57 */
961 C2_COMMONSEPARATOR, /* : - 58 */
962 C2_OTHERNEUTRAL, /* ; - 59 */
963 C2_OTHERNEUTRAL, /* < - 60 */
964 C2_OTHERNEUTRAL, /* = - 61 */
965 C2_OTHERNEUTRAL, /* > - 62 */
966 C2_OTHERNEUTRAL, /* ? - 63 */
967 C2_LEFTTORIGHT, /* @ - 64 */
968 C2_LEFTTORIGHT, /* A - 65 */
969 C2_LEFTTORIGHT, /* B - 66 */
970 C2_LEFTTORIGHT, /* C - 67 */
971 C2_LEFTTORIGHT, /* D - 68 */
972 C2_LEFTTORIGHT, /* E - 69 */
973 C2_LEFTTORIGHT, /* F - 70 */
974 C2_LEFTTORIGHT, /* G - 71 */
975 C2_LEFTTORIGHT, /* H - 72 */
976 C2_LEFTTORIGHT, /* I - 73 */
977 C2_LEFTTORIGHT, /* J - 74 */
978 C2_LEFTTORIGHT, /* K - 75 */
979 C2_LEFTTORIGHT, /* L - 76 */
980 C2_LEFTTORIGHT, /* M - 77 */
981 C2_LEFTTORIGHT, /* N - 78 */
982 C2_LEFTTORIGHT, /* O - 79 */
983 C2_LEFTTORIGHT, /* P - 80 */
984 C2_LEFTTORIGHT, /* Q - 81 */
985 C2_LEFTTORIGHT, /* R - 82 */
986 C2_LEFTTORIGHT, /* S - 83 */
987 C2_LEFTTORIGHT, /* T - 84 */
988 C2_LEFTTORIGHT, /* U - 85 */
989 C2_LEFTTORIGHT, /* V - 86 */
990 C2_LEFTTORIGHT, /* W - 87 */
991 C2_LEFTTORIGHT, /* X - 88 */
992 C2_LEFTTORIGHT, /* Y - 89 */
993 C2_LEFTTORIGHT, /* Z - 90 */
994 C2_OTHERNEUTRAL, /* [ - 91 */
995 C2_OTHERNEUTRAL, /* \ - 92 */
996 C2_OTHERNEUTRAL, /* ] - 93 */
997 C2_OTHERNEUTRAL, /* ^ - 94 */
998 C2_OTHERNEUTRAL, /* _ - 95 */
999 C2_OTHERNEUTRAL, /* ` - 96 */
1000 C2_LEFTTORIGHT, /* a - 97 */
1001 C2_LEFTTORIGHT, /* b - 98 */
1002 C2_LEFTTORIGHT, /* c - 99 */
1003 C2_LEFTTORIGHT, /* d - 100 */
1004 C2_LEFTTORIGHT, /* e - 101 */
1005 C2_LEFTTORIGHT, /* f - 102 */
1006 C2_LEFTTORIGHT, /* g - 103 */
1007 C2_LEFTTORIGHT, /* h - 104 */
1008 C2_LEFTTORIGHT, /* i - 105 */
1009 C2_LEFTTORIGHT, /* j - 106 */
1010 C2_LEFTTORIGHT, /* k - 107 */
1011 C2_LEFTTORIGHT, /* l - 108 */
1012 C2_LEFTTORIGHT, /* m - 109 */
1013 C2_LEFTTORIGHT, /* n - 110 */
1014 C2_LEFTTORIGHT, /* o - 111 */
1015 C2_LEFTTORIGHT, /* p - 112 */
1016 C2_LEFTTORIGHT, /* q - 113 */
1017 C2_LEFTTORIGHT, /* r - 114 */
1018 C2_LEFTTORIGHT, /* s - 115 */
1019 C2_LEFTTORIGHT, /* t - 116 */
1020 C2_LEFTTORIGHT, /* u - 117 */
1021 C2_LEFTTORIGHT, /* v - 118 */
1022 C2_LEFTTORIGHT, /* w - 119 */
1023 C2_LEFTTORIGHT, /* x - 120 */
1024 C2_LEFTTORIGHT, /* y - 121 */
1025 C2_LEFTTORIGHT, /* z - 122 */
1026 C2_OTHERNEUTRAL, /* { - 123 */
1027 C2_OTHERNEUTRAL, /* | - 124 */
1028 C2_OTHERNEUTRAL, /* } - 125 */
1029 C2_OTHERNEUTRAL, /* ~ - 126 */
1030 C2_NOTAPPLICABLE, /*
\7f - 127 */
1031 C2_NOTAPPLICABLE, /*
\80 - 128 */
1032 C2_NOTAPPLICABLE, /*
\81 - 129 */
1033 C2_OTHERNEUTRAL, /*
\82 - 130 */
1034 C2_LEFTTORIGHT, /*
\83 - 131 */
1035 C2_OTHERNEUTRAL, /*
\84 - 132 */
1036 C2_OTHERNEUTRAL, /*
\85 - 133 */
1037 C2_OTHERNEUTRAL, /*
\86 - 134 */
1038 C2_OTHERNEUTRAL, /*
\87 - 135 */
1039 C2_LEFTTORIGHT, /*
\88 - 136 */
1040 C2_EUROPETERMINATOR, /*
\89 - 137 */
1041 C2_LEFTTORIGHT, /*
\8a - 138 */
1042 C2_OTHERNEUTRAL, /*
\8b - 139 */
1043 C2_LEFTTORIGHT, /*
\8c - 140 */
1044 C2_NOTAPPLICABLE, /*
\8d - 141 */
1045 C2_NOTAPPLICABLE, /*
\8e - 142 */
1046 C2_NOTAPPLICABLE, /*
\8f - 143 */
1047 C2_NOTAPPLICABLE, /*
\90 - 144 */
1048 C2_OTHERNEUTRAL, /*
\91 - 145 */
1049 C2_OTHERNEUTRAL, /*
\92 - 146 */
1050 C2_OTHERNEUTRAL, /*
\93 - 147 */
1051 C2_OTHERNEUTRAL, /*
\94 - 148 */
1052 C2_OTHERNEUTRAL, /*
\95 - 149 */
1053 C2_OTHERNEUTRAL, /*
\96 - 150 */
1054 C2_OTHERNEUTRAL, /*
\97 - 151 */
1055 C2_LEFTTORIGHT, /*
\98 - 152 */
1056 C2_OTHERNEUTRAL, /*
\99 - 153 */
1057 C2_LEFTTORIGHT, /*
\9a - 154 */
1058 C2_OTHERNEUTRAL, /*
\9b - 155 */
1059 C2_LEFTTORIGHT, /*
\9c - 156 */
1060 C2_NOTAPPLICABLE, /*
\9d - 157 */
1061 C2_NOTAPPLICABLE, /*
\9e - 158 */
1062 C2_LEFTTORIGHT, /*
\9f - 159 */
1063 C2_WHITESPACE, /* - 160 */
1064 C2_OTHERNEUTRAL, /* ¡ - 161 */
1065 C2_EUROPETERMINATOR, /* ¢ - 162 */
1066 C2_EUROPETERMINATOR, /* £ - 163 */
1067 C2_EUROPETERMINATOR, /* ¤ - 164 */
1068 C2_EUROPETERMINATOR, /* ¥ - 165 */
1069 C2_OTHERNEUTRAL, /* ¦ - 166 */
1070 C2_OTHERNEUTRAL, /* § - 167 */
1071 C2_OTHERNEUTRAL, /* ¨ - 168 */
1072 C2_OTHERNEUTRAL, /* © - 169 */
1073 C2_OTHERNEUTRAL, /* ª - 170 */
1074 C2_OTHERNEUTRAL, /* « - 171 */
1075 C2_OTHERNEUTRAL, /* ¬ - 172 */
1076 C2_OTHERNEUTRAL, /* - 173 */
1077 C2_OTHERNEUTRAL, /* ® - 174 */
1078 C2_OTHERNEUTRAL, /* ¯ - 175 */
1079 C2_EUROPETERMINATOR, /* ° - 176 */
1080 C2_EUROPETERMINATOR, /* ± - 177 */
1081 C2_EUROPENUMBER, /* ² - 178 */
1082 C2_EUROPENUMBER, /* ³ - 179 */
1083 C2_OTHERNEUTRAL, /* ´ - 180 */
1084 C2_OTHERNEUTRAL, /* µ - 181 */
1085 C2_OTHERNEUTRAL, /* ¶ - 182 */
1086 C2_OTHERNEUTRAL, /* · - 183 */
1087 C2_OTHERNEUTRAL, /* ¸ - 184 */
1088 C2_EUROPENUMBER, /* ¹ - 185 */
1089 C2_OTHERNEUTRAL, /* º - 186 */
1090 C2_OTHERNEUTRAL, /* » - 187 */
1091 C2_OTHERNEUTRAL, /* ¼ - 188 */
1092 C2_OTHERNEUTRAL, /* ½ - 189 */
1093 C2_OTHERNEUTRAL, /* ¾ - 190 */
1094 C2_OTHERNEUTRAL, /* ¿ - 191 */
1095 C2_LEFTTORIGHT, /* À - 192 */
1096 C2_LEFTTORIGHT, /* Á - 193 */
1097 C2_LEFTTORIGHT, /* Â - 194 */
1098 C2_LEFTTORIGHT, /* Ã - 195 */
1099 C2_LEFTTORIGHT, /* Ä - 196 */
1100 C2_LEFTTORIGHT, /* Å - 197 */
1101 C2_LEFTTORIGHT, /* Æ - 198 */
1102 C2_LEFTTORIGHT, /* Ç - 199 */
1103 C2_LEFTTORIGHT, /* È - 200 */
1104 C2_LEFTTORIGHT, /* É - 201 */
1105 C2_LEFTTORIGHT, /* Ê - 202 */
1106 C2_LEFTTORIGHT, /* Ë - 203 */
1107 C2_LEFTTORIGHT, /* Ì - 204 */
1108 C2_LEFTTORIGHT, /* Í - 205 */
1109 C2_LEFTTORIGHT, /* Î - 206 */
1110 C2_LEFTTORIGHT, /* Ï - 207 */
1111 C2_LEFTTORIGHT, /* Ð - 208 */
1112 C2_LEFTTORIGHT, /* Ñ - 209 */
1113 C2_LEFTTORIGHT, /* Ò - 210 */
1114 C2_LEFTTORIGHT, /* Ó - 211 */
1115 C2_LEFTTORIGHT, /* Ô - 212 */
1116 C2_LEFTTORIGHT, /* Õ - 213 */
1117 C2_LEFTTORIGHT, /* Ö - 214 */
1118 C2_OTHERNEUTRAL, /* × - 215 */
1119 C2_LEFTTORIGHT, /* Ø - 216 */
1120 C2_LEFTTORIGHT, /* Ù - 217 */
1121 C2_LEFTTORIGHT, /* Ú - 218 */
1122 C2_LEFTTORIGHT, /* Û - 219 */
1123 C2_LEFTTORIGHT, /* Ü - 220 */
1124 C2_LEFTTORIGHT, /* Ý - 221 */
1125 C2_LEFTTORIGHT, /* Þ - 222 */
1126 C2_LEFTTORIGHT, /* ß - 223 */
1127 C2_LEFTTORIGHT, /* à - 224 */
1128 C2_LEFTTORIGHT, /* á - 225 */
1129 C2_LEFTTORIGHT, /* â - 226 */
1130 C2_LEFTTORIGHT, /* ã - 227 */
1131 C2_LEFTTORIGHT, /* ä - 228 */
1132 C2_LEFTTORIGHT, /* å - 229 */
1133 C2_LEFTTORIGHT, /* æ - 230 */
1134 C2_LEFTTORIGHT, /* ç - 231 */
1135 C2_LEFTTORIGHT, /* è - 232 */
1136 C2_LEFTTORIGHT, /* é - 233 */
1137 C2_LEFTTORIGHT, /* ê - 234 */
1138 C2_LEFTTORIGHT, /* ë - 235 */
1139 C2_LEFTTORIGHT, /* ì - 236 */
1140 C2_LEFTTORIGHT, /* í - 237 */
1141 C2_LEFTTORIGHT, /* î - 238 */
1142 C2_LEFTTORIGHT, /* ï - 239 */
1143 C2_LEFTTORIGHT, /* ð - 240 */
1144 C2_LEFTTORIGHT, /* ñ - 241 */
1145 C2_LEFTTORIGHT, /* ò - 242 */
1146 C2_LEFTTORIGHT, /* ó - 243 */
1147 C2_LEFTTORIGHT, /* ô - 244 */
1148 C2_LEFTTORIGHT, /* õ - 245 */
1149 C2_LEFTTORIGHT, /* ö - 246 */
1150 C2_OTHERNEUTRAL, /* ÷ - 247 */
1151 C2_LEFTTORIGHT, /* ø - 248 */
1152 C2_LEFTTORIGHT, /* ù - 249 */
1153 C2_LEFTTORIGHT, /* ú - 250 */
1154 C2_LEFTTORIGHT, /* û - 251 */
1155 C2_LEFTTORIGHT, /* ü - 252 */
1156 C2_LEFTTORIGHT, /* ý - 253 */
1157 C2_LEFTTORIGHT, /* þ - 254 */
1158 C2_LEFTTORIGHT /* ÿ - 255 */
1161 const WORD OLE2NLS_CT_CType3_LUT[] = {
1195 0x0048, /* ! - 33 */
1196 0x0448, /* " - 34 */ /* " */
1197 0x0048, /* # - 35 */
1198 0x0448, /* $ - 36 */
1199 0x0048, /* % - 37 */
1200 0x0048, /* & - 38 */
1201 0x0440, /* ' - 39 */
1202 0x0048, /* ( - 40 */
1203 0x0048, /* ) - 41 */
1204 0x0048, /* * - 42 */
1205 0x0048, /* + - 43 */
1206 0x0048, /* , - 44 */
1207 0x0440, /* - - 45 */
1208 0x0048, /* . - 46 */
1209 0x0448, /* / - 47 */
1210 0x0040, /* 0 - 48 */
1211 0x0040, /* 1 - 49 */
1212 0x0040, /* 2 - 50 */
1213 0x0040, /* 3 - 51 */
1214 0x0040, /* 4 - 52 */
1215 0x0040, /* 5 - 53 */
1216 0x0040, /* 6 - 54 */
1217 0x0040, /* 7 - 55 */
1218 0x0040, /* 8 - 56 */
1219 0x0040, /* 9 - 57 */
1220 0x0048, /* : - 58 */
1221 0x0048, /* ; - 59 */
1222 0x0048, /* < - 60 */
1223 0x0448, /* = - 61 */
1224 0x0048, /* > - 62 */
1225 0x0048, /* ? - 63 */
1226 0x0448, /* @ - 64 */
1227 0x8040, /* A - 65 */
1228 0x8040, /* B - 66 */
1229 0x8040, /* C - 67 */
1230 0x8040, /* D - 68 */
1231 0x8040, /* E - 69 */
1232 0x8040, /* F - 70 */
1233 0x8040, /* G - 71 */
1234 0x8040, /* H - 72 */
1235 0x8040, /* I - 73 */
1236 0x8040, /* J - 74 */
1237 0x8040, /* K - 75 */
1238 0x8040, /* L - 76 */
1239 0x8040, /* M - 77 */
1240 0x8040, /* N - 78 */
1241 0x8040, /* O - 79 */
1242 0x8040, /* P - 80 */
1243 0x8040, /* Q - 81 */
1244 0x8040, /* R - 82 */
1245 0x8040, /* S - 83 */
1246 0x8040, /* T - 84 */
1247 0x8040, /* U - 85 */
1248 0x8040, /* V - 86 */
1249 0x8040, /* W - 87 */
1250 0x8040, /* X - 88 */
1251 0x8040, /* Y - 89 */
1252 0x8040, /* Z - 90 */
1253 0x0048, /* [ - 91 */
1254 0x0448, /* \ - 92 */
1255 0x0048, /* ] - 93 */
1256 0x0448, /* ^ - 94 */
1257 0x0448, /* _ - 95 */
1258 0x0448, /* ` - 96 */
1259 0x8040, /* a - 97 */
1260 0x8040, /* b - 98 */
1261 0x8040, /* c - 99 */
1262 0x8040, /* d - 100 */
1263 0x8040, /* e - 101 */
1264 0x8040, /* f - 102 */
1265 0x8040, /* g - 103 */
1266 0x8040, /* h - 104 */
1267 0x8040, /* i - 105 */
1268 0x8040, /* j - 106 */
1269 0x8040, /* k - 107 */
1270 0x8040, /* l - 108 */
1271 0x8040, /* m - 109 */
1272 0x8040, /* n - 110 */
1273 0x8040, /* o - 111 */
1274 0x8040, /* p - 112 */
1275 0x8040, /* q - 113 */
1276 0x8040, /* r - 114 */
1277 0x8040, /* s - 115 */
1278 0x8040, /* t - 116 */
1279 0x8040, /* u - 117 */
1280 0x8040, /* v - 118 */
1281 0x8040, /* w - 119 */
1282 0x8040, /* x - 120 */
1283 0x8040, /* y - 121 */
1284 0x8040, /* z - 122 */
1285 0x0048, /* { - 123 */
1286 0x0048, /* | - 124 */
1287 0x0048, /* } - 125 */
1288 0x0448, /* ~ - 126 */
1289 0x0000, /*
\7f - 127 */
1290 0x0000, /*
\80 - 128 */
1291 0x0000, /*
\81 - 129 */
1292 0x0008, /*
\82 - 130 */
1293 0x8000, /*
\83 - 131 */
1294 0x0008, /*
\84 - 132 */
1295 0x0008, /*
\85 - 133 */
1296 0x0008, /*
\86 - 134 */
1297 0x0008, /*
\87 - 135 */
1298 0x0001, /*
\88 - 136 */
1299 0x0008, /*
\89 - 137 */
1300 0x8003, /*
\8a - 138 */
1301 0x0008, /*
\8b - 139 */
1302 0x8000, /*
\8c - 140 */
1303 0x0000, /*
\8d - 141 */
1304 0x0000, /*
\8e - 142 */
1305 0x0000, /*
\8f - 143 */
1306 0x0000, /*
\90 - 144 */
1307 0x0088, /*
\91 - 145 */
1308 0x0088, /*
\92 - 146 */
1309 0x0088, /*
\93 - 147 */
1310 0x0088, /*
\94 - 148 */
1311 0x0008, /*
\95 - 149 */
1312 0x0400, /*
\96 - 150 */
1313 0x0400, /*
\97 - 151 */
1314 0x0408, /*
\98 - 152 */
1315 0x0000, /*
\99 - 153 */
1316 0x8003, /*
\9a - 154 */
1317 0x0008, /*
\9b - 155 */
1318 0x8000, /*
\9c - 156 */
1319 0x0000, /*
\9d - 157 */
1320 0x0000, /*
\9e - 158 */
1321 0x8003, /*
\9f - 159 */
1323 0x0008, /* ¡ - 161 */
1324 0x0048, /* ¢ - 162 */
1325 0x0048, /* £ - 163 */
1326 0x0008, /* ¤ - 164 */
1327 0x0048, /* ¥ - 165 */
1328 0x0048, /* ¦ - 166 */
1329 0x0008, /* § - 167 */
1330 0x0408, /* ¨ - 168 */
1331 0x0008, /* © - 169 */
1332 0x0400, /* ª - 170 */
1333 0x0008, /* « - 171 */
1334 0x0048, /* ¬ - 172 */
1335 0x0408, /* - 173 */
1336 0x0008, /* ® - 174 */
1337 0x0448, /* ¯ - 175 */
1338 0x0008, /* ° - 176 */
1339 0x0008, /* ± - 177 */
1340 0x0000, /* ² - 178 */
1341 0x0000, /* ³ - 179 */
1342 0x0408, /* ´ - 180 */
1343 0x0008, /* µ - 181 */
1344 0x0008, /* ¶ - 182 */
1345 0x0008, /* · - 183 */
1346 0x0408, /* ¸ - 184 */
1347 0x0000, /* ¹ - 185 */
1348 0x0400, /* º - 186 */
1349 0x0008, /* » - 187 */
1350 0x0000, /* ¼ - 188 */
1351 0x0000, /* ½ - 189 */
1352 0x0000, /* ¾ - 190 */
1353 0x0008, /* ¿ - 191 */
1354 0x8003, /* À - 192 */
1355 0x8003, /* Á - 193 */
1356 0x8003, /* Â - 194 */
1357 0x8003, /* Ã - 195 */
1358 0x8003, /* Ä - 196 */
1359 0x8003, /* Å - 197 */
1360 0x8000, /* Æ - 198 */
1361 0x8003, /* Ç - 199 */
1362 0x8003, /* È - 200 */
1363 0x8003, /* É - 201 */
1364 0x8003, /* Ê - 202 */
1365 0x8003, /* Ë - 203 */
1366 0x8003, /* Ì - 204 */
1367 0x8003, /* Í - 205 */
1368 0x8003, /* Î - 206 */
1369 0x8003, /* Ï - 207 */
1370 0x8000, /* Ð - 208 */
1371 0x8003, /* Ñ - 209 */
1372 0x8003, /* Ò - 210 */
1373 0x8003, /* Ó - 211 */
1374 0x8003, /* Ô - 212 */
1375 0x8003, /* Õ - 213 */
1376 0x8003, /* Ö - 214 */
1377 0x0008, /* × - 215 */
1378 0x8003, /* Ø - 216 */
1379 0x8003, /* Ù - 217 */
1380 0x8003, /* Ú - 218 */
1381 0x8003, /* Û - 219 */
1382 0x8003, /* Ü - 220 */
1383 0x8003, /* Ý - 221 */
1384 0x8000, /* Þ - 222 */
1385 0x8000, /* ß - 223 */
1386 0x8003, /* à - 224 */
1387 0x8003, /* á - 225 */
1388 0x8003, /* â - 226 */
1389 0x8003, /* ã - 227 */
1390 0x8003, /* ä - 228 */
1391 0x8003, /* å - 229 */
1392 0x8000, /* æ - 230 */
1393 0x8003, /* ç - 231 */
1394 0x8003, /* è - 232 */
1395 0x8003, /* é - 233 */
1396 0x8003, /* ê - 234 */
1397 0x8003, /* ë - 235 */
1398 0x8003, /* ì - 236 */
1399 0x8003, /* í - 237 */
1400 0x8003, /* î - 238 */
1401 0x8003, /* ï - 239 */
1402 0x8000, /* ð - 240 */
1403 0x8003, /* ñ - 241 */
1404 0x8003, /* ò - 242 */
1405 0x8003, /* ó - 243 */
1406 0x8003, /* ô - 244 */
1407 0x8003, /* õ - 245 */
1408 0x8003, /* ö - 246 */
1409 0x0008, /* ÷ - 247 */
1410 0x8003, /* ø - 248 */
1411 0x8003, /* ù - 249 */
1412 0x8003, /* ú - 250 */
1413 0x8003, /* û - 251 */
1414 0x8003, /* ü - 252 */
1415 0x8003, /* ý - 253 */
1416 0x8000, /* þ - 254 */
1417 0x8003 /* ÿ - 255 */
1420 /******************************************************************************
1421 * GetStringType16 [OLE2NLS.7]
1423 BOOL16 WINAPI GetStringType16(LCID locale,DWORD dwInfoType,LPCSTR src,
1424 INT16 cchSrc,LPWORD chartype)
1426 return GetStringTypeExA(locale,dwInfoType,src,cchSrc,chartype);
1428 /******************************************************************************
1429 * GetStringType32A [KERNEL32.396]
1431 BOOL WINAPI GetStringTypeA(LCID locale,DWORD dwInfoType,LPCSTR src,
1432 INT cchSrc,LPWORD chartype)
1434 return GetStringTypeExA(locale,dwInfoType,src,cchSrc,chartype);
1437 /******************************************************************************
1438 * GetStringTypeEx32A [KERNEL32.397]
1440 * FIXME: Ignores the locale.
1442 BOOL WINAPI GetStringTypeExA(LCID locale,DWORD dwInfoType,LPCSTR src,
1443 INT cchSrc,LPWORD chartype)
1447 if ((src==NULL) || (chartype==NULL) || (src==(LPSTR)chartype))
1449 SetLastError(ERROR_INVALID_PARAMETER);
1454 cchSrc=lstrlenA(src)+1;
1456 switch (dwInfoType) {
1458 for (i=0;i<cchSrc;i++)
1461 if (isdigit(src[i])) chartype[i]|=C1_DIGIT;
1462 if (isalpha(src[i])) chartype[i]|=C1_ALPHA;
1463 if (islower(src[i])) chartype[i]|=C1_LOWER;
1464 if (isupper(src[i])) chartype[i]|=C1_UPPER;
1465 if (isspace(src[i])) chartype[i]|=C1_SPACE;
1466 if (ispunct(src[i])) chartype[i]|=C1_PUNCT;
1467 if (iscntrl(src[i])) chartype[i]|=C1_CNTRL;
1468 /* FIXME: isblank() is a GNU extension */
1469 /* if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1470 if ((src[i] == ' ') || (src[i] == '\t')) chartype[i]|=C1_BLANK;
1476 for (i=0;i<cchSrc;i++)
1478 chartype[i]=(WORD)CT_CType2_LUT[i];
1483 for (i=0;i<cchSrc;i++)
1485 chartype[i]=OLE2NLS_CT_CType3_LUT[i];
1490 ERR("Unknown dwInfoType:%ld\n",dwInfoType);
1495 /******************************************************************************
1496 * GetStringType32W [KERNEL32.399]
1499 * Yes, this is missing LCID locale. MS fault.
1501 BOOL WINAPI GetStringTypeW(DWORD dwInfoType,LPCWSTR src,INT cchSrc,
1504 return GetStringTypeExW(0/*defaultlocale*/,dwInfoType,src,cchSrc,chartype);
1507 /******************************************************************************
1508 * GetStringTypeEx32W [KERNEL32.398]
1510 * FIXME: unicode chars are assumed chars
1512 BOOL WINAPI GetStringTypeExW(LCID locale,DWORD dwInfoType,LPCWSTR src,
1513 INT cchSrc,LPWORD chartype)
1519 cchSrc=lstrlenW(src)+1;
1521 switch (dwInfoType) {
1523 FIXME("CT_CTYPE2 not supported.\n");
1526 FIXME("CT_CTYPE3 not supported.\n");
1530 for (i=0;i<cchSrc;i++) {
1532 if (isdigit(src[i])) chartype[i]|=C1_DIGIT;
1533 if (isalpha(src[i])) chartype[i]|=C1_ALPHA;
1534 if (islower(src[i])) chartype[i]|=C1_LOWER;
1535 if (isupper(src[i])) chartype[i]|=C1_UPPER;
1536 if (isspace(src[i])) chartype[i]|=C1_SPACE;
1537 if (ispunct(src[i])) chartype[i]|=C1_PUNCT;
1538 if (iscntrl(src[i])) chartype[i]|=C1_CNTRL;
1539 /* FIXME: isblank() is a GNU extension */
1540 /* if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1541 if ((src[i] == ' ') || (src[i] == '\t')) chartype[i]|=C1_BLANK;
1547 /*****************************************************************
1548 * WINE_GetLanguageName [internal]
1550 static LPCSTR WINE_GetLanguageName( UINT langid )
1553 for ( i = 0; languages[i].langid != 0; i++ )
1554 if ( langid == languages[i].langid )
1557 return languages[i].langname;
1560 /***********************************************************************
1561 * VerLanguageNameA [KERNEL32.709][VERSION.9]
1563 DWORD WINAPI VerLanguageNameA( UINT wLang, LPSTR szLang, UINT nSize )
1570 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1571 * from the registry.
1575 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1578 result = RegQueryValueA( HKEY_LOCAL_MACHINE, buffer, szLang, (LPDWORD)&nSize );
1579 if ( result == ERROR_SUCCESS || result == ERROR_MORE_DATA )
1583 * If that fails, use the internal table
1586 name = WINE_GetLanguageName( wLang );
1587 lstrcpynA( szLang, name, nSize );
1588 return lstrlenA( name );
1591 /***********************************************************************
1592 * VerLanguageNameW [KERNEL32.710][VERSION.10]
1594 DWORD WINAPI VerLanguageNameW( UINT wLang, LPWSTR szLang, UINT nSize )
1602 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1603 * from the registry.
1607 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1610 keyname = HEAP_strdupAtoW( GetProcessHeap(), 0, buffer );
1611 result = RegQueryValueW( HKEY_LOCAL_MACHINE, keyname, szLang, (LPDWORD)&nSize );
1612 HeapFree( GetProcessHeap(), 0, keyname );
1614 if ( result == ERROR_SUCCESS || result == ERROR_MORE_DATA )
1618 * If that fails, use the internal table
1621 name = WINE_GetLanguageName( wLang );
1622 lstrcpynAtoW( szLang, name, nSize );
1623 return lstrlenA( name );
1627 static const unsigned char LCM_Unicode_LUT[] = {
1660 7 , 28, /* ! - 33 */
1661 7 , 29, /* " - 34 */ /* " */
1662 7 , 31, /* # - 35 */
1663 7 , 33, /* $ - 36 */
1664 7 , 35, /* % - 37 */
1665 7 , 37, /* & - 38 */
1666 6 , 128, /* ' - 39 */
1667 7 , 39, /* ( - 40 */
1668 7 , 42, /* ) - 41 */
1669 7 , 45, /* * - 42 */
1671 7 , 47, /* , - 44 */
1672 6 , 130, /* - - 45 */
1673 7 , 51, /* . - 46 */
1674 7 , 53, /* / - 47 */
1675 12 , 3, /* 0 - 48 */
1676 12 , 33, /* 1 - 49 */
1677 12 , 51, /* 2 - 50 */
1678 12 , 70, /* 3 - 51 */
1679 12 , 88, /* 4 - 52 */
1680 12 , 106, /* 5 - 53 */
1681 12 , 125, /* 6 - 54 */
1682 12 , 144, /* 7 - 55 */
1683 12 , 162, /* 8 - 56 */
1684 12 , 180, /* 9 - 57 */
1685 7 , 55, /* : - 58 */
1686 7 , 58, /* ; - 59 */
1687 8 , 14, /* < - 60 */
1688 8 , 18, /* = - 61 */
1689 8 , 20, /* > - 62 */
1690 7 , 60, /* ? - 63 */
1691 7 , 62, /* @ - 64 */
1692 14 , 2, /* A - 65 */
1693 14 , 9, /* B - 66 */
1694 14 , 10, /* C - 67 */
1695 14 , 26, /* D - 68 */
1696 14 , 33, /* E - 69 */
1697 14 , 35, /* F - 70 */
1698 14 , 37, /* G - 71 */
1699 14 , 44, /* H - 72 */
1700 14 , 50, /* I - 73 */
1701 14 , 53, /* J - 74 */
1702 14 , 54, /* K - 75 */
1703 14 , 72, /* L - 76 */
1704 14 , 81, /* M - 77 */
1705 14 , 112, /* N - 78 */
1706 14 , 124, /* O - 79 */
1707 14 , 126, /* P - 80 */
1708 14 , 137, /* Q - 81 */
1709 14 , 138, /* R - 82 */
1710 14 , 145, /* S - 83 */
1711 14 , 153, /* T - 84 */
1712 14 , 159, /* U - 85 */
1713 14 , 162, /* V - 86 */
1714 14 , 164, /* W - 87 */
1715 14 , 166, /* X - 88 */
1716 14 , 167, /* Y - 89 */
1717 14 , 169, /* Z - 90 */
1718 7 , 63, /* [ - 91 */
1719 7 , 65, /* \ - 92 */
1720 7 , 66, /* ] - 93 */
1721 7 , 67, /* ^ - 94 */
1722 7 , 68, /* _ - 95 */
1723 7 , 72, /* ` - 96 */
1724 14 , 2, /* a - 97 */
1725 14 , 9, /* b - 98 */
1726 14 , 10, /* c - 99 */
1727 14 , 26, /* d - 100 */
1728 14 , 33, /* e - 101 */
1729 14 , 35, /* f - 102 */
1730 14 , 37, /* g - 103 */
1731 14 , 44, /* h - 104 */
1732 14 , 50, /* i - 105 */
1733 14 , 53, /* j - 106 */
1734 14 , 54, /* k - 107 */
1735 14 , 72, /* l - 108 */
1736 14 , 81, /* m - 109 */
1737 14 , 112, /* n - 110 */
1738 14 , 124, /* o - 111 */
1739 14 , 126, /* p - 112 */
1740 14 , 137, /* q - 113 */
1741 14 , 138, /* r - 114 */
1742 14 , 145, /* s - 115 */
1743 14 , 153, /* t - 116 */
1744 14 , 159, /* u - 117 */
1745 14 , 162, /* v - 118 */
1746 14 , 164, /* w - 119 */
1747 14 , 166, /* x - 120 */
1748 14 , 167, /* y - 121 */
1749 14 , 169, /* z - 122 */
1750 7 , 74, /* { - 123 */
1751 7 , 76, /* | - 124 */
1752 7 , 78, /* } - 125 */
1753 7 , 80, /* ~ - 126 */
1754 6 , 29, /*
\7f - 127 */
1755 6 , 30, /*
\80 - 128 */
1756 6 , 31, /*
\81 - 129 */
1757 7 , 123, /*
\82 - 130 */
1758 14 , 35, /*
\83 - 131 */
1759 7 , 127, /*
\84 - 132 */
1760 10 , 21, /*
\85 - 133 */
1761 10 , 15, /*
\86 - 134 */
1762 10 , 16, /*
\87 - 135 */
1763 7 , 67, /*
\88 - 136 */
1764 10 , 22, /*
\89 - 137 */
1765 14 , 145, /*
\8a - 138 */
1766 7 , 136, /*
\8b - 139 */
1767 14 + 16 , 124, /*
\8c - 140 */
1768 6 , 43, /*
\8d - 141 */
1769 6 , 44, /*
\8e - 142 */
1770 6 , 45, /*
\8f - 143 */
1771 6 , 46, /*
\90 - 144 */
1772 7 , 121, /*
\91 - 145 */
1773 7 , 122, /*
\92 - 146 */
1774 7 , 125, /*
\93 - 147 */
1775 7 , 126, /*
\94 - 148 */
1776 10 , 17, /*
\95 - 149 */
1777 6 , 137, /*
\96 - 150 */
1778 6 , 139, /*
\97 - 151 */
1779 7 , 93, /*
\98 - 152 */
1780 14 , 156, /*
\99 - 153 */
1781 14 , 145, /*
\9a - 154 */
1782 7 , 137, /*
\9b - 155 */
1783 14 + 16 , 124, /*
\9c - 156 */
1784 6 , 59, /*
\9d - 157 */
1785 6 , 60, /*
\9e - 158 */
1786 14 , 167, /*
\9f - 159 */
1788 7 , 81, /* ¡ - 161 */
1789 10 , 2, /* ¢ - 162 */
1790 10 , 3, /* £ - 163 */
1791 10 , 4, /* ¤ - 164 */
1792 10 , 5, /* ¥ - 165 */
1793 7 , 82, /* ¦ - 166 */
1794 10 , 6, /* § - 167 */
1795 7 , 83, /* ¨ - 168 */
1796 10 , 7, /* © - 169 */
1797 14 , 2, /* ª - 170 */
1798 8 , 24, /* « - 171 */
1799 10 , 8, /* ¬ - 172 */
1800 6 , 131, /* - 173 */
1801 10 , 9, /* ® - 174 */
1802 7 , 84, /* ¯ - 175 */
1803 10 , 10, /* ° - 176 */
1804 8 , 23, /* ± - 177 */
1805 12 , 51, /* ² - 178 */
1806 12 , 70, /* ³ - 179 */
1807 7 , 85, /* ´ - 180 */
1808 10 , 11, /* µ - 181 */
1809 10 , 12, /* ¶ - 182 */
1810 10 , 13, /* · - 183 */
1811 7 , 86, /* ¸ - 184 */
1812 12 , 33, /* ¹ - 185 */
1813 14 , 124, /* º - 186 */
1814 8 , 26, /* » - 187 */
1815 12 , 21, /* ¼ - 188 */
1816 12 , 25, /* ½ - 189 */
1817 12 , 29, /* ¾ - 190 */
1818 7 , 87, /* ¿ - 191 */
1819 14 , 2, /* À - 192 */
1820 14 , 2, /* Á - 193 */
1821 14 , 2, /* Â - 194 */
1822 14 , 2, /* Ã - 195 */
1823 14 , 2, /* Ä - 196 */
1824 14 , 2, /* Å - 197 */
1825 14 + 16 , 2, /* Æ - 198 */
1826 14 , 10, /* Ç - 199 */
1827 14 , 33, /* È - 200 */
1828 14 , 33, /* É - 201 */
1829 14 , 33, /* Ê - 202 */
1830 14 , 33, /* Ë - 203 */
1831 14 , 50, /* Ì - 204 */
1832 14 , 50, /* Í - 205 */
1833 14 , 50, /* Î - 206 */
1834 14 , 50, /* Ï - 207 */
1835 14 , 26, /* Ð - 208 */
1836 14 , 112, /* Ñ - 209 */
1837 14 , 124, /* Ò - 210 */
1838 14 , 124, /* Ó - 211 */
1839 14 , 124, /* Ô - 212 */
1840 14 , 124, /* Õ - 213 */
1841 14 , 124, /* Ö - 214 */
1842 8 , 28, /* × - 215 */
1843 14 , 124, /* Ø - 216 */
1844 14 , 159, /* Ù - 217 */
1845 14 , 159, /* Ú - 218 */
1846 14 , 159, /* Û - 219 */
1847 14 , 159, /* Ü - 220 */
1848 14 , 167, /* Ý - 221 */
1849 14 + 32 , 153, /* Þ - 222 */
1850 14 + 48 , 145, /* ß - 223 */
1851 14 , 2, /* à - 224 */
1852 14 , 2, /* á - 225 */
1853 14 , 2, /* â - 226 */
1854 14 , 2, /* ã - 227 */
1855 14 , 2, /* ä - 228 */
1856 14 , 2, /* å - 229 */
1857 14 + 16 , 2, /* æ - 230 */
1858 14 , 10, /* ç - 231 */
1859 14 , 33, /* è - 232 */
1860 14 , 33, /* é - 233 */
1861 14 , 33, /* ê - 234 */
1862 14 , 33, /* ë - 235 */
1863 14 , 50, /* ì - 236 */
1864 14 , 50, /* í - 237 */
1865 14 , 50, /* î - 238 */
1866 14 , 50, /* ï - 239 */
1867 14 , 26, /* ð - 240 */
1868 14 , 112, /* ñ - 241 */
1869 14 , 124, /* ò - 242 */
1870 14 , 124, /* ó - 243 */
1871 14 , 124, /* ô - 244 */
1872 14 , 124, /* õ - 245 */
1873 14 , 124, /* ö - 246 */
1874 8 , 29, /* ÷ - 247 */
1875 14 , 124, /* ø - 248 */
1876 14 , 159, /* ù - 249 */
1877 14 , 159, /* ú - 250 */
1878 14 , 159, /* û - 251 */
1879 14 , 159, /* ü - 252 */
1880 14 , 167, /* ý - 253 */
1881 14 + 32 , 153, /* þ - 254 */
1882 14 , 167 /* ÿ - 255 */ };
1884 static const unsigned char LCM_Unicode_LUT_2[] = { 33, 44, 145 };
1886 #define LCM_Diacritic_Start 131
1888 static const unsigned char LCM_Diacritic_LUT[] = {
1889 123, /*
\83 - 131 */
2016 /******************************************************************************
2017 * OLE2NLS_isPunctuation [INTERNAL]
2019 static int OLE2NLS_isPunctuation(unsigned char c)
2021 /* "punctuation character" in this context is a character which is
2022 considered "less important" during word sort comparison.
2023 See LCMapString implementation for the precise definition
2024 of "less important". */
2026 return (LCM_Unicode_LUT[-2+2*c]==6);
2029 /******************************************************************************
2030 * OLE2NLS_isNonSpacing [INTERNAL]
2032 static int OLE2NLS_isNonSpacing(unsigned char c)
2034 /* This function is used by LCMapString32A. Characters
2035 for which it returns true are ignored when mapping a
2036 string with NORM_IGNORENONSPACE */
2037 return ((c==136) || (c==170) || (c==186));
2040 /******************************************************************************
2041 * OLE2NLS_isSymbol [INTERNAL]
2043 static int OLE2NLS_isSymbol(unsigned char c)
2045 /* This function is used by LCMapString32A. Characters
2046 for which it returns true are ignored when mapping a
2047 string with NORM_IGNORESYMBOLS */
2048 return ( (c!=0) && !IsCharAlphaNumericA(c) );
2051 /******************************************************************************
2052 * identity [Internal]
2054 static int identity(int c)
2059 /*************************************************************************
2060 * LCMapString32A [KERNEL32.492]
2062 * Convert a string, or generate a sort key from it.
2064 * If (mapflags & LCMAP_SORTKEY), the function will generate
2065 * a sort key for the source string. Else, it will convert it
2066 * accordingly to the flags LCMAP_UPPERCASE, LCMAP_LOWERCASE,...
2070 * Success : length of the result string.
2073 * If called with scrlen = -1, the function will compute the length
2074 * of the 0-terminated string strsrc by itself.
2076 * If called with dstlen = 0, returns the buffer length that
2077 * would be required.
2079 * NORM_IGNOREWIDTH means to compare ASCII and wide characters
2080 * as if they are equal.
2081 * In the only code page implemented so far, there may not be
2082 * wide characters in strings passed to LCMapString32A,
2083 * so there is nothing to be done for this flag.
2085 INT WINAPI LCMapStringA(
2086 LCID lcid /* locale identifier created with MAKELCID;
2087 LOCALE_SYSTEM_DEFAULT and LOCALE_USER_DEFAULT are
2088 predefined values. */,
2089 DWORD mapflags /* flags */,
2090 LPCSTR srcstr /* source buffer */,
2091 INT srclen /* source length */,
2092 LPSTR dststr /* destination buffer */,
2093 INT dstlen /* destination buffer length */)
2097 TRACE_(string)("(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
2098 lcid,mapflags,srcstr,srclen,dststr,dstlen);
2100 if ( ((dstlen!=0) && (dststr==NULL)) || (srcstr==NULL) )
2102 ERR("(src=%s,dest=%s): Invalid NULL string\n", srcstr, dststr);
2103 SetLastError(ERROR_INVALID_PARAMETER);
2107 srclen = lstrlenA(srcstr) + 1 ; /* (include final '\0') */
2109 #define LCMAPSTRINGA_SUPPORTED_FLAGS (LCMAP_UPPERCASE | \
2113 NORM_IGNORENONSPACE | \
2115 NORM_IGNOREWIDTH | \
2116 NORM_IGNOREKANATYPE)
2117 /* FIXME: as long as we don't support Kanakana nor Hirigana
2118 * characters, we can support NORM_IGNOREKANATYPE
2120 if (mapflags & ~LCMAPSTRINGA_SUPPORTED_FLAGS)
2122 FIXME_(string)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2123 "unimplemented flags: 0x%08lx\n",
2130 mapflags & ~LCMAPSTRINGA_SUPPORTED_FLAGS
2134 if ( !(mapflags & LCMAP_SORTKEY) )
2137 int (*f)(int) = identity;
2138 int flag_ignorenonspace = mapflags & NORM_IGNORENONSPACE;
2139 int flag_ignoresymbols = mapflags & NORM_IGNORESYMBOLS;
2141 if (flag_ignorenonspace || flag_ignoresymbols)
2143 /* For some values of mapflags, the length of the resulting
2144 string is not known at this point. Windows does map the string
2145 and does not SetLastError ERROR_INSUFFICIENT_BUFFER in
2149 /* Compute required length */
2150 for (i=j=0; i < srclen; i++)
2152 if ( !(flag_ignorenonspace && OLE2NLS_isNonSpacing(srcstr[i]))
2153 && !(flag_ignoresymbols && OLE2NLS_isSymbol(srcstr[i])) )
2165 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2169 if (mapflags & LCMAP_UPPERCASE)
2171 else if (mapflags & LCMAP_LOWERCASE)
2173 /* FIXME: NORM_IGNORENONSPACE requires another conversion */
2174 for (i=j=0; (i<srclen) && (j<dstlen) ; i++)
2176 if ( !(flag_ignorenonspace && OLE2NLS_isNonSpacing(srcstr[i]))
2177 && !(flag_ignoresymbols && OLE2NLS_isSymbol(srcstr[i])) )
2179 dststr[j] = (CHAR) f(srcstr[i]);
2186 /* else ... (mapflags & LCMAP_SORTKEY) */
2190 int diacritic_len=0;
2191 int delayed_punctuation_len=0;
2192 char *case_component;
2193 char *diacritic_component;
2194 char *delayed_punctuation_component;
2196 int flag_stringsort = mapflags & SORT_STRINGSORT;
2198 /* compute how much room we will need */
2199 for (i=0;i<srclen;i++)
2202 unsigned char source_char = srcstr[i];
2203 if (source_char!='\0')
2205 if (flag_stringsort || !OLE2NLS_isPunctuation(source_char))
2208 if ( LCM_Unicode_LUT[-2+2*source_char] & ~15 )
2209 unicode_len++; /* double letter */
2213 delayed_punctuation_len++;
2217 if (isupper(source_char))
2218 case_len=unicode_len;
2220 ofs = source_char - LCM_Diacritic_Start;
2221 if ((ofs>=0) && (LCM_Diacritic_LUT[ofs]!=2))
2222 diacritic_len=unicode_len;
2225 if (mapflags & NORM_IGNORECASE)
2227 if (mapflags & NORM_IGNORENONSPACE)
2230 room = 2 * unicode_len /* "unicode" component */
2231 + diacritic_len /* "diacritic" component */
2232 + case_len /* "case" component */
2233 + 4 * delayed_punctuation_len /* punctuation in word sort mode */
2234 + 4 /* four '\1' separators */
2235 + 1 ; /* terminal '\0' */
2238 else if (dstlen<room)
2240 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2244 /*FIXME the Pointercheck should not be nessesary */
2245 if (IsBadWritePtr (dststr,room))
2246 { ERR_(string)("bad destination buffer (dststr) : %p,%d\n",dststr,dstlen);
2247 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2251 /* locate each component, write separators */
2252 diacritic_component = dststr + 2*unicode_len ;
2253 *diacritic_component++ = '\1';
2254 case_component = diacritic_component + diacritic_len ;
2255 *case_component++ = '\1';
2256 delayed_punctuation_component = case_component + case_len ;
2257 *delayed_punctuation_component++ = '\1';
2258 *delayed_punctuation_component++ = '\1';
2260 /* read source string char by char, write
2261 corresponding weight in each component. */
2262 for (i=0,count=0;i<srclen;i++)
2264 unsigned char source_char=srcstr[i];
2265 if (source_char!='\0')
2268 type = LCM_Unicode_LUT[-2+2*source_char];
2269 longcode = type >> 4;
2271 if (!flag_stringsort && OLE2NLS_isPunctuation(source_char))
2273 UINT16 encrypted_location = (1<<15) + 7 + 4*count;
2274 *delayed_punctuation_component++ = (unsigned char) (encrypted_location>>8);
2275 *delayed_punctuation_component++ = (unsigned char) (encrypted_location&255);
2276 /* big-endian is used here because it lets string comparison be
2277 compatible with numerical comparison */
2279 *delayed_punctuation_component++ = type;
2280 *delayed_punctuation_component++ = LCM_Unicode_LUT[-1+2*source_char];
2281 /* assumption : a punctuation character is never a
2282 double or accented letter */
2286 dststr[2*count] = type;
2287 dststr[2*count+1] = LCM_Unicode_LUT[-1+2*source_char];
2291 case_component[count] = ( isupper(source_char) ? 18 : 2 ) ;
2292 if (count<diacritic_len)
2293 diacritic_component[count] = 2; /* assumption: a double letter
2294 is never accented */
2297 dststr[2*count] = type;
2298 dststr[2*count+1] = *(LCM_Unicode_LUT_2 - 1 + longcode);
2299 /* 16 in the first column of LCM_Unicode_LUT --> longcode = 1
2300 32 in the first column of LCM_Unicode_LUT --> longcode = 2
2301 48 in the first column of LCM_Unicode_LUT --> longcode = 3 */
2305 case_component[count] = ( isupper(source_char) ? 18 : 2 ) ;
2306 if (count<diacritic_len)
2308 int ofs = source_char - LCM_Diacritic_Start;
2309 diacritic_component[count] = (ofs>=0 ? LCM_Diacritic_LUT[ofs] : 2);
2315 dststr[room-1] = '\0';
2320 /*************************************************************************
2321 * LCMapString32W [KERNEL32.493]
2323 * Convert a string, or generate a sort key from it.
2327 * See LCMapString32A for documentation
2329 INT WINAPI LCMapStringW(
2330 LCID lcid,DWORD mapflags,LPCWSTR srcstr,INT srclen,LPWSTR dststr,
2335 TRACE_(string)("(0x%04lx,0x%08lx,%p,%d,%p,%d)\n",
2336 lcid,mapflags,srcstr,srclen,dststr,dstlen);
2338 if ( ((dstlen!=0) && (dststr==NULL)) || (srcstr==NULL) )
2340 ERR("(src=%p,dst=%p): Invalid NULL string\n", srcstr, dststr);
2341 SetLastError(ERROR_INVALID_PARAMETER);
2345 srclen = lstrlenW(srcstr)+1;
2346 if (mapflags & LCMAP_SORTKEY)
2348 FIXME_(string)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2349 "unimplemented flags: 0x%08lx\n",
2350 lcid,mapflags,srcstr,srclen,dststr,dstlen,mapflags);
2355 int (*f)(int)=identity;
2359 if (dstlen<srclen) {
2360 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2363 if (mapflags & LCMAP_UPPERCASE)
2365 else if (mapflags & LCMAP_LOWERCASE)
2367 for (i=0; i < srclen; i++)
2368 dststr[i] = (WCHAR) f(srcstr[i]);
2373 /***********************************************************************
2374 * CompareString16 (OLE2NLS.8)
2376 UINT16 WINAPI CompareString16(DWORD lcid,DWORD fdwStyle,
2377 LPCSTR s1,DWORD l1,LPCSTR s2,DWORD l2)
2379 return (UINT16)CompareStringA(lcid,fdwStyle,s1,l1,s2,l2);
2382 /******************************************************************************
2383 * CompareString32A [KERNEL32.143]
2384 * Compares two strings using locale
2388 * success: CSTR_LESS_THAN, CSTR_EQUAL, CSTR_GREATER_THAN
2393 * Defaults to a word sort, but uses a string sort if
2394 * SORT_STRINGSORT is set.
2395 * Calls SetLastError for ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER.
2399 * This implementation ignores the locale
2403 * Quite inefficient.
2405 UINT WINAPI CompareStringA(
2406 DWORD lcid, /* locale ID */
2407 DWORD fdwStyle, /* comparison-style options */
2408 LPCSTR s1, /* first string */
2409 DWORD l1, /* length of first string */
2410 LPCSTR s2, /* second string */
2411 DWORD l2) /* length of second string */
2413 int mapstring_flags;
2417 TRACE("%s and %s\n",
2418 debugstr_a (s1), debugstr_a (s2));
2420 if ( (s1==NULL) || (s2==NULL) )
2422 ERR("(s1=%s,s2=%s): Invalid NULL string\n", s1, s2);
2423 SetLastError(ERROR_INVALID_PARAMETER);
2427 if(fdwStyle & NORM_IGNORESYMBOLS)
2428 FIXME("IGNORESYMBOLS not supported\n");
2430 mapstring_flags = LCMAP_SORTKEY | fdwStyle ;
2431 len1 = LCMapStringA(lcid,mapstring_flags,s1,l1,NULL,0);
2432 len2 = LCMapStringA(lcid,mapstring_flags,s2,l2,NULL,0);
2434 if ((len1==0)||(len2==0))
2435 return 0; /* something wrong happened */
2437 sk1 = (LPSTR)HeapAlloc(GetProcessHeap(),0,len1);
2438 sk2 = (LPSTR)HeapAlloc(GetProcessHeap(),0,len2);
2439 if ( (!LCMapStringA(lcid,mapstring_flags,s1,l1,sk1,len1))
2440 || (!LCMapStringA(lcid,mapstring_flags,s2,l2,sk2,len2)) )
2442 ERR("Bug in LCmapString32A.\n");
2447 /* strcmp doesn't necessarily return -1, 0, or 1 */
2448 result = strcmp(sk1,sk2);
2450 HeapFree(GetProcessHeap(),0,sk1);
2451 HeapFree(GetProcessHeap(),0,sk2);
2458 /* must be greater, if we reach this point */
2462 /******************************************************************************
2463 * CompareString32W [KERNEL32.144]
2464 * This implementation ignores the locale
2465 * FIXME : Does only string sort. Should
2466 * be reimplemented the same way as CompareString32A.
2468 UINT WINAPI CompareStringW(DWORD lcid, DWORD fdwStyle,
2469 LPCWSTR s1, DWORD l1, LPCWSTR s2,DWORD l2)
2472 if(fdwStyle & NORM_IGNORENONSPACE)
2473 FIXME("IGNORENONSPACE not supprted\n");
2474 if(fdwStyle & NORM_IGNORESYMBOLS)
2475 FIXME("IGNORESYMBOLS not supported\n");
2477 /* Is strcmp defaulting to string sort or to word sort?? */
2478 /* FIXME: Handle NORM_STRINGSORT */
2479 l1 = (l1==-1)?lstrlenW(s1):l1;
2480 l2 = (l2==-1)?lstrlenW(s2):l2;
2481 len = l1<l2 ? l1:l2;
2482 ret = (fdwStyle & NORM_IGNORECASE) ?
2483 CRTDLL__wcsnicmp(s1,s2,len) : CRTDLL_wcsncmp(s1,s2,len);
2484 /* not equal, return 1 or 3 */
2485 if(ret!=0) return ret+2;
2486 /* same len, return 2 */
2487 if(l1==l2) return 2;
2488 /* the longer one is lexically greater */
2489 return (l1<l2)? 1 : 3;
2492 /******************************************************************************
2493 * RegisterNLSInfoChanged [OLE2NLS.10]
2495 BOOL16 WINAPI RegisterNLSInfoChanged16(LPVOID/*FIXME*/ lpNewNLSInfo)
2497 FIXME("Fully implemented, but doesn't effect anything.\n");
2508 lpNLSInfo = lpNewNLSInfo;
2513 return FALSE; /* ptr not set */
2516 /******************************************************************************
2517 * OLE_GetFormatA [Internal]
2520 * If datelen == 0, it should return the reguired string length.
2522 This function implements stuff for GetDateFormat() and
2525 d single-digit (no leading zero) day (of month)
2526 dd two-digit day (of month)
2527 ddd short day-of-week name
2528 dddd long day-of-week name
2529 M single-digit month
2531 MMM short month name
2532 MMMM full month name
2533 y two-digit year, no leading 0
2535 yyyy four-digit year
2537 h hours with no leading zero (12-hour)
2538 hh hours with full two digits
2539 H hours with no leading zero (24-hour)
2540 HH hours with full two digits
2541 m minutes with no leading zero
2542 mm minutes with full two digits
2543 s seconds with no leading zero
2544 ss seconds with full two digits
2545 t time marker (A or P)
2546 tt time marker (AM, PM)
2547 '' used to quote literal characters
2548 '' (within a quoted string) indicates a literal '
2550 These functions REQUIRE valid locale, date, and format.
2552 static INT OLE_GetFormatA(LCID locale,
2556 LPCSTR _format, /*in*/
2561 int count, type, inquote, Overflow;
2567 const char * _dgfmt[] = { "%d", "%02d" };
2568 const char ** dgfmt = _dgfmt - 1;
2570 /* report, for debugging */
2571 TRACE("(0x%lx,0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt=%p \'%s\' , %p, len=%d)\n",
2572 locale, flags, tflags,
2573 xtime->wDay, xtime->wHour, xtime->wMinute, xtime->wSecond,
2574 _format, _format, date, datelen);
2577 FIXME("datelen = 0, returning 255\n");
2581 /* initalize state variables and output buffer */
2583 count = 0; inquote = 0; Overflow = 0;
2585 date[0] = buf[0] = '\0';
2587 strcpy(format,_format);
2589 /* alter the formatstring, while it works for all languages now in wine
2590 its possible that it fails when the time looks like ss:mm:hh as example*/
2591 if (tflags & (TIME_NOMINUTESORSECONDS))
2592 { if ((pos = strstr ( format, ":mm")))
2593 { memcpy ( pos, pos+3, strlen(format)-(pos-format)-2 );
2596 if (tflags & (TIME_NOSECONDS))
2597 { if ((pos = strstr ( format, ":ss")))
2598 { memcpy ( pos, pos+3, strlen(format)-(pos-format)-2 );
2602 for (inpos = 0;; inpos++) {
2603 /* TRACE(ole, "STATE inpos=%2d outpos=%2d count=%d inquote=%d type=%c buf,date = %c,%c\n", inpos, outpos, count, inquote, type, buf[inpos], date[outpos]); */
2605 if (format[inpos] == '\'') {
2606 if (format[inpos+1] == '\'') {
2608 date[outpos++] = '\'';
2611 continue; /* we did nothing to the output */
2613 } else if (format[inpos] == '\0') {
2614 date[outpos++] = '\0';
2615 if (outpos > datelen) Overflow = 1;
2618 date[outpos++] = format[inpos];
2619 if (outpos > datelen) {
2621 date[outpos-1] = '\0'; /* this is the last place where
2622 it's safe to write */
2626 } else if ( (count && (format[inpos] != type))
2628 || (count == 2 && strchr("ghHmst", type)) )
2632 GetLocaleInfoA(locale,
2634 + xtime->wDayOfWeek - 1,
2636 } else if (count == 3) {
2637 GetLocaleInfoA(locale,
2638 LOCALE_SABBREVDAYNAME1
2639 + xtime->wDayOfWeek - 1,
2642 sprintf(buf, dgfmt[count], xtime->wDay);
2644 } else if (type == 'M') {
2646 GetLocaleInfoA(locale,
2647 LOCALE_SABBREVMONTHNAME1
2648 + xtime->wMonth - 1,
2650 } else if (count == 4) {
2651 GetLocaleInfoA(locale,
2653 + xtime->wMonth - 1,
2656 sprintf(buf, dgfmt[count], xtime->wMonth);
2658 } else if (type == 'y') {
2660 sprintf(buf, "%d", xtime->wYear);
2661 } else if (count == 3) {
2663 WARN("unknown format, c=%c, n=%d\n", type, count);
2665 sprintf(buf, dgfmt[count], xtime->wYear % 100);
2667 } else if (type == 'g') {
2669 FIXME("LOCALE_ICALENDARTYPE unimp.\n");
2673 WARN("unknown format, c=%c, n=%d\n", type, count);
2675 } else if (type == 'h') {
2676 /* gives us hours 1:00 -- 12:00 */
2677 sprintf(buf, dgfmt[count], (xtime->wHour-1)%12 +1);
2678 } else if (type == 'H') {
2680 sprintf(buf, dgfmt[count], xtime->wHour);
2681 } else if ( type == 'm') {
2682 sprintf(buf, dgfmt[count], xtime->wMinute);
2683 } else if ( type == 's') {
2684 sprintf(buf, dgfmt[count], xtime->wSecond);
2685 } else if (type == 't') {
2687 sprintf(buf, "%c", (xtime->wHour < 12) ? 'A' : 'P');
2688 } else if (count == 2) {
2689 /* sprintf(buf, "%s", (xtime->wHour < 12) ? "AM" : "PM"); */
2690 GetLocaleInfoA(locale,
2692 ? LOCALE_S1159 : LOCALE_S2359,
2697 /* we need to check the next char in the format string
2698 again, no matter what happened */
2701 /* add the contents of buf to the output */
2702 buflen = strlen(buf);
2703 if (outpos + buflen < datelen) {
2704 date[outpos] = '\0'; /* for strcat to hook onto */
2708 date[outpos] = '\0';
2709 strncat(date, buf, datelen - outpos);
2710 date[datelen - 1] = '\0';
2711 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2712 WARN("insufficient buffer\n");
2716 /* reset the variables we used to keep track of this item */
2719 } else if (format[inpos] == '\0') {
2720 /* we can't check for this at the loop-head, because
2721 that breaks the printing of the last format-item */
2722 date[outpos] = '\0';
2725 /* continuing a code for an item */
2728 } else if (strchr("hHmstyMdg", format[inpos])) {
2729 type = format[inpos];
2732 } else if (format[inpos] == '\'') {
2736 date[outpos++] = format[inpos];
2738 /* now deal with a possible buffer overflow */
2739 if (outpos >= datelen) {
2740 date[datelen - 1] = '\0';
2741 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2747 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2750 /* finish it off with a string terminator */
2753 if (outpos > datelen-1) outpos = datelen-1;
2754 date[outpos] = '\0';
2756 TRACE("OLE_GetFormatA returns string '%s', len %d\n",
2761 /******************************************************************************
2762 * OLE_GetFormatW [INTERNAL]
2764 static INT OLE_GetFormatW(LCID locale, DWORD flags, DWORD tflags,
2767 LPWSTR output, INT outlen)
2770 int count, type=0, inquote;
2771 int Overflow; /* loop check */
2774 WCHAR arg0[] = {0}, arg1[] = {'%','d',0};
2775 WCHAR arg2[] = {'%','0','2','d',0};
2777 int datevars=0, timevars=0;
2783 /* make a debug report */
2784 TRACE("args: 0x%lx, 0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt:%s (at %p), "
2785 "%p with max len %d\n",
2786 locale, flags, tflags,
2787 xtime->wDay, xtime->wHour, xtime->wMinute, xtime->wSecond,
2788 debugstr_w(format), format, output, outlen);
2791 FIXME("outlen = 0, returning 255\n");
2795 /* initialize state variables */
2798 inquote = Overflow = 0;
2799 /* this is really just a sanity check */
2800 output[0] = buf[0] = 0;
2802 /* this loop is the core of the function */
2803 for (inpos = 0; /* we have several break points */ ; inpos++) {
2805 if (format[inpos] == (WCHAR) '\'') {
2806 if (format[inpos+1] == '\'') {
2808 output[outpos++] = '\'';
2813 } else if (format[inpos] == 0) {
2814 output[outpos++] = 0;
2815 if (outpos > outlen) Overflow = 1;
2816 break; /* normal exit (within a quote) */
2818 output[outpos++] = format[inpos]; /* copy input */
2819 if (outpos > outlen) {
2821 output[outpos-1] = 0;
2825 } else if ( (count && (format[inpos] != type))
2826 || ( (count==4 && type =='y') ||
2827 (count==4 && type =='M') ||
2828 (count==4 && type =='d') ||
2829 (count==2 && type =='g') ||
2830 (count==2 && type =='h') ||
2831 (count==2 && type =='H') ||
2832 (count==2 && type =='m') ||
2833 (count==2 && type =='s') ||
2834 (count==2 && type =='t') ) ) {
2837 GetLocaleInfoW(locale,
2838 LOCALE_SDAYNAME1 + xtime->wDayOfWeek -1,
2839 buf, sizeof(buf)/sizeof(WCHAR) );
2840 } else if (count == 3) {
2841 GetLocaleInfoW(locale,
2842 LOCALE_SABBREVDAYNAME1 +
2843 xtime->wDayOfWeek -1,
2844 buf, sizeof(buf)/sizeof(WCHAR) );
2846 wsnprintfW(buf, 5, argarr[count], xtime->wDay );
2848 } else if (type == 'M') {
2850 GetLocaleInfoW(locale, LOCALE_SMONTHNAME1 +
2851 xtime->wMonth -1, buf,
2852 sizeof(buf)/sizeof(WCHAR) );
2853 } else if (count == 3) {
2854 GetLocaleInfoW(locale, LOCALE_SABBREVMONTHNAME1 +
2855 xtime->wMonth -1, buf,
2856 sizeof(buf)/sizeof(WCHAR) );
2858 wsnprintfW(buf, 5, argarr[count], xtime->wMonth);
2860 } else if (type == 'y') {
2862 wsnprintfW(buf, 6, argarr[1] /* "%d" */,
2864 } else if (count == 3) {
2865 lstrcpynAtoW(buf, "yyy", 5);
2867 wsnprintfW(buf, 6, argarr[count],
2868 xtime->wYear % 100);
2870 } else if (type == 'g') {
2872 FIXME("LOCALE_ICALENDARTYPE unimplemented\n");
2873 lstrcpynAtoW(buf, "AD", 5);
2875 /* Win API sez we copy it verbatim */
2876 lstrcpynAtoW(buf, "g", 5);
2878 } else if (type == 'h') {
2879 /* hours 1:00-12:00 --- is this right? */
2880 wsnprintfW(buf, 5, argarr[count],
2881 (xtime->wHour-1)%12 +1);
2882 } else if (type == 'H') {
2883 wsnprintfW(buf, 5, argarr[count],
2885 } else if (type == 'm' ) {
2886 wsnprintfW(buf, 5, argarr[count],
2888 } else if (type == 's' ) {
2889 wsnprintfW(buf, 5, argarr[count],
2891 } else if (type == 't') {
2892 GetLocaleInfoW(locale, (xtime->wHour < 12) ?
2893 LOCALE_S1159 : LOCALE_S2359,
2900 /* no matter what happened, we need to check this next
2901 character the next time we loop through */
2904 /* cat buf onto the output */
2905 outlen = lstrlenW(buf);
2906 if (outpos + buflen < outlen) {
2907 lstrcpyW( output + outpos, buf );
2910 lstrcpynW( output + outpos, buf, outlen - outpos );
2912 break; /* Abnormal exit */
2915 /* reset the variables we used this time */
2918 } else if (format[inpos] == 0) {
2919 /* we can't check for this at the beginning, because that
2920 would keep us from printing a format spec that ended the
2923 break; /* NORMAL EXIT */
2925 /* how we keep track of the middle of a format spec */
2928 } else if ( (datevars && (format[inpos]=='d' ||
2929 format[inpos]=='M' ||
2930 format[inpos]=='y' ||
2931 format[inpos]=='g') ) ||
2932 (timevars && (format[inpos]=='H' ||
2933 format[inpos]=='h' ||
2934 format[inpos]=='m' ||
2935 format[inpos]=='s' ||
2936 format[inpos]=='t') ) ) {
2937 type = format[inpos];
2940 } else if (format[inpos] == '\'') {
2944 /* unquoted literals */
2945 output[outpos++] = format[inpos];
2950 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2951 WARN(" buffer overflow\n");
2954 /* final string terminator and sanity check */
2956 if (outpos > outlen-1) outpos = outlen-1;
2957 output[outpos] = '0';
2959 TRACE(" returning %s\n", debugstr_w(output));
2961 return (!Overflow) ? outlen : 0;
2966 /******************************************************************************
2967 * GetDateFormat32A [KERNEL32.310]
2968 * Makes an ASCII string of the date
2970 * This function uses format to format the date, or, if format
2971 * is NULL, uses the default for the locale. format is a string
2972 * of literal fields and characters as follows:
2974 * - d single-digit (no leading zero) day (of month)
2975 * - dd two-digit day (of month)
2976 * - ddd short day-of-week name
2977 * - dddd long day-of-week name
2978 * - M single-digit month
2979 * - MM two-digit month
2980 * - MMM short month name
2981 * - MMMM full month name
2982 * - y two-digit year, no leading 0
2983 * - yy two-digit year
2984 * - yyyy four-digit year
2988 INT WINAPI GetDateFormatA(LCID locale,DWORD flags,
2990 LPCSTR format, LPSTR date,INT datelen)
2993 char format_buf[40];
2996 LPSYSTEMTIME thistime;
3000 TRACE("(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",
3001 locale,flags,xtime,format,date,datelen);
3004 locale = LOCALE_SYSTEM_DEFAULT;
3007 if (locale == LOCALE_SYSTEM_DEFAULT) {
3008 thislocale = GetSystemDefaultLCID();
3009 } else if (locale == LOCALE_USER_DEFAULT) {
3010 thislocale = GetUserDefaultLCID();
3012 thislocale = locale;
3015 if (xtime == NULL) {
3022 if (format == NULL) {
3023 GetLocaleInfoA(thislocale, ((flags&DATE_LONGDATE)
3025 : LOCALE_SSHORTDATE),
3026 format_buf, sizeof(format_buf));
3027 thisformat = format_buf;
3029 thisformat = format;
3033 ret = OLE_GetFormatA(thislocale, flags, 0, thistime, thisformat,
3038 "GetDateFormat32A() returning %d, with data=%s\n",
3043 /******************************************************************************
3044 * GetDateFormat32W [KERNEL32.311]
3045 * Makes a Unicode string of the date
3047 * Acts the same as GetDateFormat32A(), except that it's Unicode.
3048 * Accepts & returns sizes as counts of Unicode characters.
3051 INT WINAPI GetDateFormatW(LCID locale,DWORD flags,
3054 LPWSTR date, INT datelen)
3056 unsigned short datearr[] = {'1','9','9','4','-','1','-','1',0};
3058 FIXME("STUB (should call OLE_GetFormatW)\n");
3059 lstrcpynW(date, datearr, datelen);
3060 return ( datelen < 9) ? datelen : 9;
3065 /**************************************************************************
3066 * EnumDateFormats32A (KERNEL32.198)
3068 BOOL WINAPI EnumDateFormatsA(
3069 DATEFMT_ENUMPROCA lpDateFmtEnumProc, LCID Locale, DWORD dwFlags)
3071 FIXME("Only US English supported\n");
3073 if(!lpDateFmtEnumProc)
3075 SetLastError(ERROR_INVALID_PARAMETER);
3081 case DATE_SHORTDATE:
3082 if(!(*lpDateFmtEnumProc)("M/d/yy")) return TRUE;
3083 if(!(*lpDateFmtEnumProc)("M/d/yyyy")) return TRUE;
3084 if(!(*lpDateFmtEnumProc)("MM/dd/yy")) return TRUE;
3085 if(!(*lpDateFmtEnumProc)("MM/dd/yyyy")) return TRUE;
3086 if(!(*lpDateFmtEnumProc)("yy/MM/dd")) return TRUE;
3087 if(!(*lpDateFmtEnumProc)("dd-MMM-yy")) return TRUE;
3090 if(!(*lpDateFmtEnumProc)("dddd, MMMM dd, yyyy")) return TRUE;
3091 if(!(*lpDateFmtEnumProc)("MMMM dd, yyyy")) return TRUE;
3092 if(!(*lpDateFmtEnumProc)("dddd, dd MMMM, yyyy")) return TRUE;
3093 if(!(*lpDateFmtEnumProc)("dd MMMM, yyyy")) return TRUE;
3096 FIXME("Unknown date format (%ld)\n", dwFlags);
3097 SetLastError(ERROR_INVALID_PARAMETER);
3102 /**************************************************************************
3103 * EnumDateFormats32W (KERNEL32.199)
3105 BOOL WINAPI EnumDateFormatsW(
3106 DATEFMT_ENUMPROCW lpDateFmtEnumProc, LCID Locale, DWORD dwFlags)
3108 FIXME("(%p, %ld, %ld): stub\n", lpDateFmtEnumProc, Locale, dwFlags);
3109 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3113 /**************************************************************************
3114 * EnumTimeFormats32A (KERNEL32.210)
3116 BOOL WINAPI EnumTimeFormatsA(
3117 TIMEFMT_ENUMPROCA lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags)
3119 FIXME("Only US English supported\n");
3121 if(!lpTimeFmtEnumProc)
3123 SetLastError(ERROR_INVALID_PARAMETER);
3129 FIXME("Unknown time format (%ld)\n", dwFlags);
3132 if(!(*lpTimeFmtEnumProc)("h:mm:ss tt")) return TRUE;
3133 if(!(*lpTimeFmtEnumProc)("hh:mm:ss tt")) return TRUE;
3134 if(!(*lpTimeFmtEnumProc)("H:mm:ss")) return TRUE;
3135 if(!(*lpTimeFmtEnumProc)("HH:mm:ss")) return TRUE;
3140 /**************************************************************************
3141 * EnumTimeFormats32W (KERNEL32.211)
3143 BOOL WINAPI EnumTimeFormatsW(
3144 TIMEFMT_ENUMPROCW lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags)
3146 FIXME("(%p,%ld,%ld): stub\n", lpTimeFmtEnumProc, Locale, dwFlags);
3147 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3152 /**************************************************************************
3153 * GetNumberFormat32A (KERNEL32.355)
3155 INT WINAPI GetNumberFormatA(LCID locale, DWORD dwflags,
3156 LPCSTR lpValue, const NUMBERFMTA * lpFormat,
3157 LPSTR lpNumberStr, int cchNumber)
3161 UINT thisleadingzero;
3162 UINT thisgrouping[8]={ -1 };
3163 LPCSTR thisdecimalsep;
3164 LPCSTR thisthousandsep;
3165 UINT thisnegativeorder;
3170 char roundbuffer[24]; /* Should be enough */
3173 int dotflag=0,negflag=0;
3174 char misc_buf[8], negative_buf[4], decimal_buf[4], thousand_buf[4];
3175 char digits_buf[11];
3176 int intsize=0,decsize=0,totalsize,lastgroup, leadingzeros=0;
3177 int negsignsize,decimalsepsize,thousandsepsize;
3179 /* Default setting stuff - partially borrowed from GetFormatedDate */
3181 locale = LOCALE_SYSTEM_DEFAULT;
3184 if (locale == LOCALE_SYSTEM_DEFAULT) {
3185 thislocale = GetSystemDefaultLCID();
3186 } else if (locale == LOCALE_USER_DEFAULT) {
3187 thislocale = GetUserDefaultLCID();
3189 thislocale = locale;
3191 /* Partial implementation: things like native digits are not considered */
3192 if (lpFormat == NULL) {
3194 GetLocaleInfoA(thislocale, LOCALE_IDIGITS,
3195 misc_buf, sizeof(misc_buf));
3196 thisnumdigits = atoi(misc_buf);
3198 GetLocaleInfoA(thislocale, LOCALE_ILZERO,
3199 misc_buf, sizeof(misc_buf));
3200 thisleadingzero = atoi(misc_buf);
3202 GetLocaleInfoA(thislocale, LOCALE_SGROUPING,
3203 misc_buf, sizeof(misc_buf));
3205 /* About grouping mechanism:
3206 I parse the string and pour the group size values along the
3207 thisgrouping[] array, starting by element 1. Then I convert these
3208 values to indexes for insertion into the integer part.
3209 thisgrouping[0]==-1, therefore I ensure index correctness without
3210 need for range checking and related stuff.
3211 The only drawback is the 7 separators limit, hopefully that means
3212 it will fail with numbers bigger than 10^21 if using groups of three
3216 for (i=1,gptr=misc_buf;*gptr!='\0';i++) {
3217 /* In control panel, groups up 9 digits long are allowed. If there is any way to use larger groups,
3218 then the next line must be replaced with the following code:
3219 thisgrouping[i] = atoi(gptr);
3220 for (;*gptr!=';' && *gptr!='\0';gptr++) ; */
3222 thisgrouping[i] = *(gptr++)-'0';
3228 /* Take care for repeating group size */
3229 if (thisgrouping[i-1]==0) {
3231 thisgrouping[j]=thisgrouping[i-2];
3236 for (i=2;i<=lastgroup;i++)
3237 thisgrouping[i]+=thisgrouping[i-1];
3239 GetLocaleInfoA(thislocale, LOCALE_SDECIMAL,
3240 decimal_buf, sizeof(decimal_buf));
3241 thisdecimalsep = decimal_buf;
3243 GetLocaleInfoA(thislocale, LOCALE_STHOUSAND,
3244 thousand_buf, sizeof(thousand_buf));
3245 thisthousandsep = thousand_buf;
3247 GetLocaleInfoA(thislocale, LOCALE_INEGNUMBER,
3248 misc_buf, sizeof(misc_buf));
3249 thisnegativeorder = atoi(misc_buf);
3253 thisnumdigits = lpFormat->NumDigits;
3254 thisleadingzero = lpFormat->LeadingZero;
3256 thisgrouping[1] = lpFormat->Grouping;
3258 thisgrouping[i]=thisgrouping[i-1]+lpFormat->Grouping;
3261 thisdecimalsep = lpFormat->lpDecimalSep;
3262 thisthousandsep = lpFormat->lpThousandSep;
3263 thisnegativeorder = lpFormat->NegativeOrder;
3267 GetLocaleInfoA(thislocale, LOCALE_SNATIVEDIGITS,
3268 digits_buf, sizeof(digits_buf));
3270 GetLocaleInfoA(thislocale, LOCALE_SNEGATIVESIGN,
3271 negative_buf, sizeof(negative_buf));
3273 negsignsize=strlen(negative_buf);
3274 decimalsepsize=strlen(thisdecimalsep);
3275 thousandsepsize=strlen(thisthousandsep);
3277 /* Size calculation */
3283 for (; *sptr=='0'; sptr++) leadingzeros++; /* Ignore leading zeros */
3284 for (; *sptr!='\0'; sptr++) {
3285 if (!dotflag && *sptr=='.') {
3287 } else if (*sptr<'0' || *sptr>'9') {
3288 SetLastError(ERROR_INVALID_PARAMETER);
3300 /* Take care of eventual rounding. Only, if I need to do it, then I write
3301 the rounded lpValue copy into roundbuffer, and create the formatted
3302 string from the proper source. This is smarter than copying it always
3303 The buffer includes an extra leading zero, as the number can carry and
3304 get and extra one. If it doesn't, the zero is ignored as any other
3305 useless leading zero
3308 if (decsize>0 && decsize>thisnumdigits) {
3309 sptr-=(decsize-thisnumdigits);
3312 strcpy(roundbuffer+1,lpValue);
3315 *(roundbuffer+1)='0';
3318 sptr=roundbuffer+(sptr-lpValue); // +1-1
3320 while ( (++*sptr) > '9') {
3322 if (*sptr=='.') sptr--;
3324 if ((negflag ? *(roundbuffer+leadingzeros+1) : *(roundbuffer+leadingzeros)) == '1')
3334 if (intsize==0 && (decsize==0 || thisleadingzero))
3338 totalsize+= thisnegativeorder == 1 || thisnegativeorder == 3 ? negsignsize
3339 : thisnegativeorder == 2 || thisnegativeorder == 4 ? negsignsize+1 : 2 ;
3341 /* Look for the first grouping to be done */
3342 for (j=lastgroup;thisgrouping[j]>=intsize && j>0;j--) ;
3345 totalsize+=thousandsepsize * j;
3346 if (thisnumdigits>0)
3347 totalsize+=decimalsepsize+thisnumdigits;
3349 if (cchNumber==0) /* if cchNumber is zero, just return size needed */
3352 if (cchNumber<totalsize+1) { /* +1 = Null terminator (right?) */
3353 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3358 /* Formatting stuff starts here */
3363 if (thisnegativeorder==0)
3365 else if (thisnegativeorder<=2) {
3366 strcpy(dptr,negative_buf);
3368 if (thisnegativeorder==2)
3374 for (i=1;*sptr=='0' ;i++, sptr++) ; /* Ignore leading zeros from source*/
3375 if (intsize==0 && (decsize==0 || thisleadingzero)) // Insert one leading zero into destination if required
3376 *(dptr++)=digits_buf[0];
3377 for (i=1;i<=intsize;i++) {
3379 *(dptr++)=digits_buf[*(sptr++)-'0'];
3381 /* Insert a group separator if we just reached the end of a group */
3382 if (i==intsize-thisgrouping[j]) {
3383 strcpy(dptr,thisthousandsep);
3384 dptr+=thousandsepsize;
3391 if (thisnumdigits>0) {
3392 strcpy(dptr,decimal_buf);
3393 dptr+=decimalsepsize;
3394 for (i=0;i<thisnumdigits;i++)
3395 *(dptr++)=*sptr !='\0' ? digits_buf[*(sptr++)-'0'] : digits_buf[0];
3399 if (thisnegativeorder==0)
3401 else if (thisnegativeorder>=3) {
3402 if (thisnegativeorder==4)
3404 strcpy(dptr,negative_buf);
3416 /**************************************************************************
3417 * GetNumberFormat32W (KERNEL32.xxx)
3419 INT WINAPI GetNumberFormatW(LCID locale, DWORD dwflags,
3420 LPCWSTR lpvalue, const NUMBERFMTW * lpFormat,
3421 LPWSTR lpNumberStr, int cchNumber)
3423 FIXME("%s: stub, no reformating done\n",debugstr_w(lpvalue));
3425 lstrcpynW( lpNumberStr, lpvalue, cchNumber );
3426 return cchNumber? lstrlenW( lpNumberStr ) : 0;
3428 /******************************************************************************
3429 * OLE2NLS_CheckLocale [intern]
3431 static LCID OLE2NLS_CheckLocale (LCID locale)
3434 { locale = LOCALE_SYSTEM_DEFAULT;
3437 if (locale == LOCALE_SYSTEM_DEFAULT)
3438 { return GetSystemDefaultLCID();
3440 else if (locale == LOCALE_USER_DEFAULT)
3441 { return GetUserDefaultLCID();
3447 /******************************************************************************
3448 * GetTimeFormat32A [KERNEL32.422]
3449 * Makes an ASCII string of the time
3451 * Formats date according to format, or locale default if format is
3452 * NULL. The format consists of literal characters and fields as follows:
3454 * h hours with no leading zero (12-hour)
3455 * hh hours with full two digits
3456 * H hours with no leading zero (24-hour)
3457 * HH hours with full two digits
3458 * m minutes with no leading zero
3459 * mm minutes with full two digits
3460 * s seconds with no leading zero
3461 * ss seconds with full two digits
3462 * t time marker (A or P)
3463 * tt time marker (AM, PM)
3467 GetTimeFormatA(LCID locale, /* in */
3468 DWORD flags, /* in */
3469 LPSYSTEMTIME xtime, /* in */
3470 LPCSTR format, /* in */
3471 LPSTR timestr, /* out */
3472 INT timelen /* in */)
3473 { char format_buf[40];
3476 LPSYSTEMTIME thistime;
3478 DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */
3481 TRACE("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale,flags,xtime,format,timestr,timelen);
3483 thislocale = OLE2NLS_CheckLocale ( locale );
3485 if ( flags & (TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT ))
3486 { FIXME("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3489 flags &= (TIME_NOSECONDS | TIME_NOMINUTESORSECONDS); /* mask for OLE_GetFormatA*/
3492 { if (flags & LOCALE_NOUSEROVERRIDE) /*use system default*/
3493 { thislocale = GetSystemDefaultLCID();
3495 GetLocaleInfoA(thislocale, thisflags, format_buf, sizeof(format_buf));
3496 thisformat = format_buf;
3499 { thisformat = format;
3502 if (xtime == NULL) /* NULL means use the current local time*/
3509 ret = OLE_GetFormatA(thislocale, thisflags, flags, thistime, thisformat,
3515 /******************************************************************************
3516 * GetTimeFormat32W [KERNEL32.423]
3517 * Makes a Unicode string of the time
3520 GetTimeFormatW(LCID locale, /* in */
3521 DWORD flags, /* in */
3522 LPSYSTEMTIME xtime, /* in */
3523 LPCWSTR format, /* in */
3524 LPWSTR timestr, /* out */
3525 INT timelen /* in */)
3526 { WCHAR format_buf[40];
3529 LPSYSTEMTIME thistime;
3531 DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */
3534 TRACE("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale,flags,
3535 xtime,debugstr_w(format),timestr,timelen);
3537 thislocale = OLE2NLS_CheckLocale ( locale );
3539 if ( flags & (TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT ))
3540 { FIXME("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3543 flags &= (TIME_NOSECONDS | TIME_NOMINUTESORSECONDS); /* mask for OLE_GetFormatA*/
3546 { if (flags & LOCALE_NOUSEROVERRIDE) /*use system default*/
3547 { thislocale = GetSystemDefaultLCID();
3549 GetLocaleInfoW(thislocale, thisflags, format_buf, 40);
3550 thisformat = format_buf;
3553 { thisformat = format;
3556 if (xtime == NULL) /* NULL means use the current local time*/
3557 { GetSystemTime(&t);
3564 ret = OLE_GetFormatW(thislocale, thisflags, flags, thistime, thisformat,
3569 /******************************************************************************
3570 * EnumCalendarInfoA [KERNEL32.196]
3572 BOOL WINAPI EnumCalendarInfoA(
3573 CALINFO_ENUMPROCA calinfoproc,LCID locale,CALID calendar,CALTYPE caltype
3575 FIXME("(%p,0x%04lx,0x%08lx,0x%08lx),stub!\n",calinfoproc,locale,calendar,caltype);