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_JAPANESE
, SUBLANG_DEFAULT
) /*0x0411*/
205 #include "nls/jpn.nls"
208 LANG_BEGIN (LANG_KOREAN
, SUBLANG_KOREAN
) /*0x0412*/
209 #include "nls/kor.nls"
212 LANG_BEGIN (LANG_DUTCH
, SUBLANG_DUTCH
) /*0x0413*/
213 #include "nls/nld.nls"
215 LANG_BEGIN (LANG_DUTCH
, SUBLANG_DUTCH_BELGIAN
) /*0x0813*/
216 #include "nls/nlb.nls"
218 LANG_BEGIN (LANG_DUTCH
, SUBLANG_DUTCH_SURINAM
) /*0x0C13*/
219 #include "nls/nls.nls"
222 LANG_BEGIN (LANG_NORWEGIAN
, SUBLANG_NORWEGIAN_BOKMAL
) /*0x0414*/
223 #include "nls/nor.nls"
225 LANG_BEGIN (LANG_NORWEGIAN
, SUBLANG_NORWEGIAN_NYNORSK
) /*0x0814*/
226 #include "nls/non.nls"
229 LANG_BEGIN (LANG_POLISH
, SUBLANG_DEFAULT
) /*0x0415*/
230 #include "nls/plk.nls"
233 LANG_BEGIN (LANG_PORTUGUESE
,SUBLANG_PORTUGUESE_BRAZILIAN
) /*0x0416*/
234 #include "nls/ptb.nls"
236 LANG_BEGIN (LANG_PORTUGUESE
,SUBLANG_PORTUGUESE
) /*0x0816*/
237 #include "nls/ptg.nls"
240 LANG_BEGIN (LANG_RUSSIAN
, SUBLANG_DEFAULT
) /*0x419*/
241 #include "nls/rus.nls"
244 LANG_BEGIN (LANG_SLOVAK
, SUBLANG_DEFAULT
) /*0x041b*/
245 #include "nls/sky.nls"
248 LANG_BEGIN (LANG_SWEDISH
, SUBLANG_SWEDISH
) /*0x041d*/
249 #include "nls/sve.nls"
251 LANG_BEGIN (LANG_SWEDISH
, SUBLANG_SWEDISH_FINLAND
) /*0x081d*/
252 #include "nls/svf.nls"
255 LANG_BEGIN (LANG_THAI
, SUBLANG_DEFAULT
) /*0x41e*/
256 #include "nls/tha.nls"
258 LANG_BEGIN (LANG_GAELIC
, SUBLANG_DEFAULT
) /* 0x043c */
259 #include "nls/gae.nls"
262 LANG_BEGIN (LANG_GAELIC
, SUBLANG_GAELIC_SCOTTISH
)
263 #include "nls/gdh.nls"
266 LANG_BEGIN (LANG_GAELIC
, SUBLANG_GAELIC_MANX
)
267 #include "nls/gdv.nls"
270 LANG_BEGIN (LANG_ESPERANTO
, SUBLANG_DEFAULT
) /*0x048f*/
271 #include "nls/esperanto.nls"
274 LANG_BEGIN (LANG_WALON
, SUBLANG_DEFAULT
) /*0x0490*/
275 #include "nls/wal.nls"
278 LANG_BEGIN (LANG_CORNISH
, SUBLANG_DEFAULT
) /* 0x0491 */
279 #include "nls/cor.nls"
282 LANG_BEGIN (LANG_WELSH
, SUBLANG_DEFAULT
) /* 0x0492 */
283 #include "nls/cym.nls"
286 LANG_BEGIN (LANG_BRETON
, SUBLANG_DEFAULT
) /* 0x0x93 */
287 #include "nls/brf.nls"
293 /* Locale name to id map. used by EnumSystemLocales, GetLocaleInfoA
294 * MUST contain all #defines from winnls.h
295 * last entry has NULL name, 0 id.
297 #define LOCALE_ENTRY(x) {#x,LOCALE_##x}
298 static struct tagLOCALE_NAME2ID
{
301 } locale_name2id
[]= {
302 LOCALE_ENTRY(ILANGUAGE
),
303 LOCALE_ENTRY(SLANGUAGE
),
304 LOCALE_ENTRY(SENGLANGUAGE
),
305 LOCALE_ENTRY(SABBREVLANGNAME
),
306 LOCALE_ENTRY(SNATIVELANGNAME
),
307 LOCALE_ENTRY(ICOUNTRY
),
308 LOCALE_ENTRY(SCOUNTRY
),
309 LOCALE_ENTRY(SENGCOUNTRY
),
310 LOCALE_ENTRY(SABBREVCTRYNAME
),
311 LOCALE_ENTRY(SNATIVECTRYNAME
),
312 LOCALE_ENTRY(IDEFAULTLANGUAGE
),
313 LOCALE_ENTRY(IDEFAULTCOUNTRY
),
314 LOCALE_ENTRY(IDEFAULTCODEPAGE
),
315 LOCALE_ENTRY(IDEFAULTANSICODEPAGE
),
316 LOCALE_ENTRY(IDEFAULTMACCODEPAGE
),
318 LOCALE_ENTRY(IMEASURE
),
319 LOCALE_ENTRY(SDECIMAL
),
320 LOCALE_ENTRY(STHOUSAND
),
321 LOCALE_ENTRY(SGROUPING
),
322 LOCALE_ENTRY(IDIGITS
),
323 LOCALE_ENTRY(ILZERO
),
324 LOCALE_ENTRY(INEGNUMBER
),
325 LOCALE_ENTRY(SNATIVEDIGITS
),
326 LOCALE_ENTRY(SCURRENCY
),
327 LOCALE_ENTRY(SINTLSYMBOL
),
328 LOCALE_ENTRY(SMONDECIMALSEP
),
329 LOCALE_ENTRY(SMONTHOUSANDSEP
),
330 LOCALE_ENTRY(SMONGROUPING
),
331 LOCALE_ENTRY(ICURRDIGITS
),
332 LOCALE_ENTRY(IINTLCURRDIGITS
),
333 LOCALE_ENTRY(ICURRENCY
),
334 LOCALE_ENTRY(INEGCURR
),
337 LOCALE_ENTRY(SSHORTDATE
),
338 LOCALE_ENTRY(SLONGDATE
),
339 LOCALE_ENTRY(STIMEFORMAT
),
341 LOCALE_ENTRY(ILDATE
),
343 LOCALE_ENTRY(ITIMEMARKPOSN
),
344 LOCALE_ENTRY(ICENTURY
),
345 LOCALE_ENTRY(ITLZERO
),
346 LOCALE_ENTRY(IDAYLZERO
),
347 LOCALE_ENTRY(IMONLZERO
),
350 LOCALE_ENTRY(ICALENDARTYPE
),
351 LOCALE_ENTRY(IOPTIONALCALENDAR
),
352 LOCALE_ENTRY(IFIRSTDAYOFWEEK
),
353 LOCALE_ENTRY(IFIRSTWEEKOFYEAR
),
354 LOCALE_ENTRY(SDAYNAME1
),
355 LOCALE_ENTRY(SDAYNAME2
),
356 LOCALE_ENTRY(SDAYNAME3
),
357 LOCALE_ENTRY(SDAYNAME4
),
358 LOCALE_ENTRY(SDAYNAME5
),
359 LOCALE_ENTRY(SDAYNAME6
),
360 LOCALE_ENTRY(SDAYNAME7
),
361 LOCALE_ENTRY(SABBREVDAYNAME1
),
362 LOCALE_ENTRY(SABBREVDAYNAME2
),
363 LOCALE_ENTRY(SABBREVDAYNAME3
),
364 LOCALE_ENTRY(SABBREVDAYNAME4
),
365 LOCALE_ENTRY(SABBREVDAYNAME5
),
366 LOCALE_ENTRY(SABBREVDAYNAME6
),
367 LOCALE_ENTRY(SABBREVDAYNAME7
),
368 LOCALE_ENTRY(SMONTHNAME1
),
369 LOCALE_ENTRY(SMONTHNAME2
),
370 LOCALE_ENTRY(SMONTHNAME3
),
371 LOCALE_ENTRY(SMONTHNAME4
),
372 LOCALE_ENTRY(SMONTHNAME5
),
373 LOCALE_ENTRY(SMONTHNAME6
),
374 LOCALE_ENTRY(SMONTHNAME7
),
375 LOCALE_ENTRY(SMONTHNAME8
),
376 LOCALE_ENTRY(SMONTHNAME9
),
377 LOCALE_ENTRY(SMONTHNAME10
),
378 LOCALE_ENTRY(SMONTHNAME11
),
379 LOCALE_ENTRY(SMONTHNAME12
),
380 LOCALE_ENTRY(SMONTHNAME13
),
381 LOCALE_ENTRY(SABBREVMONTHNAME1
),
382 LOCALE_ENTRY(SABBREVMONTHNAME2
),
383 LOCALE_ENTRY(SABBREVMONTHNAME3
),
384 LOCALE_ENTRY(SABBREVMONTHNAME4
),
385 LOCALE_ENTRY(SABBREVMONTHNAME5
),
386 LOCALE_ENTRY(SABBREVMONTHNAME6
),
387 LOCALE_ENTRY(SABBREVMONTHNAME7
),
388 LOCALE_ENTRY(SABBREVMONTHNAME8
),
389 LOCALE_ENTRY(SABBREVMONTHNAME9
),
390 LOCALE_ENTRY(SABBREVMONTHNAME10
),
391 LOCALE_ENTRY(SABBREVMONTHNAME11
),
392 LOCALE_ENTRY(SABBREVMONTHNAME12
),
393 LOCALE_ENTRY(SABBREVMONTHNAME13
),
394 LOCALE_ENTRY(SPOSITIVESIGN
),
395 LOCALE_ENTRY(SNEGATIVESIGN
),
396 LOCALE_ENTRY(IPOSSIGNPOSN
),
397 LOCALE_ENTRY(INEGSIGNPOSN
),
398 LOCALE_ENTRY(IPOSSYMPRECEDES
),
399 LOCALE_ENTRY(IPOSSEPBYSPACE
),
400 LOCALE_ENTRY(INEGSYMPRECEDES
),
401 LOCALE_ENTRY(INEGSEPBYSPACE
),
402 LOCALE_ENTRY(FONTSIGNATURE
),
403 LOCALE_ENTRY(SISO639LANGNAME
),
404 LOCALE_ENTRY(SISO3166CTRYNAME
),
408 const struct map_lcid2str
{
410 const char *langname
;
412 {0x0401,"Arabic (Saudi Arabia)"},
413 {0x0801,"Arabic (Iraq)"},
414 {0x0c01,"Arabic (Egypt)"},
415 {0x1001,"Arabic (Libya)"},
416 {0x1401,"Arabic (Algeria)"},
417 {0x1801,"Arabic (Morocco)"},
418 {0x1c01,"Arabic (Tunisia)"},
419 {0x2001,"Arabic (Oman)"},
420 {0x2401,"Arabic (Yemen)"},
421 {0x2801,"Arabic (Syria)"},
422 {0x2c01,"Arabic (Jordan)"},
423 {0x3001,"Arabic (Lebanon)"},
424 {0x3401,"Arabic (Kuwait)"},
425 {0x3801,"Arabic (United Arab Emirates)"},
426 {0x3c01,"Arabic (Bahrain)"},
427 {0x4001,"Arabic (Qatar)"},
428 {0x0402,"Bulgarian"},
430 {0x0404,"Chinese (Taiwan)"},
431 {0x0804,"Chinese (People's Republic of China)"},
432 {0x0c04,"Chinese (Hong Kong)"},
433 {0x1004,"Chinese (Singapore)"},
434 {0x1404,"Chinese (Macau)"},
437 {0x0407,"German (Germany)"},
438 {0x0807,"German (Switzerland)"},
439 {0x0c07,"German (Austria)"},
440 {0x1007,"German (Luxembourg)"},
441 {0x1407,"German (Liechtenstein)"},
443 {0x0409,"English (United States)"},
444 {0x0809,"English (United Kingdom)"},
445 {0x0c09,"English (Australia)"},
446 {0x1009,"English (Canada)"},
447 {0x1409,"English (New Zealand)"},
448 {0x1809,"English (Ireland)"},
449 {0x1c09,"English (South Africa)"},
450 {0x2009,"English (Jamaica)"},
451 {0x2409,"English (Caribbean)"},
452 {0x2809,"English (Belize)"},
453 {0x2c09,"English (Trinidad)"},
454 {0x3009,"English (Zimbabwe)"},
455 {0x3409,"English (Philippines)"},
456 {0x040a,"Spanish (Spain, traditional sorting)"},
457 {0x080a,"Spanish (Mexico)"},
458 {0x0c0a,"Spanish (Spain, international sorting)"},
459 {0x100a,"Spanish (Guatemala)"},
460 {0x140a,"Spanish (Costa Rica)"},
461 {0x180a,"Spanish (Panama)"},
462 {0x1c0a,"Spanish (Dominican Republic)"},
463 {0x200a,"Spanish (Venezuela)"},
464 {0x240a,"Spanish (Colombia)"},
465 {0x280a,"Spanish (Peru)"},
466 {0x2c0a,"Spanish (Argentina)"},
467 {0x300a,"Spanish (Ecuador)"},
468 {0x340a,"Spanish (Chile)"},
469 {0x380a,"Spanish (Uruguay)"},
470 {0x3c0a,"Spanish (Paraguay)"},
471 {0x400a,"Spanish (Bolivia)"},
472 {0x440a,"Spanish (El Salvador)"},
473 {0x480a,"Spanish (Honduras)"},
474 {0x4c0a,"Spanish (Nicaragua)"},
475 {0x500a,"Spanish (Puerto Rico)"},
477 {0x040c,"French (France)"},
478 {0x080c,"French (Belgium)"},
479 {0x0c0c,"French (Canada)"},
480 {0x100c,"French (Switzerland)"},
481 {0x140c,"French (Luxembourg)"},
482 {0x180c,"French (Monaco)"},
484 {0x040e,"Hungarian"},
485 {0x040f,"Icelandic"},
486 {0x0410,"Italian (Italy)"},
487 {0x0810,"Italian (Switzerland)"},
489 {0x0412,"Korean (Wansung)"},
490 {0x0812,"Korean (Johab)"},
491 {0x0413,"Dutch (Netherlands)"},
492 {0x0813,"Dutch (Belgium)"},
493 {0x0414,"Norwegian (Bokmal)"},
494 {0x0814,"Norwegian (Nynorsk)"},
496 {0x0416,"Portuguese (Brazil)"},
497 {0x0816,"Portuguese (Portugal)"},
498 {0x0417,"Rhaeto Romanic"},
500 {0x0818,"Moldavian"},
501 {0x0419,"Russian (Russia)"},
502 {0x0819,"Russian (Moldavia)"},
504 {0x081a,"Serbian (latin)"},
505 {0x0c1a,"Serbian (cyrillic)"},
508 {0x041d,"Swedish (Sweden)"},
509 {0x081d,"Swedish (Finland)"},
513 {0x0421,"Indonesian"},
514 {0x0422,"Ukrainian"},
515 {0x0423,"Belarusian"},
519 {0x0427,"Lithuanian (modern)"},
520 {0x0827,"Lithuanian (classic)"},
523 {0x042a,"Vietnamese"},
525 {0x042c,"Azeri (latin)"},
526 {0x082c,"Azeri (cyrillic)"},
529 {0x042f,"Macedonian"},
536 {0x0436,"Afrikaans"},
542 {0x043c,"Irish gaelic"},
543 {0x083c,"Scottish gaelic"},
544 {0x0c3c,"Manx Gaelic"},
545 {0x043e,"Malay (Malaysia)"},
546 {0x083e,"Malay (Brunei Darussalam)"},
549 {0x0443,"Uzbek (latin)"},
550 {0x0843,"Uzbek (cyrillic)"},
559 {0x044c,"Malayalam"},
564 {0x048f,"Esperanto"}, /* Non official */
565 {0x0490,"Walon"}, /* Non official */
566 {0x0491,"Cornish"}, /* Not official */
567 {0x0492,"Welsh"}, /* Not official */
568 {0x0493,"Breton"}, /* Not official */
572 {0x0402,"Bulgarisch"},
573 {0x0403,"Katalanisch"},
574 {0x0404,"Traditionales Chinesisch"},
575 {0x0405,"Tschecisch"},
578 {0x0408,"Griechisch"},
579 {0x0409,"Amerikanisches Englisch"},
580 {0x040A,"Kastilisches Spanisch"},
582 {0x040C,"Franzvsisch"},
583 {0x040D,"Hebrdisch"},
584 {0x040E,"Ungarisch"},
585 {0x040F,"Isldndisch"},
586 {0x0410,"Italienisch"},
587 {0x0411,"Japanisch"},
588 {0x0412,"Koreanisch"},
589 {0x0413,"Niederldndisch"},
590 {0x0414,"Norwegisch-Bokmal"},
592 {0x0416,"Brasilianisches Portugiesisch"},
593 {0x0417,"Rdtoromanisch"},
594 {0x0418,"Rumdnisch"},
596 {0x041A,"Kroatoserbisch (lateinisch)"},
597 {0x041B,"Slowenisch"},
598 {0x041C,"Albanisch"},
599 {0x041D,"Schwedisch"},
604 {0x0804,"Vereinfachtes Chinesisch"},
605 {0x0807,"Schweizerdeutsch"},
606 {0x0809,"Britisches Englisch"},
607 {0x080A,"Mexikanisches Spanisch"},
608 {0x080C,"Belgisches Franzvsisch"},
609 {0x0810,"Schweizerisches Italienisch"},
610 {0x0813,"Belgisches Niederldndisch"},
611 {0x0814,"Norgwegisch-Nynorsk"},
612 {0x0816,"Portugiesisch"},
613 {0x081A,"Serbokratisch (kyrillisch)"},
614 {0x0C1C,"Kanadisches Franzvsisch"},
615 {0x100C,"Schweizerisches Franzvsisch"},
616 {0x0000,"Unbekannt"},
619 /***********************************************************************
620 * GetUserDefaultLCID (OLE2NLS.1)
622 LCID WINAPI
GetUserDefaultLCID()
624 return MAKELCID( GetUserDefaultLangID() , SORT_DEFAULT
);
627 /***********************************************************************
628 * GetSystemDefaultLCID (OLE2NLS.2)
630 LCID WINAPI
GetSystemDefaultLCID()
632 return GetUserDefaultLCID();
635 /***********************************************************************
636 * GetUserDefaultLangID (OLE2NLS.3)
638 LANGID WINAPI
GetUserDefaultLangID()
640 /* caching result, if defined from environment, which should (?) not change during a WINE session */
641 static LANGID userLCID
= 0;
642 if (Options
.language
) {
643 return Languages
[Options
.language
].langid
;
648 char *lang
,*country
,*charset
,*dialect
,*next
;
651 buf
=getenv("LANGUAGE");
652 if (!buf
) buf
=getenv("LANG");
653 if (!buf
) buf
=getenv("LC_ALL");
654 if (!buf
) buf
=getenv("LC_MESSAGES");
655 if (!buf
) buf
=getenv("LC_CTYPE");
656 if (!buf
) return userLCID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
);
658 if (!strcmp(buf
,"POSIX") || !strcmp(buf
,"C")) {
659 return MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
);
665 next
=strchr(lang
,':'); if (next
) *next
++='\0';
666 dialect
=strchr(lang
,'@'); if (dialect
) *dialect
++='\0';
667 charset
=strchr(lang
,'.'); if (charset
) *charset
++='\0';
668 country
=strchr(lang
,'_'); if (country
) *country
++='\0';
670 ret
=MAIN_GetLanguageID(lang
, country
, charset
, dialect
);
674 } while (lang
&& !ret
);
676 /* FIXME : are strings returned by getenv() to be free()'ed ? */
677 userLCID
= (LANGID
)ret
;
682 /***********************************************************************
683 * GetSystemDefaultLangID (OLE2NLS.4)
685 LANGID WINAPI
GetSystemDefaultLangID()
687 return GetUserDefaultLangID();
690 /******************************************************************************
691 * GetLocaleInfo16 [OLE2NLS.5]
692 * Is the last parameter really WORD for Win16?
694 INT16 WINAPI
GetLocaleInfo16(LCID lcid
,LCTYPE LCType
,LPSTR buf
,INT16 len
)
696 return GetLocaleInfoA(lcid
,LCType
,buf
,len
);
698 /******************************************************************************
699 * ConvertDefaultLocale32 [KERNEL32.147]
701 LCID WINAPI
ConvertDefaultLocale32 (LCID lcid
)
703 { case LOCALE_SYSTEM_DEFAULT
:
704 return GetSystemDefaultLCID();
705 case LOCALE_USER_DEFAULT
:
706 return GetUserDefaultLCID();
708 return MAKELCID (LANG_NEUTRAL
, SUBLANG_NEUTRAL
);
710 return MAKELANGID( PRIMARYLANGID(lcid
), SUBLANG_NEUTRAL
);
712 /******************************************************************************
713 * GetLocaleInfo32A [KERNEL32.342]
716 * LANG_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
718 * MS online documentation states that the string returned is NULL terminated
719 * except for LOCALE_FONTSIGNATURE which "will return a non-NULL
720 * terminated string".
722 INT WINAPI
GetLocaleInfoA(LCID lcid
,LCTYPE LCType
,LPSTR buf
,INT len
)
728 TRACE("(lcid=0x%lx,lctype=0x%lx,%p,%x)\n",lcid
,LCType
,buf
,len
);
730 if (len
&& (! buf
) ) {
731 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
735 if (lcid
==0 || lcid
== LANG_SYSTEM_DEFAULT
|| (LCType
& LOCALE_NOUSEROVERRIDE
) ) /* 0x00, 0x400 */
737 lcid
= GetSystemDefaultLCID();
739 else if (lcid
== LANG_USER_DEFAULT
) /*0x800*/
741 lcid
= GetUserDefaultLCID();
743 LCType
&= ~(LOCALE_NOUSEROVERRIDE
|LOCALE_USE_CP_ACP
);
745 /* As an option, we could obtain the value from win.ini.
746 This would not match the Wine compile-time option.
747 Also, not all identifiers are available from win.ini */
749 /* If we are through all of this, retLen should not be zero anymore.
750 If it is, the value is not supported */
752 while (locale_name2id
[i
].name
!=NULL
) {
753 if (LCType
== locale_name2id
[i
].id
) {
754 retString
= locale_name2id
[i
].name
;
760 FIXME("Unkown LC type %lX\n",LCType
);
765 for (i
=0;(i
<3 && !found
);i
++) {
768 for (j
=0;j
<sizeof(langlocales
)/sizeof(langlocales
[0]);j
++) {
769 if (langlocales
[j
].lang
== lang
) {
772 for (k
=0;k
<sizeof(langlocales
[j
].locvars
)/sizeof(langlocales
[j
].locvars
[0]) && (langlocales
[j
].locvars
[k
].type
);k
++) {
773 if (langlocales
[j
].locvars
[k
].type
== LCType
) {
775 retString
= langlocales
[j
].locvars
[k
].val
;
783 /* language not found, try without a sublanguage*/
784 if (i
==1) lang
=MAKELANGID( PRIMARYLANGID(lang
), SUBLANG_DEFAULT
);
785 /* mask the LC Value */
786 if (i
==2) LCType
&= 0xfff;
790 ERR("'%s' not supported for your language (%04X).\n",
791 retString
,(WORD
)lcid
);
792 SetLastError(ERROR_INVALID_PARAMETER
);
795 /* a FONTSIGNATURE is not a string, just 6 DWORDs */
796 if (LCType
== LOCALE_FONTSIGNATURE
) {
798 memcpy(buf
, retString
, (len
<=sizeof(FONTSIGNATURE
))?len
:sizeof(FONTSIGNATURE
));
799 return sizeof(FONTSIGNATURE
);
801 /* if len=0 return only the length, don't touch the buffer*/
802 if (len
) lstrcpynA(buf
,retString
,len
);
803 return strlen(retString
)+1;
806 /******************************************************************************
807 * GetLocaleInfo32W [KERNEL32.343]
810 * MS documentation states that len "specifies the size, in bytes (ANSI version)
811 * or characters (Unicode version), of" wbuf. Thus the number returned is
812 * the same between GetLocaleInfo32W and GetLocaleInfo32A.
814 INT WINAPI
GetLocaleInfoW(LCID lcid
,LCTYPE LCType
,LPWSTR wbuf
,INT len
)
818 if (len
&& (! wbuf
) )
819 { SetLastError(ERROR_INSUFFICIENT_BUFFER
);
823 abuf
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,len
);
824 wlen
= GetLocaleInfoA(lcid
, LCType
, abuf
, len
);
826 if (wlen
&& len
) /* if len=0 return only the length*/
827 lstrcpynAtoW(wbuf
,abuf
,len
);
829 HeapFree(GetProcessHeap(),0,abuf
);
833 /******************************************************************************
834 * SetLocaleInfoA [KERNEL32.656]
836 BOOL16 WINAPI
SetLocaleInfoA(DWORD lcid
, DWORD lctype
, LPCSTR data
)
838 FIXME("(%ld,%ld,%s): stub\n",lcid
,lctype
,data
);
842 /******************************************************************************
843 * IsValidLocale [KERNEL32.489]
845 BOOL WINAPI
IsValidLocale(LCID lcid
,DWORD flags
)
847 /* we support ANY language. Well, at least say that...*/
851 /******************************************************************************
852 * EnumSystemLocales32W [KERNEL32.209]
854 BOOL WINAPI
EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum
,
862 TRACE_(win32
)("(%p,%08lx)\n",lpfnLocaleEnum
,flags
);
863 /* see if we can reuse the Win95 registry entries.... */
864 if (ERROR_SUCCESS
==RegOpenKeyA(HKEY_LOCAL_MACHINE
,"System\\CurrentControlSet\\control\\Nls\\Locale\\",&xhkey
)) {
867 if (ERROR_SUCCESS
!=RegEnumKeyW(xhkey
,i
,buffer
,sizeof(buffer
)))
869 if (!lpfnLocaleEnum(buffer
))
878 while (languages
[i
].langid
!=0)
883 sprintf(xbuffer
,"%08lx",(DWORD
)languages
[i
].langid
);
885 cp
= HEAP_strdupAtoW( GetProcessHeap(), 0, xbuffer
);
886 ret
= lpfnLocaleEnum(cp
);
887 HeapFree( GetProcessHeap(), 0, cp
);
894 /******************************************************************************
895 * EnumSystemLocales32A [KERNEL32.208]
897 BOOL WINAPI
EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum
,
904 TRACE_(win32
)("(%p,%08lx)\n",
908 if ( ERROR_SUCCESS
==RegOpenKeyA(HKEY_LOCAL_MACHINE
,
909 "System\\CurrentControlSet\\Control\\Nls\\Locale\\",
913 DWORD size
=sizeof(buffer
);
914 if (ERROR_SUCCESS
!=RegEnumValueA(xhkey
,i
,buffer
,&size
,NULL
,
917 if (size
&& !lpfnLocaleEnum(buffer
))
925 while (languages
[i
].langid
!=0) {
926 sprintf(buffer
,"%08lx",(DWORD
)languages
[i
].langid
);
927 if (!lpfnLocaleEnum(buffer
))
934 static const unsigned char CT_CType2_LUT
[] = {
935 C2_NOTAPPLICABLE
, /* - 0 */
936 C2_NOTAPPLICABLE
, /* - 1 */
937 C2_NOTAPPLICABLE
, /* - 2 */
938 C2_NOTAPPLICABLE
, /* - 3 */
939 C2_NOTAPPLICABLE
, /* - 4 */
940 C2_NOTAPPLICABLE
, /* - 5 */
941 C2_NOTAPPLICABLE
, /* - 6 */
942 C2_NOTAPPLICABLE
, /* - 7 */
943 C2_NOTAPPLICABLE
, /* - 8 */
944 C2_SEGMENTSEPARATOR
, /* - 9 */
945 C2_NOTAPPLICABLE
, /* - 10 */
946 C2_NOTAPPLICABLE
, /* - 11 */
947 C2_NOTAPPLICABLE
, /* - 12 */
948 C2_NOTAPPLICABLE
, /* - 13 */
949 C2_NOTAPPLICABLE
, /* - 14 */
950 C2_NOTAPPLICABLE
, /* - 15 */
951 C2_NOTAPPLICABLE
, /* - 16 */
952 C2_NOTAPPLICABLE
, /* - 17 */
953 C2_NOTAPPLICABLE
, /* - 18 */
954 C2_NOTAPPLICABLE
, /* - 19 */
955 C2_NOTAPPLICABLE
, /* - 20 */
956 C2_NOTAPPLICABLE
, /* - 21 */
957 C2_NOTAPPLICABLE
, /* - 22 */
958 C2_NOTAPPLICABLE
, /* - 23 */
959 C2_NOTAPPLICABLE
, /* - 24 */
960 C2_NOTAPPLICABLE
, /* - 25 */
961 C2_NOTAPPLICABLE
, /* - 26 */
962 C2_NOTAPPLICABLE
, /* - 27 */
963 C2_NOTAPPLICABLE
, /* - 28 */
964 C2_NOTAPPLICABLE
, /* - 29 */
965 C2_NOTAPPLICABLE
, /* - 30 */
966 C2_NOTAPPLICABLE
, /* - 31 */
967 C2_WHITESPACE
, /* - 32 */
968 C2_OTHERNEUTRAL
, /* ! - 33 */
969 C2_OTHERNEUTRAL
, /* " - 34 */ /* " */
970 C2_EUROPETERMINATOR
, /* # - 35 */
971 C2_EUROPETERMINATOR
, /* $ - 36 */
972 C2_EUROPETERMINATOR
, /* % - 37 */
973 C2_LEFTTORIGHT
, /* & - 38 */
974 C2_OTHERNEUTRAL
, /* ' - 39 */
975 C2_OTHERNEUTRAL
, /* ( - 40 */
976 C2_OTHERNEUTRAL
, /* ) - 41 */
977 C2_OTHERNEUTRAL
, /* * - 42 */
978 C2_EUROPETERMINATOR
, /* + - 43 */
979 C2_COMMONSEPARATOR
, /* , - 44 */
980 C2_EUROPETERMINATOR
, /* - - 45 */
981 C2_EUROPESEPARATOR
, /* . - 46 */
982 C2_EUROPESEPARATOR
, /* / - 47 */
983 C2_EUROPENUMBER
, /* 0 - 48 */
984 C2_EUROPENUMBER
, /* 1 - 49 */
985 C2_EUROPENUMBER
, /* 2 - 50 */
986 C2_EUROPENUMBER
, /* 3 - 51 */
987 C2_EUROPENUMBER
, /* 4 - 52 */
988 C2_EUROPENUMBER
, /* 5 - 53 */
989 C2_EUROPENUMBER
, /* 6 - 54 */
990 C2_EUROPENUMBER
, /* 7 - 55 */
991 C2_EUROPENUMBER
, /* 8 - 56 */
992 C2_EUROPENUMBER
, /* 9 - 57 */
993 C2_COMMONSEPARATOR
, /* : - 58 */
994 C2_OTHERNEUTRAL
, /* ; - 59 */
995 C2_OTHERNEUTRAL
, /* < - 60 */
996 C2_OTHERNEUTRAL
, /* = - 61 */
997 C2_OTHERNEUTRAL
, /* > - 62 */
998 C2_OTHERNEUTRAL
, /* ? - 63 */
999 C2_LEFTTORIGHT
, /* @ - 64 */
1000 C2_LEFTTORIGHT
, /* A - 65 */
1001 C2_LEFTTORIGHT
, /* B - 66 */
1002 C2_LEFTTORIGHT
, /* C - 67 */
1003 C2_LEFTTORIGHT
, /* D - 68 */
1004 C2_LEFTTORIGHT
, /* E - 69 */
1005 C2_LEFTTORIGHT
, /* F - 70 */
1006 C2_LEFTTORIGHT
, /* G - 71 */
1007 C2_LEFTTORIGHT
, /* H - 72 */
1008 C2_LEFTTORIGHT
, /* I - 73 */
1009 C2_LEFTTORIGHT
, /* J - 74 */
1010 C2_LEFTTORIGHT
, /* K - 75 */
1011 C2_LEFTTORIGHT
, /* L - 76 */
1012 C2_LEFTTORIGHT
, /* M - 77 */
1013 C2_LEFTTORIGHT
, /* N - 78 */
1014 C2_LEFTTORIGHT
, /* O - 79 */
1015 C2_LEFTTORIGHT
, /* P - 80 */
1016 C2_LEFTTORIGHT
, /* Q - 81 */
1017 C2_LEFTTORIGHT
, /* R - 82 */
1018 C2_LEFTTORIGHT
, /* S - 83 */
1019 C2_LEFTTORIGHT
, /* T - 84 */
1020 C2_LEFTTORIGHT
, /* U - 85 */
1021 C2_LEFTTORIGHT
, /* V - 86 */
1022 C2_LEFTTORIGHT
, /* W - 87 */
1023 C2_LEFTTORIGHT
, /* X - 88 */
1024 C2_LEFTTORIGHT
, /* Y - 89 */
1025 C2_LEFTTORIGHT
, /* Z - 90 */
1026 C2_OTHERNEUTRAL
, /* [ - 91 */
1027 C2_OTHERNEUTRAL
, /* \ - 92 */
1028 C2_OTHERNEUTRAL
, /* ] - 93 */
1029 C2_OTHERNEUTRAL
, /* ^ - 94 */
1030 C2_OTHERNEUTRAL
, /* _ - 95 */
1031 C2_OTHERNEUTRAL
, /* ` - 96 */
1032 C2_LEFTTORIGHT
, /* a - 97 */
1033 C2_LEFTTORIGHT
, /* b - 98 */
1034 C2_LEFTTORIGHT
, /* c - 99 */
1035 C2_LEFTTORIGHT
, /* d - 100 */
1036 C2_LEFTTORIGHT
, /* e - 101 */
1037 C2_LEFTTORIGHT
, /* f - 102 */
1038 C2_LEFTTORIGHT
, /* g - 103 */
1039 C2_LEFTTORIGHT
, /* h - 104 */
1040 C2_LEFTTORIGHT
, /* i - 105 */
1041 C2_LEFTTORIGHT
, /* j - 106 */
1042 C2_LEFTTORIGHT
, /* k - 107 */
1043 C2_LEFTTORIGHT
, /* l - 108 */
1044 C2_LEFTTORIGHT
, /* m - 109 */
1045 C2_LEFTTORIGHT
, /* n - 110 */
1046 C2_LEFTTORIGHT
, /* o - 111 */
1047 C2_LEFTTORIGHT
, /* p - 112 */
1048 C2_LEFTTORIGHT
, /* q - 113 */
1049 C2_LEFTTORIGHT
, /* r - 114 */
1050 C2_LEFTTORIGHT
, /* s - 115 */
1051 C2_LEFTTORIGHT
, /* t - 116 */
1052 C2_LEFTTORIGHT
, /* u - 117 */
1053 C2_LEFTTORIGHT
, /* v - 118 */
1054 C2_LEFTTORIGHT
, /* w - 119 */
1055 C2_LEFTTORIGHT
, /* x - 120 */
1056 C2_LEFTTORIGHT
, /* y - 121 */
1057 C2_LEFTTORIGHT
, /* z - 122 */
1058 C2_OTHERNEUTRAL
, /* { - 123 */
1059 C2_OTHERNEUTRAL
, /* | - 124 */
1060 C2_OTHERNEUTRAL
, /* } - 125 */
1061 C2_OTHERNEUTRAL
, /* ~ - 126 */
1062 C2_NOTAPPLICABLE
, /* \x7f - 127 */
1063 C2_NOTAPPLICABLE
, /* € - 128 */
1064 C2_NOTAPPLICABLE
, /* � - 129 */
1065 C2_OTHERNEUTRAL
, /* ‚ - 130 */
1066 C2_LEFTTORIGHT
, /* ƒ - 131 */
1067 C2_OTHERNEUTRAL
, /* „ - 132 */
1068 C2_OTHERNEUTRAL
, /* … - 133 */
1069 C2_OTHERNEUTRAL
, /* † - 134 */
1070 C2_OTHERNEUTRAL
, /* ‡ - 135 */
1071 C2_LEFTTORIGHT
, /* ˆ - 136 */
1072 C2_EUROPETERMINATOR
, /* ‰ - 137 */
1073 C2_LEFTTORIGHT
, /* Š - 138 */
1074 C2_OTHERNEUTRAL
, /* ‹ - 139 */
1075 C2_LEFTTORIGHT
, /* Œ - 140 */
1076 C2_NOTAPPLICABLE
, /* � - 141 */
1077 C2_NOTAPPLICABLE
, /* Ž - 142 */
1078 C2_NOTAPPLICABLE
, /* � - 143 */
1079 C2_NOTAPPLICABLE
, /* � - 144 */
1080 C2_OTHERNEUTRAL
, /* ‘ - 145 */
1081 C2_OTHERNEUTRAL
, /* ’ - 146 */
1082 C2_OTHERNEUTRAL
, /* “ - 147 */
1083 C2_OTHERNEUTRAL
, /* ” - 148 */
1084 C2_OTHERNEUTRAL
, /* • - 149 */
1085 C2_OTHERNEUTRAL
, /* – - 150 */
1086 C2_OTHERNEUTRAL
, /* — - 151 */
1087 C2_LEFTTORIGHT
, /* ˜ - 152 */
1088 C2_OTHERNEUTRAL
, /* ™ - 153 */
1089 C2_LEFTTORIGHT
, /* š - 154 */
1090 C2_OTHERNEUTRAL
, /* › - 155 */
1091 C2_LEFTTORIGHT
, /* œ - 156 */
1092 C2_NOTAPPLICABLE
, /* � - 157 */
1093 C2_NOTAPPLICABLE
, /* ž - 158 */
1094 C2_LEFTTORIGHT
, /* Ÿ - 159 */
1095 C2_WHITESPACE
, /* - 160 */
1096 C2_OTHERNEUTRAL
, /* ¡ - 161 */
1097 C2_EUROPETERMINATOR
, /* ¢ - 162 */
1098 C2_EUROPETERMINATOR
, /* £ - 163 */
1099 C2_EUROPETERMINATOR
, /* ¤ - 164 */
1100 C2_EUROPETERMINATOR
, /* ¥ - 165 */
1101 C2_OTHERNEUTRAL
, /* ¦ - 166 */
1102 C2_OTHERNEUTRAL
, /* § - 167 */
1103 C2_OTHERNEUTRAL
, /* ¨ - 168 */
1104 C2_OTHERNEUTRAL
, /* © - 169 */
1105 C2_OTHERNEUTRAL
, /* ª - 170 */
1106 C2_OTHERNEUTRAL
, /* « - 171 */
1107 C2_OTHERNEUTRAL
, /* ¬ - 172 */
1108 C2_OTHERNEUTRAL
, /* - 173 */
1109 C2_OTHERNEUTRAL
, /* ® - 174 */
1110 C2_OTHERNEUTRAL
, /* ¯ - 175 */
1111 C2_EUROPETERMINATOR
, /* ° - 176 */
1112 C2_EUROPETERMINATOR
, /* ± - 177 */
1113 C2_EUROPENUMBER
, /* ² - 178 */
1114 C2_EUROPENUMBER
, /* ³ - 179 */
1115 C2_OTHERNEUTRAL
, /* ´ - 180 */
1116 C2_OTHERNEUTRAL
, /* µ - 181 */
1117 C2_OTHERNEUTRAL
, /* ¶ - 182 */
1118 C2_OTHERNEUTRAL
, /* · - 183 */
1119 C2_OTHERNEUTRAL
, /* ¸ - 184 */
1120 C2_EUROPENUMBER
, /* ¹ - 185 */
1121 C2_OTHERNEUTRAL
, /* º - 186 */
1122 C2_OTHERNEUTRAL
, /* » - 187 */
1123 C2_OTHERNEUTRAL
, /* ¼ - 188 */
1124 C2_OTHERNEUTRAL
, /* ½ - 189 */
1125 C2_OTHERNEUTRAL
, /* ¾ - 190 */
1126 C2_OTHERNEUTRAL
, /* ¿ - 191 */
1127 C2_LEFTTORIGHT
, /* À - 192 */
1128 C2_LEFTTORIGHT
, /* Á - 193 */
1129 C2_LEFTTORIGHT
, /* Â - 194 */
1130 C2_LEFTTORIGHT
, /* Ã - 195 */
1131 C2_LEFTTORIGHT
, /* Ä - 196 */
1132 C2_LEFTTORIGHT
, /* Å - 197 */
1133 C2_LEFTTORIGHT
, /* Æ - 198 */
1134 C2_LEFTTORIGHT
, /* Ç - 199 */
1135 C2_LEFTTORIGHT
, /* È - 200 */
1136 C2_LEFTTORIGHT
, /* É - 201 */
1137 C2_LEFTTORIGHT
, /* Ê - 202 */
1138 C2_LEFTTORIGHT
, /* Ë - 203 */
1139 C2_LEFTTORIGHT
, /* Ì - 204 */
1140 C2_LEFTTORIGHT
, /* Í - 205 */
1141 C2_LEFTTORIGHT
, /* Î - 206 */
1142 C2_LEFTTORIGHT
, /* Ï - 207 */
1143 C2_LEFTTORIGHT
, /* Ð - 208 */
1144 C2_LEFTTORIGHT
, /* Ñ - 209 */
1145 C2_LEFTTORIGHT
, /* Ò - 210 */
1146 C2_LEFTTORIGHT
, /* Ó - 211 */
1147 C2_LEFTTORIGHT
, /* Ô - 212 */
1148 C2_LEFTTORIGHT
, /* Õ - 213 */
1149 C2_LEFTTORIGHT
, /* Ö - 214 */
1150 C2_OTHERNEUTRAL
, /* × - 215 */
1151 C2_LEFTTORIGHT
, /* Ø - 216 */
1152 C2_LEFTTORIGHT
, /* Ù - 217 */
1153 C2_LEFTTORIGHT
, /* Ú - 218 */
1154 C2_LEFTTORIGHT
, /* Û - 219 */
1155 C2_LEFTTORIGHT
, /* Ü - 220 */
1156 C2_LEFTTORIGHT
, /* Ý - 221 */
1157 C2_LEFTTORIGHT
, /* Þ - 222 */
1158 C2_LEFTTORIGHT
, /* ß - 223 */
1159 C2_LEFTTORIGHT
, /* à - 224 */
1160 C2_LEFTTORIGHT
, /* á - 225 */
1161 C2_LEFTTORIGHT
, /* â - 226 */
1162 C2_LEFTTORIGHT
, /* ã - 227 */
1163 C2_LEFTTORIGHT
, /* ä - 228 */
1164 C2_LEFTTORIGHT
, /* å - 229 */
1165 C2_LEFTTORIGHT
, /* æ - 230 */
1166 C2_LEFTTORIGHT
, /* ç - 231 */
1167 C2_LEFTTORIGHT
, /* è - 232 */
1168 C2_LEFTTORIGHT
, /* é - 233 */
1169 C2_LEFTTORIGHT
, /* ê - 234 */
1170 C2_LEFTTORIGHT
, /* ë - 235 */
1171 C2_LEFTTORIGHT
, /* ì - 236 */
1172 C2_LEFTTORIGHT
, /* í - 237 */
1173 C2_LEFTTORIGHT
, /* î - 238 */
1174 C2_LEFTTORIGHT
, /* ï - 239 */
1175 C2_LEFTTORIGHT
, /* ð - 240 */
1176 C2_LEFTTORIGHT
, /* ñ - 241 */
1177 C2_LEFTTORIGHT
, /* ò - 242 */
1178 C2_LEFTTORIGHT
, /* ó - 243 */
1179 C2_LEFTTORIGHT
, /* ô - 244 */
1180 C2_LEFTTORIGHT
, /* õ - 245 */
1181 C2_LEFTTORIGHT
, /* ö - 246 */
1182 C2_OTHERNEUTRAL
, /* ÷ - 247 */
1183 C2_LEFTTORIGHT
, /* ø - 248 */
1184 C2_LEFTTORIGHT
, /* ù - 249 */
1185 C2_LEFTTORIGHT
, /* ú - 250 */
1186 C2_LEFTTORIGHT
, /* û - 251 */
1187 C2_LEFTTORIGHT
, /* ü - 252 */
1188 C2_LEFTTORIGHT
, /* ý - 253 */
1189 C2_LEFTTORIGHT
, /* þ - 254 */
1190 C2_LEFTTORIGHT
/* ÿ - 255 */
1193 const WORD OLE2NLS_CT_CType3_LUT
[] = {
1227 0x0048, /* ! - 33 */
1228 0x0448, /* " - 34 */ /* " */
1229 0x0048, /* # - 35 */
1230 0x0448, /* $ - 36 */
1231 0x0048, /* % - 37 */
1232 0x0048, /* & - 38 */
1233 0x0440, /* ' - 39 */
1234 0x0048, /* ( - 40 */
1235 0x0048, /* ) - 41 */
1236 0x0048, /* * - 42 */
1237 0x0048, /* + - 43 */
1238 0x0048, /* , - 44 */
1239 0x0440, /* - - 45 */
1240 0x0048, /* . - 46 */
1241 0x0448, /* / - 47 */
1242 0x0040, /* 0 - 48 */
1243 0x0040, /* 1 - 49 */
1244 0x0040, /* 2 - 50 */
1245 0x0040, /* 3 - 51 */
1246 0x0040, /* 4 - 52 */
1247 0x0040, /* 5 - 53 */
1248 0x0040, /* 6 - 54 */
1249 0x0040, /* 7 - 55 */
1250 0x0040, /* 8 - 56 */
1251 0x0040, /* 9 - 57 */
1252 0x0048, /* : - 58 */
1253 0x0048, /* ; - 59 */
1254 0x0048, /* < - 60 */
1255 0x0448, /* = - 61 */
1256 0x0048, /* > - 62 */
1257 0x0048, /* ? - 63 */
1258 0x0448, /* @ - 64 */
1259 0x8040, /* A - 65 */
1260 0x8040, /* B - 66 */
1261 0x8040, /* C - 67 */
1262 0x8040, /* D - 68 */
1263 0x8040, /* E - 69 */
1264 0x8040, /* F - 70 */
1265 0x8040, /* G - 71 */
1266 0x8040, /* H - 72 */
1267 0x8040, /* I - 73 */
1268 0x8040, /* J - 74 */
1269 0x8040, /* K - 75 */
1270 0x8040, /* L - 76 */
1271 0x8040, /* M - 77 */
1272 0x8040, /* N - 78 */
1273 0x8040, /* O - 79 */
1274 0x8040, /* P - 80 */
1275 0x8040, /* Q - 81 */
1276 0x8040, /* R - 82 */
1277 0x8040, /* S - 83 */
1278 0x8040, /* T - 84 */
1279 0x8040, /* U - 85 */
1280 0x8040, /* V - 86 */
1281 0x8040, /* W - 87 */
1282 0x8040, /* X - 88 */
1283 0x8040, /* Y - 89 */
1284 0x8040, /* Z - 90 */
1285 0x0048, /* [ - 91 */
1286 0x0448, /* \ - 92 */
1287 0x0048, /* ] - 93 */
1288 0x0448, /* ^ - 94 */
1289 0x0448, /* _ - 95 */
1290 0x0448, /* ` - 96 */
1291 0x8040, /* a - 97 */
1292 0x8040, /* b - 98 */
1293 0x8040, /* c - 99 */
1294 0x8040, /* d - 100 */
1295 0x8040, /* e - 101 */
1296 0x8040, /* f - 102 */
1297 0x8040, /* g - 103 */
1298 0x8040, /* h - 104 */
1299 0x8040, /* i - 105 */
1300 0x8040, /* j - 106 */
1301 0x8040, /* k - 107 */
1302 0x8040, /* l - 108 */
1303 0x8040, /* m - 109 */
1304 0x8040, /* n - 110 */
1305 0x8040, /* o - 111 */
1306 0x8040, /* p - 112 */
1307 0x8040, /* q - 113 */
1308 0x8040, /* r - 114 */
1309 0x8040, /* s - 115 */
1310 0x8040, /* t - 116 */
1311 0x8040, /* u - 117 */
1312 0x8040, /* v - 118 */
1313 0x8040, /* w - 119 */
1314 0x8040, /* x - 120 */
1315 0x8040, /* y - 121 */
1316 0x8040, /* z - 122 */
1317 0x0048, /* { - 123 */
1318 0x0048, /* | - 124 */
1319 0x0048, /* } - 125 */
1320 0x0448, /* ~ - 126 */
1321 0x0000, /* \x7f - 127 */
1322 0x0000, /* € - 128 */
1323 0x0000, /* � - 129 */
1324 0x0008, /* ‚ - 130 */
1325 0x8000, /* ƒ - 131 */
1326 0x0008, /* „ - 132 */
1327 0x0008, /* … - 133 */
1328 0x0008, /* † - 134 */
1329 0x0008, /* ‡ - 135 */
1330 0x0001, /* ˆ - 136 */
1331 0x0008, /* ‰ - 137 */
1332 0x8003, /* Š - 138 */
1333 0x0008, /* ‹ - 139 */
1334 0x8000, /* Œ - 140 */
1335 0x0000, /* � - 141 */
1336 0x0000, /* Ž - 142 */
1337 0x0000, /* � - 143 */
1338 0x0000, /* � - 144 */
1339 0x0088, /* ‘ - 145 */
1340 0x0088, /* ’ - 146 */
1341 0x0088, /* “ - 147 */
1342 0x0088, /* ” - 148 */
1343 0x0008, /* • - 149 */
1344 0x0400, /* – - 150 */
1345 0x0400, /* — - 151 */
1346 0x0408, /* ˜ - 152 */
1347 0x0000, /* ™ - 153 */
1348 0x8003, /* š - 154 */
1349 0x0008, /* › - 155 */
1350 0x8000, /* œ - 156 */
1351 0x0000, /* � - 157 */
1352 0x0000, /* ž - 158 */
1353 0x8003, /* Ÿ - 159 */
1355 0x0008, /* ¡ - 161 */
1356 0x0048, /* ¢ - 162 */
1357 0x0048, /* £ - 163 */
1358 0x0008, /* ¤ - 164 */
1359 0x0048, /* ¥ - 165 */
1360 0x0048, /* ¦ - 166 */
1361 0x0008, /* § - 167 */
1362 0x0408, /* ¨ - 168 */
1363 0x0008, /* © - 169 */
1364 0x0400, /* ª - 170 */
1365 0x0008, /* « - 171 */
1366 0x0048, /* ¬ - 172 */
1367 0x0408, /* - 173 */
1368 0x0008, /* ® - 174 */
1369 0x0448, /* ¯ - 175 */
1370 0x0008, /* ° - 176 */
1371 0x0008, /* ± - 177 */
1372 0x0000, /* ² - 178 */
1373 0x0000, /* ³ - 179 */
1374 0x0408, /* ´ - 180 */
1375 0x0008, /* µ - 181 */
1376 0x0008, /* ¶ - 182 */
1377 0x0008, /* · - 183 */
1378 0x0408, /* ¸ - 184 */
1379 0x0000, /* ¹ - 185 */
1380 0x0400, /* º - 186 */
1381 0x0008, /* » - 187 */
1382 0x0000, /* ¼ - 188 */
1383 0x0000, /* ½ - 189 */
1384 0x0000, /* ¾ - 190 */
1385 0x0008, /* ¿ - 191 */
1386 0x8003, /* À - 192 */
1387 0x8003, /* Á - 193 */
1388 0x8003, /* Â - 194 */
1389 0x8003, /* Ã - 195 */
1390 0x8003, /* Ä - 196 */
1391 0x8003, /* Å - 197 */
1392 0x8000, /* Æ - 198 */
1393 0x8003, /* Ç - 199 */
1394 0x8003, /* È - 200 */
1395 0x8003, /* É - 201 */
1396 0x8003, /* Ê - 202 */
1397 0x8003, /* Ë - 203 */
1398 0x8003, /* Ì - 204 */
1399 0x8003, /* Í - 205 */
1400 0x8003, /* Î - 206 */
1401 0x8003, /* Ï - 207 */
1402 0x8000, /* Ð - 208 */
1403 0x8003, /* Ñ - 209 */
1404 0x8003, /* Ò - 210 */
1405 0x8003, /* Ó - 211 */
1406 0x8003, /* Ô - 212 */
1407 0x8003, /* Õ - 213 */
1408 0x8003, /* Ö - 214 */
1409 0x0008, /* × - 215 */
1410 0x8003, /* Ø - 216 */
1411 0x8003, /* Ù - 217 */
1412 0x8003, /* Ú - 218 */
1413 0x8003, /* Û - 219 */
1414 0x8003, /* Ü - 220 */
1415 0x8003, /* Ý - 221 */
1416 0x8000, /* Þ - 222 */
1417 0x8000, /* ß - 223 */
1418 0x8003, /* à - 224 */
1419 0x8003, /* á - 225 */
1420 0x8003, /* â - 226 */
1421 0x8003, /* ã - 227 */
1422 0x8003, /* ä - 228 */
1423 0x8003, /* å - 229 */
1424 0x8000, /* æ - 230 */
1425 0x8003, /* ç - 231 */
1426 0x8003, /* è - 232 */
1427 0x8003, /* é - 233 */
1428 0x8003, /* ê - 234 */
1429 0x8003, /* ë - 235 */
1430 0x8003, /* ì - 236 */
1431 0x8003, /* í - 237 */
1432 0x8003, /* î - 238 */
1433 0x8003, /* ï - 239 */
1434 0x8000, /* ð - 240 */
1435 0x8003, /* ñ - 241 */
1436 0x8003, /* ò - 242 */
1437 0x8003, /* ó - 243 */
1438 0x8003, /* ô - 244 */
1439 0x8003, /* õ - 245 */
1440 0x8003, /* ö - 246 */
1441 0x0008, /* ÷ - 247 */
1442 0x8003, /* ø - 248 */
1443 0x8003, /* ù - 249 */
1444 0x8003, /* ú - 250 */
1445 0x8003, /* û - 251 */
1446 0x8003, /* ü - 252 */
1447 0x8003, /* ý - 253 */
1448 0x8000, /* þ - 254 */
1449 0x8003 /* ÿ - 255 */
1452 /******************************************************************************
1453 * GetStringType16 [OLE2NLS.7]
1455 BOOL16 WINAPI
GetStringType16(LCID locale
,DWORD dwInfoType
,LPCSTR src
,
1456 INT16 cchSrc
,LPWORD chartype
)
1458 return GetStringTypeExA(locale
,dwInfoType
,src
,cchSrc
,chartype
);
1460 /******************************************************************************
1461 * GetStringType32A [KERNEL32.396]
1463 BOOL WINAPI
GetStringTypeA(LCID locale
,DWORD dwInfoType
,LPCSTR src
,
1464 INT cchSrc
,LPWORD chartype
)
1466 return GetStringTypeExA(locale
,dwInfoType
,src
,cchSrc
,chartype
);
1469 /******************************************************************************
1470 * GetStringTypeEx32A [KERNEL32.397]
1472 * FIXME: Ignores the locale.
1474 BOOL WINAPI
GetStringTypeExA(LCID locale
,DWORD dwInfoType
,LPCSTR src
,
1475 INT cchSrc
,LPWORD chartype
)
1479 if ((src
==NULL
) || (chartype
==NULL
) || (src
==(LPSTR
)chartype
))
1481 SetLastError(ERROR_INVALID_PARAMETER
);
1486 cchSrc
=lstrlenA(src
)+1;
1488 switch (dwInfoType
) {
1490 for (i
=0;i
<cchSrc
;i
++)
1493 if (isdigit(src
[i
])) chartype
[i
]|=C1_DIGIT
;
1494 if (isalpha(src
[i
])) chartype
[i
]|=C1_ALPHA
;
1495 if (islower(src
[i
])) chartype
[i
]|=C1_LOWER
;
1496 if (isupper(src
[i
])) chartype
[i
]|=C1_UPPER
;
1497 if (isspace(src
[i
])) chartype
[i
]|=C1_SPACE
;
1498 if (ispunct(src
[i
])) chartype
[i
]|=C1_PUNCT
;
1499 if (iscntrl(src
[i
])) chartype
[i
]|=C1_CNTRL
;
1500 /* FIXME: isblank() is a GNU extension */
1501 /* if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1502 if ((src
[i
] == ' ') || (src
[i
] == '\t')) chartype
[i
]|=C1_BLANK
;
1508 for (i
=0;i
<cchSrc
;i
++)
1510 chartype
[i
]=(WORD
)CT_CType2_LUT
[i
];
1515 for (i
=0;i
<cchSrc
;i
++)
1517 chartype
[i
]=OLE2NLS_CT_CType3_LUT
[i
];
1522 ERR("Unknown dwInfoType:%ld\n",dwInfoType
);
1527 /******************************************************************************
1528 * GetStringType32W [KERNEL32.399]
1531 * Yes, this is missing LCID locale. MS fault.
1533 BOOL WINAPI
GetStringTypeW(DWORD dwInfoType
,LPCWSTR src
,INT cchSrc
,
1536 return GetStringTypeExW(0/*defaultlocale*/,dwInfoType
,src
,cchSrc
,chartype
);
1539 /******************************************************************************
1540 * GetStringTypeEx32W [KERNEL32.398]
1542 * FIXME: unicode chars are assumed chars
1544 BOOL WINAPI
GetStringTypeExW(LCID locale
,DWORD dwInfoType
,LPCWSTR src
,
1545 INT cchSrc
,LPWORD chartype
)
1551 cchSrc
=lstrlenW(src
)+1;
1553 switch (dwInfoType
) {
1555 FIXME("CT_CTYPE2 not supported.\n");
1558 FIXME("CT_CTYPE3 not supported.\n");
1562 for (i
=0;i
<cchSrc
;i
++) {
1564 if (isdigit(src
[i
])) chartype
[i
]|=C1_DIGIT
;
1565 if (isalpha(src
[i
])) chartype
[i
]|=C1_ALPHA
;
1566 if (islower(src
[i
])) chartype
[i
]|=C1_LOWER
;
1567 if (isupper(src
[i
])) chartype
[i
]|=C1_UPPER
;
1568 if (isspace(src
[i
])) chartype
[i
]|=C1_SPACE
;
1569 if (ispunct(src
[i
])) chartype
[i
]|=C1_PUNCT
;
1570 if (iscntrl(src
[i
])) chartype
[i
]|=C1_CNTRL
;
1571 /* FIXME: isblank() is a GNU extension */
1572 /* if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1573 if ((src
[i
] == ' ') || (src
[i
] == '\t')) chartype
[i
]|=C1_BLANK
;
1579 /*****************************************************************
1580 * WINE_GetLanguageName [internal]
1582 static LPCSTR
WINE_GetLanguageName( UINT langid
)
1585 for ( i
= 0; languages
[i
].langid
!= 0; i
++ )
1586 if ( langid
== languages
[i
].langid
)
1589 return languages
[i
].langname
;
1592 /***********************************************************************
1593 * VerLanguageNameA [KERNEL32.709][VERSION.9]
1595 DWORD WINAPI
VerLanguageNameA( UINT wLang
, LPSTR szLang
, UINT nSize
)
1602 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1603 * from the registry.
1607 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1610 result
= RegQueryValueA( HKEY_LOCAL_MACHINE
, buffer
, szLang
, (LPDWORD
)&nSize
);
1611 if ( result
== ERROR_SUCCESS
|| result
== ERROR_MORE_DATA
)
1615 * If that fails, use the internal table
1618 name
= WINE_GetLanguageName( wLang
);
1619 lstrcpynA( szLang
, name
, nSize
);
1620 return lstrlenA( name
);
1623 /***********************************************************************
1624 * VerLanguageNameW [KERNEL32.710][VERSION.10]
1626 DWORD WINAPI
VerLanguageNameW( UINT wLang
, LPWSTR szLang
, UINT nSize
)
1634 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1635 * from the registry.
1639 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1642 keyname
= HEAP_strdupAtoW( GetProcessHeap(), 0, buffer
);
1643 result
= RegQueryValueW( HKEY_LOCAL_MACHINE
, keyname
, szLang
, (LPDWORD
)&nSize
);
1644 HeapFree( GetProcessHeap(), 0, keyname
);
1646 if ( result
== ERROR_SUCCESS
|| result
== ERROR_MORE_DATA
)
1650 * If that fails, use the internal table
1653 name
= WINE_GetLanguageName( wLang
);
1654 lstrcpynAtoW( szLang
, name
, nSize
);
1655 return lstrlenA( name
);
1659 static const unsigned char LCM_Unicode_LUT
[] = {
1692 7 , 28, /* ! - 33 */
1693 7 , 29, /* " - 34 */ /* " */
1694 7 , 31, /* # - 35 */
1695 7 , 33, /* $ - 36 */
1696 7 , 35, /* % - 37 */
1697 7 , 37, /* & - 38 */
1698 6 , 128, /* ' - 39 */
1699 7 , 39, /* ( - 40 */
1700 7 , 42, /* ) - 41 */
1701 7 , 45, /* * - 42 */
1703 7 , 47, /* , - 44 */
1704 6 , 130, /* - - 45 */
1705 7 , 51, /* . - 46 */
1706 7 , 53, /* / - 47 */
1707 12 , 3, /* 0 - 48 */
1708 12 , 33, /* 1 - 49 */
1709 12 , 51, /* 2 - 50 */
1710 12 , 70, /* 3 - 51 */
1711 12 , 88, /* 4 - 52 */
1712 12 , 106, /* 5 - 53 */
1713 12 , 125, /* 6 - 54 */
1714 12 , 144, /* 7 - 55 */
1715 12 , 162, /* 8 - 56 */
1716 12 , 180, /* 9 - 57 */
1717 7 , 55, /* : - 58 */
1718 7 , 58, /* ; - 59 */
1719 8 , 14, /* < - 60 */
1720 8 , 18, /* = - 61 */
1721 8 , 20, /* > - 62 */
1722 7 , 60, /* ? - 63 */
1723 7 , 62, /* @ - 64 */
1724 14 , 2, /* A - 65 */
1725 14 , 9, /* B - 66 */
1726 14 , 10, /* C - 67 */
1727 14 , 26, /* D - 68 */
1728 14 , 33, /* E - 69 */
1729 14 , 35, /* F - 70 */
1730 14 , 37, /* G - 71 */
1731 14 , 44, /* H - 72 */
1732 14 , 50, /* I - 73 */
1733 14 , 53, /* J - 74 */
1734 14 , 54, /* K - 75 */
1735 14 , 72, /* L - 76 */
1736 14 , 81, /* M - 77 */
1737 14 , 112, /* N - 78 */
1738 14 , 124, /* O - 79 */
1739 14 , 126, /* P - 80 */
1740 14 , 137, /* Q - 81 */
1741 14 , 138, /* R - 82 */
1742 14 , 145, /* S - 83 */
1743 14 , 153, /* T - 84 */
1744 14 , 159, /* U - 85 */
1745 14 , 162, /* V - 86 */
1746 14 , 164, /* W - 87 */
1747 14 , 166, /* X - 88 */
1748 14 , 167, /* Y - 89 */
1749 14 , 169, /* Z - 90 */
1750 7 , 63, /* [ - 91 */
1751 7 , 65, /* \ - 92 */
1752 7 , 66, /* ] - 93 */
1753 7 , 67, /* ^ - 94 */
1754 7 , 68, /* _ - 95 */
1755 7 , 72, /* ` - 96 */
1756 14 , 2, /* a - 97 */
1757 14 , 9, /* b - 98 */
1758 14 , 10, /* c - 99 */
1759 14 , 26, /* d - 100 */
1760 14 , 33, /* e - 101 */
1761 14 , 35, /* f - 102 */
1762 14 , 37, /* g - 103 */
1763 14 , 44, /* h - 104 */
1764 14 , 50, /* i - 105 */
1765 14 , 53, /* j - 106 */
1766 14 , 54, /* k - 107 */
1767 14 , 72, /* l - 108 */
1768 14 , 81, /* m - 109 */
1769 14 , 112, /* n - 110 */
1770 14 , 124, /* o - 111 */
1771 14 , 126, /* p - 112 */
1772 14 , 137, /* q - 113 */
1773 14 , 138, /* r - 114 */
1774 14 , 145, /* s - 115 */
1775 14 , 153, /* t - 116 */
1776 14 , 159, /* u - 117 */
1777 14 , 162, /* v - 118 */
1778 14 , 164, /* w - 119 */
1779 14 , 166, /* x - 120 */
1780 14 , 167, /* y - 121 */
1781 14 , 169, /* z - 122 */
1782 7 , 74, /* { - 123 */
1783 7 , 76, /* | - 124 */
1784 7 , 78, /* } - 125 */
1785 7 , 80, /* ~ - 126 */
1786 6 , 29, /* \x7f - 127 */
1787 6 , 30, /* € - 128 */
1788 6 , 31, /* � - 129 */
1789 7 , 123, /* ‚ - 130 */
1790 14 , 35, /* ƒ - 131 */
1791 7 , 127, /* „ - 132 */
1792 10 , 21, /* … - 133 */
1793 10 , 15, /* † - 134 */
1794 10 , 16, /* ‡ - 135 */
1795 7 , 67, /* ˆ - 136 */
1796 10 , 22, /* ‰ - 137 */
1797 14 , 145, /* Š - 138 */
1798 7 , 136, /* ‹ - 139 */
1799 14 + 16 , 124, /* Œ - 140 */
1800 6 , 43, /* � - 141 */
1801 6 , 44, /* Ž - 142 */
1802 6 , 45, /* � - 143 */
1803 6 , 46, /* � - 144 */
1804 7 , 121, /* ‘ - 145 */
1805 7 , 122, /* ’ - 146 */
1806 7 , 125, /* “ - 147 */
1807 7 , 126, /* ” - 148 */
1808 10 , 17, /* • - 149 */
1809 6 , 137, /* – - 150 */
1810 6 , 139, /* — - 151 */
1811 7 , 93, /* ˜ - 152 */
1812 14 , 156, /* ™ - 153 */
1813 14 , 145, /* š - 154 */
1814 7 , 137, /* › - 155 */
1815 14 + 16 , 124, /* œ - 156 */
1816 6 , 59, /* � - 157 */
1817 6 , 60, /* ž - 158 */
1818 14 , 167, /* Ÿ - 159 */
1820 7 , 81, /* ¡ - 161 */
1821 10 , 2, /* ¢ - 162 */
1822 10 , 3, /* £ - 163 */
1823 10 , 4, /* ¤ - 164 */
1824 10 , 5, /* ¥ - 165 */
1825 7 , 82, /* ¦ - 166 */
1826 10 , 6, /* § - 167 */
1827 7 , 83, /* ¨ - 168 */
1828 10 , 7, /* © - 169 */
1829 14 , 2, /* ª - 170 */
1830 8 , 24, /* « - 171 */
1831 10 , 8, /* ¬ - 172 */
1832 6 , 131, /* - 173 */
1833 10 , 9, /* ® - 174 */
1834 7 , 84, /* ¯ - 175 */
1835 10 , 10, /* ° - 176 */
1836 8 , 23, /* ± - 177 */
1837 12 , 51, /* ² - 178 */
1838 12 , 70, /* ³ - 179 */
1839 7 , 85, /* ´ - 180 */
1840 10 , 11, /* µ - 181 */
1841 10 , 12, /* ¶ - 182 */
1842 10 , 13, /* · - 183 */
1843 7 , 86, /* ¸ - 184 */
1844 12 , 33, /* ¹ - 185 */
1845 14 , 124, /* º - 186 */
1846 8 , 26, /* » - 187 */
1847 12 , 21, /* ¼ - 188 */
1848 12 , 25, /* ½ - 189 */
1849 12 , 29, /* ¾ - 190 */
1850 7 , 87, /* ¿ - 191 */
1851 14 , 2, /* À - 192 */
1852 14 , 2, /* Á - 193 */
1853 14 , 2, /* Â - 194 */
1854 14 , 2, /* Ã - 195 */
1855 14 , 2, /* Ä - 196 */
1856 14 , 2, /* Å - 197 */
1857 14 + 16 , 2, /* Æ - 198 */
1858 14 , 10, /* Ç - 199 */
1859 14 , 33, /* È - 200 */
1860 14 , 33, /* É - 201 */
1861 14 , 33, /* Ê - 202 */
1862 14 , 33, /* Ë - 203 */
1863 14 , 50, /* Ì - 204 */
1864 14 , 50, /* Í - 205 */
1865 14 , 50, /* Î - 206 */
1866 14 , 50, /* Ï - 207 */
1867 14 , 26, /* Ð - 208 */
1868 14 , 112, /* Ñ - 209 */
1869 14 , 124, /* Ò - 210 */
1870 14 , 124, /* Ó - 211 */
1871 14 , 124, /* Ô - 212 */
1872 14 , 124, /* Õ - 213 */
1873 14 , 124, /* Ö - 214 */
1874 8 , 28, /* × - 215 */
1875 14 , 124, /* Ø - 216 */
1876 14 , 159, /* Ù - 217 */
1877 14 , 159, /* Ú - 218 */
1878 14 , 159, /* Û - 219 */
1879 14 , 159, /* Ü - 220 */
1880 14 , 167, /* Ý - 221 */
1881 14 + 32 , 153, /* Þ - 222 */
1882 14 + 48 , 145, /* ß - 223 */
1883 14 , 2, /* à - 224 */
1884 14 , 2, /* á - 225 */
1885 14 , 2, /* â - 226 */
1886 14 , 2, /* ã - 227 */
1887 14 , 2, /* ä - 228 */
1888 14 , 2, /* å - 229 */
1889 14 + 16 , 2, /* æ - 230 */
1890 14 , 10, /* ç - 231 */
1891 14 , 33, /* è - 232 */
1892 14 , 33, /* é - 233 */
1893 14 , 33, /* ê - 234 */
1894 14 , 33, /* ë - 235 */
1895 14 , 50, /* ì - 236 */
1896 14 , 50, /* í - 237 */
1897 14 , 50, /* î - 238 */
1898 14 , 50, /* ï - 239 */
1899 14 , 26, /* ð - 240 */
1900 14 , 112, /* ñ - 241 */
1901 14 , 124, /* ò - 242 */
1902 14 , 124, /* ó - 243 */
1903 14 , 124, /* ô - 244 */
1904 14 , 124, /* õ - 245 */
1905 14 , 124, /* ö - 246 */
1906 8 , 29, /* ÷ - 247 */
1907 14 , 124, /* ø - 248 */
1908 14 , 159, /* ù - 249 */
1909 14 , 159, /* ú - 250 */
1910 14 , 159, /* û - 251 */
1911 14 , 159, /* ü - 252 */
1912 14 , 167, /* ý - 253 */
1913 14 + 32 , 153, /* þ - 254 */
1914 14 , 167 /* ÿ - 255 */ };
1916 static const unsigned char LCM_Unicode_LUT_2
[] = { 33, 44, 145 };
1918 #define LCM_Diacritic_Start 131
1920 static const unsigned char LCM_Diacritic_LUT
[] = {
2048 /******************************************************************************
2049 * OLE2NLS_isPunctuation [INTERNAL]
2051 static int OLE2NLS_isPunctuation(unsigned char c
)
2053 /* "punctuation character" in this context is a character which is
2054 considered "less important" during word sort comparison.
2055 See LCMapString implementation for the precise definition
2056 of "less important". */
2058 return (LCM_Unicode_LUT
[-2+2*c
]==6);
2061 /******************************************************************************
2062 * OLE2NLS_isNonSpacing [INTERNAL]
2064 static int OLE2NLS_isNonSpacing(unsigned char c
)
2066 /* This function is used by LCMapString32A. Characters
2067 for which it returns true are ignored when mapping a
2068 string with NORM_IGNORENONSPACE */
2069 return ((c
==136) || (c
==170) || (c
==186));
2072 /******************************************************************************
2073 * OLE2NLS_isSymbol [INTERNAL]
2075 static int OLE2NLS_isSymbol(unsigned char c
)
2077 /* This function is used by LCMapString32A. Characters
2078 for which it returns true are ignored when mapping a
2079 string with NORM_IGNORESYMBOLS */
2080 return ( (c
!=0) && !IsCharAlphaNumericA(c
) );
2083 /******************************************************************************
2084 * identity [Internal]
2086 static int identity(int c
)
2091 /*************************************************************************
2092 * LCMapString32A [KERNEL32.492]
2094 * Convert a string, or generate a sort key from it.
2096 * If (mapflags & LCMAP_SORTKEY), the function will generate
2097 * a sort key for the source string. Else, it will convert it
2098 * accordingly to the flags LCMAP_UPPERCASE, LCMAP_LOWERCASE,...
2102 * Success : length of the result string.
2105 * If called with scrlen = -1, the function will compute the length
2106 * of the 0-terminated string strsrc by itself.
2108 * If called with dstlen = 0, returns the buffer length that
2109 * would be required.
2111 * NORM_IGNOREWIDTH means to compare ASCII and wide characters
2112 * as if they are equal.
2113 * In the only code page implemented so far, there may not be
2114 * wide characters in strings passed to LCMapString32A,
2115 * so there is nothing to be done for this flag.
2117 INT WINAPI
LCMapStringA(
2118 LCID lcid
/* locale identifier created with MAKELCID;
2119 LOCALE_SYSTEM_DEFAULT and LOCALE_USER_DEFAULT are
2120 predefined values. */,
2121 DWORD mapflags
/* flags */,
2122 LPCSTR srcstr
/* source buffer */,
2123 INT srclen
/* source length */,
2124 LPSTR dststr
/* destination buffer */,
2125 INT dstlen
/* destination buffer length */)
2129 TRACE_(string
)("(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
2130 lcid
,mapflags
,srcstr
,srclen
,dststr
,dstlen
);
2132 if ( ((dstlen
!=0) && (dststr
==NULL
)) || (srcstr
==NULL
) )
2134 ERR("(src=%s,dest=%s): Invalid NULL string\n", srcstr
, dststr
);
2135 SetLastError(ERROR_INVALID_PARAMETER
);
2139 srclen
= lstrlenA(srcstr
) + 1 ; /* (include final '\0') */
2141 #define LCMAPSTRINGA_SUPPORTED_FLAGS (LCMAP_UPPERCASE | \
2145 NORM_IGNORENONSPACE | \
2147 NORM_IGNOREWIDTH | \
2148 NORM_IGNOREKANATYPE)
2149 /* FIXME: as long as we don't support Kanakana nor Hirigana
2150 * characters, we can support NORM_IGNOREKANATYPE
2152 if (mapflags
& ~LCMAPSTRINGA_SUPPORTED_FLAGS
)
2154 FIXME_(string
)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2155 "unimplemented flags: 0x%08lx\n",
2162 mapflags
& ~LCMAPSTRINGA_SUPPORTED_FLAGS
2166 if ( !(mapflags
& LCMAP_SORTKEY
) )
2169 int (*f
)(int) = identity
;
2170 int flag_ignorenonspace
= mapflags
& NORM_IGNORENONSPACE
;
2171 int flag_ignoresymbols
= mapflags
& NORM_IGNORESYMBOLS
;
2173 if (flag_ignorenonspace
|| flag_ignoresymbols
)
2175 /* For some values of mapflags, the length of the resulting
2176 string is not known at this point. Windows does map the string
2177 and does not SetLastError ERROR_INSUFFICIENT_BUFFER in
2181 /* Compute required length */
2182 for (i
=j
=0; i
< srclen
; i
++)
2184 if ( !(flag_ignorenonspace
&& OLE2NLS_isNonSpacing(srcstr
[i
]))
2185 && !(flag_ignoresymbols
&& OLE2NLS_isSymbol(srcstr
[i
])) )
2197 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2201 if (mapflags
& LCMAP_UPPERCASE
)
2203 else if (mapflags
& LCMAP_LOWERCASE
)
2205 /* FIXME: NORM_IGNORENONSPACE requires another conversion */
2206 for (i
=j
=0; (i
<srclen
) && (j
<dstlen
) ; i
++)
2208 if ( !(flag_ignorenonspace
&& OLE2NLS_isNonSpacing(srcstr
[i
]))
2209 && !(flag_ignoresymbols
&& OLE2NLS_isSymbol(srcstr
[i
])) )
2211 dststr
[j
] = (CHAR
) f(srcstr
[i
]);
2218 /* else ... (mapflags & LCMAP_SORTKEY) */
2222 int diacritic_len
=0;
2223 int delayed_punctuation_len
=0;
2224 char *case_component
;
2225 char *diacritic_component
;
2226 char *delayed_punctuation_component
;
2228 int flag_stringsort
= mapflags
& SORT_STRINGSORT
;
2230 /* compute how much room we will need */
2231 for (i
=0;i
<srclen
;i
++)
2234 unsigned char source_char
= srcstr
[i
];
2235 if (source_char
!='\0')
2237 if (flag_stringsort
|| !OLE2NLS_isPunctuation(source_char
))
2240 if ( LCM_Unicode_LUT
[-2+2*source_char
] & ~15 )
2241 unicode_len
++; /* double letter */
2245 delayed_punctuation_len
++;
2249 if (isupper(source_char
))
2250 case_len
=unicode_len
;
2252 ofs
= source_char
- LCM_Diacritic_Start
;
2253 if ((ofs
>=0) && (LCM_Diacritic_LUT
[ofs
]!=2))
2254 diacritic_len
=unicode_len
;
2257 if (mapflags
& NORM_IGNORECASE
)
2259 if (mapflags
& NORM_IGNORENONSPACE
)
2262 room
= 2 * unicode_len
/* "unicode" component */
2263 + diacritic_len
/* "diacritic" component */
2264 + case_len
/* "case" component */
2265 + 4 * delayed_punctuation_len
/* punctuation in word sort mode */
2266 + 4 /* four '\1' separators */
2267 + 1 ; /* terminal '\0' */
2270 else if (dstlen
<room
)
2272 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2276 /*FIXME the Pointercheck should not be nessesary */
2277 if (IsBadWritePtr (dststr
,room
))
2278 { ERR_(string
)("bad destination buffer (dststr) : %p,%d\n",dststr
,dstlen
);
2279 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2283 /* locate each component, write separators */
2284 diacritic_component
= dststr
+ 2*unicode_len
;
2285 *diacritic_component
++ = '\1';
2286 case_component
= diacritic_component
+ diacritic_len
;
2287 *case_component
++ = '\1';
2288 delayed_punctuation_component
= case_component
+ case_len
;
2289 *delayed_punctuation_component
++ = '\1';
2290 *delayed_punctuation_component
++ = '\1';
2292 /* read source string char by char, write
2293 corresponding weight in each component. */
2294 for (i
=0,count
=0;i
<srclen
;i
++)
2296 unsigned char source_char
=srcstr
[i
];
2297 if (source_char
!='\0')
2300 type
= LCM_Unicode_LUT
[-2+2*source_char
];
2301 longcode
= type
>> 4;
2303 if (!flag_stringsort
&& OLE2NLS_isPunctuation(source_char
))
2305 UINT16 encrypted_location
= (1<<15) + 7 + 4*count
;
2306 *delayed_punctuation_component
++ = (unsigned char) (encrypted_location
>>8);
2307 *delayed_punctuation_component
++ = (unsigned char) (encrypted_location
&255);
2308 /* big-endian is used here because it lets string comparison be
2309 compatible with numerical comparison */
2311 *delayed_punctuation_component
++ = type
;
2312 *delayed_punctuation_component
++ = LCM_Unicode_LUT
[-1+2*source_char
];
2313 /* assumption : a punctuation character is never a
2314 double or accented letter */
2318 dststr
[2*count
] = type
;
2319 dststr
[2*count
+1] = LCM_Unicode_LUT
[-1+2*source_char
];
2323 case_component
[count
] = ( isupper(source_char
) ? 18 : 2 ) ;
2324 if (count
<diacritic_len
)
2325 diacritic_component
[count
] = 2; /* assumption: a double letter
2326 is never accented */
2329 dststr
[2*count
] = type
;
2330 dststr
[2*count
+1] = *(LCM_Unicode_LUT_2
- 1 + longcode
);
2331 /* 16 in the first column of LCM_Unicode_LUT --> longcode = 1
2332 32 in the first column of LCM_Unicode_LUT --> longcode = 2
2333 48 in the first column of LCM_Unicode_LUT --> longcode = 3 */
2337 case_component
[count
] = ( isupper(source_char
) ? 18 : 2 ) ;
2338 if (count
<diacritic_len
)
2340 int ofs
= source_char
- LCM_Diacritic_Start
;
2341 diacritic_component
[count
] = (ofs
>=0 ? LCM_Diacritic_LUT
[ofs
] : 2);
2347 dststr
[room
-1] = '\0';
2352 /*************************************************************************
2353 * LCMapString32W [KERNEL32.493]
2355 * Convert a string, or generate a sort key from it.
2359 * See LCMapString32A for documentation
2361 INT WINAPI
LCMapStringW(
2362 LCID lcid
,DWORD mapflags
,LPCWSTR srcstr
,INT srclen
,LPWSTR dststr
,
2367 TRACE_(string
)("(0x%04lx,0x%08lx,%p,%d,%p,%d)\n",
2368 lcid
,mapflags
,srcstr
,srclen
,dststr
,dstlen
);
2370 if ( ((dstlen
!=0) && (dststr
==NULL
)) || (srcstr
==NULL
) )
2372 ERR("(src=%p,dst=%p): Invalid NULL string\n", srcstr
, dststr
);
2373 SetLastError(ERROR_INVALID_PARAMETER
);
2377 srclen
= lstrlenW(srcstr
)+1;
2383 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2386 if (mapflags
& LCMAP_SORTKEY
)
2388 FIXME_(string
)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2389 "unimplemented flags: 0x%08lx. Ignoring LC_COLLATE.\n",
2390 lcid
,mapflags
,srcstr
,srclen
,dststr
,dstlen
,mapflags
);
2391 memcpy(dststr
, srcstr
, srclen
* sizeof(*srcstr
));
2396 int (*f
)(int)=identity
;
2398 if (mapflags
& LCMAP_UPPERCASE
)
2400 else if (mapflags
& LCMAP_LOWERCASE
)
2402 for (i
=0; i
< srclen
; i
++)
2403 dststr
[i
] = (WCHAR
) f(srcstr
[i
]);
2408 /***********************************************************************
2409 * CompareString16 (OLE2NLS.8)
2411 UINT16 WINAPI
CompareString16(DWORD lcid
,DWORD fdwStyle
,
2412 LPCSTR s1
,DWORD l1
,LPCSTR s2
,DWORD l2
)
2414 return (UINT16
)CompareStringA(lcid
,fdwStyle
,s1
,l1
,s2
,l2
);
2417 /******************************************************************************
2418 * CompareString32A [KERNEL32.143]
2419 * Compares two strings using locale
2423 * success: CSTR_LESS_THAN, CSTR_EQUAL, CSTR_GREATER_THAN
2428 * Defaults to a word sort, but uses a string sort if
2429 * SORT_STRINGSORT is set.
2430 * Calls SetLastError for ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER.
2434 * This implementation ignores the locale
2438 * Quite inefficient.
2440 UINT WINAPI
CompareStringA(
2441 DWORD lcid
, /* locale ID */
2442 DWORD fdwStyle
, /* comparison-style options */
2443 LPCSTR s1
, /* first string */
2444 DWORD l1
, /* length of first string */
2445 LPCSTR s2
, /* second string */
2446 DWORD l2
) /* length of second string */
2448 int mapstring_flags
;
2452 TRACE("%s and %s\n",
2453 debugstr_a (s1
), debugstr_a (s2
));
2455 if ( (s1
==NULL
) || (s2
==NULL
) )
2457 ERR("(s1=%s,s2=%s): Invalid NULL string\n", s1
, s2
);
2458 SetLastError(ERROR_INVALID_PARAMETER
);
2462 if(fdwStyle
& NORM_IGNORESYMBOLS
)
2463 FIXME("IGNORESYMBOLS not supported\n");
2465 mapstring_flags
= LCMAP_SORTKEY
| fdwStyle
;
2466 len1
= LCMapStringA(lcid
,mapstring_flags
,s1
,l1
,NULL
,0);
2467 len2
= LCMapStringA(lcid
,mapstring_flags
,s2
,l2
,NULL
,0);
2469 if ((len1
==0)||(len2
==0))
2470 return 0; /* something wrong happened */
2472 sk1
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,len1
);
2473 sk2
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,len2
);
2474 if ( (!LCMapStringA(lcid
,mapstring_flags
,s1
,l1
,sk1
,len1
))
2475 || (!LCMapStringA(lcid
,mapstring_flags
,s2
,l2
,sk2
,len2
)) )
2477 ERR("Bug in LCmapString32A.\n");
2482 /* strcmp doesn't necessarily return -1, 0, or 1 */
2483 result
= strcmp(sk1
,sk2
);
2485 HeapFree(GetProcessHeap(),0,sk1
);
2486 HeapFree(GetProcessHeap(),0,sk2
);
2493 /* must be greater, if we reach this point */
2497 /******************************************************************************
2498 * CompareString32W [KERNEL32.144]
2499 * This implementation ignores the locale
2500 * FIXME : Does only string sort. Should
2501 * be reimplemented the same way as CompareString32A.
2503 UINT WINAPI
CompareStringW(DWORD lcid
, DWORD fdwStyle
,
2504 LPCWSTR s1
, DWORD l1
, LPCWSTR s2
,DWORD l2
)
2507 if(fdwStyle
& NORM_IGNORENONSPACE
)
2508 FIXME("IGNORENONSPACE not supprted\n");
2509 if(fdwStyle
& NORM_IGNORESYMBOLS
)
2510 FIXME("IGNORESYMBOLS not supported\n");
2512 /* Is strcmp defaulting to string sort or to word sort?? */
2513 /* FIXME: Handle NORM_STRINGSORT */
2514 l1
= (l1
==-1)?lstrlenW(s1
):l1
;
2515 l2
= (l2
==-1)?lstrlenW(s2
):l2
;
2516 len
= l1
<l2
? l1
:l2
;
2517 ret
= (fdwStyle
& NORM_IGNORECASE
) ?
2518 CRTDLL__wcsnicmp(s1
,s2
,len
) : CRTDLL_wcsncmp(s1
,s2
,len
);
2519 /* not equal, return 1 or 3 */
2520 if(ret
!=0) return ret
+2;
2521 /* same len, return 2 */
2522 if(l1
==l2
) return 2;
2523 /* the longer one is lexically greater */
2524 return (l1
<l2
)? 1 : 3;
2527 /******************************************************************************
2528 * RegisterNLSInfoChanged [OLE2NLS.10]
2530 BOOL16 WINAPI
RegisterNLSInfoChanged16(LPVOID
/*FIXME*/ lpNewNLSInfo
)
2532 FIXME("Fully implemented, but doesn't effect anything.\n");
2543 lpNLSInfo
= lpNewNLSInfo
;
2548 return FALSE
; /* ptr not set */
2551 /******************************************************************************
2552 * OLE_GetFormatA [Internal]
2555 * If datelen == 0, it should return the reguired string length.
2557 This function implements stuff for GetDateFormat() and
2560 d single-digit (no leading zero) day (of month)
2561 dd two-digit day (of month)
2562 ddd short day-of-week name
2563 dddd long day-of-week name
2564 M single-digit month
2566 MMM short month name
2567 MMMM full month name
2568 y two-digit year, no leading 0
2570 yyyy four-digit year
2572 h hours with no leading zero (12-hour)
2573 hh hours with full two digits
2574 H hours with no leading zero (24-hour)
2575 HH hours with full two digits
2576 m minutes with no leading zero
2577 mm minutes with full two digits
2578 s seconds with no leading zero
2579 ss seconds with full two digits
2580 t time marker (A or P)
2581 tt time marker (AM, PM)
2582 '' used to quote literal characters
2583 '' (within a quoted string) indicates a literal '
2585 These functions REQUIRE valid locale, date, and format.
2587 static INT
OLE_GetFormatA(LCID locale
,
2591 LPCSTR _format
, /*in*/
2596 int count
, type
, inquote
, Overflow
;
2602 const char * _dgfmt
[] = { "%d", "%02d" };
2603 const char ** dgfmt
= _dgfmt
- 1;
2605 /* report, for debugging */
2606 TRACE("(0x%lx,0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt=%p \'%s\' , %p, len=%d)\n",
2607 locale
, flags
, tflags
,
2608 xtime
->wDay
, xtime
->wHour
, xtime
->wMinute
, xtime
->wSecond
,
2609 _format
, _format
, date
, datelen
);
2612 FIXME("datelen = 0, returning 255\n");
2616 /* initalize state variables and output buffer */
2618 count
= 0; inquote
= 0; Overflow
= 0;
2620 date
[0] = buf
[0] = '\0';
2622 strcpy(format
,_format
);
2624 /* alter the formatstring, while it works for all languages now in wine
2625 its possible that it fails when the time looks like ss:mm:hh as example*/
2626 if (tflags
& (TIME_NOMINUTESORSECONDS
))
2627 { if ((pos
= strstr ( format
, ":mm")))
2628 { memcpy ( pos
, pos
+3, strlen(format
)-(pos
-format
)-2 );
2631 if (tflags
& (TIME_NOSECONDS
))
2632 { if ((pos
= strstr ( format
, ":ss")))
2633 { memcpy ( pos
, pos
+3, strlen(format
)-(pos
-format
)-2 );
2637 for (inpos
= 0;; inpos
++) {
2638 /* 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]); */
2640 if (format
[inpos
] == '\'') {
2641 if (format
[inpos
+1] == '\'') {
2643 date
[outpos
++] = '\'';
2646 continue; /* we did nothing to the output */
2648 } else if (format
[inpos
] == '\0') {
2649 date
[outpos
++] = '\0';
2650 if (outpos
> datelen
) Overflow
= 1;
2653 date
[outpos
++] = format
[inpos
];
2654 if (outpos
> datelen
) {
2656 date
[outpos
-1] = '\0'; /* this is the last place where
2657 it's safe to write */
2661 } else if ( (count
&& (format
[inpos
] != type
))
2663 || (count
== 2 && strchr("ghHmst", type
)) )
2667 GetLocaleInfoA(locale
,
2669 + xtime
->wDayOfWeek
- 1,
2671 } else if (count
== 3) {
2672 GetLocaleInfoA(locale
,
2673 LOCALE_SABBREVDAYNAME1
2674 + xtime
->wDayOfWeek
- 1,
2677 sprintf(buf
, dgfmt
[count
], xtime
->wDay
);
2679 } else if (type
== 'M') {
2681 GetLocaleInfoA(locale
,
2682 LOCALE_SABBREVMONTHNAME1
2683 + xtime
->wMonth
- 1,
2685 } else if (count
== 4) {
2686 GetLocaleInfoA(locale
,
2688 + xtime
->wMonth
- 1,
2691 sprintf(buf
, dgfmt
[count
], xtime
->wMonth
);
2693 } else if (type
== 'y') {
2695 sprintf(buf
, "%d", xtime
->wYear
);
2696 } else if (count
== 3) {
2698 WARN("unknown format, c=%c, n=%d\n", type
, count
);
2700 sprintf(buf
, dgfmt
[count
], xtime
->wYear
% 100);
2702 } else if (type
== 'g') {
2704 FIXME("LOCALE_ICALENDARTYPE unimp.\n");
2708 WARN("unknown format, c=%c, n=%d\n", type
, count
);
2710 } else if (type
== 'h') {
2711 /* gives us hours 1:00 -- 12:00 */
2712 sprintf(buf
, dgfmt
[count
], (xtime
->wHour
-1)%12 +1);
2713 } else if (type
== 'H') {
2715 sprintf(buf
, dgfmt
[count
], xtime
->wHour
);
2716 } else if ( type
== 'm') {
2717 sprintf(buf
, dgfmt
[count
], xtime
->wMinute
);
2718 } else if ( type
== 's') {
2719 sprintf(buf
, dgfmt
[count
], xtime
->wSecond
);
2720 } else if (type
== 't') {
2722 sprintf(buf
, "%c", (xtime
->wHour
< 12) ? 'A' : 'P');
2723 } else if (count
== 2) {
2724 /* sprintf(buf, "%s", (xtime->wHour < 12) ? "AM" : "PM"); */
2725 GetLocaleInfoA(locale
,
2727 ? LOCALE_S1159
: LOCALE_S2359
,
2732 /* we need to check the next char in the format string
2733 again, no matter what happened */
2736 /* add the contents of buf to the output */
2737 buflen
= strlen(buf
);
2738 if (outpos
+ buflen
< datelen
) {
2739 date
[outpos
] = '\0'; /* for strcat to hook onto */
2743 date
[outpos
] = '\0';
2744 strncat(date
, buf
, datelen
- outpos
);
2745 date
[datelen
- 1] = '\0';
2746 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2747 WARN("insufficient buffer\n");
2751 /* reset the variables we used to keep track of this item */
2754 } else if (format
[inpos
] == '\0') {
2755 /* we can't check for this at the loop-head, because
2756 that breaks the printing of the last format-item */
2757 date
[outpos
] = '\0';
2760 /* continuing a code for an item */
2763 } else if (strchr("hHmstyMdg", format
[inpos
])) {
2764 type
= format
[inpos
];
2767 } else if (format
[inpos
] == '\'') {
2771 date
[outpos
++] = format
[inpos
];
2773 /* now deal with a possible buffer overflow */
2774 if (outpos
>= datelen
) {
2775 date
[datelen
- 1] = '\0';
2776 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2782 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2785 /* finish it off with a string terminator */
2788 if (outpos
> datelen
-1) outpos
= datelen
-1;
2789 date
[outpos
] = '\0';
2791 TRACE("OLE_GetFormatA returns string '%s', len %d\n",
2796 /******************************************************************************
2797 * OLE_GetFormatW [INTERNAL]
2799 static INT
OLE_GetFormatW(LCID locale
, DWORD flags
, DWORD tflags
,
2802 LPWSTR output
, INT outlen
)
2805 int count
, type
=0, inquote
;
2806 int Overflow
; /* loop check */
2809 WCHAR arg0
[] = {0}, arg1
[] = {'%','d',0};
2810 WCHAR arg2
[] = {'%','0','2','d',0};
2812 int datevars
=0, timevars
=0;
2818 /* make a debug report */
2819 TRACE("args: 0x%lx, 0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt:%s (at %p), "
2820 "%p with max len %d\n",
2821 locale
, flags
, tflags
,
2822 xtime
->wDay
, xtime
->wHour
, xtime
->wMinute
, xtime
->wSecond
,
2823 debugstr_w(format
), format
, output
, outlen
);
2826 FIXME("outlen = 0, returning 255\n");
2830 /* initialize state variables */
2833 inquote
= Overflow
= 0;
2834 /* this is really just a sanity check */
2835 output
[0] = buf
[0] = 0;
2837 /* this loop is the core of the function */
2838 for (inpos
= 0; /* we have several break points */ ; inpos
++) {
2840 if (format
[inpos
] == (WCHAR
) '\'') {
2841 if (format
[inpos
+1] == '\'') {
2843 output
[outpos
++] = '\'';
2848 } else if (format
[inpos
] == 0) {
2849 output
[outpos
++] = 0;
2850 if (outpos
> outlen
) Overflow
= 1;
2851 break; /* normal exit (within a quote) */
2853 output
[outpos
++] = format
[inpos
]; /* copy input */
2854 if (outpos
> outlen
) {
2856 output
[outpos
-1] = 0;
2860 } else if ( (count
&& (format
[inpos
] != type
))
2861 || ( (count
==4 && type
=='y') ||
2862 (count
==4 && type
=='M') ||
2863 (count
==4 && type
=='d') ||
2864 (count
==2 && type
=='g') ||
2865 (count
==2 && type
=='h') ||
2866 (count
==2 && type
=='H') ||
2867 (count
==2 && type
=='m') ||
2868 (count
==2 && type
=='s') ||
2869 (count
==2 && type
=='t') ) ) {
2872 GetLocaleInfoW(locale
,
2873 LOCALE_SDAYNAME1
+ xtime
->wDayOfWeek
-1,
2874 buf
, sizeof(buf
)/sizeof(WCHAR
) );
2875 } else if (count
== 3) {
2876 GetLocaleInfoW(locale
,
2877 LOCALE_SABBREVDAYNAME1
+
2878 xtime
->wDayOfWeek
-1,
2879 buf
, sizeof(buf
)/sizeof(WCHAR
) );
2881 wsnprintfW(buf
, 5, argarr
[count
], xtime
->wDay
);
2883 } else if (type
== 'M') {
2885 GetLocaleInfoW(locale
, LOCALE_SMONTHNAME1
+
2886 xtime
->wMonth
-1, buf
,
2887 sizeof(buf
)/sizeof(WCHAR
) );
2888 } else if (count
== 3) {
2889 GetLocaleInfoW(locale
, LOCALE_SABBREVMONTHNAME1
+
2890 xtime
->wMonth
-1, buf
,
2891 sizeof(buf
)/sizeof(WCHAR
) );
2893 wsnprintfW(buf
, 5, argarr
[count
], xtime
->wMonth
);
2895 } else if (type
== 'y') {
2897 wsnprintfW(buf
, 6, argarr
[1] /* "%d" */,
2899 } else if (count
== 3) {
2900 lstrcpynAtoW(buf
, "yyy", 5);
2902 wsnprintfW(buf
, 6, argarr
[count
],
2903 xtime
->wYear
% 100);
2905 } else if (type
== 'g') {
2907 FIXME("LOCALE_ICALENDARTYPE unimplemented\n");
2908 lstrcpynAtoW(buf
, "AD", 5);
2910 /* Win API sez we copy it verbatim */
2911 lstrcpynAtoW(buf
, "g", 5);
2913 } else if (type
== 'h') {
2914 /* hours 1:00-12:00 --- is this right? */
2915 wsnprintfW(buf
, 5, argarr
[count
],
2916 (xtime
->wHour
-1)%12 +1);
2917 } else if (type
== 'H') {
2918 wsnprintfW(buf
, 5, argarr
[count
],
2920 } else if (type
== 'm' ) {
2921 wsnprintfW(buf
, 5, argarr
[count
],
2923 } else if (type
== 's' ) {
2924 wsnprintfW(buf
, 5, argarr
[count
],
2926 } else if (type
== 't') {
2927 GetLocaleInfoW(locale
, (xtime
->wHour
< 12) ?
2928 LOCALE_S1159
: LOCALE_S2359
,
2935 /* no matter what happened, we need to check this next
2936 character the next time we loop through */
2939 /* cat buf onto the output */
2940 outlen
= lstrlenW(buf
);
2941 if (outpos
+ buflen
< outlen
) {
2942 lstrcpyW( output
+ outpos
, buf
);
2945 lstrcpynW( output
+ outpos
, buf
, outlen
- outpos
);
2947 break; /* Abnormal exit */
2950 /* reset the variables we used this time */
2953 } else if (format
[inpos
] == 0) {
2954 /* we can't check for this at the beginning, because that
2955 would keep us from printing a format spec that ended the
2958 break; /* NORMAL EXIT */
2960 /* how we keep track of the middle of a format spec */
2963 } else if ( (datevars
&& (format
[inpos
]=='d' ||
2964 format
[inpos
]=='M' ||
2965 format
[inpos
]=='y' ||
2966 format
[inpos
]=='g') ) ||
2967 (timevars
&& (format
[inpos
]=='H' ||
2968 format
[inpos
]=='h' ||
2969 format
[inpos
]=='m' ||
2970 format
[inpos
]=='s' ||
2971 format
[inpos
]=='t') ) ) {
2972 type
= format
[inpos
];
2975 } else if (format
[inpos
] == '\'') {
2979 /* unquoted literals */
2980 output
[outpos
++] = format
[inpos
];
2985 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2986 WARN(" buffer overflow\n");
2989 /* final string terminator and sanity check */
2991 if (outpos
> outlen
-1) outpos
= outlen
-1;
2992 output
[outpos
] = '0';
2994 TRACE(" returning %s\n", debugstr_w(output
));
2996 return (!Overflow
) ? outlen
: 0;
3001 /******************************************************************************
3002 * GetDateFormat32A [KERNEL32.310]
3003 * Makes an ASCII string of the date
3005 * This function uses format to format the date, or, if format
3006 * is NULL, uses the default for the locale. format is a string
3007 * of literal fields and characters as follows:
3009 * - d single-digit (no leading zero) day (of month)
3010 * - dd two-digit day (of month)
3011 * - ddd short day-of-week name
3012 * - dddd long day-of-week name
3013 * - M single-digit month
3014 * - MM two-digit month
3015 * - MMM short month name
3016 * - MMMM full month name
3017 * - y two-digit year, no leading 0
3018 * - yy two-digit year
3019 * - yyyy four-digit year
3023 INT WINAPI
GetDateFormatA(LCID locale
,DWORD flags
,
3025 LPCSTR format
, LPSTR date
,INT datelen
)
3028 char format_buf
[40];
3031 LPSYSTEMTIME thistime
;
3035 TRACE("(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",
3036 locale
,flags
,xtime
,format
,date
,datelen
);
3039 locale
= LOCALE_SYSTEM_DEFAULT
;
3042 if (locale
== LOCALE_SYSTEM_DEFAULT
) {
3043 thislocale
= GetSystemDefaultLCID();
3044 } else if (locale
== LOCALE_USER_DEFAULT
) {
3045 thislocale
= GetUserDefaultLCID();
3047 thislocale
= locale
;
3050 if (xtime
== NULL
) {
3057 if (format
== NULL
) {
3058 GetLocaleInfoA(thislocale
, ((flags
&DATE_LONGDATE
)
3060 : LOCALE_SSHORTDATE
),
3061 format_buf
, sizeof(format_buf
));
3062 thisformat
= format_buf
;
3064 thisformat
= format
;
3068 ret
= OLE_GetFormatA(thislocale
, flags
, 0, thistime
, thisformat
,
3073 "GetDateFormat32A() returning %d, with data=%s\n",
3078 /******************************************************************************
3079 * GetDateFormat32W [KERNEL32.311]
3080 * Makes a Unicode string of the date
3082 * Acts the same as GetDateFormat32A(), except that it's Unicode.
3083 * Accepts & returns sizes as counts of Unicode characters.
3086 INT WINAPI
GetDateFormatW(LCID locale
,DWORD flags
,
3089 LPWSTR date
, INT datelen
)
3091 unsigned short datearr
[] = {'1','9','9','4','-','1','-','1',0};
3093 FIXME("STUB (should call OLE_GetFormatW)\n");
3094 lstrcpynW(date
, datearr
, datelen
);
3095 return ( datelen
< 9) ? datelen
: 9;
3100 /**************************************************************************
3101 * EnumDateFormats32A (KERNEL32.198)
3103 BOOL WINAPI
EnumDateFormatsA(
3104 DATEFMT_ENUMPROCA lpDateFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3106 FIXME("Only US English supported\n");
3108 if(!lpDateFmtEnumProc
)
3110 SetLastError(ERROR_INVALID_PARAMETER
);
3116 case DATE_SHORTDATE
:
3117 if(!(*lpDateFmtEnumProc
)("M/d/yy")) return TRUE
;
3118 if(!(*lpDateFmtEnumProc
)("M/d/yyyy")) return TRUE
;
3119 if(!(*lpDateFmtEnumProc
)("MM/dd/yy")) return TRUE
;
3120 if(!(*lpDateFmtEnumProc
)("MM/dd/yyyy")) return TRUE
;
3121 if(!(*lpDateFmtEnumProc
)("yy/MM/dd")) return TRUE
;
3122 if(!(*lpDateFmtEnumProc
)("dd-MMM-yy")) return TRUE
;
3125 if(!(*lpDateFmtEnumProc
)("dddd, MMMM dd, yyyy")) return TRUE
;
3126 if(!(*lpDateFmtEnumProc
)("MMMM dd, yyyy")) return TRUE
;
3127 if(!(*lpDateFmtEnumProc
)("dddd, dd MMMM, yyyy")) return TRUE
;
3128 if(!(*lpDateFmtEnumProc
)("dd MMMM, yyyy")) return TRUE
;
3131 FIXME("Unknown date format (%ld)\n", dwFlags
);
3132 SetLastError(ERROR_INVALID_PARAMETER
);
3137 /**************************************************************************
3138 * EnumDateFormats32W (KERNEL32.199)
3140 BOOL WINAPI
EnumDateFormatsW(
3141 DATEFMT_ENUMPROCW lpDateFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3143 FIXME("(%p, %ld, %ld): stub\n", lpDateFmtEnumProc
, Locale
, dwFlags
);
3144 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3148 /**************************************************************************
3149 * EnumTimeFormats32A (KERNEL32.210)
3151 BOOL WINAPI
EnumTimeFormatsA(
3152 TIMEFMT_ENUMPROCA lpTimeFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3154 FIXME("Only US English supported\n");
3156 if(!lpTimeFmtEnumProc
)
3158 SetLastError(ERROR_INVALID_PARAMETER
);
3164 FIXME("Unknown time format (%ld)\n", dwFlags
);
3167 if(!(*lpTimeFmtEnumProc
)("h:mm:ss tt")) return TRUE
;
3168 if(!(*lpTimeFmtEnumProc
)("hh:mm:ss tt")) return TRUE
;
3169 if(!(*lpTimeFmtEnumProc
)("H:mm:ss")) return TRUE
;
3170 if(!(*lpTimeFmtEnumProc
)("HH:mm:ss")) return TRUE
;
3175 /**************************************************************************
3176 * EnumTimeFormats32W (KERNEL32.211)
3178 BOOL WINAPI
EnumTimeFormatsW(
3179 TIMEFMT_ENUMPROCW lpTimeFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3181 FIXME("(%p,%ld,%ld): stub\n", lpTimeFmtEnumProc
, Locale
, dwFlags
);
3182 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3187 /**************************************************************************
3188 * GetNumberFormat32A (KERNEL32.355)
3190 INT WINAPI
GetNumberFormatA(LCID locale
, DWORD dwflags
,
3191 LPCSTR lpValue
, const NUMBERFMTA
* lpFormat
,
3192 LPSTR lpNumberStr
, int cchNumber
)
3196 UINT thisleadingzero
;
3197 UINT thisgrouping
[8]={ -1 };
3198 LPCSTR thisdecimalsep
;
3199 LPCSTR thisthousandsep
;
3200 UINT thisnegativeorder
;
3205 char roundbuffer
[24]; /* Should be enough */
3208 int dotflag
=0,negflag
=0;
3209 char misc_buf
[8], negative_buf
[4], decimal_buf
[4], thousand_buf
[4];
3210 char digits_buf
[11];
3211 int intsize
=0,decsize
=0,totalsize
,lastgroup
, leadingzeros
=0;
3212 int negsignsize
,decimalsepsize
,thousandsepsize
;
3214 /* Default setting stuff - partially borrowed from GetFormatedDate */
3216 locale
= LOCALE_SYSTEM_DEFAULT
;
3219 if (locale
== LOCALE_SYSTEM_DEFAULT
) {
3220 thislocale
= GetSystemDefaultLCID();
3221 } else if (locale
== LOCALE_USER_DEFAULT
) {
3222 thislocale
= GetUserDefaultLCID();
3224 thislocale
= locale
;
3226 /* Partial implementation: things like native digits are not considered */
3227 if (lpFormat
== NULL
) {
3229 GetLocaleInfoA(thislocale
, LOCALE_IDIGITS
,
3230 misc_buf
, sizeof(misc_buf
));
3231 thisnumdigits
= atoi(misc_buf
);
3233 GetLocaleInfoA(thislocale
, LOCALE_ILZERO
,
3234 misc_buf
, sizeof(misc_buf
));
3235 thisleadingzero
= atoi(misc_buf
);
3237 GetLocaleInfoA(thislocale
, LOCALE_SGROUPING
,
3238 misc_buf
, sizeof(misc_buf
));
3240 /* About grouping mechanism:
3241 I parse the string and pour the group size values along the
3242 thisgrouping[] array, starting by element 1. Then I convert these
3243 values to indexes for insertion into the integer part.
3244 thisgrouping[0]==-1, therefore I ensure index correctness without
3245 need for range checking and related stuff.
3246 The only drawback is the 7 separators limit, hopefully that means
3247 it will fail with numbers bigger than 10^21 if using groups of three
3251 for (i
=1,gptr
=misc_buf
;*gptr
!='\0';i
++) {
3252 /* In control panel, groups up 9 digits long are allowed. If there is any way to use larger groups,
3253 then the next line must be replaced with the following code:
3254 thisgrouping[i] = atoi(gptr);
3255 for (;*gptr!=';' && *gptr!='\0';gptr++) ; */
3257 thisgrouping
[i
] = *(gptr
++)-'0';
3263 /* Take care for repeating group size */
3264 if (thisgrouping
[i
-1]==0) {
3266 thisgrouping
[j
]=thisgrouping
[i
-2];
3271 for (i
=2;i
<=lastgroup
;i
++)
3272 thisgrouping
[i
]+=thisgrouping
[i
-1];
3274 GetLocaleInfoA(thislocale
, LOCALE_SDECIMAL
,
3275 decimal_buf
, sizeof(decimal_buf
));
3276 thisdecimalsep
= decimal_buf
;
3278 GetLocaleInfoA(thislocale
, LOCALE_STHOUSAND
,
3279 thousand_buf
, sizeof(thousand_buf
));
3280 thisthousandsep
= thousand_buf
;
3282 GetLocaleInfoA(thislocale
, LOCALE_INEGNUMBER
,
3283 misc_buf
, sizeof(misc_buf
));
3284 thisnegativeorder
= atoi(misc_buf
);
3288 thisnumdigits
= lpFormat
->NumDigits
;
3289 thisleadingzero
= lpFormat
->LeadingZero
;
3291 thisgrouping
[1] = lpFormat
->Grouping
;
3293 thisgrouping
[i
]=thisgrouping
[i
-1]+lpFormat
->Grouping
;
3296 thisdecimalsep
= lpFormat
->lpDecimalSep
;
3297 thisthousandsep
= lpFormat
->lpThousandSep
;
3298 thisnegativeorder
= lpFormat
->NegativeOrder
;
3302 GetLocaleInfoA(thislocale
, LOCALE_SNATIVEDIGITS
,
3303 digits_buf
, sizeof(digits_buf
));
3305 GetLocaleInfoA(thislocale
, LOCALE_SNEGATIVESIGN
,
3306 negative_buf
, sizeof(negative_buf
));
3308 negsignsize
=strlen(negative_buf
);
3309 decimalsepsize
=strlen(thisdecimalsep
);
3310 thousandsepsize
=strlen(thisthousandsep
);
3312 /* Size calculation */
3318 for (; *sptr
=='0'; sptr
++) leadingzeros
++; /* Ignore leading zeros */
3319 for (; *sptr
!='\0'; sptr
++) {
3320 if (!dotflag
&& *sptr
=='.') {
3322 } else if (*sptr
<'0' || *sptr
>'9') {
3323 SetLastError(ERROR_INVALID_PARAMETER
);
3335 /* Take care of eventual rounding. Only, if I need to do it, then I write
3336 the rounded lpValue copy into roundbuffer, and create the formatted
3337 string from the proper source. This is smarter than copying it always
3338 The buffer includes an extra leading zero, as the number can carry and
3339 get and extra one. If it doesn't, the zero is ignored as any other
3340 useless leading zero
3343 if (decsize
>0 && decsize
>thisnumdigits
) {
3344 sptr
-=(decsize
-thisnumdigits
);
3347 strcpy(roundbuffer
+1,lpValue
);
3350 *(roundbuffer
+1)='0';
3353 dptr
=roundbuffer
+(sptr
-lpValue
); // +1-1
3355 while ( (++*dptr
) > '9') {
3357 if (*dptr
=='.') dptr
--;
3359 if ((negflag
? *(roundbuffer
+leadingzeros
+1) : *(roundbuffer
+leadingzeros
)) == '1')
3369 if (intsize
==0 && (decsize
==0 || thisleadingzero
))
3373 totalsize
+= thisnegativeorder
== 1 || thisnegativeorder
== 3 ? negsignsize
3374 : thisnegativeorder
== 2 || thisnegativeorder
== 4 ? negsignsize
+1 : 2 ;
3376 /* Look for the first grouping to be done */
3377 for (j
=lastgroup
;thisgrouping
[j
]>=intsize
&& j
>0;j
--) ;
3380 totalsize
+=thousandsepsize
* j
;
3381 if (thisnumdigits
>0)
3382 totalsize
+=decimalsepsize
+thisnumdigits
;
3384 if (cchNumber
==0) /* if cchNumber is zero, just return size needed */
3387 if (cchNumber
<totalsize
+1) { /* +1 = Null terminator (right?) */
3388 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3393 /* Formatting stuff starts here */
3398 if (thisnegativeorder
==0)
3400 else if (thisnegativeorder
<=2) {
3401 strcpy(dptr
,negative_buf
);
3403 if (thisnegativeorder
==2)
3409 for (i
=1;*sptr
=='0' ;i
++, sptr
++) ; /* Ignore leading zeros from source*/
3410 if (intsize
==0 && (decsize
==0 || thisleadingzero
)) /* Insert one leading zero into destination if required */
3411 *(dptr
++)=digits_buf
[0];
3412 for (i
=1;i
<=intsize
;i
++) {
3414 *(dptr
++)=digits_buf
[*(sptr
++)-'0'];
3416 /* Insert a group separator if we just reached the end of a group */
3417 if (i
==intsize
-thisgrouping
[j
]) {
3418 strcpy(dptr
,thisthousandsep
);
3419 dptr
+=thousandsepsize
;
3426 if (thisnumdigits
>0) {
3427 strcpy(dptr
,decimal_buf
);
3428 dptr
+=decimalsepsize
;
3429 for (i
=0;i
<thisnumdigits
;i
++)
3430 *(dptr
++)=*sptr
!='\0' ? digits_buf
[*(sptr
++)-'0'] : digits_buf
[0];
3434 if (thisnegativeorder
==0)
3436 else if (thisnegativeorder
>=3) {
3437 if (thisnegativeorder
==4)
3439 strcpy(dptr
,negative_buf
);
3451 /**************************************************************************
3452 * GetNumberFormat32W (KERNEL32.xxx)
3454 INT WINAPI
GetNumberFormatW(LCID locale
, DWORD dwflags
,
3455 LPCWSTR lpvalue
, const NUMBERFMTW
* lpFormat
,
3456 LPWSTR lpNumberStr
, int cchNumber
)
3458 FIXME("%s: stub, no reformating done\n",debugstr_w(lpvalue
));
3460 lstrcpynW( lpNumberStr
, lpvalue
, cchNumber
);
3461 return cchNumber
? lstrlenW( lpNumberStr
) : 0;
3463 /******************************************************************************
3464 * OLE2NLS_CheckLocale [intern]
3466 static LCID
OLE2NLS_CheckLocale (LCID locale
)
3469 { locale
= LOCALE_SYSTEM_DEFAULT
;
3472 if (locale
== LOCALE_SYSTEM_DEFAULT
)
3473 { return GetSystemDefaultLCID();
3475 else if (locale
== LOCALE_USER_DEFAULT
)
3476 { return GetUserDefaultLCID();
3482 /******************************************************************************
3483 * GetTimeFormat32A [KERNEL32.422]
3484 * Makes an ASCII string of the time
3486 * Formats date according to format, or locale default if format is
3487 * NULL. The format consists of literal characters and fields as follows:
3489 * h hours with no leading zero (12-hour)
3490 * hh hours with full two digits
3491 * H hours with no leading zero (24-hour)
3492 * HH hours with full two digits
3493 * m minutes with no leading zero
3494 * mm minutes with full two digits
3495 * s seconds with no leading zero
3496 * ss seconds with full two digits
3497 * t time marker (A or P)
3498 * tt time marker (AM, PM)
3502 GetTimeFormatA(LCID locale
, /* in */
3503 DWORD flags
, /* in */
3504 LPSYSTEMTIME xtime
, /* in */
3505 LPCSTR format
, /* in */
3506 LPSTR timestr
, /* out */
3507 INT timelen
/* in */)
3508 { char format_buf
[40];
3511 LPSYSTEMTIME thistime
;
3513 DWORD thisflags
=LOCALE_STIMEFORMAT
; /* standart timeformat */
3516 TRACE("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale
,flags
,xtime
,format
,timestr
,timelen
);
3518 thislocale
= OLE2NLS_CheckLocale ( locale
);
3520 if ( flags
& (TIME_NOTIMEMARKER
| TIME_FORCE24HOURFORMAT
))
3521 { FIXME("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3524 flags
&= (TIME_NOSECONDS
| TIME_NOMINUTESORSECONDS
); /* mask for OLE_GetFormatA*/
3527 { if (flags
& LOCALE_NOUSEROVERRIDE
) /*use system default*/
3528 { thislocale
= GetSystemDefaultLCID();
3530 GetLocaleInfoA(thislocale
, thisflags
, format_buf
, sizeof(format_buf
));
3531 thisformat
= format_buf
;
3534 { thisformat
= format
;
3537 if (xtime
== NULL
) /* NULL means use the current local time*/
3544 ret
= OLE_GetFormatA(thislocale
, thisflags
, flags
, thistime
, thisformat
,
3550 /******************************************************************************
3551 * GetTimeFormat32W [KERNEL32.423]
3552 * Makes a Unicode string of the time
3555 GetTimeFormatW(LCID locale
, /* in */
3556 DWORD flags
, /* in */
3557 LPSYSTEMTIME xtime
, /* in */
3558 LPCWSTR format
, /* in */
3559 LPWSTR timestr
, /* out */
3560 INT timelen
/* in */)
3561 { WCHAR format_buf
[40];
3564 LPSYSTEMTIME thistime
;
3566 DWORD thisflags
=LOCALE_STIMEFORMAT
; /* standart timeformat */
3569 TRACE("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale
,flags
,
3570 xtime
,debugstr_w(format
),timestr
,timelen
);
3572 thislocale
= OLE2NLS_CheckLocale ( locale
);
3574 if ( flags
& (TIME_NOTIMEMARKER
| TIME_FORCE24HOURFORMAT
))
3575 { FIXME("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3578 flags
&= (TIME_NOSECONDS
| TIME_NOMINUTESORSECONDS
); /* mask for OLE_GetFormatA*/
3581 { if (flags
& LOCALE_NOUSEROVERRIDE
) /*use system default*/
3582 { thislocale
= GetSystemDefaultLCID();
3584 GetLocaleInfoW(thislocale
, thisflags
, format_buf
, 40);
3585 thisformat
= format_buf
;
3588 { thisformat
= format
;
3591 if (xtime
== NULL
) /* NULL means use the current local time*/
3592 { GetSystemTime(&t
);
3599 ret
= OLE_GetFormatW(thislocale
, thisflags
, flags
, thistime
, thisformat
,
3604 /******************************************************************************
3605 * EnumCalendarInfoA [KERNEL32.196]
3607 BOOL WINAPI
EnumCalendarInfoA(
3608 CALINFO_ENUMPROCA calinfoproc
,LCID locale
,CALID calendar
,CALTYPE caltype
3610 FIXME("(%p,0x%04lx,0x%08lx,0x%08lx),stub!\n",calinfoproc
,locale
,calendar
,caltype
);