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"
254 LANG_BEGIN (LANG_GAELIC
, SUBLANG_DEFAULT
) /* 0x043c */
255 #include "nls/gae.nls"
258 LANG_BEGIN (LANG_GAELIC
, SUBLANG_GAELIC_SCOTTISH
)
259 #include "nls/gdh.nls"
262 LANG_BEGIN (LANG_GAELIC
, SUBLANG_GAELIC_MANX
)
263 #include "nls/gdv.nls"
266 LANG_BEGIN (LANG_ESPERANTO
, SUBLANG_DEFAULT
) /*0x048f*/
267 #include "nls/esperanto.nls"
270 LANG_BEGIN (LANG_WALON
, SUBLANG_DEFAULT
) /*0x0490*/
271 #include "nls/wal.nls"
274 LANG_BEGIN (LANG_CORNISH
, SUBLANG_DEFAULT
) /* 0x0491 */
275 #include "nls/cor.nls"
278 LANG_BEGIN (LANG_WELSH
, SUBLANG_DEFAULT
) /* 0x0492 */
279 #include "nls/cym.nls"
282 LANG_BEGIN (LANG_BRETON
, SUBLANG_DEFAULT
) /* 0x0x93 */
283 #include "nls/brf.nls"
289 /* Locale name to id map. used by EnumSystemLocales, GetLocaleInfoA
290 * MUST contain all #defines from winnls.h
291 * last entry has NULL name, 0 id.
293 #define LOCALE_ENTRY(x) {#x,LOCALE_##x}
294 static struct tagLOCALE_NAME2ID
{
297 } locale_name2id
[]= {
298 LOCALE_ENTRY(ILANGUAGE
),
299 LOCALE_ENTRY(SLANGUAGE
),
300 LOCALE_ENTRY(SENGLANGUAGE
),
301 LOCALE_ENTRY(SABBREVLANGNAME
),
302 LOCALE_ENTRY(SNATIVELANGNAME
),
303 LOCALE_ENTRY(ICOUNTRY
),
304 LOCALE_ENTRY(SCOUNTRY
),
305 LOCALE_ENTRY(SENGCOUNTRY
),
306 LOCALE_ENTRY(SABBREVCTRYNAME
),
307 LOCALE_ENTRY(SNATIVECTRYNAME
),
308 LOCALE_ENTRY(IDEFAULTLANGUAGE
),
309 LOCALE_ENTRY(IDEFAULTCOUNTRY
),
310 LOCALE_ENTRY(IDEFAULTCODEPAGE
),
311 LOCALE_ENTRY(IDEFAULTANSICODEPAGE
),
312 LOCALE_ENTRY(IDEFAULTMACCODEPAGE
),
314 LOCALE_ENTRY(IMEASURE
),
315 LOCALE_ENTRY(SDECIMAL
),
316 LOCALE_ENTRY(STHOUSAND
),
317 LOCALE_ENTRY(SGROUPING
),
318 LOCALE_ENTRY(IDIGITS
),
319 LOCALE_ENTRY(ILZERO
),
320 LOCALE_ENTRY(INEGNUMBER
),
321 LOCALE_ENTRY(SNATIVEDIGITS
),
322 LOCALE_ENTRY(SCURRENCY
),
323 LOCALE_ENTRY(SINTLSYMBOL
),
324 LOCALE_ENTRY(SMONDECIMALSEP
),
325 LOCALE_ENTRY(SMONTHOUSANDSEP
),
326 LOCALE_ENTRY(SMONGROUPING
),
327 LOCALE_ENTRY(ICURRDIGITS
),
328 LOCALE_ENTRY(IINTLCURRDIGITS
),
329 LOCALE_ENTRY(ICURRENCY
),
330 LOCALE_ENTRY(INEGCURR
),
333 LOCALE_ENTRY(SSHORTDATE
),
334 LOCALE_ENTRY(SLONGDATE
),
335 LOCALE_ENTRY(STIMEFORMAT
),
337 LOCALE_ENTRY(ILDATE
),
339 LOCALE_ENTRY(ITIMEMARKPOSN
),
340 LOCALE_ENTRY(ICENTURY
),
341 LOCALE_ENTRY(ITLZERO
),
342 LOCALE_ENTRY(IDAYLZERO
),
343 LOCALE_ENTRY(IMONLZERO
),
346 LOCALE_ENTRY(ICALENDARTYPE
),
347 LOCALE_ENTRY(IOPTIONALCALENDAR
),
348 LOCALE_ENTRY(IFIRSTDAYOFWEEK
),
349 LOCALE_ENTRY(IFIRSTWEEKOFYEAR
),
350 LOCALE_ENTRY(SDAYNAME1
),
351 LOCALE_ENTRY(SDAYNAME2
),
352 LOCALE_ENTRY(SDAYNAME3
),
353 LOCALE_ENTRY(SDAYNAME4
),
354 LOCALE_ENTRY(SDAYNAME5
),
355 LOCALE_ENTRY(SDAYNAME6
),
356 LOCALE_ENTRY(SDAYNAME7
),
357 LOCALE_ENTRY(SABBREVDAYNAME1
),
358 LOCALE_ENTRY(SABBREVDAYNAME2
),
359 LOCALE_ENTRY(SABBREVDAYNAME3
),
360 LOCALE_ENTRY(SABBREVDAYNAME4
),
361 LOCALE_ENTRY(SABBREVDAYNAME5
),
362 LOCALE_ENTRY(SABBREVDAYNAME6
),
363 LOCALE_ENTRY(SABBREVDAYNAME7
),
364 LOCALE_ENTRY(SMONTHNAME1
),
365 LOCALE_ENTRY(SMONTHNAME2
),
366 LOCALE_ENTRY(SMONTHNAME3
),
367 LOCALE_ENTRY(SMONTHNAME4
),
368 LOCALE_ENTRY(SMONTHNAME5
),
369 LOCALE_ENTRY(SMONTHNAME6
),
370 LOCALE_ENTRY(SMONTHNAME7
),
371 LOCALE_ENTRY(SMONTHNAME8
),
372 LOCALE_ENTRY(SMONTHNAME9
),
373 LOCALE_ENTRY(SMONTHNAME10
),
374 LOCALE_ENTRY(SMONTHNAME11
),
375 LOCALE_ENTRY(SMONTHNAME12
),
376 LOCALE_ENTRY(SMONTHNAME13
),
377 LOCALE_ENTRY(SABBREVMONTHNAME1
),
378 LOCALE_ENTRY(SABBREVMONTHNAME2
),
379 LOCALE_ENTRY(SABBREVMONTHNAME3
),
380 LOCALE_ENTRY(SABBREVMONTHNAME4
),
381 LOCALE_ENTRY(SABBREVMONTHNAME5
),
382 LOCALE_ENTRY(SABBREVMONTHNAME6
),
383 LOCALE_ENTRY(SABBREVMONTHNAME7
),
384 LOCALE_ENTRY(SABBREVMONTHNAME8
),
385 LOCALE_ENTRY(SABBREVMONTHNAME9
),
386 LOCALE_ENTRY(SABBREVMONTHNAME10
),
387 LOCALE_ENTRY(SABBREVMONTHNAME11
),
388 LOCALE_ENTRY(SABBREVMONTHNAME12
),
389 LOCALE_ENTRY(SABBREVMONTHNAME13
),
390 LOCALE_ENTRY(SPOSITIVESIGN
),
391 LOCALE_ENTRY(SNEGATIVESIGN
),
392 LOCALE_ENTRY(IPOSSIGNPOSN
),
393 LOCALE_ENTRY(INEGSIGNPOSN
),
394 LOCALE_ENTRY(IPOSSYMPRECEDES
),
395 LOCALE_ENTRY(IPOSSEPBYSPACE
),
396 LOCALE_ENTRY(INEGSYMPRECEDES
),
397 LOCALE_ENTRY(INEGSEPBYSPACE
),
398 LOCALE_ENTRY(FONTSIGNATURE
),
399 LOCALE_ENTRY(SISO639LANGNAME
),
400 LOCALE_ENTRY(SISO3166CTRYNAME
),
404 const struct map_lcid2str
{
406 const char *langname
;
408 {0x0401,"Arabic (Saudi Arabia)"},
409 {0x0801,"Arabic (Iraq)"},
410 {0x0c01,"Arabic (Egypt)"},
411 {0x1001,"Arabic (Libya)"},
412 {0x1401,"Arabic (Algeria)"},
413 {0x1801,"Arabic (Morocco)"},
414 {0x1c01,"Arabic (Tunisia)"},
415 {0x2001,"Arabic (Oman)"},
416 {0x2401,"Arabic (Yemen)"},
417 {0x2801,"Arabic (Syria)"},
418 {0x2c01,"Arabic (Jordan)"},
419 {0x3001,"Arabic (Lebanon)"},
420 {0x3401,"Arabic (Kuwait)"},
421 {0x3801,"Arabic (United Arab Emirates)"},
422 {0x3c01,"Arabic (Bahrain)"},
423 {0x4001,"Arabic (Qatar)"},
424 {0x0402,"Bulgarian"},
426 {0x0404,"Chinese (Taiwan)"},
427 {0x0804,"Chinese (People's Republic of China)"},
428 {0x0c04,"Chinese (Hong Kong)"},
429 {0x1004,"Chinese (Singapore)"},
430 {0x1404,"Chinese (Macau)"},
433 {0x0407,"German (Germany)"},
434 {0x0807,"German (Switzerland)"},
435 {0x0c07,"German (Austria)"},
436 {0x1007,"German (Luxembourg)"},
437 {0x1407,"German (Liechtenstein)"},
439 {0x0409,"English (United States)"},
440 {0x0809,"English (United Kingdom)"},
441 {0x0c09,"English (Australia)"},
442 {0x1009,"English (Canada)"},
443 {0x1409,"English (New Zealand)"},
444 {0x1809,"English (Ireland)"},
445 {0x1c09,"English (South Africa)"},
446 {0x2009,"English (Jamaica)"},
447 {0x2409,"English (Caribbean)"},
448 {0x2809,"English (Belize)"},
449 {0x2c09,"English (Trinidad)"},
450 {0x3009,"English (Zimbabwe)"},
451 {0x3409,"English (Philippines)"},
452 {0x040a,"Spanish (Spain, traditional sorting)"},
453 {0x080a,"Spanish (Mexico)"},
454 {0x0c0a,"Spanish (Spain, international sorting)"},
455 {0x100a,"Spanish (Guatemala)"},
456 {0x140a,"Spanish (Costa Rica)"},
457 {0x180a,"Spanish (Panama)"},
458 {0x1c0a,"Spanish (Dominican Republic)"},
459 {0x200a,"Spanish (Venezuela)"},
460 {0x240a,"Spanish (Colombia)"},
461 {0x280a,"Spanish (Peru)"},
462 {0x2c0a,"Spanish (Argentina)"},
463 {0x300a,"Spanish (Ecuador)"},
464 {0x340a,"Spanish (Chile)"},
465 {0x380a,"Spanish (Uruguay)"},
466 {0x3c0a,"Spanish (Paraguay)"},
467 {0x400a,"Spanish (Bolivia)"},
468 {0x440a,"Spanish (El Salvador)"},
469 {0x480a,"Spanish (Honduras)"},
470 {0x4c0a,"Spanish (Nicaragua)"},
471 {0x500a,"Spanish (Puerto Rico)"},
473 {0x040c,"French (France)"},
474 {0x080c,"French (Belgium)"},
475 {0x0c0c,"French (Canada)"},
476 {0x100c,"French (Switzerland)"},
477 {0x140c,"French (Luxembourg)"},
478 {0x180c,"French (Monaco)"},
480 {0x040e,"Hungarian"},
481 {0x040f,"Icelandic"},
482 {0x0410,"Italian (Italy)"},
483 {0x0810,"Italian (Switzerland)"},
485 {0x0412,"Korean (Wansung)"},
486 {0x0812,"Korean (Johab)"},
487 {0x0413,"Dutch (Netherlands)"},
488 {0x0813,"Dutch (Belgium)"},
489 {0x0414,"Norwegian (Bokmal)"},
490 {0x0814,"Norwegian (Nynorsk)"},
492 {0x0416,"Portuguese (Brazil)"},
493 {0x0816,"Portuguese (Portugal)"},
494 {0x0417,"Rhaeto Romanic"},
496 {0x0818,"Moldavian"},
497 {0x0419,"Russian (Russia)"},
498 {0x0819,"Russian (Moldavia)"},
500 {0x081a,"Serbian (latin)"},
501 {0x0c1a,"Serbian (cyrillic)"},
504 {0x041d,"Swedish (Sweden)"},
505 {0x081d,"Swedish (Finland)"},
509 {0x0421,"Indonesian"},
510 {0x0422,"Ukrainian"},
511 {0x0423,"Belarusian"},
515 {0x0427,"Lithuanian (modern)"},
516 {0x0827,"Lithuanian (classic)"},
519 {0x042a,"Vietnamese"},
521 {0x042c,"Azeri (latin)"},
522 {0x082c,"Azeri (cyrillic)"},
525 {0x042f,"Macedonian"},
532 {0x0436,"Afrikaans"},
538 {0x043c,"Irish gaelic"},
539 {0x083c,"Scottish gaelic"},
540 {0x0c3c,"Manx Gaelic"},
541 {0x043e,"Malay (Malaysia)"},
542 {0x083e,"Malay (Brunei Darussalam)"},
545 {0x0443,"Uzbek (latin)"},
546 {0x0843,"Uzbek (cyrillic)"},
555 {0x044c,"Malayalam"},
560 {0x048f,"Esperanto"}, /* Non official */
561 {0x0490,"Walon"}, /* Non official */
562 {0x0491,"Cornish"}, /* Not official */
563 {0x0492,"Welsh"}, /* Not official */
564 {0x0493,"Breton"}, /* Not official */
568 {0x0402,"Bulgarisch"},
569 {0x0403,"Katalanisch"},
570 {0x0404,"Traditionales Chinesisch"},
571 {0x0405,"Tschecisch"},
574 {0x0408,"Griechisch"},
575 {0x0409,"Amerikanisches Englisch"},
576 {0x040A,"Kastilisches Spanisch"},
578 {0x040C,"Franzvsisch"},
579 {0x040D,"Hebrdisch"},
580 {0x040E,"Ungarisch"},
581 {0x040F,"Isldndisch"},
582 {0x0410,"Italienisch"},
583 {0x0411,"Japanisch"},
584 {0x0412,"Koreanisch"},
585 {0x0413,"Niederldndisch"},
586 {0x0414,"Norwegisch-Bokmal"},
588 {0x0416,"Brasilianisches Portugiesisch"},
589 {0x0417,"Rdtoromanisch"},
590 {0x0418,"Rumdnisch"},
592 {0x041A,"Kroatoserbisch (lateinisch)"},
593 {0x041B,"Slowenisch"},
594 {0x041C,"Albanisch"},
595 {0x041D,"Schwedisch"},
600 {0x0804,"Vereinfachtes Chinesisch"},
601 {0x0807,"Schweizerdeutsch"},
602 {0x0809,"Britisches Englisch"},
603 {0x080A,"Mexikanisches Spanisch"},
604 {0x080C,"Belgisches Franzvsisch"},
605 {0x0810,"Schweizerisches Italienisch"},
606 {0x0813,"Belgisches Niederldndisch"},
607 {0x0814,"Norgwegisch-Nynorsk"},
608 {0x0816,"Portugiesisch"},
609 {0x081A,"Serbokratisch (kyrillisch)"},
610 {0x0C1C,"Kanadisches Franzvsisch"},
611 {0x100C,"Schweizerisches Franzvsisch"},
612 {0x0000,"Unbekannt"},
615 /***********************************************************************
616 * GetUserDefaultLCID (OLE2NLS.1)
618 LCID WINAPI
GetUserDefaultLCID()
620 return MAKELCID( GetUserDefaultLangID() , SORT_DEFAULT
);
623 /***********************************************************************
624 * GetSystemDefaultLCID (OLE2NLS.2)
626 LCID WINAPI
GetSystemDefaultLCID()
628 return GetUserDefaultLCID();
631 /***********************************************************************
632 * GetUserDefaultLangID (OLE2NLS.3)
634 LANGID WINAPI
GetUserDefaultLangID()
636 /* caching result, if defined from environment, which should (?) not change during a WINE session */
637 static LANGID userLCID
= 0;
638 if (Options
.language
) {
639 return Languages
[Options
.language
].langid
;
644 char *lang
,*country
,*charset
,*dialect
,*next
;
647 buf
=getenv("LANGUAGE");
648 if (!buf
) buf
=getenv("LANG");
649 if (!buf
) buf
=getenv("LC_ALL");
650 if (!buf
) buf
=getenv("LC_MESSAGES");
651 if (!buf
) buf
=getenv("LC_CTYPE");
652 if (!buf
) return userLCID
= MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
);
654 if (!strcmp(buf
,"POSIX") || !strcmp(buf
,"C")) {
655 return MAKELANGID( LANG_ENGLISH
, SUBLANG_DEFAULT
);
661 next
=strchr(lang
,':'); if (next
) *next
++='\0';
662 dialect
=strchr(lang
,'@'); if (dialect
) *dialect
++='\0';
663 charset
=strchr(lang
,'.'); if (charset
) *charset
++='\0';
664 country
=strchr(lang
,'_'); if (country
) *country
++='\0';
666 ret
=MAIN_GetLanguageID(lang
, country
, charset
, dialect
);
670 } while (lang
&& !ret
);
672 /* FIXME : are strings returned by getenv() to be free()'ed ? */
673 userLCID
= (LANGID
)ret
;
678 /***********************************************************************
679 * GetSystemDefaultLangID (OLE2NLS.4)
681 LANGID WINAPI
GetSystemDefaultLangID()
683 return GetUserDefaultLangID();
686 /******************************************************************************
687 * GetLocaleInfo16 [OLE2NLS.5]
688 * Is the last parameter really WORD for Win16?
690 INT16 WINAPI
GetLocaleInfo16(LCID lcid
,LCTYPE LCType
,LPSTR buf
,INT16 len
)
692 return GetLocaleInfoA(lcid
,LCType
,buf
,len
);
694 /******************************************************************************
695 * ConvertDefaultLocale32 [KERNEL32.147]
697 LCID WINAPI
ConvertDefaultLocale32 (LCID lcid
)
699 { case LOCALE_SYSTEM_DEFAULT
:
700 return GetSystemDefaultLCID();
701 case LOCALE_USER_DEFAULT
:
702 return GetUserDefaultLCID();
704 return MAKELCID (LANG_NEUTRAL
, SUBLANG_NEUTRAL
);
706 return MAKELANGID( PRIMARYLANGID(lcid
), SUBLANG_NEUTRAL
);
708 /******************************************************************************
709 * GetLocaleInfo32A [KERNEL32.342]
712 * LANG_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
714 * MS online documentation states that the string returned is NULL terminated
715 * except for LOCALE_FONTSIGNATURE which "will return a non-NULL
716 * terminated string".
718 INT WINAPI
GetLocaleInfoA(LCID lcid
,LCTYPE LCType
,LPSTR buf
,INT len
)
724 TRACE("(lcid=0x%lx,lctype=0x%lx,%p,%x)\n",lcid
,LCType
,buf
,len
);
726 if (len
&& (! buf
) ) {
727 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
731 if (lcid
==0 || lcid
== LANG_SYSTEM_DEFAULT
|| (LCType
& LOCALE_NOUSEROVERRIDE
) ) /* 0x00, 0x400 */
733 lcid
= GetSystemDefaultLCID();
735 else if (lcid
== LANG_USER_DEFAULT
) /*0x800*/
737 lcid
= GetUserDefaultLCID();
739 LCType
&= ~(LOCALE_NOUSEROVERRIDE
|LOCALE_USE_CP_ACP
);
741 /* As an option, we could obtain the value from win.ini.
742 This would not match the Wine compile-time option.
743 Also, not all identifiers are available from win.ini */
745 /* If we are through all of this, retLen should not be zero anymore.
746 If it is, the value is not supported */
748 while (locale_name2id
[i
].name
!=NULL
) {
749 if (LCType
== locale_name2id
[i
].id
) {
750 retString
= locale_name2id
[i
].name
;
756 FIXME("Unkown LC type %lX\n",LCType
);
761 for (i
=0;(i
<3 && !found
);i
++) {
764 for (j
=0;j
<sizeof(langlocales
)/sizeof(langlocales
[0]);j
++) {
765 if (langlocales
[j
].lang
== lang
) {
768 for (k
=0;k
<sizeof(langlocales
[j
].locvars
)/sizeof(langlocales
[j
].locvars
[0]) && (langlocales
[j
].locvars
[k
].type
);k
++) {
769 if (langlocales
[j
].locvars
[k
].type
== LCType
) {
771 retString
= langlocales
[j
].locvars
[k
].val
;
779 /* language not found, try without a sublanguage*/
780 if (i
==1) lang
=MAKELANGID( PRIMARYLANGID(lang
), SUBLANG_DEFAULT
);
781 /* mask the LC Value */
782 if (i
==2) LCType
&= 0xfff;
786 ERR("'%s' not supported for your language (%04X).\n",
787 retString
,(WORD
)lcid
);
788 SetLastError(ERROR_INVALID_PARAMETER
);
791 /* a FONTSIGNATURE is not a string, just 6 DWORDs */
792 if (LCType
== LOCALE_FONTSIGNATURE
) {
794 memcpy(buf
, retString
, (len
<=sizeof(FONTSIGNATURE
))?len
:sizeof(FONTSIGNATURE
));
795 return sizeof(FONTSIGNATURE
);
797 /* if len=0 return only the length, don't touch the buffer*/
798 if (len
) lstrcpynA(buf
,retString
,len
);
799 return strlen(retString
)+1;
802 /******************************************************************************
803 * GetLocaleInfo32W [KERNEL32.343]
806 * MS documentation states that len "specifies the size, in bytes (ANSI version)
807 * or characters (Unicode version), of" wbuf. Thus the number returned is
808 * the same between GetLocaleInfo32W and GetLocaleInfo32A.
810 INT WINAPI
GetLocaleInfoW(LCID lcid
,LCTYPE LCType
,LPWSTR wbuf
,INT len
)
814 if (len
&& (! wbuf
) )
815 { SetLastError(ERROR_INSUFFICIENT_BUFFER
);
819 abuf
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,len
);
820 wlen
= GetLocaleInfoA(lcid
, LCType
, abuf
, len
);
822 if (wlen
&& len
) /* if len=0 return only the length*/
823 lstrcpynAtoW(wbuf
,abuf
,len
);
825 HeapFree(GetProcessHeap(),0,abuf
);
829 /******************************************************************************
830 * SetLocaleInfoA [KERNEL32.656]
832 BOOL16 WINAPI
SetLocaleInfoA(DWORD lcid
, DWORD lctype
, LPCSTR data
)
834 FIXME("(%ld,%ld,%s): stub\n",lcid
,lctype
,data
);
838 /******************************************************************************
839 * IsValidLocale [KERNEL32.489]
841 BOOL WINAPI
IsValidLocale(LCID lcid
,DWORD flags
)
843 /* we support ANY language. Well, at least say that...*/
847 /******************************************************************************
848 * EnumSystemLocales32W [KERNEL32.209]
850 BOOL WINAPI
EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum
,
858 TRACE_(win32
)("(%p,%08lx)\n",lpfnLocaleEnum
,flags
);
859 /* see if we can reuse the Win95 registry entries.... */
860 if (ERROR_SUCCESS
==RegOpenKeyA(HKEY_LOCAL_MACHINE
,"System\\CurrentControlSet\\control\\Nls\\Locale\\",&xhkey
)) {
863 if (ERROR_SUCCESS
!=RegEnumKeyW(xhkey
,i
,buffer
,sizeof(buffer
)))
865 if (!lpfnLocaleEnum(buffer
))
874 while (languages
[i
].langid
!=0)
879 sprintf(xbuffer
,"%08lx",(DWORD
)languages
[i
].langid
);
881 cp
= HEAP_strdupAtoW( GetProcessHeap(), 0, xbuffer
);
882 ret
= lpfnLocaleEnum(cp
);
883 HeapFree( GetProcessHeap(), 0, cp
);
890 /******************************************************************************
891 * EnumSystemLocales32A [KERNEL32.208]
893 BOOL WINAPI
EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum
,
900 TRACE_(win32
)("(%p,%08lx)\n",
904 if ( ERROR_SUCCESS
==RegOpenKeyA(HKEY_LOCAL_MACHINE
,
905 "System\\CurrentControlSet\\Control\\Nls\\Locale\\",
909 DWORD size
=sizeof(buffer
);
910 if (ERROR_SUCCESS
!=RegEnumValueA(xhkey
,i
,buffer
,&size
,NULL
,
913 if (size
&& !lpfnLocaleEnum(buffer
))
921 while (languages
[i
].langid
!=0) {
922 sprintf(buffer
,"%08lx",(DWORD
)languages
[i
].langid
);
923 if (!lpfnLocaleEnum(buffer
))
930 static const unsigned char CT_CType2_LUT
[] = {
931 C2_NOTAPPLICABLE
, /* - 0 */
932 C2_NOTAPPLICABLE
, /* - 1 */
933 C2_NOTAPPLICABLE
, /* - 2 */
934 C2_NOTAPPLICABLE
, /* - 3 */
935 C2_NOTAPPLICABLE
, /* - 4 */
936 C2_NOTAPPLICABLE
, /* - 5 */
937 C2_NOTAPPLICABLE
, /* - 6 */
938 C2_NOTAPPLICABLE
, /* - 7 */
939 C2_NOTAPPLICABLE
, /* - 8 */
940 C2_SEGMENTSEPARATOR
, /* - 9 */
941 C2_NOTAPPLICABLE
, /* - 10 */
942 C2_NOTAPPLICABLE
, /* - 11 */
943 C2_NOTAPPLICABLE
, /* - 12 */
944 C2_NOTAPPLICABLE
, /* - 13 */
945 C2_NOTAPPLICABLE
, /* - 14 */
946 C2_NOTAPPLICABLE
, /* - 15 */
947 C2_NOTAPPLICABLE
, /* - 16 */
948 C2_NOTAPPLICABLE
, /* - 17 */
949 C2_NOTAPPLICABLE
, /* - 18 */
950 C2_NOTAPPLICABLE
, /* - 19 */
951 C2_NOTAPPLICABLE
, /* - 20 */
952 C2_NOTAPPLICABLE
, /* - 21 */
953 C2_NOTAPPLICABLE
, /* - 22 */
954 C2_NOTAPPLICABLE
, /* - 23 */
955 C2_NOTAPPLICABLE
, /* - 24 */
956 C2_NOTAPPLICABLE
, /* - 25 */
957 C2_NOTAPPLICABLE
, /* - 26 */
958 C2_NOTAPPLICABLE
, /* - 27 */
959 C2_NOTAPPLICABLE
, /* - 28 */
960 C2_NOTAPPLICABLE
, /* - 29 */
961 C2_NOTAPPLICABLE
, /* - 30 */
962 C2_NOTAPPLICABLE
, /* - 31 */
963 C2_WHITESPACE
, /* - 32 */
964 C2_OTHERNEUTRAL
, /* ! - 33 */
965 C2_OTHERNEUTRAL
, /* " - 34 */ /* " */
966 C2_EUROPETERMINATOR
, /* # - 35 */
967 C2_EUROPETERMINATOR
, /* $ - 36 */
968 C2_EUROPETERMINATOR
, /* % - 37 */
969 C2_LEFTTORIGHT
, /* & - 38 */
970 C2_OTHERNEUTRAL
, /* ' - 39 */
971 C2_OTHERNEUTRAL
, /* ( - 40 */
972 C2_OTHERNEUTRAL
, /* ) - 41 */
973 C2_OTHERNEUTRAL
, /* * - 42 */
974 C2_EUROPETERMINATOR
, /* + - 43 */
975 C2_COMMONSEPARATOR
, /* , - 44 */
976 C2_EUROPETERMINATOR
, /* - - 45 */
977 C2_EUROPESEPARATOR
, /* . - 46 */
978 C2_EUROPESEPARATOR
, /* / - 47 */
979 C2_EUROPENUMBER
, /* 0 - 48 */
980 C2_EUROPENUMBER
, /* 1 - 49 */
981 C2_EUROPENUMBER
, /* 2 - 50 */
982 C2_EUROPENUMBER
, /* 3 - 51 */
983 C2_EUROPENUMBER
, /* 4 - 52 */
984 C2_EUROPENUMBER
, /* 5 - 53 */
985 C2_EUROPENUMBER
, /* 6 - 54 */
986 C2_EUROPENUMBER
, /* 7 - 55 */
987 C2_EUROPENUMBER
, /* 8 - 56 */
988 C2_EUROPENUMBER
, /* 9 - 57 */
989 C2_COMMONSEPARATOR
, /* : - 58 */
990 C2_OTHERNEUTRAL
, /* ; - 59 */
991 C2_OTHERNEUTRAL
, /* < - 60 */
992 C2_OTHERNEUTRAL
, /* = - 61 */
993 C2_OTHERNEUTRAL
, /* > - 62 */
994 C2_OTHERNEUTRAL
, /* ? - 63 */
995 C2_LEFTTORIGHT
, /* @ - 64 */
996 C2_LEFTTORIGHT
, /* A - 65 */
997 C2_LEFTTORIGHT
, /* B - 66 */
998 C2_LEFTTORIGHT
, /* C - 67 */
999 C2_LEFTTORIGHT
, /* D - 68 */
1000 C2_LEFTTORIGHT
, /* E - 69 */
1001 C2_LEFTTORIGHT
, /* F - 70 */
1002 C2_LEFTTORIGHT
, /* G - 71 */
1003 C2_LEFTTORIGHT
, /* H - 72 */
1004 C2_LEFTTORIGHT
, /* I - 73 */
1005 C2_LEFTTORIGHT
, /* J - 74 */
1006 C2_LEFTTORIGHT
, /* K - 75 */
1007 C2_LEFTTORIGHT
, /* L - 76 */
1008 C2_LEFTTORIGHT
, /* M - 77 */
1009 C2_LEFTTORIGHT
, /* N - 78 */
1010 C2_LEFTTORIGHT
, /* O - 79 */
1011 C2_LEFTTORIGHT
, /* P - 80 */
1012 C2_LEFTTORIGHT
, /* Q - 81 */
1013 C2_LEFTTORIGHT
, /* R - 82 */
1014 C2_LEFTTORIGHT
, /* S - 83 */
1015 C2_LEFTTORIGHT
, /* T - 84 */
1016 C2_LEFTTORIGHT
, /* U - 85 */
1017 C2_LEFTTORIGHT
, /* V - 86 */
1018 C2_LEFTTORIGHT
, /* W - 87 */
1019 C2_LEFTTORIGHT
, /* X - 88 */
1020 C2_LEFTTORIGHT
, /* Y - 89 */
1021 C2_LEFTTORIGHT
, /* Z - 90 */
1022 C2_OTHERNEUTRAL
, /* [ - 91 */
1023 C2_OTHERNEUTRAL
, /* \ - 92 */
1024 C2_OTHERNEUTRAL
, /* ] - 93 */
1025 C2_OTHERNEUTRAL
, /* ^ - 94 */
1026 C2_OTHERNEUTRAL
, /* _ - 95 */
1027 C2_OTHERNEUTRAL
, /* ` - 96 */
1028 C2_LEFTTORIGHT
, /* a - 97 */
1029 C2_LEFTTORIGHT
, /* b - 98 */
1030 C2_LEFTTORIGHT
, /* c - 99 */
1031 C2_LEFTTORIGHT
, /* d - 100 */
1032 C2_LEFTTORIGHT
, /* e - 101 */
1033 C2_LEFTTORIGHT
, /* f - 102 */
1034 C2_LEFTTORIGHT
, /* g - 103 */
1035 C2_LEFTTORIGHT
, /* h - 104 */
1036 C2_LEFTTORIGHT
, /* i - 105 */
1037 C2_LEFTTORIGHT
, /* j - 106 */
1038 C2_LEFTTORIGHT
, /* k - 107 */
1039 C2_LEFTTORIGHT
, /* l - 108 */
1040 C2_LEFTTORIGHT
, /* m - 109 */
1041 C2_LEFTTORIGHT
, /* n - 110 */
1042 C2_LEFTTORIGHT
, /* o - 111 */
1043 C2_LEFTTORIGHT
, /* p - 112 */
1044 C2_LEFTTORIGHT
, /* q - 113 */
1045 C2_LEFTTORIGHT
, /* r - 114 */
1046 C2_LEFTTORIGHT
, /* s - 115 */
1047 C2_LEFTTORIGHT
, /* t - 116 */
1048 C2_LEFTTORIGHT
, /* u - 117 */
1049 C2_LEFTTORIGHT
, /* v - 118 */
1050 C2_LEFTTORIGHT
, /* w - 119 */
1051 C2_LEFTTORIGHT
, /* x - 120 */
1052 C2_LEFTTORIGHT
, /* y - 121 */
1053 C2_LEFTTORIGHT
, /* z - 122 */
1054 C2_OTHERNEUTRAL
, /* { - 123 */
1055 C2_OTHERNEUTRAL
, /* | - 124 */
1056 C2_OTHERNEUTRAL
, /* } - 125 */
1057 C2_OTHERNEUTRAL
, /* ~ - 126 */
1058 C2_NOTAPPLICABLE
, /* \x7f - 127 */
1059 C2_NOTAPPLICABLE
, /* € - 128 */
1060 C2_NOTAPPLICABLE
, /* � - 129 */
1061 C2_OTHERNEUTRAL
, /* ‚ - 130 */
1062 C2_LEFTTORIGHT
, /* ƒ - 131 */
1063 C2_OTHERNEUTRAL
, /* „ - 132 */
1064 C2_OTHERNEUTRAL
, /* … - 133 */
1065 C2_OTHERNEUTRAL
, /* † - 134 */
1066 C2_OTHERNEUTRAL
, /* ‡ - 135 */
1067 C2_LEFTTORIGHT
, /* ˆ - 136 */
1068 C2_EUROPETERMINATOR
, /* ‰ - 137 */
1069 C2_LEFTTORIGHT
, /* Š - 138 */
1070 C2_OTHERNEUTRAL
, /* ‹ - 139 */
1071 C2_LEFTTORIGHT
, /* Œ - 140 */
1072 C2_NOTAPPLICABLE
, /* � - 141 */
1073 C2_NOTAPPLICABLE
, /* Ž - 142 */
1074 C2_NOTAPPLICABLE
, /* � - 143 */
1075 C2_NOTAPPLICABLE
, /* � - 144 */
1076 C2_OTHERNEUTRAL
, /* ‘ - 145 */
1077 C2_OTHERNEUTRAL
, /* ’ - 146 */
1078 C2_OTHERNEUTRAL
, /* “ - 147 */
1079 C2_OTHERNEUTRAL
, /* ” - 148 */
1080 C2_OTHERNEUTRAL
, /* • - 149 */
1081 C2_OTHERNEUTRAL
, /* – - 150 */
1082 C2_OTHERNEUTRAL
, /* — - 151 */
1083 C2_LEFTTORIGHT
, /* ˜ - 152 */
1084 C2_OTHERNEUTRAL
, /* ™ - 153 */
1085 C2_LEFTTORIGHT
, /* š - 154 */
1086 C2_OTHERNEUTRAL
, /* › - 155 */
1087 C2_LEFTTORIGHT
, /* œ - 156 */
1088 C2_NOTAPPLICABLE
, /* � - 157 */
1089 C2_NOTAPPLICABLE
, /* ž - 158 */
1090 C2_LEFTTORIGHT
, /* Ÿ - 159 */
1091 C2_WHITESPACE
, /* - 160 */
1092 C2_OTHERNEUTRAL
, /* ¡ - 161 */
1093 C2_EUROPETERMINATOR
, /* ¢ - 162 */
1094 C2_EUROPETERMINATOR
, /* £ - 163 */
1095 C2_EUROPETERMINATOR
, /* ¤ - 164 */
1096 C2_EUROPETERMINATOR
, /* ¥ - 165 */
1097 C2_OTHERNEUTRAL
, /* ¦ - 166 */
1098 C2_OTHERNEUTRAL
, /* § - 167 */
1099 C2_OTHERNEUTRAL
, /* ¨ - 168 */
1100 C2_OTHERNEUTRAL
, /* © - 169 */
1101 C2_OTHERNEUTRAL
, /* ª - 170 */
1102 C2_OTHERNEUTRAL
, /* « - 171 */
1103 C2_OTHERNEUTRAL
, /* ¬ - 172 */
1104 C2_OTHERNEUTRAL
, /* - 173 */
1105 C2_OTHERNEUTRAL
, /* ® - 174 */
1106 C2_OTHERNEUTRAL
, /* ¯ - 175 */
1107 C2_EUROPETERMINATOR
, /* ° - 176 */
1108 C2_EUROPETERMINATOR
, /* ± - 177 */
1109 C2_EUROPENUMBER
, /* ² - 178 */
1110 C2_EUROPENUMBER
, /* ³ - 179 */
1111 C2_OTHERNEUTRAL
, /* ´ - 180 */
1112 C2_OTHERNEUTRAL
, /* µ - 181 */
1113 C2_OTHERNEUTRAL
, /* ¶ - 182 */
1114 C2_OTHERNEUTRAL
, /* · - 183 */
1115 C2_OTHERNEUTRAL
, /* ¸ - 184 */
1116 C2_EUROPENUMBER
, /* ¹ - 185 */
1117 C2_OTHERNEUTRAL
, /* º - 186 */
1118 C2_OTHERNEUTRAL
, /* » - 187 */
1119 C2_OTHERNEUTRAL
, /* ¼ - 188 */
1120 C2_OTHERNEUTRAL
, /* ½ - 189 */
1121 C2_OTHERNEUTRAL
, /* ¾ - 190 */
1122 C2_OTHERNEUTRAL
, /* ¿ - 191 */
1123 C2_LEFTTORIGHT
, /* À - 192 */
1124 C2_LEFTTORIGHT
, /* Á - 193 */
1125 C2_LEFTTORIGHT
, /* Â - 194 */
1126 C2_LEFTTORIGHT
, /* Ã - 195 */
1127 C2_LEFTTORIGHT
, /* Ä - 196 */
1128 C2_LEFTTORIGHT
, /* Å - 197 */
1129 C2_LEFTTORIGHT
, /* Æ - 198 */
1130 C2_LEFTTORIGHT
, /* Ç - 199 */
1131 C2_LEFTTORIGHT
, /* È - 200 */
1132 C2_LEFTTORIGHT
, /* É - 201 */
1133 C2_LEFTTORIGHT
, /* Ê - 202 */
1134 C2_LEFTTORIGHT
, /* Ë - 203 */
1135 C2_LEFTTORIGHT
, /* Ì - 204 */
1136 C2_LEFTTORIGHT
, /* Í - 205 */
1137 C2_LEFTTORIGHT
, /* Î - 206 */
1138 C2_LEFTTORIGHT
, /* Ï - 207 */
1139 C2_LEFTTORIGHT
, /* Ð - 208 */
1140 C2_LEFTTORIGHT
, /* Ñ - 209 */
1141 C2_LEFTTORIGHT
, /* Ò - 210 */
1142 C2_LEFTTORIGHT
, /* Ó - 211 */
1143 C2_LEFTTORIGHT
, /* Ô - 212 */
1144 C2_LEFTTORIGHT
, /* Õ - 213 */
1145 C2_LEFTTORIGHT
, /* Ö - 214 */
1146 C2_OTHERNEUTRAL
, /* × - 215 */
1147 C2_LEFTTORIGHT
, /* Ø - 216 */
1148 C2_LEFTTORIGHT
, /* Ù - 217 */
1149 C2_LEFTTORIGHT
, /* Ú - 218 */
1150 C2_LEFTTORIGHT
, /* Û - 219 */
1151 C2_LEFTTORIGHT
, /* Ü - 220 */
1152 C2_LEFTTORIGHT
, /* Ý - 221 */
1153 C2_LEFTTORIGHT
, /* Þ - 222 */
1154 C2_LEFTTORIGHT
, /* ß - 223 */
1155 C2_LEFTTORIGHT
, /* à - 224 */
1156 C2_LEFTTORIGHT
, /* á - 225 */
1157 C2_LEFTTORIGHT
, /* â - 226 */
1158 C2_LEFTTORIGHT
, /* ã - 227 */
1159 C2_LEFTTORIGHT
, /* ä - 228 */
1160 C2_LEFTTORIGHT
, /* å - 229 */
1161 C2_LEFTTORIGHT
, /* æ - 230 */
1162 C2_LEFTTORIGHT
, /* ç - 231 */
1163 C2_LEFTTORIGHT
, /* è - 232 */
1164 C2_LEFTTORIGHT
, /* é - 233 */
1165 C2_LEFTTORIGHT
, /* ê - 234 */
1166 C2_LEFTTORIGHT
, /* ë - 235 */
1167 C2_LEFTTORIGHT
, /* ì - 236 */
1168 C2_LEFTTORIGHT
, /* í - 237 */
1169 C2_LEFTTORIGHT
, /* î - 238 */
1170 C2_LEFTTORIGHT
, /* ï - 239 */
1171 C2_LEFTTORIGHT
, /* ð - 240 */
1172 C2_LEFTTORIGHT
, /* ñ - 241 */
1173 C2_LEFTTORIGHT
, /* ò - 242 */
1174 C2_LEFTTORIGHT
, /* ó - 243 */
1175 C2_LEFTTORIGHT
, /* ô - 244 */
1176 C2_LEFTTORIGHT
, /* õ - 245 */
1177 C2_LEFTTORIGHT
, /* ö - 246 */
1178 C2_OTHERNEUTRAL
, /* ÷ - 247 */
1179 C2_LEFTTORIGHT
, /* ø - 248 */
1180 C2_LEFTTORIGHT
, /* ù - 249 */
1181 C2_LEFTTORIGHT
, /* ú - 250 */
1182 C2_LEFTTORIGHT
, /* û - 251 */
1183 C2_LEFTTORIGHT
, /* ü - 252 */
1184 C2_LEFTTORIGHT
, /* ý - 253 */
1185 C2_LEFTTORIGHT
, /* þ - 254 */
1186 C2_LEFTTORIGHT
/* ÿ - 255 */
1189 const WORD OLE2NLS_CT_CType3_LUT
[] = {
1223 0x0048, /* ! - 33 */
1224 0x0448, /* " - 34 */ /* " */
1225 0x0048, /* # - 35 */
1226 0x0448, /* $ - 36 */
1227 0x0048, /* % - 37 */
1228 0x0048, /* & - 38 */
1229 0x0440, /* ' - 39 */
1230 0x0048, /* ( - 40 */
1231 0x0048, /* ) - 41 */
1232 0x0048, /* * - 42 */
1233 0x0048, /* + - 43 */
1234 0x0048, /* , - 44 */
1235 0x0440, /* - - 45 */
1236 0x0048, /* . - 46 */
1237 0x0448, /* / - 47 */
1238 0x0040, /* 0 - 48 */
1239 0x0040, /* 1 - 49 */
1240 0x0040, /* 2 - 50 */
1241 0x0040, /* 3 - 51 */
1242 0x0040, /* 4 - 52 */
1243 0x0040, /* 5 - 53 */
1244 0x0040, /* 6 - 54 */
1245 0x0040, /* 7 - 55 */
1246 0x0040, /* 8 - 56 */
1247 0x0040, /* 9 - 57 */
1248 0x0048, /* : - 58 */
1249 0x0048, /* ; - 59 */
1250 0x0048, /* < - 60 */
1251 0x0448, /* = - 61 */
1252 0x0048, /* > - 62 */
1253 0x0048, /* ? - 63 */
1254 0x0448, /* @ - 64 */
1255 0x8040, /* A - 65 */
1256 0x8040, /* B - 66 */
1257 0x8040, /* C - 67 */
1258 0x8040, /* D - 68 */
1259 0x8040, /* E - 69 */
1260 0x8040, /* F - 70 */
1261 0x8040, /* G - 71 */
1262 0x8040, /* H - 72 */
1263 0x8040, /* I - 73 */
1264 0x8040, /* J - 74 */
1265 0x8040, /* K - 75 */
1266 0x8040, /* L - 76 */
1267 0x8040, /* M - 77 */
1268 0x8040, /* N - 78 */
1269 0x8040, /* O - 79 */
1270 0x8040, /* P - 80 */
1271 0x8040, /* Q - 81 */
1272 0x8040, /* R - 82 */
1273 0x8040, /* S - 83 */
1274 0x8040, /* T - 84 */
1275 0x8040, /* U - 85 */
1276 0x8040, /* V - 86 */
1277 0x8040, /* W - 87 */
1278 0x8040, /* X - 88 */
1279 0x8040, /* Y - 89 */
1280 0x8040, /* Z - 90 */
1281 0x0048, /* [ - 91 */
1282 0x0448, /* \ - 92 */
1283 0x0048, /* ] - 93 */
1284 0x0448, /* ^ - 94 */
1285 0x0448, /* _ - 95 */
1286 0x0448, /* ` - 96 */
1287 0x8040, /* a - 97 */
1288 0x8040, /* b - 98 */
1289 0x8040, /* c - 99 */
1290 0x8040, /* d - 100 */
1291 0x8040, /* e - 101 */
1292 0x8040, /* f - 102 */
1293 0x8040, /* g - 103 */
1294 0x8040, /* h - 104 */
1295 0x8040, /* i - 105 */
1296 0x8040, /* j - 106 */
1297 0x8040, /* k - 107 */
1298 0x8040, /* l - 108 */
1299 0x8040, /* m - 109 */
1300 0x8040, /* n - 110 */
1301 0x8040, /* o - 111 */
1302 0x8040, /* p - 112 */
1303 0x8040, /* q - 113 */
1304 0x8040, /* r - 114 */
1305 0x8040, /* s - 115 */
1306 0x8040, /* t - 116 */
1307 0x8040, /* u - 117 */
1308 0x8040, /* v - 118 */
1309 0x8040, /* w - 119 */
1310 0x8040, /* x - 120 */
1311 0x8040, /* y - 121 */
1312 0x8040, /* z - 122 */
1313 0x0048, /* { - 123 */
1314 0x0048, /* | - 124 */
1315 0x0048, /* } - 125 */
1316 0x0448, /* ~ - 126 */
1317 0x0000, /* \x7f - 127 */
1318 0x0000, /* € - 128 */
1319 0x0000, /* � - 129 */
1320 0x0008, /* ‚ - 130 */
1321 0x8000, /* ƒ - 131 */
1322 0x0008, /* „ - 132 */
1323 0x0008, /* … - 133 */
1324 0x0008, /* † - 134 */
1325 0x0008, /* ‡ - 135 */
1326 0x0001, /* ˆ - 136 */
1327 0x0008, /* ‰ - 137 */
1328 0x8003, /* Š - 138 */
1329 0x0008, /* ‹ - 139 */
1330 0x8000, /* Œ - 140 */
1331 0x0000, /* � - 141 */
1332 0x0000, /* Ž - 142 */
1333 0x0000, /* � - 143 */
1334 0x0000, /* � - 144 */
1335 0x0088, /* ‘ - 145 */
1336 0x0088, /* ’ - 146 */
1337 0x0088, /* “ - 147 */
1338 0x0088, /* ” - 148 */
1339 0x0008, /* • - 149 */
1340 0x0400, /* – - 150 */
1341 0x0400, /* — - 151 */
1342 0x0408, /* ˜ - 152 */
1343 0x0000, /* ™ - 153 */
1344 0x8003, /* š - 154 */
1345 0x0008, /* › - 155 */
1346 0x8000, /* œ - 156 */
1347 0x0000, /* � - 157 */
1348 0x0000, /* ž - 158 */
1349 0x8003, /* Ÿ - 159 */
1351 0x0008, /* ¡ - 161 */
1352 0x0048, /* ¢ - 162 */
1353 0x0048, /* £ - 163 */
1354 0x0008, /* ¤ - 164 */
1355 0x0048, /* ¥ - 165 */
1356 0x0048, /* ¦ - 166 */
1357 0x0008, /* § - 167 */
1358 0x0408, /* ¨ - 168 */
1359 0x0008, /* © - 169 */
1360 0x0400, /* ª - 170 */
1361 0x0008, /* « - 171 */
1362 0x0048, /* ¬ - 172 */
1363 0x0408, /* - 173 */
1364 0x0008, /* ® - 174 */
1365 0x0448, /* ¯ - 175 */
1366 0x0008, /* ° - 176 */
1367 0x0008, /* ± - 177 */
1368 0x0000, /* ² - 178 */
1369 0x0000, /* ³ - 179 */
1370 0x0408, /* ´ - 180 */
1371 0x0008, /* µ - 181 */
1372 0x0008, /* ¶ - 182 */
1373 0x0008, /* · - 183 */
1374 0x0408, /* ¸ - 184 */
1375 0x0000, /* ¹ - 185 */
1376 0x0400, /* º - 186 */
1377 0x0008, /* » - 187 */
1378 0x0000, /* ¼ - 188 */
1379 0x0000, /* ½ - 189 */
1380 0x0000, /* ¾ - 190 */
1381 0x0008, /* ¿ - 191 */
1382 0x8003, /* À - 192 */
1383 0x8003, /* Á - 193 */
1384 0x8003, /* Â - 194 */
1385 0x8003, /* Ã - 195 */
1386 0x8003, /* Ä - 196 */
1387 0x8003, /* Å - 197 */
1388 0x8000, /* Æ - 198 */
1389 0x8003, /* Ç - 199 */
1390 0x8003, /* È - 200 */
1391 0x8003, /* É - 201 */
1392 0x8003, /* Ê - 202 */
1393 0x8003, /* Ë - 203 */
1394 0x8003, /* Ì - 204 */
1395 0x8003, /* Í - 205 */
1396 0x8003, /* Î - 206 */
1397 0x8003, /* Ï - 207 */
1398 0x8000, /* Ð - 208 */
1399 0x8003, /* Ñ - 209 */
1400 0x8003, /* Ò - 210 */
1401 0x8003, /* Ó - 211 */
1402 0x8003, /* Ô - 212 */
1403 0x8003, /* Õ - 213 */
1404 0x8003, /* Ö - 214 */
1405 0x0008, /* × - 215 */
1406 0x8003, /* Ø - 216 */
1407 0x8003, /* Ù - 217 */
1408 0x8003, /* Ú - 218 */
1409 0x8003, /* Û - 219 */
1410 0x8003, /* Ü - 220 */
1411 0x8003, /* Ý - 221 */
1412 0x8000, /* Þ - 222 */
1413 0x8000, /* ß - 223 */
1414 0x8003, /* à - 224 */
1415 0x8003, /* á - 225 */
1416 0x8003, /* â - 226 */
1417 0x8003, /* ã - 227 */
1418 0x8003, /* ä - 228 */
1419 0x8003, /* å - 229 */
1420 0x8000, /* æ - 230 */
1421 0x8003, /* ç - 231 */
1422 0x8003, /* è - 232 */
1423 0x8003, /* é - 233 */
1424 0x8003, /* ê - 234 */
1425 0x8003, /* ë - 235 */
1426 0x8003, /* ì - 236 */
1427 0x8003, /* í - 237 */
1428 0x8003, /* î - 238 */
1429 0x8003, /* ï - 239 */
1430 0x8000, /* ð - 240 */
1431 0x8003, /* ñ - 241 */
1432 0x8003, /* ò - 242 */
1433 0x8003, /* ó - 243 */
1434 0x8003, /* ô - 244 */
1435 0x8003, /* õ - 245 */
1436 0x8003, /* ö - 246 */
1437 0x0008, /* ÷ - 247 */
1438 0x8003, /* ø - 248 */
1439 0x8003, /* ù - 249 */
1440 0x8003, /* ú - 250 */
1441 0x8003, /* û - 251 */
1442 0x8003, /* ü - 252 */
1443 0x8003, /* ý - 253 */
1444 0x8000, /* þ - 254 */
1445 0x8003 /* ÿ - 255 */
1448 /******************************************************************************
1449 * GetStringType16 [OLE2NLS.7]
1451 BOOL16 WINAPI
GetStringType16(LCID locale
,DWORD dwInfoType
,LPCSTR src
,
1452 INT16 cchSrc
,LPWORD chartype
)
1454 return GetStringTypeExA(locale
,dwInfoType
,src
,cchSrc
,chartype
);
1456 /******************************************************************************
1457 * GetStringType32A [KERNEL32.396]
1459 BOOL WINAPI
GetStringTypeA(LCID locale
,DWORD dwInfoType
,LPCSTR src
,
1460 INT cchSrc
,LPWORD chartype
)
1462 return GetStringTypeExA(locale
,dwInfoType
,src
,cchSrc
,chartype
);
1465 /******************************************************************************
1466 * GetStringTypeEx32A [KERNEL32.397]
1468 * FIXME: Ignores the locale.
1470 BOOL WINAPI
GetStringTypeExA(LCID locale
,DWORD dwInfoType
,LPCSTR src
,
1471 INT cchSrc
,LPWORD chartype
)
1475 if ((src
==NULL
) || (chartype
==NULL
) || (src
==(LPSTR
)chartype
))
1477 SetLastError(ERROR_INVALID_PARAMETER
);
1482 cchSrc
=lstrlenA(src
)+1;
1484 switch (dwInfoType
) {
1486 for (i
=0;i
<cchSrc
;i
++)
1489 if (isdigit(src
[i
])) chartype
[i
]|=C1_DIGIT
;
1490 if (isalpha(src
[i
])) chartype
[i
]|=C1_ALPHA
;
1491 if (islower(src
[i
])) chartype
[i
]|=C1_LOWER
;
1492 if (isupper(src
[i
])) chartype
[i
]|=C1_UPPER
;
1493 if (isspace(src
[i
])) chartype
[i
]|=C1_SPACE
;
1494 if (ispunct(src
[i
])) chartype
[i
]|=C1_PUNCT
;
1495 if (iscntrl(src
[i
])) chartype
[i
]|=C1_CNTRL
;
1496 /* FIXME: isblank() is a GNU extension */
1497 /* if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1498 if ((src
[i
] == ' ') || (src
[i
] == '\t')) chartype
[i
]|=C1_BLANK
;
1504 for (i
=0;i
<cchSrc
;i
++)
1506 chartype
[i
]=(WORD
)CT_CType2_LUT
[i
];
1511 for (i
=0;i
<cchSrc
;i
++)
1513 chartype
[i
]=OLE2NLS_CT_CType3_LUT
[i
];
1518 ERR("Unknown dwInfoType:%ld\n",dwInfoType
);
1523 /******************************************************************************
1524 * GetStringType32W [KERNEL32.399]
1527 * Yes, this is missing LCID locale. MS fault.
1529 BOOL WINAPI
GetStringTypeW(DWORD dwInfoType
,LPCWSTR src
,INT cchSrc
,
1532 return GetStringTypeExW(0/*defaultlocale*/,dwInfoType
,src
,cchSrc
,chartype
);
1535 /******************************************************************************
1536 * GetStringTypeEx32W [KERNEL32.398]
1538 * FIXME: unicode chars are assumed chars
1540 BOOL WINAPI
GetStringTypeExW(LCID locale
,DWORD dwInfoType
,LPCWSTR src
,
1541 INT cchSrc
,LPWORD chartype
)
1547 cchSrc
=lstrlenW(src
)+1;
1549 switch (dwInfoType
) {
1551 FIXME("CT_CTYPE2 not supported.\n");
1554 FIXME("CT_CTYPE3 not supported.\n");
1558 for (i
=0;i
<cchSrc
;i
++) {
1560 if (isdigit(src
[i
])) chartype
[i
]|=C1_DIGIT
;
1561 if (isalpha(src
[i
])) chartype
[i
]|=C1_ALPHA
;
1562 if (islower(src
[i
])) chartype
[i
]|=C1_LOWER
;
1563 if (isupper(src
[i
])) chartype
[i
]|=C1_UPPER
;
1564 if (isspace(src
[i
])) chartype
[i
]|=C1_SPACE
;
1565 if (ispunct(src
[i
])) chartype
[i
]|=C1_PUNCT
;
1566 if (iscntrl(src
[i
])) chartype
[i
]|=C1_CNTRL
;
1567 /* FIXME: isblank() is a GNU extension */
1568 /* if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1569 if ((src
[i
] == ' ') || (src
[i
] == '\t')) chartype
[i
]|=C1_BLANK
;
1575 /*****************************************************************
1576 * WINE_GetLanguageName [internal]
1578 static LPCSTR
WINE_GetLanguageName( UINT langid
)
1581 for ( i
= 0; languages
[i
].langid
!= 0; i
++ )
1582 if ( langid
== languages
[i
].langid
)
1585 return languages
[i
].langname
;
1588 /***********************************************************************
1589 * VerLanguageNameA [KERNEL32.709][VERSION.9]
1591 DWORD WINAPI
VerLanguageNameA( UINT wLang
, LPSTR szLang
, UINT nSize
)
1598 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1599 * from the registry.
1603 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1606 result
= RegQueryValueA( HKEY_LOCAL_MACHINE
, buffer
, szLang
, (LPDWORD
)&nSize
);
1607 if ( result
== ERROR_SUCCESS
|| result
== ERROR_MORE_DATA
)
1611 * If that fails, use the internal table
1614 name
= WINE_GetLanguageName( wLang
);
1615 lstrcpynA( szLang
, name
, nSize
);
1616 return lstrlenA( name
);
1619 /***********************************************************************
1620 * VerLanguageNameW [KERNEL32.710][VERSION.10]
1622 DWORD WINAPI
VerLanguageNameW( UINT wLang
, LPWSTR szLang
, UINT nSize
)
1630 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1631 * from the registry.
1635 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1638 keyname
= HEAP_strdupAtoW( GetProcessHeap(), 0, buffer
);
1639 result
= RegQueryValueW( HKEY_LOCAL_MACHINE
, keyname
, szLang
, (LPDWORD
)&nSize
);
1640 HeapFree( GetProcessHeap(), 0, keyname
);
1642 if ( result
== ERROR_SUCCESS
|| result
== ERROR_MORE_DATA
)
1646 * If that fails, use the internal table
1649 name
= WINE_GetLanguageName( wLang
);
1650 lstrcpynAtoW( szLang
, name
, nSize
);
1651 return lstrlenA( name
);
1655 static const unsigned char LCM_Unicode_LUT
[] = {
1688 7 , 28, /* ! - 33 */
1689 7 , 29, /* " - 34 */ /* " */
1690 7 , 31, /* # - 35 */
1691 7 , 33, /* $ - 36 */
1692 7 , 35, /* % - 37 */
1693 7 , 37, /* & - 38 */
1694 6 , 128, /* ' - 39 */
1695 7 , 39, /* ( - 40 */
1696 7 , 42, /* ) - 41 */
1697 7 , 45, /* * - 42 */
1699 7 , 47, /* , - 44 */
1700 6 , 130, /* - - 45 */
1701 7 , 51, /* . - 46 */
1702 7 , 53, /* / - 47 */
1703 12 , 3, /* 0 - 48 */
1704 12 , 33, /* 1 - 49 */
1705 12 , 51, /* 2 - 50 */
1706 12 , 70, /* 3 - 51 */
1707 12 , 88, /* 4 - 52 */
1708 12 , 106, /* 5 - 53 */
1709 12 , 125, /* 6 - 54 */
1710 12 , 144, /* 7 - 55 */
1711 12 , 162, /* 8 - 56 */
1712 12 , 180, /* 9 - 57 */
1713 7 , 55, /* : - 58 */
1714 7 , 58, /* ; - 59 */
1715 8 , 14, /* < - 60 */
1716 8 , 18, /* = - 61 */
1717 8 , 20, /* > - 62 */
1718 7 , 60, /* ? - 63 */
1719 7 , 62, /* @ - 64 */
1720 14 , 2, /* A - 65 */
1721 14 , 9, /* B - 66 */
1722 14 , 10, /* C - 67 */
1723 14 , 26, /* D - 68 */
1724 14 , 33, /* E - 69 */
1725 14 , 35, /* F - 70 */
1726 14 , 37, /* G - 71 */
1727 14 , 44, /* H - 72 */
1728 14 , 50, /* I - 73 */
1729 14 , 53, /* J - 74 */
1730 14 , 54, /* K - 75 */
1731 14 , 72, /* L - 76 */
1732 14 , 81, /* M - 77 */
1733 14 , 112, /* N - 78 */
1734 14 , 124, /* O - 79 */
1735 14 , 126, /* P - 80 */
1736 14 , 137, /* Q - 81 */
1737 14 , 138, /* R - 82 */
1738 14 , 145, /* S - 83 */
1739 14 , 153, /* T - 84 */
1740 14 , 159, /* U - 85 */
1741 14 , 162, /* V - 86 */
1742 14 , 164, /* W - 87 */
1743 14 , 166, /* X - 88 */
1744 14 , 167, /* Y - 89 */
1745 14 , 169, /* Z - 90 */
1746 7 , 63, /* [ - 91 */
1747 7 , 65, /* \ - 92 */
1748 7 , 66, /* ] - 93 */
1749 7 , 67, /* ^ - 94 */
1750 7 , 68, /* _ - 95 */
1751 7 , 72, /* ` - 96 */
1752 14 , 2, /* a - 97 */
1753 14 , 9, /* b - 98 */
1754 14 , 10, /* c - 99 */
1755 14 , 26, /* d - 100 */
1756 14 , 33, /* e - 101 */
1757 14 , 35, /* f - 102 */
1758 14 , 37, /* g - 103 */
1759 14 , 44, /* h - 104 */
1760 14 , 50, /* i - 105 */
1761 14 , 53, /* j - 106 */
1762 14 , 54, /* k - 107 */
1763 14 , 72, /* l - 108 */
1764 14 , 81, /* m - 109 */
1765 14 , 112, /* n - 110 */
1766 14 , 124, /* o - 111 */
1767 14 , 126, /* p - 112 */
1768 14 , 137, /* q - 113 */
1769 14 , 138, /* r - 114 */
1770 14 , 145, /* s - 115 */
1771 14 , 153, /* t - 116 */
1772 14 , 159, /* u - 117 */
1773 14 , 162, /* v - 118 */
1774 14 , 164, /* w - 119 */
1775 14 , 166, /* x - 120 */
1776 14 , 167, /* y - 121 */
1777 14 , 169, /* z - 122 */
1778 7 , 74, /* { - 123 */
1779 7 , 76, /* | - 124 */
1780 7 , 78, /* } - 125 */
1781 7 , 80, /* ~ - 126 */
1782 6 , 29, /* \x7f - 127 */
1783 6 , 30, /* € - 128 */
1784 6 , 31, /* � - 129 */
1785 7 , 123, /* ‚ - 130 */
1786 14 , 35, /* ƒ - 131 */
1787 7 , 127, /* „ - 132 */
1788 10 , 21, /* … - 133 */
1789 10 , 15, /* † - 134 */
1790 10 , 16, /* ‡ - 135 */
1791 7 , 67, /* ˆ - 136 */
1792 10 , 22, /* ‰ - 137 */
1793 14 , 145, /* Š - 138 */
1794 7 , 136, /* ‹ - 139 */
1795 14 + 16 , 124, /* Œ - 140 */
1796 6 , 43, /* � - 141 */
1797 6 , 44, /* Ž - 142 */
1798 6 , 45, /* � - 143 */
1799 6 , 46, /* � - 144 */
1800 7 , 121, /* ‘ - 145 */
1801 7 , 122, /* ’ - 146 */
1802 7 , 125, /* “ - 147 */
1803 7 , 126, /* ” - 148 */
1804 10 , 17, /* • - 149 */
1805 6 , 137, /* – - 150 */
1806 6 , 139, /* — - 151 */
1807 7 , 93, /* ˜ - 152 */
1808 14 , 156, /* ™ - 153 */
1809 14 , 145, /* š - 154 */
1810 7 , 137, /* › - 155 */
1811 14 + 16 , 124, /* œ - 156 */
1812 6 , 59, /* � - 157 */
1813 6 , 60, /* ž - 158 */
1814 14 , 167, /* Ÿ - 159 */
1816 7 , 81, /* ¡ - 161 */
1817 10 , 2, /* ¢ - 162 */
1818 10 , 3, /* £ - 163 */
1819 10 , 4, /* ¤ - 164 */
1820 10 , 5, /* ¥ - 165 */
1821 7 , 82, /* ¦ - 166 */
1822 10 , 6, /* § - 167 */
1823 7 , 83, /* ¨ - 168 */
1824 10 , 7, /* © - 169 */
1825 14 , 2, /* ª - 170 */
1826 8 , 24, /* « - 171 */
1827 10 , 8, /* ¬ - 172 */
1828 6 , 131, /* - 173 */
1829 10 , 9, /* ® - 174 */
1830 7 , 84, /* ¯ - 175 */
1831 10 , 10, /* ° - 176 */
1832 8 , 23, /* ± - 177 */
1833 12 , 51, /* ² - 178 */
1834 12 , 70, /* ³ - 179 */
1835 7 , 85, /* ´ - 180 */
1836 10 , 11, /* µ - 181 */
1837 10 , 12, /* ¶ - 182 */
1838 10 , 13, /* · - 183 */
1839 7 , 86, /* ¸ - 184 */
1840 12 , 33, /* ¹ - 185 */
1841 14 , 124, /* º - 186 */
1842 8 , 26, /* » - 187 */
1843 12 , 21, /* ¼ - 188 */
1844 12 , 25, /* ½ - 189 */
1845 12 , 29, /* ¾ - 190 */
1846 7 , 87, /* ¿ - 191 */
1847 14 , 2, /* À - 192 */
1848 14 , 2, /* Á - 193 */
1849 14 , 2, /* Â - 194 */
1850 14 , 2, /* Ã - 195 */
1851 14 , 2, /* Ä - 196 */
1852 14 , 2, /* Å - 197 */
1853 14 + 16 , 2, /* Æ - 198 */
1854 14 , 10, /* Ç - 199 */
1855 14 , 33, /* È - 200 */
1856 14 , 33, /* É - 201 */
1857 14 , 33, /* Ê - 202 */
1858 14 , 33, /* Ë - 203 */
1859 14 , 50, /* Ì - 204 */
1860 14 , 50, /* Í - 205 */
1861 14 , 50, /* Î - 206 */
1862 14 , 50, /* Ï - 207 */
1863 14 , 26, /* Ð - 208 */
1864 14 , 112, /* Ñ - 209 */
1865 14 , 124, /* Ò - 210 */
1866 14 , 124, /* Ó - 211 */
1867 14 , 124, /* Ô - 212 */
1868 14 , 124, /* Õ - 213 */
1869 14 , 124, /* Ö - 214 */
1870 8 , 28, /* × - 215 */
1871 14 , 124, /* Ø - 216 */
1872 14 , 159, /* Ù - 217 */
1873 14 , 159, /* Ú - 218 */
1874 14 , 159, /* Û - 219 */
1875 14 , 159, /* Ü - 220 */
1876 14 , 167, /* Ý - 221 */
1877 14 + 32 , 153, /* Þ - 222 */
1878 14 + 48 , 145, /* ß - 223 */
1879 14 , 2, /* à - 224 */
1880 14 , 2, /* á - 225 */
1881 14 , 2, /* â - 226 */
1882 14 , 2, /* ã - 227 */
1883 14 , 2, /* ä - 228 */
1884 14 , 2, /* å - 229 */
1885 14 + 16 , 2, /* æ - 230 */
1886 14 , 10, /* ç - 231 */
1887 14 , 33, /* è - 232 */
1888 14 , 33, /* é - 233 */
1889 14 , 33, /* ê - 234 */
1890 14 , 33, /* ë - 235 */
1891 14 , 50, /* ì - 236 */
1892 14 , 50, /* í - 237 */
1893 14 , 50, /* î - 238 */
1894 14 , 50, /* ï - 239 */
1895 14 , 26, /* ð - 240 */
1896 14 , 112, /* ñ - 241 */
1897 14 , 124, /* ò - 242 */
1898 14 , 124, /* ó - 243 */
1899 14 , 124, /* ô - 244 */
1900 14 , 124, /* õ - 245 */
1901 14 , 124, /* ö - 246 */
1902 8 , 29, /* ÷ - 247 */
1903 14 , 124, /* ø - 248 */
1904 14 , 159, /* ù - 249 */
1905 14 , 159, /* ú - 250 */
1906 14 , 159, /* û - 251 */
1907 14 , 159, /* ü - 252 */
1908 14 , 167, /* ý - 253 */
1909 14 + 32 , 153, /* þ - 254 */
1910 14 , 167 /* ÿ - 255 */ };
1912 static const unsigned char LCM_Unicode_LUT_2
[] = { 33, 44, 145 };
1914 #define LCM_Diacritic_Start 131
1916 static const unsigned char LCM_Diacritic_LUT
[] = {
2044 /******************************************************************************
2045 * OLE2NLS_isPunctuation [INTERNAL]
2047 static int OLE2NLS_isPunctuation(unsigned char c
)
2049 /* "punctuation character" in this context is a character which is
2050 considered "less important" during word sort comparison.
2051 See LCMapString implementation for the precise definition
2052 of "less important". */
2054 return (LCM_Unicode_LUT
[-2+2*c
]==6);
2057 /******************************************************************************
2058 * OLE2NLS_isNonSpacing [INTERNAL]
2060 static int OLE2NLS_isNonSpacing(unsigned char c
)
2062 /* This function is used by LCMapString32A. Characters
2063 for which it returns true are ignored when mapping a
2064 string with NORM_IGNORENONSPACE */
2065 return ((c
==136) || (c
==170) || (c
==186));
2068 /******************************************************************************
2069 * OLE2NLS_isSymbol [INTERNAL]
2071 static int OLE2NLS_isSymbol(unsigned char c
)
2073 /* This function is used by LCMapString32A. Characters
2074 for which it returns true are ignored when mapping a
2075 string with NORM_IGNORESYMBOLS */
2076 return ( (c
!=0) && !IsCharAlphaNumericA(c
) );
2079 /******************************************************************************
2080 * identity [Internal]
2082 static int identity(int c
)
2087 /*************************************************************************
2088 * LCMapString32A [KERNEL32.492]
2090 * Convert a string, or generate a sort key from it.
2092 * If (mapflags & LCMAP_SORTKEY), the function will generate
2093 * a sort key for the source string. Else, it will convert it
2094 * accordingly to the flags LCMAP_UPPERCASE, LCMAP_LOWERCASE,...
2098 * Success : length of the result string.
2101 * If called with scrlen = -1, the function will compute the length
2102 * of the 0-terminated string strsrc by itself.
2104 * If called with dstlen = 0, returns the buffer length that
2105 * would be required.
2107 * NORM_IGNOREWIDTH means to compare ASCII and wide characters
2108 * as if they are equal.
2109 * In the only code page implemented so far, there may not be
2110 * wide characters in strings passed to LCMapString32A,
2111 * so there is nothing to be done for this flag.
2113 INT WINAPI
LCMapStringA(
2114 LCID lcid
/* locale identifier created with MAKELCID;
2115 LOCALE_SYSTEM_DEFAULT and LOCALE_USER_DEFAULT are
2116 predefined values. */,
2117 DWORD mapflags
/* flags */,
2118 LPCSTR srcstr
/* source buffer */,
2119 INT srclen
/* source length */,
2120 LPSTR dststr
/* destination buffer */,
2121 INT dstlen
/* destination buffer length */)
2125 TRACE_(string
)("(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
2126 lcid
,mapflags
,srcstr
,srclen
,dststr
,dstlen
);
2128 if ( ((dstlen
!=0) && (dststr
==NULL
)) || (srcstr
==NULL
) )
2130 ERR("(src=%s,dest=%s): Invalid NULL string\n", srcstr
, dststr
);
2131 SetLastError(ERROR_INVALID_PARAMETER
);
2135 srclen
= lstrlenA(srcstr
) + 1 ; /* (include final '\0') */
2137 #define LCMAPSTRINGA_SUPPORTED_FLAGS (LCMAP_UPPERCASE | \
2141 NORM_IGNORENONSPACE | \
2143 NORM_IGNOREWIDTH | \
2144 NORM_IGNOREKANATYPE)
2145 /* FIXME: as long as we don't support Kanakana nor Hirigana
2146 * characters, we can support NORM_IGNOREKANATYPE
2148 if (mapflags
& ~LCMAPSTRINGA_SUPPORTED_FLAGS
)
2150 FIXME_(string
)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2151 "unimplemented flags: 0x%08lx\n",
2158 mapflags
& ~LCMAPSTRINGA_SUPPORTED_FLAGS
2162 if ( !(mapflags
& LCMAP_SORTKEY
) )
2165 int (*f
)(int) = identity
;
2166 int flag_ignorenonspace
= mapflags
& NORM_IGNORENONSPACE
;
2167 int flag_ignoresymbols
= mapflags
& NORM_IGNORESYMBOLS
;
2169 if (flag_ignorenonspace
|| flag_ignoresymbols
)
2171 /* For some values of mapflags, the length of the resulting
2172 string is not known at this point. Windows does map the string
2173 and does not SetLastError ERROR_INSUFFICIENT_BUFFER in
2177 /* Compute required length */
2178 for (i
=j
=0; i
< srclen
; i
++)
2180 if ( !(flag_ignorenonspace
&& OLE2NLS_isNonSpacing(srcstr
[i
]))
2181 && !(flag_ignoresymbols
&& OLE2NLS_isSymbol(srcstr
[i
])) )
2193 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2197 if (mapflags
& LCMAP_UPPERCASE
)
2199 else if (mapflags
& LCMAP_LOWERCASE
)
2201 /* FIXME: NORM_IGNORENONSPACE requires another conversion */
2202 for (i
=j
=0; (i
<srclen
) && (j
<dstlen
) ; i
++)
2204 if ( !(flag_ignorenonspace
&& OLE2NLS_isNonSpacing(srcstr
[i
]))
2205 && !(flag_ignoresymbols
&& OLE2NLS_isSymbol(srcstr
[i
])) )
2207 dststr
[j
] = (CHAR
) f(srcstr
[i
]);
2214 /* else ... (mapflags & LCMAP_SORTKEY) */
2218 int diacritic_len
=0;
2219 int delayed_punctuation_len
=0;
2220 char *case_component
;
2221 char *diacritic_component
;
2222 char *delayed_punctuation_component
;
2224 int flag_stringsort
= mapflags
& SORT_STRINGSORT
;
2226 /* compute how much room we will need */
2227 for (i
=0;i
<srclen
;i
++)
2230 unsigned char source_char
= srcstr
[i
];
2231 if (source_char
!='\0')
2233 if (flag_stringsort
|| !OLE2NLS_isPunctuation(source_char
))
2236 if ( LCM_Unicode_LUT
[-2+2*source_char
] & ~15 )
2237 unicode_len
++; /* double letter */
2241 delayed_punctuation_len
++;
2245 if (isupper(source_char
))
2246 case_len
=unicode_len
;
2248 ofs
= source_char
- LCM_Diacritic_Start
;
2249 if ((ofs
>=0) && (LCM_Diacritic_LUT
[ofs
]!=2))
2250 diacritic_len
=unicode_len
;
2253 if (mapflags
& NORM_IGNORECASE
)
2255 if (mapflags
& NORM_IGNORENONSPACE
)
2258 room
= 2 * unicode_len
/* "unicode" component */
2259 + diacritic_len
/* "diacritic" component */
2260 + case_len
/* "case" component */
2261 + 4 * delayed_punctuation_len
/* punctuation in word sort mode */
2262 + 4 /* four '\1' separators */
2263 + 1 ; /* terminal '\0' */
2266 else if (dstlen
<room
)
2268 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2272 /*FIXME the Pointercheck should not be nessesary */
2273 if (IsBadWritePtr (dststr
,room
))
2274 { ERR_(string
)("bad destination buffer (dststr) : %p,%d\n",dststr
,dstlen
);
2275 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2279 /* locate each component, write separators */
2280 diacritic_component
= dststr
+ 2*unicode_len
;
2281 *diacritic_component
++ = '\1';
2282 case_component
= diacritic_component
+ diacritic_len
;
2283 *case_component
++ = '\1';
2284 delayed_punctuation_component
= case_component
+ case_len
;
2285 *delayed_punctuation_component
++ = '\1';
2286 *delayed_punctuation_component
++ = '\1';
2288 /* read source string char by char, write
2289 corresponding weight in each component. */
2290 for (i
=0,count
=0;i
<srclen
;i
++)
2292 unsigned char source_char
=srcstr
[i
];
2293 if (source_char
!='\0')
2296 type
= LCM_Unicode_LUT
[-2+2*source_char
];
2297 longcode
= type
>> 4;
2299 if (!flag_stringsort
&& OLE2NLS_isPunctuation(source_char
))
2301 UINT16 encrypted_location
= (1<<15) + 7 + 4*count
;
2302 *delayed_punctuation_component
++ = (unsigned char) (encrypted_location
>>8);
2303 *delayed_punctuation_component
++ = (unsigned char) (encrypted_location
&255);
2304 /* big-endian is used here because it lets string comparison be
2305 compatible with numerical comparison */
2307 *delayed_punctuation_component
++ = type
;
2308 *delayed_punctuation_component
++ = LCM_Unicode_LUT
[-1+2*source_char
];
2309 /* assumption : a punctuation character is never a
2310 double or accented letter */
2314 dststr
[2*count
] = type
;
2315 dststr
[2*count
+1] = LCM_Unicode_LUT
[-1+2*source_char
];
2319 case_component
[count
] = ( isupper(source_char
) ? 18 : 2 ) ;
2320 if (count
<diacritic_len
)
2321 diacritic_component
[count
] = 2; /* assumption: a double letter
2322 is never accented */
2325 dststr
[2*count
] = type
;
2326 dststr
[2*count
+1] = *(LCM_Unicode_LUT_2
- 1 + longcode
);
2327 /* 16 in the first column of LCM_Unicode_LUT --> longcode = 1
2328 32 in the first column of LCM_Unicode_LUT --> longcode = 2
2329 48 in the first column of LCM_Unicode_LUT --> longcode = 3 */
2333 case_component
[count
] = ( isupper(source_char
) ? 18 : 2 ) ;
2334 if (count
<diacritic_len
)
2336 int ofs
= source_char
- LCM_Diacritic_Start
;
2337 diacritic_component
[count
] = (ofs
>=0 ? LCM_Diacritic_LUT
[ofs
] : 2);
2343 dststr
[room
-1] = '\0';
2348 /*************************************************************************
2349 * LCMapString32W [KERNEL32.493]
2351 * Convert a string, or generate a sort key from it.
2355 * See LCMapString32A for documentation
2357 INT WINAPI
LCMapStringW(
2358 LCID lcid
,DWORD mapflags
,LPCWSTR srcstr
,INT srclen
,LPWSTR dststr
,
2363 TRACE_(string
)("(0x%04lx,0x%08lx,%p,%d,%p,%d)\n",
2364 lcid
,mapflags
,srcstr
,srclen
,dststr
,dstlen
);
2366 if ( ((dstlen
!=0) && (dststr
==NULL
)) || (srcstr
==NULL
) )
2368 ERR("(src=%p,dst=%p): Invalid NULL string\n", srcstr
, dststr
);
2369 SetLastError(ERROR_INVALID_PARAMETER
);
2373 srclen
= lstrlenW(srcstr
)+1;
2374 if (mapflags
& LCMAP_SORTKEY
)
2376 FIXME_(string
)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2377 "unimplemented flags: 0x%08lx\n",
2378 lcid
,mapflags
,srcstr
,srclen
,dststr
,dstlen
,mapflags
);
2383 int (*f
)(int)=identity
;
2387 if (dstlen
<srclen
) {
2388 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2391 if (mapflags
& LCMAP_UPPERCASE
)
2393 else if (mapflags
& LCMAP_LOWERCASE
)
2395 for (i
=0; i
< srclen
; i
++)
2396 dststr
[i
] = (WCHAR
) f(srcstr
[i
]);
2401 /***********************************************************************
2402 * CompareString16 (OLE2NLS.8)
2404 UINT16 WINAPI
CompareString16(DWORD lcid
,DWORD fdwStyle
,
2405 LPCSTR s1
,DWORD l1
,LPCSTR s2
,DWORD l2
)
2407 return (UINT16
)CompareStringA(lcid
,fdwStyle
,s1
,l1
,s2
,l2
);
2410 /******************************************************************************
2411 * CompareString32A [KERNEL32.143]
2412 * Compares two strings using locale
2416 * success: CSTR_LESS_THAN, CSTR_EQUAL, CSTR_GREATER_THAN
2421 * Defaults to a word sort, but uses a string sort if
2422 * SORT_STRINGSORT is set.
2423 * Calls SetLastError for ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER.
2427 * This implementation ignores the locale
2431 * Quite inefficient.
2433 UINT WINAPI
CompareStringA(
2434 DWORD lcid
, /* locale ID */
2435 DWORD fdwStyle
, /* comparison-style options */
2436 LPCSTR s1
, /* first string */
2437 DWORD l1
, /* length of first string */
2438 LPCSTR s2
, /* second string */
2439 DWORD l2
) /* length of second string */
2441 int mapstring_flags
;
2445 TRACE("%s and %s\n",
2446 debugstr_a (s1
), debugstr_a (s2
));
2448 if ( (s1
==NULL
) || (s2
==NULL
) )
2450 ERR("(s1=%s,s2=%s): Invalid NULL string\n", s1
, s2
);
2451 SetLastError(ERROR_INVALID_PARAMETER
);
2455 if(fdwStyle
& NORM_IGNORESYMBOLS
)
2456 FIXME("IGNORESYMBOLS not supported\n");
2458 mapstring_flags
= LCMAP_SORTKEY
| fdwStyle
;
2459 len1
= LCMapStringA(lcid
,mapstring_flags
,s1
,l1
,NULL
,0);
2460 len2
= LCMapStringA(lcid
,mapstring_flags
,s2
,l2
,NULL
,0);
2462 if ((len1
==0)||(len2
==0))
2463 return 0; /* something wrong happened */
2465 sk1
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,len1
);
2466 sk2
= (LPSTR
)HeapAlloc(GetProcessHeap(),0,len2
);
2467 if ( (!LCMapStringA(lcid
,mapstring_flags
,s1
,l1
,sk1
,len1
))
2468 || (!LCMapStringA(lcid
,mapstring_flags
,s2
,l2
,sk2
,len2
)) )
2470 ERR("Bug in LCmapString32A.\n");
2475 /* strcmp doesn't necessarily return -1, 0, or 1 */
2476 result
= strcmp(sk1
,sk2
);
2478 HeapFree(GetProcessHeap(),0,sk1
);
2479 HeapFree(GetProcessHeap(),0,sk2
);
2486 /* must be greater, if we reach this point */
2490 /******************************************************************************
2491 * CompareString32W [KERNEL32.144]
2492 * This implementation ignores the locale
2493 * FIXME : Does only string sort. Should
2494 * be reimplemented the same way as CompareString32A.
2496 UINT WINAPI
CompareStringW(DWORD lcid
, DWORD fdwStyle
,
2497 LPCWSTR s1
, DWORD l1
, LPCWSTR s2
,DWORD l2
)
2500 if(fdwStyle
& NORM_IGNORENONSPACE
)
2501 FIXME("IGNORENONSPACE not supprted\n");
2502 if(fdwStyle
& NORM_IGNORESYMBOLS
)
2503 FIXME("IGNORESYMBOLS not supported\n");
2505 /* Is strcmp defaulting to string sort or to word sort?? */
2506 /* FIXME: Handle NORM_STRINGSORT */
2507 l1
= (l1
==-1)?lstrlenW(s1
):l1
;
2508 l2
= (l2
==-1)?lstrlenW(s2
):l2
;
2509 len
= l1
<l2
? l1
:l2
;
2510 ret
= (fdwStyle
& NORM_IGNORECASE
) ?
2511 CRTDLL__wcsnicmp(s1
,s2
,len
) : CRTDLL_wcsncmp(s1
,s2
,len
);
2512 /* not equal, return 1 or 3 */
2513 if(ret
!=0) return ret
+2;
2514 /* same len, return 2 */
2515 if(l1
==l2
) return 2;
2516 /* the longer one is lexically greater */
2517 return (l1
<l2
)? 1 : 3;
2520 /******************************************************************************
2521 * RegisterNLSInfoChanged [OLE2NLS.10]
2523 BOOL16 WINAPI
RegisterNLSInfoChanged16(LPVOID
/*FIXME*/ lpNewNLSInfo
)
2525 FIXME("Fully implemented, but doesn't effect anything.\n");
2536 lpNLSInfo
= lpNewNLSInfo
;
2541 return FALSE
; /* ptr not set */
2544 /******************************************************************************
2545 * OLE_GetFormatA [Internal]
2548 * If datelen == 0, it should return the reguired string length.
2550 This function implements stuff for GetDateFormat() and
2553 d single-digit (no leading zero) day (of month)
2554 dd two-digit day (of month)
2555 ddd short day-of-week name
2556 dddd long day-of-week name
2557 M single-digit month
2559 MMM short month name
2560 MMMM full month name
2561 y two-digit year, no leading 0
2563 yyyy four-digit year
2565 h hours with no leading zero (12-hour)
2566 hh hours with full two digits
2567 H hours with no leading zero (24-hour)
2568 HH hours with full two digits
2569 m minutes with no leading zero
2570 mm minutes with full two digits
2571 s seconds with no leading zero
2572 ss seconds with full two digits
2573 t time marker (A or P)
2574 tt time marker (AM, PM)
2575 '' used to quote literal characters
2576 '' (within a quoted string) indicates a literal '
2578 These functions REQUIRE valid locale, date, and format.
2580 static INT
OLE_GetFormatA(LCID locale
,
2584 LPCSTR _format
, /*in*/
2589 int count
, type
, inquote
, Overflow
;
2595 const char * _dgfmt
[] = { "%d", "%02d" };
2596 const char ** dgfmt
= _dgfmt
- 1;
2598 /* report, for debugging */
2599 TRACE("(0x%lx,0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt=%p \'%s\' , %p, len=%d)\n",
2600 locale
, flags
, tflags
,
2601 xtime
->wDay
, xtime
->wHour
, xtime
->wMinute
, xtime
->wSecond
,
2602 _format
, _format
, date
, datelen
);
2605 FIXME("datelen = 0, returning 255\n");
2609 /* initalize state variables and output buffer */
2611 count
= 0; inquote
= 0; Overflow
= 0;
2613 date
[0] = buf
[0] = '\0';
2615 strcpy(format
,_format
);
2617 /* alter the formatstring, while it works for all languages now in wine
2618 its possible that it fails when the time looks like ss:mm:hh as example*/
2619 if (tflags
& (TIME_NOMINUTESORSECONDS
))
2620 { if ((pos
= strstr ( format
, ":mm")))
2621 { memcpy ( pos
, pos
+3, strlen(format
)-(pos
-format
)-2 );
2624 if (tflags
& (TIME_NOSECONDS
))
2625 { if ((pos
= strstr ( format
, ":ss")))
2626 { memcpy ( pos
, pos
+3, strlen(format
)-(pos
-format
)-2 );
2630 for (inpos
= 0;; inpos
++) {
2631 /* 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]); */
2633 if (format
[inpos
] == '\'') {
2634 if (format
[inpos
+1] == '\'') {
2636 date
[outpos
++] = '\'';
2639 continue; /* we did nothing to the output */
2641 } else if (format
[inpos
] == '\0') {
2642 date
[outpos
++] = '\0';
2643 if (outpos
> datelen
) Overflow
= 1;
2646 date
[outpos
++] = format
[inpos
];
2647 if (outpos
> datelen
) {
2649 date
[outpos
-1] = '\0'; /* this is the last place where
2650 it's safe to write */
2654 } else if ( (count
&& (format
[inpos
] != type
))
2656 || (count
== 2 && strchr("ghHmst", type
)) )
2660 GetLocaleInfoA(locale
,
2662 + xtime
->wDayOfWeek
- 1,
2664 } else if (count
== 3) {
2665 GetLocaleInfoA(locale
,
2666 LOCALE_SABBREVDAYNAME1
2667 + xtime
->wDayOfWeek
- 1,
2670 sprintf(buf
, dgfmt
[count
], xtime
->wDay
);
2672 } else if (type
== 'M') {
2674 GetLocaleInfoA(locale
,
2675 LOCALE_SABBREVMONTHNAME1
2676 + xtime
->wMonth
- 1,
2678 } else if (count
== 4) {
2679 GetLocaleInfoA(locale
,
2681 + xtime
->wMonth
- 1,
2684 sprintf(buf
, dgfmt
[count
], xtime
->wMonth
);
2686 } else if (type
== 'y') {
2688 sprintf(buf
, "%d", xtime
->wYear
);
2689 } else if (count
== 3) {
2691 WARN("unknown format, c=%c, n=%d\n", type
, count
);
2693 sprintf(buf
, dgfmt
[count
], xtime
->wYear
% 100);
2695 } else if (type
== 'g') {
2697 FIXME("LOCALE_ICALENDARTYPE unimp.\n");
2701 WARN("unknown format, c=%c, n=%d\n", type
, count
);
2703 } else if (type
== 'h') {
2704 /* gives us hours 1:00 -- 12:00 */
2705 sprintf(buf
, dgfmt
[count
], (xtime
->wHour
-1)%12 +1);
2706 } else if (type
== 'H') {
2708 sprintf(buf
, dgfmt
[count
], xtime
->wHour
);
2709 } else if ( type
== 'm') {
2710 sprintf(buf
, dgfmt
[count
], xtime
->wMinute
);
2711 } else if ( type
== 's') {
2712 sprintf(buf
, dgfmt
[count
], xtime
->wSecond
);
2713 } else if (type
== 't') {
2715 sprintf(buf
, "%c", (xtime
->wHour
< 12) ? 'A' : 'P');
2716 } else if (count
== 2) {
2717 /* sprintf(buf, "%s", (xtime->wHour < 12) ? "AM" : "PM"); */
2718 GetLocaleInfoA(locale
,
2720 ? LOCALE_S1159
: LOCALE_S2359
,
2725 /* we need to check the next char in the format string
2726 again, no matter what happened */
2729 /* add the contents of buf to the output */
2730 buflen
= strlen(buf
);
2731 if (outpos
+ buflen
< datelen
) {
2732 date
[outpos
] = '\0'; /* for strcat to hook onto */
2736 date
[outpos
] = '\0';
2737 strncat(date
, buf
, datelen
- outpos
);
2738 date
[datelen
- 1] = '\0';
2739 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2740 WARN("insufficient buffer\n");
2744 /* reset the variables we used to keep track of this item */
2747 } else if (format
[inpos
] == '\0') {
2748 /* we can't check for this at the loop-head, because
2749 that breaks the printing of the last format-item */
2750 date
[outpos
] = '\0';
2753 /* continuing a code for an item */
2756 } else if (strchr("hHmstyMdg", format
[inpos
])) {
2757 type
= format
[inpos
];
2760 } else if (format
[inpos
] == '\'') {
2764 date
[outpos
++] = format
[inpos
];
2766 /* now deal with a possible buffer overflow */
2767 if (outpos
>= datelen
) {
2768 date
[datelen
- 1] = '\0';
2769 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2775 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2778 /* finish it off with a string terminator */
2781 if (outpos
> datelen
-1) outpos
= datelen
-1;
2782 date
[outpos
] = '\0';
2784 TRACE("OLE_GetFormatA returns string '%s', len %d\n",
2789 /******************************************************************************
2790 * OLE_GetFormatW [INTERNAL]
2792 static INT
OLE_GetFormatW(LCID locale
, DWORD flags
, DWORD tflags
,
2795 LPWSTR output
, INT outlen
)
2798 int count
, type
=0, inquote
;
2799 int Overflow
; /* loop check */
2802 WCHAR arg0
[] = {0}, arg1
[] = {'%','d',0};
2803 WCHAR arg2
[] = {'%','0','2','d',0};
2805 int datevars
=0, timevars
=0;
2811 /* make a debug report */
2812 TRACE("args: 0x%lx, 0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt:%s (at %p), "
2813 "%p with max len %d\n",
2814 locale
, flags
, tflags
,
2815 xtime
->wDay
, xtime
->wHour
, xtime
->wMinute
, xtime
->wSecond
,
2816 debugstr_w(format
), format
, output
, outlen
);
2819 FIXME("outlen = 0, returning 255\n");
2823 /* initialize state variables */
2826 inquote
= Overflow
= 0;
2827 /* this is really just a sanity check */
2828 output
[0] = buf
[0] = 0;
2830 /* this loop is the core of the function */
2831 for (inpos
= 0; /* we have several break points */ ; inpos
++) {
2833 if (format
[inpos
] == (WCHAR
) '\'') {
2834 if (format
[inpos
+1] == '\'') {
2836 output
[outpos
++] = '\'';
2841 } else if (format
[inpos
] == 0) {
2842 output
[outpos
++] = 0;
2843 if (outpos
> outlen
) Overflow
= 1;
2844 break; /* normal exit (within a quote) */
2846 output
[outpos
++] = format
[inpos
]; /* copy input */
2847 if (outpos
> outlen
) {
2849 output
[outpos
-1] = 0;
2853 } else if ( (count
&& (format
[inpos
] != type
))
2854 || ( (count
==4 && type
=='y') ||
2855 (count
==4 && type
=='M') ||
2856 (count
==4 && type
=='d') ||
2857 (count
==2 && type
=='g') ||
2858 (count
==2 && type
=='h') ||
2859 (count
==2 && type
=='H') ||
2860 (count
==2 && type
=='m') ||
2861 (count
==2 && type
=='s') ||
2862 (count
==2 && type
=='t') ) ) {
2865 GetLocaleInfoW(locale
,
2866 LOCALE_SDAYNAME1
+ xtime
->wDayOfWeek
-1,
2867 buf
, sizeof(buf
)/sizeof(WCHAR
) );
2868 } else if (count
== 3) {
2869 GetLocaleInfoW(locale
,
2870 LOCALE_SABBREVDAYNAME1
+
2871 xtime
->wDayOfWeek
-1,
2872 buf
, sizeof(buf
)/sizeof(WCHAR
) );
2874 wsnprintfW(buf
, 5, argarr
[count
], xtime
->wDay
);
2876 } else if (type
== 'M') {
2878 GetLocaleInfoW(locale
, LOCALE_SMONTHNAME1
+
2879 xtime
->wMonth
-1, buf
,
2880 sizeof(buf
)/sizeof(WCHAR
) );
2881 } else if (count
== 3) {
2882 GetLocaleInfoW(locale
, LOCALE_SABBREVMONTHNAME1
+
2883 xtime
->wMonth
-1, buf
,
2884 sizeof(buf
)/sizeof(WCHAR
) );
2886 wsnprintfW(buf
, 5, argarr
[count
], xtime
->wMonth
);
2888 } else if (type
== 'y') {
2890 wsnprintfW(buf
, 6, argarr
[1] /* "%d" */,
2892 } else if (count
== 3) {
2893 lstrcpynAtoW(buf
, "yyy", 5);
2895 wsnprintfW(buf
, 6, argarr
[count
],
2896 xtime
->wYear
% 100);
2898 } else if (type
== 'g') {
2900 FIXME("LOCALE_ICALENDARTYPE unimplemented\n");
2901 lstrcpynAtoW(buf
, "AD", 5);
2903 /* Win API sez we copy it verbatim */
2904 lstrcpynAtoW(buf
, "g", 5);
2906 } else if (type
== 'h') {
2907 /* hours 1:00-12:00 --- is this right? */
2908 wsnprintfW(buf
, 5, argarr
[count
],
2909 (xtime
->wHour
-1)%12 +1);
2910 } else if (type
== 'H') {
2911 wsnprintfW(buf
, 5, argarr
[count
],
2913 } else if (type
== 'm' ) {
2914 wsnprintfW(buf
, 5, argarr
[count
],
2916 } else if (type
== 's' ) {
2917 wsnprintfW(buf
, 5, argarr
[count
],
2919 } else if (type
== 't') {
2920 GetLocaleInfoW(locale
, (xtime
->wHour
< 12) ?
2921 LOCALE_S1159
: LOCALE_S2359
,
2928 /* no matter what happened, we need to check this next
2929 character the next time we loop through */
2932 /* cat buf onto the output */
2933 outlen
= lstrlenW(buf
);
2934 if (outpos
+ buflen
< outlen
) {
2935 lstrcpyW( output
+ outpos
, buf
);
2938 lstrcpynW( output
+ outpos
, buf
, outlen
- outpos
);
2940 break; /* Abnormal exit */
2943 /* reset the variables we used this time */
2946 } else if (format
[inpos
] == 0) {
2947 /* we can't check for this at the beginning, because that
2948 would keep us from printing a format spec that ended the
2951 break; /* NORMAL EXIT */
2953 /* how we keep track of the middle of a format spec */
2956 } else if ( (datevars
&& (format
[inpos
]=='d' ||
2957 format
[inpos
]=='M' ||
2958 format
[inpos
]=='y' ||
2959 format
[inpos
]=='g') ) ||
2960 (timevars
&& (format
[inpos
]=='H' ||
2961 format
[inpos
]=='h' ||
2962 format
[inpos
]=='m' ||
2963 format
[inpos
]=='s' ||
2964 format
[inpos
]=='t') ) ) {
2965 type
= format
[inpos
];
2968 } else if (format
[inpos
] == '\'') {
2972 /* unquoted literals */
2973 output
[outpos
++] = format
[inpos
];
2978 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2979 WARN(" buffer overflow\n");
2982 /* final string terminator and sanity check */
2984 if (outpos
> outlen
-1) outpos
= outlen
-1;
2985 output
[outpos
] = '0';
2987 TRACE(" returning %s\n", debugstr_w(output
));
2989 return (!Overflow
) ? outlen
: 0;
2994 /******************************************************************************
2995 * GetDateFormat32A [KERNEL32.310]
2996 * Makes an ASCII string of the date
2998 * This function uses format to format the date, or, if format
2999 * is NULL, uses the default for the locale. format is a string
3000 * of literal fields and characters as follows:
3002 * - d single-digit (no leading zero) day (of month)
3003 * - dd two-digit day (of month)
3004 * - ddd short day-of-week name
3005 * - dddd long day-of-week name
3006 * - M single-digit month
3007 * - MM two-digit month
3008 * - MMM short month name
3009 * - MMMM full month name
3010 * - y two-digit year, no leading 0
3011 * - yy two-digit year
3012 * - yyyy four-digit year
3016 INT WINAPI
GetDateFormatA(LCID locale
,DWORD flags
,
3018 LPCSTR format
, LPSTR date
,INT datelen
)
3021 char format_buf
[40];
3024 LPSYSTEMTIME thistime
;
3028 TRACE("(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",
3029 locale
,flags
,xtime
,format
,date
,datelen
);
3032 locale
= LOCALE_SYSTEM_DEFAULT
;
3035 if (locale
== LOCALE_SYSTEM_DEFAULT
) {
3036 thislocale
= GetSystemDefaultLCID();
3037 } else if (locale
== LOCALE_USER_DEFAULT
) {
3038 thislocale
= GetUserDefaultLCID();
3040 thislocale
= locale
;
3043 if (xtime
== NULL
) {
3050 if (format
== NULL
) {
3051 GetLocaleInfoA(thislocale
, ((flags
&DATE_LONGDATE
)
3053 : LOCALE_SSHORTDATE
),
3054 format_buf
, sizeof(format_buf
));
3055 thisformat
= format_buf
;
3057 thisformat
= format
;
3061 ret
= OLE_GetFormatA(thislocale
, flags
, 0, thistime
, thisformat
,
3066 "GetDateFormat32A() returning %d, with data=%s\n",
3071 /******************************************************************************
3072 * GetDateFormat32W [KERNEL32.311]
3073 * Makes a Unicode string of the date
3075 * Acts the same as GetDateFormat32A(), except that it's Unicode.
3076 * Accepts & returns sizes as counts of Unicode characters.
3079 INT WINAPI
GetDateFormatW(LCID locale
,DWORD flags
,
3082 LPWSTR date
, INT datelen
)
3084 unsigned short datearr
[] = {'1','9','9','4','-','1','-','1',0};
3086 FIXME("STUB (should call OLE_GetFormatW)\n");
3087 lstrcpynW(date
, datearr
, datelen
);
3088 return ( datelen
< 9) ? datelen
: 9;
3093 /**************************************************************************
3094 * EnumDateFormats32A (KERNEL32.198)
3096 BOOL WINAPI
EnumDateFormatsA(
3097 DATEFMT_ENUMPROCA lpDateFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3099 FIXME("Only US English supported\n");
3101 if(!lpDateFmtEnumProc
)
3103 SetLastError(ERROR_INVALID_PARAMETER
);
3109 case DATE_SHORTDATE
:
3110 if(!(*lpDateFmtEnumProc
)("M/d/yy")) return TRUE
;
3111 if(!(*lpDateFmtEnumProc
)("M/d/yyyy")) return TRUE
;
3112 if(!(*lpDateFmtEnumProc
)("MM/dd/yy")) return TRUE
;
3113 if(!(*lpDateFmtEnumProc
)("MM/dd/yyyy")) return TRUE
;
3114 if(!(*lpDateFmtEnumProc
)("yy/MM/dd")) return TRUE
;
3115 if(!(*lpDateFmtEnumProc
)("dd-MMM-yy")) return TRUE
;
3118 if(!(*lpDateFmtEnumProc
)("dddd, MMMM dd, yyyy")) return TRUE
;
3119 if(!(*lpDateFmtEnumProc
)("MMMM dd, yyyy")) return TRUE
;
3120 if(!(*lpDateFmtEnumProc
)("dddd, dd MMMM, yyyy")) return TRUE
;
3121 if(!(*lpDateFmtEnumProc
)("dd MMMM, yyyy")) return TRUE
;
3124 FIXME("Unknown date format (%ld)\n", dwFlags
);
3125 SetLastError(ERROR_INVALID_PARAMETER
);
3130 /**************************************************************************
3131 * EnumDateFormats32W (KERNEL32.199)
3133 BOOL WINAPI
EnumDateFormatsW(
3134 DATEFMT_ENUMPROCW lpDateFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3136 FIXME("(%p, %ld, %ld): stub\n", lpDateFmtEnumProc
, Locale
, dwFlags
);
3137 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3141 /**************************************************************************
3142 * EnumTimeFormats32A (KERNEL32.210)
3144 BOOL WINAPI
EnumTimeFormatsA(
3145 TIMEFMT_ENUMPROCA lpTimeFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3147 FIXME("Only US English supported\n");
3149 if(!lpTimeFmtEnumProc
)
3151 SetLastError(ERROR_INVALID_PARAMETER
);
3157 FIXME("Unknown time format (%ld)\n", dwFlags
);
3160 if(!(*lpTimeFmtEnumProc
)("h:mm:ss tt")) return TRUE
;
3161 if(!(*lpTimeFmtEnumProc
)("hh:mm:ss tt")) return TRUE
;
3162 if(!(*lpTimeFmtEnumProc
)("H:mm:ss")) return TRUE
;
3163 if(!(*lpTimeFmtEnumProc
)("HH:mm:ss")) return TRUE
;
3168 /**************************************************************************
3169 * EnumTimeFormats32W (KERNEL32.211)
3171 BOOL WINAPI
EnumTimeFormatsW(
3172 TIMEFMT_ENUMPROCW lpTimeFmtEnumProc
, LCID Locale
, DWORD dwFlags
)
3174 FIXME("(%p,%ld,%ld): stub\n", lpTimeFmtEnumProc
, Locale
, dwFlags
);
3175 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3180 /**************************************************************************
3181 * GetNumberFormat32A (KERNEL32.355)
3183 INT WINAPI
GetNumberFormatA(LCID locale
, DWORD dwflags
,
3184 LPCSTR lpValue
, const NUMBERFMTA
* lpFormat
,
3185 LPSTR lpNumberStr
, int cchNumber
)
3189 UINT thisleadingzero
;
3190 UINT thisgrouping
[8]={ -1 };
3191 LPCSTR thisdecimalsep
;
3192 LPCSTR thisthousandsep
;
3193 UINT thisnegativeorder
;
3198 char roundbuffer
[24]; /* Should be enough */
3201 int dotflag
=0,negflag
=0;
3202 char misc_buf
[8], negative_buf
[4], decimal_buf
[4], thousand_buf
[4];
3203 char digits_buf
[11];
3204 int intsize
=0,decsize
=0,totalsize
,lastgroup
, leadingzeros
=0;
3205 int negsignsize
,decimalsepsize
,thousandsepsize
;
3207 /* Default setting stuff - partially borrowed from GetFormatedDate */
3209 locale
= LOCALE_SYSTEM_DEFAULT
;
3212 if (locale
== LOCALE_SYSTEM_DEFAULT
) {
3213 thislocale
= GetSystemDefaultLCID();
3214 } else if (locale
== LOCALE_USER_DEFAULT
) {
3215 thislocale
= GetUserDefaultLCID();
3217 thislocale
= locale
;
3219 /* Partial implementation: things like native digits are not considered */
3220 if (lpFormat
== NULL
) {
3222 GetLocaleInfoA(thislocale
, LOCALE_IDIGITS
,
3223 misc_buf
, sizeof(misc_buf
));
3224 thisnumdigits
= atoi(misc_buf
);
3226 GetLocaleInfoA(thislocale
, LOCALE_ILZERO
,
3227 misc_buf
, sizeof(misc_buf
));
3228 thisleadingzero
= atoi(misc_buf
);
3230 GetLocaleInfoA(thislocale
, LOCALE_SGROUPING
,
3231 misc_buf
, sizeof(misc_buf
));
3233 /* About grouping mechanism:
3234 I parse the string and pour the group size values along the
3235 thisgrouping[] array, starting by element 1. Then I convert these
3236 values to indexes for insertion into the integer part.
3237 thisgrouping[0]==-1, therefore I ensure index correctness without
3238 need for range checking and related stuff.
3239 The only drawback is the 7 separators limit, hopefully that means
3240 it will fail with numbers bigger than 10^21 if using groups of three
3244 for (i
=1,gptr
=misc_buf
;*gptr
!='\0';i
++) {
3245 /* In control panel, groups up 9 digits long are allowed. If there is any way to use larger groups,
3246 then the next line must be replaced with the following code:
3247 thisgrouping[i] = atoi(gptr);
3248 for (;*gptr!=';' && *gptr!='\0';gptr++) ; */
3250 thisgrouping
[i
] = *(gptr
++)-'0';
3256 /* Take care for repeating group size */
3257 if (thisgrouping
[i
-1]==0) {
3259 thisgrouping
[j
]=thisgrouping
[i
-2];
3264 for (i
=2;i
<=lastgroup
;i
++)
3265 thisgrouping
[i
]+=thisgrouping
[i
-1];
3267 GetLocaleInfoA(thislocale
, LOCALE_SDECIMAL
,
3268 decimal_buf
, sizeof(decimal_buf
));
3269 thisdecimalsep
= decimal_buf
;
3271 GetLocaleInfoA(thislocale
, LOCALE_STHOUSAND
,
3272 thousand_buf
, sizeof(thousand_buf
));
3273 thisthousandsep
= thousand_buf
;
3275 GetLocaleInfoA(thislocale
, LOCALE_INEGNUMBER
,
3276 misc_buf
, sizeof(misc_buf
));
3277 thisnegativeorder
= atoi(misc_buf
);
3281 thisnumdigits
= lpFormat
->NumDigits
;
3282 thisleadingzero
= lpFormat
->LeadingZero
;
3284 thisgrouping
[1] = lpFormat
->Grouping
;
3286 thisgrouping
[i
]=thisgrouping
[i
-1]+lpFormat
->Grouping
;
3289 thisdecimalsep
= lpFormat
->lpDecimalSep
;
3290 thisthousandsep
= lpFormat
->lpThousandSep
;
3291 thisnegativeorder
= lpFormat
->NegativeOrder
;
3295 GetLocaleInfoA(thislocale
, LOCALE_SNATIVEDIGITS
,
3296 digits_buf
, sizeof(digits_buf
));
3298 GetLocaleInfoA(thislocale
, LOCALE_SNEGATIVESIGN
,
3299 negative_buf
, sizeof(negative_buf
));
3301 negsignsize
=strlen(negative_buf
);
3302 decimalsepsize
=strlen(thisdecimalsep
);
3303 thousandsepsize
=strlen(thisthousandsep
);
3305 /* Size calculation */
3311 for (; *sptr
=='0'; sptr
++) leadingzeros
++; /* Ignore leading zeros */
3312 for (; *sptr
!='\0'; sptr
++) {
3313 if (!dotflag
&& *sptr
=='.') {
3315 } else if (*sptr
<'0' || *sptr
>'9') {
3316 SetLastError(ERROR_INVALID_PARAMETER
);
3328 /* Take care of eventual rounding. Only, if I need to do it, then I write
3329 the rounded lpValue copy into roundbuffer, and create the formatted
3330 string from the proper source. This is smarter than copying it always
3331 The buffer includes an extra leading zero, as the number can carry and
3332 get and extra one. If it doesn't, the zero is ignored as any other
3333 useless leading zero
3336 if (decsize
>0 && decsize
>thisnumdigits
) {
3337 sptr
-=(decsize
-thisnumdigits
);
3340 strcpy(roundbuffer
+1,lpValue
);
3343 *(roundbuffer
+1)='0';
3346 sptr
=roundbuffer
+(sptr
-lpValue
); // +1-1
3348 while ( (++*sptr
) > '9') {
3350 if (*sptr
=='.') sptr
--;
3352 if ((negflag
? *(roundbuffer
+leadingzeros
+1) : *(roundbuffer
+leadingzeros
)) == '1')
3362 if (intsize
==0 && (decsize
==0 || thisleadingzero
))
3366 totalsize
+= thisnegativeorder
== 1 || thisnegativeorder
== 3 ? negsignsize
3367 : thisnegativeorder
== 2 || thisnegativeorder
== 4 ? negsignsize
+1 : 2 ;
3369 /* Look for the first grouping to be done */
3370 for (j
=lastgroup
;thisgrouping
[j
]>=intsize
&& j
>0;j
--) ;
3373 totalsize
+=thousandsepsize
* j
;
3374 if (thisnumdigits
>0)
3375 totalsize
+=decimalsepsize
+thisnumdigits
;
3377 if (cchNumber
==0) /* if cchNumber is zero, just return size needed */
3380 if (cchNumber
<totalsize
+1) { /* +1 = Null terminator (right?) */
3381 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3386 /* Formatting stuff starts here */
3391 if (thisnegativeorder
==0)
3393 else if (thisnegativeorder
<=2) {
3394 strcpy(dptr
,negative_buf
);
3396 if (thisnegativeorder
==2)
3402 for (i
=1;*sptr
=='0' ;i
++, sptr
++) ; /* Ignore leading zeros from source*/
3403 if (intsize
==0 && (decsize
==0 || thisleadingzero
)) // Insert one leading zero into destination if required
3404 *(dptr
++)=digits_buf
[0];
3405 for (i
=1;i
<=intsize
;i
++) {
3407 *(dptr
++)=digits_buf
[*(sptr
++)-'0'];
3409 /* Insert a group separator if we just reached the end of a group */
3410 if (i
==intsize
-thisgrouping
[j
]) {
3411 strcpy(dptr
,thisthousandsep
);
3412 dptr
+=thousandsepsize
;
3419 if (thisnumdigits
>0) {
3420 strcpy(dptr
,decimal_buf
);
3421 dptr
+=decimalsepsize
;
3422 for (i
=0;i
<thisnumdigits
;i
++)
3423 *(dptr
++)=*sptr
!='\0' ? digits_buf
[*(sptr
++)-'0'] : digits_buf
[0];
3427 if (thisnegativeorder
==0)
3429 else if (thisnegativeorder
>=3) {
3430 if (thisnegativeorder
==4)
3432 strcpy(dptr
,negative_buf
);
3444 /**************************************************************************
3445 * GetNumberFormat32W (KERNEL32.xxx)
3447 INT WINAPI
GetNumberFormatW(LCID locale
, DWORD dwflags
,
3448 LPCWSTR lpvalue
, const NUMBERFMTW
* lpFormat
,
3449 LPWSTR lpNumberStr
, int cchNumber
)
3451 FIXME("%s: stub, no reformating done\n",debugstr_w(lpvalue
));
3453 lstrcpynW( lpNumberStr
, lpvalue
, cchNumber
);
3454 return cchNumber
? lstrlenW( lpNumberStr
) : 0;
3456 /******************************************************************************
3457 * OLE2NLS_CheckLocale [intern]
3459 static LCID
OLE2NLS_CheckLocale (LCID locale
)
3462 { locale
= LOCALE_SYSTEM_DEFAULT
;
3465 if (locale
== LOCALE_SYSTEM_DEFAULT
)
3466 { return GetSystemDefaultLCID();
3468 else if (locale
== LOCALE_USER_DEFAULT
)
3469 { return GetUserDefaultLCID();
3475 /******************************************************************************
3476 * GetTimeFormat32A [KERNEL32.422]
3477 * Makes an ASCII string of the time
3479 * Formats date according to format, or locale default if format is
3480 * NULL. The format consists of literal characters and fields as follows:
3482 * h hours with no leading zero (12-hour)
3483 * hh hours with full two digits
3484 * H hours with no leading zero (24-hour)
3485 * HH hours with full two digits
3486 * m minutes with no leading zero
3487 * mm minutes with full two digits
3488 * s seconds with no leading zero
3489 * ss seconds with full two digits
3490 * t time marker (A or P)
3491 * tt time marker (AM, PM)
3495 GetTimeFormatA(LCID locale
, /* in */
3496 DWORD flags
, /* in */
3497 LPSYSTEMTIME xtime
, /* in */
3498 LPCSTR format
, /* in */
3499 LPSTR timestr
, /* out */
3500 INT timelen
/* in */)
3501 { char format_buf
[40];
3504 LPSYSTEMTIME thistime
;
3506 DWORD thisflags
=LOCALE_STIMEFORMAT
; /* standart timeformat */
3509 TRACE("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale
,flags
,xtime
,format
,timestr
,timelen
);
3511 thislocale
= OLE2NLS_CheckLocale ( locale
);
3513 if ( flags
& (TIME_NOTIMEMARKER
| TIME_FORCE24HOURFORMAT
))
3514 { FIXME("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3517 flags
&= (TIME_NOSECONDS
| TIME_NOMINUTESORSECONDS
); /* mask for OLE_GetFormatA*/
3520 { if (flags
& LOCALE_NOUSEROVERRIDE
) /*use system default*/
3521 { thislocale
= GetSystemDefaultLCID();
3523 GetLocaleInfoA(thislocale
, thisflags
, format_buf
, sizeof(format_buf
));
3524 thisformat
= format_buf
;
3527 { thisformat
= format
;
3530 if (xtime
== NULL
) /* NULL means use the current local time*/
3537 ret
= OLE_GetFormatA(thislocale
, thisflags
, flags
, thistime
, thisformat
,
3543 /******************************************************************************
3544 * GetTimeFormat32W [KERNEL32.423]
3545 * Makes a Unicode string of the time
3548 GetTimeFormatW(LCID locale
, /* in */
3549 DWORD flags
, /* in */
3550 LPSYSTEMTIME xtime
, /* in */
3551 LPCWSTR format
, /* in */
3552 LPWSTR timestr
, /* out */
3553 INT timelen
/* in */)
3554 { WCHAR format_buf
[40];
3557 LPSYSTEMTIME thistime
;
3559 DWORD thisflags
=LOCALE_STIMEFORMAT
; /* standart timeformat */
3562 TRACE("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale
,flags
,
3563 xtime
,debugstr_w(format
),timestr
,timelen
);
3565 thislocale
= OLE2NLS_CheckLocale ( locale
);
3567 if ( flags
& (TIME_NOTIMEMARKER
| TIME_FORCE24HOURFORMAT
))
3568 { FIXME("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3571 flags
&= (TIME_NOSECONDS
| TIME_NOMINUTESORSECONDS
); /* mask for OLE_GetFormatA*/
3574 { if (flags
& LOCALE_NOUSEROVERRIDE
) /*use system default*/
3575 { thislocale
= GetSystemDefaultLCID();
3577 GetLocaleInfoW(thislocale
, thisflags
, format_buf
, 40);
3578 thisformat
= format_buf
;
3581 { thisformat
= format
;
3584 if (xtime
== NULL
) /* NULL means use the current local time*/
3585 { GetSystemTime(&t
);
3592 ret
= OLE_GetFormatW(thislocale
, thisflags
, flags
, thistime
, thisformat
,
3597 /******************************************************************************
3598 * EnumCalendarInfoA [KERNEL32.196]
3600 BOOL WINAPI
EnumCalendarInfoA(
3601 CALINFO_ENUMPROCA calinfoproc
,LCID locale
,CALID calendar
,CALTYPE caltype
3603 FIXME("(%p,0x%04lx,0x%08lx,0x%08lx),stub!\n",calinfoproc
,locale
,calendar
,caltype
);