Fixed ANSI C violations.
[wine/dcerpc.git] / ole / ole2nls.c
blob29fe249d9607c14643ebbf250b88d629a925c47b
1 /*
2 * OLE2NLS library
4 * Copyright 1995 Martin von Loewis
5 * Copyright 1998 David Lee Lambert
6 * Copyright 2000 Julio César Gázquez
7 */
9 #include <string.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include <stdlib.h>
13 #include "windef.h"
14 #include "wingdi.h"
15 #include "winuser.h"
16 #include "heap.h"
17 #include "options.h"
18 #include "winver.h"
19 #include "winnls.h"
20 #include "winreg.h"
21 #include "winerror.h"
22 #include "debugtools.h"
23 #include "crtdll.h"
24 #include "main.h"
26 DEFAULT_DEBUG_CHANNEL(ole);
27 DECLARE_DEBUG_CHANNEL(string);
28 DECLARE_DEBUG_CHANNEL(win32);
30 struct NLS_langlocale {
31 const int lang;
32 struct NLS_localevar {
33 const int type;
34 const char *val;
35 } locvars[150];
38 static LPVOID lpNLSInfo = NULL;
40 #define LANG_BEGIN(l,s) { MAKELANGID(l,s), {
42 #define LOCVAL(type,value) {type,value},
44 #define LANG_END }},
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"
52 LANG_END
54 LANG_BEGIN (LANG_CZECH, SUBLANG_DEFAULT) /*0x0405*/
55 #include "nls/cze.nls"
56 LANG_END
58 LANG_BEGIN (LANG_DANISH, SUBLANG_DEFAULT) /*0x0406*/
59 #include "nls/dan.nls"
60 LANG_END
62 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN) /*0x0407*/
63 #include "nls/deu.nls"
64 LANG_END
65 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_SWISS) /*0x0807*/
66 #include "nls/des.nls"
67 LANG_END
68 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN) /*0x0C07*/
69 #include "nls/dea.nls"
70 LANG_END
71 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG) /*0x1007*/
72 #include "nls/del.nls"
73 LANG_END
74 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LIECHTENSTEIN) /*0x1407*/
75 #include "nls/dec.nls"
76 LANG_END
78 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_US) /*0x0409*/
79 #include "nls/enu.nls"
80 LANG_END
81 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_UK) /*0x0809*/
82 #include "nls/eng.nls"
83 LANG_END
84 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_AUS) /*0x0C09*/
85 #include "nls/ena.nls"
86 LANG_END
87 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CAN) /*0x1009*/
88 #include "nls/enc.nls"
89 LANG_END
90 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_NZ) /*0x1409*/
91 #include "nls/enz.nls"
92 LANG_END
93 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_EIRE) /*0x1809*/
94 #include "nls/irl.nls"
95 LANG_END
96 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_SAFRICA) /*0x1C09*/
97 #include "nls/ens.nls"
98 LANG_END
99 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_JAMAICA) /*0x2009*/
100 #include "nls/enj.nls"
101 LANG_END
102 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CARRIBEAN) /*0x2409*/
103 #include "nls/enb.nls"
104 LANG_END
105 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_BELIZE) /*0x2809*/
106 #include "nls/enl.nls"
107 LANG_END
108 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_TRINIDAD) /*0x2C09*/
109 #include "nls/ent.nls"
110 LANG_END
112 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH) /*0x040a*/
113 #include "nls/esp.nls"
114 LANG_END
115 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MEXICAN) /*0x080a*/
116 #include "nls/esm.nls"
117 LANG_END
118 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MODERN) /*0x0C0a*/
119 #include "nls/esn.nls"
120 LANG_END
121 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_GUATEMALA) /*0x100a*/
122 #include "nls/esg.nls"
123 LANG_END
124 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COSTARICA) /*0x140a*/
125 #include "nls/esc.nls"
126 LANG_END
127 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PANAMA) /*0x180a*/
128 #include "nls/esa.nls"
129 LANG_END
130 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_DOMINICAN) /*0x1C0A*/
131 #include "nls/esd.nls"
132 LANG_END
133 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_VENEZUELA) /*0x200a*/
134 #include "nls/esv.nls"
135 LANG_END
136 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COLOMBIA) /*0x240a*/
137 #include "nls/eso.nls"
138 LANG_END
139 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PERU) /*0x280a*/
140 #include "nls/esr.nls"
141 LANG_END
142 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA) /*0x2c0a*/
143 #include "nls/ess.nls"
144 LANG_END
145 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ECUADOR) /*0x300a*/
146 #include "nls/esf.nls"
147 LANG_END
148 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_CHILE) /*0x340a*/
149 #include "nls/esl.nls"
150 LANG_END
151 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_URUGUAY) /*0x380a*/
152 #include "nls/esy.nls"
153 LANG_END
154 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PARAGUAY) /*0x3c0a*/
155 #include "nls/esz.nls"
156 LANG_END
157 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_BOLIVIA) /*0x400a*/
158 #include "nls/esb.nls"
159 LANG_END
160 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_EL_SALVADOR) /*0x440a*/
161 #include "nls/ese.nls"
162 LANG_END
163 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_HONDURAS) /*0x480a*/
164 #include "nls/esh.nls"
165 LANG_END
166 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_NICARAGUA) /*0x4c0a*/
167 #include "nls/esi.nls"
168 LANG_END
169 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PUERTO_RICO) /*0x500a*/
170 #include "nls/esu.nls"
171 LANG_END
173 LANG_BEGIN (LANG_FINNISH, SUBLANG_DEFAULT) /*0x040B*/
174 #include "nls/fin.nls"
175 LANG_END
177 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH) /*0x040C*/
178 #include "nls/fra.nls"
179 LANG_END
180 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_BELGIAN) /*0x080C*/
181 #include "nls/frb.nls"
182 LANG_END
183 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_CANADIAN) /*0x0C0C*/
184 #include "nls/frc.nls"
185 LANG_END
186 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_SWISS) /*0x100C*/
187 #include "nls/frs.nls"
188 LANG_END
189 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_LUXEMBOURG) /*0x140C*/
190 #include "nls/frl.nls"
191 LANG_END
193 LANG_BEGIN (LANG_HUNGARIAN, SUBLANG_DEFAULT) /*0x040e*/
194 #include "nls/hun.nls"
195 LANG_END
197 LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN) /*0x0410*/
198 #include "nls/ita.nls"
199 LANG_END
200 LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN_SWISS) /*0x0810*/
201 #include "nls/its.nls"
202 LANG_END
204 LANG_BEGIN (LANG_JAPANESE, SUBLANG_DEFAULT) /*0x0411*/
205 #include "nls/jpn.nls"
206 LANG_END
208 LANG_BEGIN (LANG_KOREAN, SUBLANG_KOREAN) /*0x0412*/
209 #include "nls/kor.nls"
210 LANG_END
212 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH) /*0x0413*/
213 #include "nls/nld.nls"
214 LANG_END
215 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH_BELGIAN) /*0x0813*/
216 #include "nls/nlb.nls"
217 LANG_END
218 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH_SURINAM) /*0x0C13*/
219 #include "nls/nls.nls"
220 LANG_END
222 LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL) /*0x0414*/
223 #include "nls/nor.nls"
224 LANG_END
225 LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK) /*0x0814*/
226 #include "nls/non.nls"
227 LANG_END
229 LANG_BEGIN (LANG_POLISH, SUBLANG_DEFAULT) /*0x0415*/
230 #include "nls/plk.nls"
231 LANG_END
233 LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE_BRAZILIAN) /*0x0416*/
234 #include "nls/ptb.nls"
235 LANG_END
236 LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE) /*0x0816*/
237 #include "nls/ptg.nls"
238 LANG_END
240 LANG_BEGIN (LANG_RUSSIAN, SUBLANG_DEFAULT) /*0x419*/
241 #include "nls/rus.nls"
242 LANG_END
244 LANG_BEGIN (LANG_SLOVAK, SUBLANG_DEFAULT) /*0x041b*/
245 #include "nls/sky.nls"
246 LANG_END
248 LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH) /*0x041d*/
249 #include "nls/sve.nls"
250 LANG_END
251 LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH_FINLAND) /*0x081d*/
252 #include "nls/svf.nls"
253 LANG_END
255 LANG_BEGIN (LANG_THAI, SUBLANG_DEFAULT) /*0x41e*/
256 #include "nls/tha.nls"
257 LANG_END
258 LANG_BEGIN (LANG_GAELIC, SUBLANG_DEFAULT) /* 0x043c */
259 #include "nls/gae.nls"
260 LANG_END
262 LANG_BEGIN (LANG_GAELIC, SUBLANG_GAELIC_SCOTTISH)
263 #include "nls/gdh.nls"
264 LANG_END
266 LANG_BEGIN (LANG_GAELIC, SUBLANG_GAELIC_MANX)
267 #include "nls/gdv.nls"
268 LANG_END
270 LANG_BEGIN (LANG_ESPERANTO, SUBLANG_DEFAULT) /*0x048f*/
271 #include "nls/esperanto.nls"
272 LANG_END
274 LANG_BEGIN (LANG_WALON, SUBLANG_DEFAULT) /*0x0490*/
275 #include "nls/wal.nls"
276 LANG_END
278 LANG_BEGIN (LANG_CORNISH, SUBLANG_DEFAULT) /* 0x0491 */
279 #include "nls/cor.nls"
280 LANG_END
282 LANG_BEGIN (LANG_WELSH, SUBLANG_DEFAULT) /* 0x0492 */
283 #include "nls/cym.nls"
284 LANG_END
286 LANG_BEGIN (LANG_BRETON, SUBLANG_DEFAULT) /* 0x0x93 */
287 #include "nls/brf.nls"
288 LANG_END
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 {
299 char *name;
300 DWORD id;
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),
317 LOCALE_ENTRY(SLIST),
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),
335 LOCALE_ENTRY(SDATE),
336 LOCALE_ENTRY(STIME),
337 LOCALE_ENTRY(SSHORTDATE),
338 LOCALE_ENTRY(SLONGDATE),
339 LOCALE_ENTRY(STIMEFORMAT),
340 LOCALE_ENTRY(IDATE),
341 LOCALE_ENTRY(ILDATE),
342 LOCALE_ENTRY(ITIME),
343 LOCALE_ENTRY(ITIMEMARKPOSN),
344 LOCALE_ENTRY(ICENTURY),
345 LOCALE_ENTRY(ITLZERO),
346 LOCALE_ENTRY(IDAYLZERO),
347 LOCALE_ENTRY(IMONLZERO),
348 LOCALE_ENTRY(S1159),
349 LOCALE_ENTRY(S2359),
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),
405 {NULL,0},
408 const struct map_lcid2str {
409 LCID langid;
410 const char *langname;
411 } languages[]={
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"},
429 {0x0403,"Catalan"},
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)"},
435 {0x0405,"Czech"},
436 {0x0406,"Danish"},
437 {0x0407,"German (Germany)"},
438 {0x0807,"German (Switzerland)"},
439 {0x0c07,"German (Austria)"},
440 {0x1007,"German (Luxembourg)"},
441 {0x1407,"German (Liechtenstein)"},
442 {0x0408,"Greek"},
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)"},
476 {0x040b,"Finnish"},
477 {0x040c,"French (France)"},
478 {0x080c,"French (Belgium)"},
479 {0x0c0c,"French (Canada)"},
480 {0x100c,"French (Switzerland)"},
481 {0x140c,"French (Luxembourg)"},
482 {0x180c,"French (Monaco)"},
483 {0x040d,"Hebrew"},
484 {0x040e,"Hungarian"},
485 {0x040f,"Icelandic"},
486 {0x0410,"Italian (Italy)"},
487 {0x0810,"Italian (Switzerland)"},
488 {0x0411,"Japanese"},
489 {0x0412,"Korean (Wansung)"},
490 {0x0812,"Korean (Johab)"},
491 {0x0413,"Dutch (Netherlands)"},
492 {0x0813,"Dutch (Belgium)"},
493 {0x0414,"Norwegian (Bokmal)"},
494 {0x0814,"Norwegian (Nynorsk)"},
495 {0x0415,"Polish"},
496 {0x0416,"Portuguese (Brazil)"},
497 {0x0816,"Portuguese (Portugal)"},
498 {0x0417,"Rhaeto Romanic"},
499 {0x0418,"Romanian"},
500 {0x0818,"Moldavian"},
501 {0x0419,"Russian (Russia)"},
502 {0x0819,"Russian (Moldavia)"},
503 {0x041a,"Croatian"},
504 {0x081a,"Serbian (latin)"},
505 {0x0c1a,"Serbian (cyrillic)"},
506 {0x041b,"Slovak"},
507 {0x041c,"Albanian"},
508 {0x041d,"Swedish (Sweden)"},
509 {0x081d,"Swedish (Finland)"},
510 {0x041e,"Thai"},
511 {0x041f,"Turkish"},
512 {0x0420,"Urdu"},
513 {0x0421,"Indonesian"},
514 {0x0422,"Ukrainian"},
515 {0x0423,"Belarusian"},
516 {0x0424,"Slovene"},
517 {0x0425,"Estonian"},
518 {0x0426,"Latvian"},
519 {0x0427,"Lithuanian (modern)"},
520 {0x0827,"Lithuanian (classic)"},
521 {0x0428,"Maori"},
522 {0x0429,"Farsi"},
523 {0x042a,"Vietnamese"},
524 {0x042b,"Armenian"},
525 {0x042c,"Azeri (latin)"},
526 {0x082c,"Azeri (cyrillic)"},
527 {0x042d,"Basque"},
528 {0x042e,"Sorbian"},
529 {0x042f,"Macedonian"},
530 {0x0430,"Sutu"},
531 {0x0431,"Tsonga"},
532 {0x0432,"Tswana"},
533 {0x0433,"Venda"},
534 {0x0434,"Xhosa"},
535 {0x0435,"Zulu"},
536 {0x0436,"Afrikaans"},
537 {0x0437,"Georgian"},
538 {0x0438,"Faeroese"},
539 {0x0439,"Hindi"},
540 {0x043a,"Maltese"},
541 {0x043b,"Saami"},
542 {0x043c,"Irish gaelic"},
543 {0x083c,"Scottish gaelic"},
544 {0x0c3c,"Manx Gaelic"},
545 {0x043e,"Malay (Malaysia)"},
546 {0x083e,"Malay (Brunei Darussalam)"},
547 {0x043f,"Kazak"},
548 {0x0441,"Swahili"},
549 {0x0443,"Uzbek (latin)"},
550 {0x0843,"Uzbek (cyrillic)"},
551 {0x0444,"Tatar"},
552 {0x0445,"Bengali"},
553 {0x0446,"Punjabi"},
554 {0x0447,"Gujarati"},
555 {0x0448,"Oriya"},
556 {0x0449,"Tamil"},
557 {0x044a,"Telugu"},
558 {0x044b,"Kannada"},
559 {0x044c,"Malayalam"},
560 {0x044d,"Assamese"},
561 {0x044e,"Marathi"},
562 {0x044f,"Sanskrit"},
563 {0x0457,"Konkani"},
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 */
569 {0x0000,"Unknown"}
570 }, languages_de[]={
571 {0x0401,"Arabic"},
572 {0x0402,"Bulgarisch"},
573 {0x0403,"Katalanisch"},
574 {0x0404,"Traditionales Chinesisch"},
575 {0x0405,"Tschecisch"},
576 {0x0406,"Dänisch"},
577 {0x0407,"Deutsch"},
578 {0x0408,"Griechisch"},
579 {0x0409,"Amerikanisches Englisch"},
580 {0x040A,"Kastilisches Spanisch"},
581 {0x040B,"Finnisch"},
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"},
591 {0x0415,"Polnisch"},
592 {0x0416,"Brasilianisches Portugiesisch"},
593 {0x0417,"Rdtoromanisch"},
594 {0x0418,"Rumdnisch"},
595 {0x0419,"Russisch"},
596 {0x041A,"Kroatoserbisch (lateinisch)"},
597 {0x041B,"Slowenisch"},
598 {0x041C,"Albanisch"},
599 {0x041D,"Schwedisch"},
600 {0x041E,"Thai"},
601 {0x041F,"Türkisch"},
602 {0x0420,"Urdu"},
603 {0x0421,"Bahasa"},
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;
646 if (userLCID == 0) {
647 char *buf=NULL;
648 char *lang,*country,*charset,*dialect,*next;
649 int ret=0;
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 );
662 lang=buf;
664 do {
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);
672 lang=next;
674 } while (lang && !ret);
676 /* FIXME : are strings returned by getenv() to be free()'ed ? */
677 userLCID = (LANGID)ret;
679 return userLCID;
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)
702 { switch (lcid)
703 { case LOCALE_SYSTEM_DEFAULT:
704 return GetSystemDefaultLCID();
705 case LOCALE_USER_DEFAULT:
706 return GetUserDefaultLCID();
707 case 0:
708 return MAKELCID (LANG_NEUTRAL, SUBLANG_NEUTRAL);
710 return MAKELANGID( PRIMARYLANGID(lcid), SUBLANG_NEUTRAL);
712 /******************************************************************************
713 * GetLocaleInfo32A [KERNEL32.342]
715 * NOTES
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)
724 LPCSTR retString;
725 int found,i;
726 int lang=0;
728 TRACE("(lcid=0x%lx,lctype=0x%lx,%p,%x)\n",lcid,LCType,buf,len);
730 if (len && (! buf) ) {
731 SetLastError(ERROR_INSUFFICIENT_BUFFER);
732 return 0;
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 */
748 retString=0;
749 /* If we are through all of this, retLen should not be zero anymore.
750 If it is, the value is not supported */
751 i=0;
752 while (locale_name2id[i].name!=NULL) {
753 if (LCType == locale_name2id[i].id) {
754 retString = locale_name2id[i].name;
755 break;
757 i++;
759 if (!retString) {
760 FIXME("Unkown LC type %lX\n",LCType);
761 return 0;
764 found=0;lang=lcid;
765 for (i=0;(i<3 && !found);i++) {
766 int j;
768 for (j=0;j<sizeof(langlocales)/sizeof(langlocales[0]);j++) {
769 if (langlocales[j].lang == lang) {
770 int k;
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) {
774 found = 1;
775 retString = langlocales[j].locvars[k].val;
776 break;
779 if (found)
780 break;
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;
789 if(!found) {
790 ERR("'%s' not supported for your language (%04X).\n",
791 retString,(WORD)lcid);
792 SetLastError(ERROR_INVALID_PARAMETER);
793 return 0;
795 /* a FONTSIGNATURE is not a string, just 6 DWORDs */
796 if (LCType == LOCALE_FONTSIGNATURE) {
797 if (len)
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]
809 * NOTES
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)
815 { WORD wlen;
816 LPSTR abuf;
818 if (len && (! wbuf) )
819 { SetLastError(ERROR_INSUFFICIENT_BUFFER);
820 return 0;
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);
830 return wlen;
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);
839 return TRUE;
842 /******************************************************************************
843 * IsValidLocale [KERNEL32.489]
845 BOOL WINAPI IsValidLocale(LCID lcid,DWORD flags)
847 /* we support ANY language. Well, at least say that...*/
848 return TRUE;
851 /******************************************************************************
852 * EnumSystemLocales32W [KERNEL32.209]
854 BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum,
855 DWORD flags )
857 int i;
858 BOOL ret;
859 WCHAR buffer[200];
860 HKEY xhkey;
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)) {
865 i=0;
866 while (1) {
867 if (ERROR_SUCCESS!=RegEnumKeyW(xhkey,i,buffer,sizeof(buffer)))
868 break;
869 if (!lpfnLocaleEnum(buffer))
870 break;
871 i++;
873 RegCloseKey(xhkey);
874 return TRUE;
877 i=0;
878 while (languages[i].langid!=0)
880 LPWSTR cp;
881 char xbuffer[10];
883 sprintf(xbuffer,"%08lx",(DWORD)languages[i].langid);
885 cp = HEAP_strdupAtoW( GetProcessHeap(), 0, xbuffer );
886 ret = lpfnLocaleEnum(cp);
887 HeapFree( GetProcessHeap(), 0, cp );
888 if (!ret) break;
889 i++;
891 return TRUE;
894 /******************************************************************************
895 * EnumSystemLocales32A [KERNEL32.208]
897 BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum,
898 DWORD flags)
900 int i;
901 CHAR buffer[200];
902 HKEY xhkey;
904 TRACE_(win32)("(%p,%08lx)\n",
905 lpfnLocaleEnum,flags
908 if ( ERROR_SUCCESS==RegOpenKeyA(HKEY_LOCAL_MACHINE,
909 "System\\CurrentControlSet\\Control\\Nls\\Locale\\",
910 &xhkey)) {
911 i=0;
912 while (1) {
913 DWORD size=sizeof(buffer);
914 if (ERROR_SUCCESS!=RegEnumValueA(xhkey,i,buffer,&size,NULL,
915 NULL, NULL,NULL))
916 break;
917 if (size && !lpfnLocaleEnum(buffer))
918 break;
919 i++;
921 RegCloseKey(xhkey);
922 return TRUE;
924 i=0;
925 while (languages[i].langid!=0) {
926 sprintf(buffer,"%08lx",(DWORD)languages[i].langid);
927 if (!lpfnLocaleEnum(buffer))
928 break;
929 i++;
931 return TRUE;
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[] = {
1194 0x0000, /* - 0 */
1195 0x0000, /* - 1 */
1196 0x0000, /* - 2 */
1197 0x0000, /* - 3 */
1198 0x0000, /* - 4 */
1199 0x0000, /* - 5 */
1200 0x0000, /* - 6 */
1201 0x0000, /* - 7 */
1202 0x0000, /* - 8 */
1203 0x0008, /* - 9 */
1204 0x0008, /* - 10 */
1205 0x0008, /* - 11 */
1206 0x0008, /* - 12 */
1207 0x0008, /* - 13 */
1208 0x0000, /* - 14 */
1209 0x0000, /* - 15 */
1210 0x0000, /* - 16 */
1211 0x0000, /* - 17 */
1212 0x0000, /* - 18 */
1213 0x0000, /* - 19 */
1214 0x0000, /* - 20 */
1215 0x0000, /* - 21 */
1216 0x0000, /* - 22 */
1217 0x0000, /* - 23 */
1218 0x0000, /* - 24 */
1219 0x0000, /* - 25 */
1220 0x0000, /* - 26 */
1221 0x0000, /* - 27 */
1222 0x0000, /* - 28 */
1223 0x0000, /* - 29 */
1224 0x0000, /* - 30 */
1225 0x0000, /* - 31 */
1226 0x0048, /* - 32 */
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 */
1354 0x0008, /*   - 160 */
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)
1477 int i;
1479 if ((src==NULL) || (chartype==NULL) || (src==(LPSTR)chartype))
1481 SetLastError(ERROR_INVALID_PARAMETER);
1482 return FALSE;
1485 if (cchSrc==-1)
1486 cchSrc=lstrlenA(src)+1;
1488 switch (dwInfoType) {
1489 case CT_CTYPE1:
1490 for (i=0;i<cchSrc;i++)
1492 chartype[i] = 0;
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;
1503 /* C1_XDIGIT */
1505 return TRUE;
1507 case CT_CTYPE2:
1508 for (i=0;i<cchSrc;i++)
1510 chartype[i]=(WORD)CT_CType2_LUT[i];
1512 return TRUE;
1514 case CT_CTYPE3:
1515 for (i=0;i<cchSrc;i++)
1517 chartype[i]=OLE2NLS_CT_CType3_LUT[i];
1519 return TRUE;
1521 default:
1522 ERR("Unknown dwInfoType:%ld\n",dwInfoType);
1523 return FALSE;
1527 /******************************************************************************
1528 * GetStringType32W [KERNEL32.399]
1530 * NOTES
1531 * Yes, this is missing LCID locale. MS fault.
1533 BOOL WINAPI GetStringTypeW(DWORD dwInfoType,LPCWSTR src,INT cchSrc,
1534 LPWORD chartype)
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)
1547 int i;
1550 if (cchSrc==-1)
1551 cchSrc=lstrlenW(src)+1;
1553 switch (dwInfoType) {
1554 case CT_CTYPE2:
1555 FIXME("CT_CTYPE2 not supported.\n");
1556 return FALSE;
1557 case CT_CTYPE3:
1558 FIXME("CT_CTYPE3 not supported.\n");
1559 return FALSE;
1560 default:break;
1562 for (i=0;i<cchSrc;i++) {
1563 chartype[i] = 0;
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;
1574 /* C1_XDIGIT */
1576 return TRUE;
1579 /*****************************************************************
1580 * WINE_GetLanguageName [internal]
1582 static LPCSTR WINE_GetLanguageName( UINT langid )
1584 int i;
1585 for ( i = 0; languages[i].langid != 0; i++ )
1586 if ( langid == languages[i].langid )
1587 break;
1589 return languages[i].langname;
1592 /***********************************************************************
1593 * VerLanguageNameA [KERNEL32.709][VERSION.9]
1595 DWORD WINAPI VerLanguageNameA( UINT wLang, LPSTR szLang, UINT nSize )
1597 char buffer[80];
1598 LPCSTR name;
1599 DWORD result;
1602 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1603 * from the registry.
1606 sprintf( buffer,
1607 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1608 wLang );
1610 result = RegQueryValueA( HKEY_LOCAL_MACHINE, buffer, szLang, (LPDWORD)&nSize );
1611 if ( result == ERROR_SUCCESS || result == ERROR_MORE_DATA )
1612 return nSize;
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 )
1628 char buffer[80];
1629 LPWSTR keyname;
1630 LPCSTR name;
1631 DWORD result;
1634 * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1635 * from the registry.
1638 sprintf( buffer,
1639 "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1640 wLang );
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 )
1647 return nSize;
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[] = {
1660 6 , 3, /* - 1 */
1661 6 , 4, /* - 2 */
1662 6 , 5, /* - 3 */
1663 6 , 6, /* - 4 */
1664 6 , 7, /* - 5 */
1665 6 , 8, /* - 6 */
1666 6 , 9, /* - 7 */
1667 6 , 10, /* - 8 */
1668 7 , 5, /* - 9 */
1669 7 , 6, /* - 10 */
1670 7 , 7, /* - 11 */
1671 7 , 8, /* - 12 */
1672 7 , 9, /* - 13 */
1673 6 , 11, /* - 14 */
1674 6 , 12, /* - 15 */
1675 6 , 13, /* - 16 */
1676 6 , 14, /* - 17 */
1677 6 , 15, /* - 18 */
1678 6 , 16, /* - 19 */
1679 6 , 17, /* - 20 */
1680 6 , 18, /* - 21 */
1681 6 , 19, /* - 22 */
1682 6 , 20, /* - 23 */
1683 6 , 21, /* - 24 */
1684 6 , 22, /* - 25 */
1685 6 , 23, /* - 26 */
1686 6 , 24, /* - 27 */
1687 6 , 25, /* - 28 */
1688 6 , 26, /* - 29 */
1689 6 , 27, /* - 30 */
1690 6 , 28, /* - 31 */
1691 7 , 2, /* - 32 */
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 */
1702 8 , 3, /* + - 43 */
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 */
1819 7 , 4, /*   - 160 */
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[] = {
1921 123, /* ƒ - 131 */
1922 2, /* „ - 132 */
1923 2, /* … - 133 */
1924 2, /* † - 134 */
1925 2, /* ‡ - 135 */
1926 3, /* ˆ - 136 */
1927 2, /* ‰ - 137 */
1928 20, /* Š - 138 */
1929 2, /* ‹ - 139 */
1930 2, /* Π- 140 */
1931 2, /* � - 141 */
1932 2, /* Ž - 142 */
1933 2, /* � - 143 */
1934 2, /* � - 144 */
1935 2, /* ‘ - 145 */
1936 2, /* ’ - 146 */
1937 2, /* “ - 147 */
1938 2, /* ” - 148 */
1939 2, /* • - 149 */
1940 2, /* – - 150 */
1941 2, /* — - 151 */
1942 2, /* ˜ - 152 */
1943 2, /* ™ - 153 */
1944 20, /* š - 154 */
1945 2, /* › - 155 */
1946 2, /* œ - 156 */
1947 2, /* � - 157 */
1948 2, /* ž - 158 */
1949 19, /* Ÿ - 159 */
1950 2, /*   - 160 */
1951 2, /* ¡ - 161 */
1952 2, /* ¢ - 162 */
1953 2, /* £ - 163 */
1954 2, /* ¤ - 164 */
1955 2, /* ¥ - 165 */
1956 2, /* ¦ - 166 */
1957 2, /* § - 167 */
1958 2, /* ¨ - 168 */
1959 2, /* © - 169 */
1960 3, /* ª - 170 */
1961 2, /* « - 171 */
1962 2, /* ¬ - 172 */
1963 2, /* ­ - 173 */
1964 2, /* ® - 174 */
1965 2, /* ¯ - 175 */
1966 2, /* ° - 176 */
1967 2, /* ± - 177 */
1968 2, /* ² - 178 */
1969 2, /* ³ - 179 */
1970 2, /* ´ - 180 */
1971 2, /* µ - 181 */
1972 2, /* ¶ - 182 */
1973 2, /* · - 183 */
1974 2, /* ¸ - 184 */
1975 2, /* ¹ - 185 */
1976 3, /* º - 186 */
1977 2, /* » - 187 */
1978 2, /* ¼ - 188 */
1979 2, /* ½ - 189 */
1980 2, /* ¾ - 190 */
1981 2, /* ¿ - 191 */
1982 15, /* À - 192 */
1983 14, /* Á - 193 */
1984 18, /* Â - 194 */
1985 25, /* Ã - 195 */
1986 19, /* Ä - 196 */
1987 26, /* Å - 197 */
1988 2, /* Æ - 198 */
1989 28, /* Ç - 199 */
1990 15, /* È - 200 */
1991 14, /* É - 201 */
1992 18, /* Ê - 202 */
1993 19, /* Ë - 203 */
1994 15, /* Ì - 204 */
1995 14, /* Í - 205 */
1996 18, /* Î - 206 */
1997 19, /* Ï - 207 */
1998 104, /* Ð - 208 */
1999 25, /* Ñ - 209 */
2000 15, /* Ò - 210 */
2001 14, /* Ó - 211 */
2002 18, /* Ô - 212 */
2003 25, /* Õ - 213 */
2004 19, /* Ö - 214 */
2005 2, /* × - 215 */
2006 33, /* Ø - 216 */
2007 15, /* Ù - 217 */
2008 14, /* Ú - 218 */
2009 18, /* Û - 219 */
2010 19, /* Ü - 220 */
2011 14, /* Ý - 221 */
2012 2, /* Þ - 222 */
2013 2, /* ß - 223 */
2014 15, /* à - 224 */
2015 14, /* á - 225 */
2016 18, /* â - 226 */
2017 25, /* ã - 227 */
2018 19, /* ä - 228 */
2019 26, /* å - 229 */
2020 2, /* æ - 230 */
2021 28, /* ç - 231 */
2022 15, /* è - 232 */
2023 14, /* é - 233 */
2024 18, /* ê - 234 */
2025 19, /* ë - 235 */
2026 15, /* ì - 236 */
2027 14, /* í - 237 */
2028 18, /* î - 238 */
2029 19, /* ï - 239 */
2030 104, /* ð - 240 */
2031 25, /* ñ - 241 */
2032 15, /* ò - 242 */
2033 14, /* ó - 243 */
2034 18, /* ô - 244 */
2035 25, /* õ - 245 */
2036 19, /* ö - 246 */
2037 2, /* ÷ - 247 */
2038 33, /* ø - 248 */
2039 15, /* ù - 249 */
2040 14, /* ú - 250 */
2041 18, /* û - 251 */
2042 19, /* ü - 252 */
2043 14, /* ý - 253 */
2044 2, /* þ - 254 */
2045 19, /* ÿ - 255 */
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)
2088 return 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,...
2100 * RETURNS
2101 * Error : 0.
2102 * Success : length of the result string.
2104 * NOTES
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 */)
2127 int i;
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);
2136 return 0;
2138 if (srclen == -1)
2139 srclen = lstrlenA(srcstr) + 1 ; /* (include final '\0') */
2141 #define LCMAPSTRINGA_SUPPORTED_FLAGS (LCMAP_UPPERCASE | \
2142 LCMAP_LOWERCASE | \
2143 LCMAP_SORTKEY | \
2144 NORM_IGNORECASE | \
2145 NORM_IGNORENONSPACE | \
2146 SORT_STRINGSORT | \
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",
2156 lcid,
2157 mapflags,
2158 srcstr,
2159 srclen,
2160 dststr,
2161 dstlen,
2162 mapflags & ~LCMAPSTRINGA_SUPPORTED_FLAGS
2166 if ( !(mapflags & LCMAP_SORTKEY) )
2168 int i,j;
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
2178 these cases. */
2179 if (dstlen==0)
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])) )
2186 j++;
2188 return j;
2191 else
2193 if (dstlen==0)
2194 return srclen;
2195 if (dstlen<srclen)
2197 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2198 return 0;
2201 if (mapflags & LCMAP_UPPERCASE)
2202 f = toupper;
2203 else if (mapflags & LCMAP_LOWERCASE)
2204 f = tolower;
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]);
2212 j++;
2215 return j;
2218 /* else ... (mapflags & LCMAP_SORTKEY) */
2220 int unicode_len=0;
2221 int case_len=0;
2222 int diacritic_len=0;
2223 int delayed_punctuation_len=0;
2224 char *case_component;
2225 char *diacritic_component;
2226 char *delayed_punctuation_component;
2227 int room,count;
2228 int flag_stringsort = mapflags & SORT_STRINGSORT;
2230 /* compute how much room we will need */
2231 for (i=0;i<srclen;i++)
2233 int ofs;
2234 unsigned char source_char = srcstr[i];
2235 if (source_char!='\0')
2237 if (flag_stringsort || !OLE2NLS_isPunctuation(source_char))
2239 unicode_len++;
2240 if ( LCM_Unicode_LUT[-2+2*source_char] & ~15 )
2241 unicode_len++; /* double letter */
2243 else
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)
2258 case_len=0;
2259 if (mapflags & NORM_IGNORENONSPACE)
2260 diacritic_len=0;
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' */
2268 if (dstlen==0)
2269 return room;
2270 else if (dstlen<room)
2272 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2273 return 0;
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);
2280 return 0;
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')
2299 int type,longcode;
2300 type = LCM_Unicode_LUT[-2+2*source_char];
2301 longcode = type >> 4;
2302 type &= 15;
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 */
2316 else
2318 dststr[2*count] = type;
2319 dststr[2*count+1] = LCM_Unicode_LUT[-1+2*source_char];
2320 if (longcode)
2322 if (count<case_len)
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 */
2327 count++;
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 */
2336 if (count<case_len)
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);
2343 count++;
2347 dststr[room-1] = '\0';
2348 return room;
2352 /*************************************************************************
2353 * LCMapString32W [KERNEL32.493]
2355 * Convert a string, or generate a sort key from it.
2357 * NOTE
2359 * See LCMapString32A for documentation
2361 INT WINAPI LCMapStringW(
2362 LCID lcid,DWORD mapflags,LPCWSTR srcstr,INT srclen,LPWSTR dststr,
2363 INT dstlen)
2365 int i;
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);
2374 return 0;
2376 if (srclen==-1)
2377 srclen = lstrlenW(srcstr)+1;
2379 if (dstlen==0)
2380 return srclen;
2381 if (dstlen<srclen)
2383 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2384 return 0;
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));
2392 return srclen;
2394 else
2396 int (*f)(int)=identity;
2398 if (mapflags & LCMAP_UPPERCASE)
2399 f = toupper;
2400 else if (mapflags & LCMAP_LOWERCASE)
2401 f = tolower;
2402 for (i=0; i < srclen; i++)
2403 dststr[i] = (WCHAR) f(srcstr[i]);
2404 return srclen;
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
2421 * RETURNS
2423 * success: CSTR_LESS_THAN, CSTR_EQUAL, CSTR_GREATER_THAN
2424 * failure: 0
2426 * NOTES
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.
2432 * BUGS
2434 * This implementation ignores the locale
2436 * FIXME
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;
2449 int len1,len2;
2450 int result;
2451 LPSTR sk1,sk2;
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);
2459 return 0;
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");
2478 result = 0;
2480 else
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);
2488 if (result < 0)
2489 return 1;
2490 if (result == 0)
2491 return 2;
2493 /* must be greater, if we reach this point */
2494 return 3;
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)
2506 int len,ret;
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");
2534 if (!lpNewNLSInfo)
2536 lpNLSInfo = NULL;
2537 return TRUE;
2539 else
2541 if (!lpNLSInfo)
2543 lpNLSInfo = lpNewNLSInfo;
2544 return TRUE;
2548 return FALSE; /* ptr not set */
2551 /******************************************************************************
2552 * OLE_GetFormatA [Internal]
2554 * FIXME
2555 * If datelen == 0, it should return the reguired string length.
2557 This function implements stuff for GetDateFormat() and
2558 GetTimeFormat().
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
2565 MM two-digit month
2566 MMM short month name
2567 MMMM full month name
2568 y two-digit year, no leading 0
2569 yy two-digit year
2570 yyyy four-digit year
2571 gg era string
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,
2588 DWORD flags,
2589 DWORD tflags,
2590 LPSYSTEMTIME xtime,
2591 LPCSTR _format, /*in*/
2592 LPSTR date, /*out*/
2593 INT datelen)
2595 INT inpos, outpos;
2596 int count, type, inquote, Overflow;
2597 char buf[40];
2598 char format[40];
2599 char * pos;
2600 int buflen;
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);
2611 if(datelen == 0) {
2612 FIXME("datelen = 0, returning 255\n");
2613 return 255;
2616 /* initalize state variables and output buffer */
2617 inpos = outpos = 0;
2618 count = 0; inquote = 0; Overflow = 0;
2619 type = '\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]); */
2639 if (inquote) {
2640 if (format[inpos] == '\'') {
2641 if (format[inpos+1] == '\'') {
2642 inpos += 1;
2643 date[outpos++] = '\'';
2644 } else {
2645 inquote = 0;
2646 continue; /* we did nothing to the output */
2648 } else if (format[inpos] == '\0') {
2649 date[outpos++] = '\0';
2650 if (outpos > datelen) Overflow = 1;
2651 break;
2652 } else {
2653 date[outpos++] = format[inpos];
2654 if (outpos > datelen) {
2655 Overflow = 1;
2656 date[outpos-1] = '\0'; /* this is the last place where
2657 it's safe to write */
2658 break;
2661 } else if ( (count && (format[inpos] != type))
2662 || count == 4
2663 || (count == 2 && strchr("ghHmst", type)) )
2665 if (type == 'd') {
2666 if (count == 4) {
2667 GetLocaleInfoA(locale,
2668 LOCALE_SDAYNAME1
2669 + xtime->wDayOfWeek - 1,
2670 buf, sizeof(buf));
2671 } else if (count == 3) {
2672 GetLocaleInfoA(locale,
2673 LOCALE_SABBREVDAYNAME1
2674 + xtime->wDayOfWeek - 1,
2675 buf, sizeof(buf));
2676 } else {
2677 sprintf(buf, dgfmt[count], xtime->wDay);
2679 } else if (type == 'M') {
2680 if (count == 3) {
2681 GetLocaleInfoA(locale,
2682 LOCALE_SABBREVMONTHNAME1
2683 + xtime->wMonth - 1,
2684 buf, sizeof(buf));
2685 } else if (count == 4) {
2686 GetLocaleInfoA(locale,
2687 LOCALE_SMONTHNAME1
2688 + xtime->wMonth - 1,
2689 buf, sizeof(buf));
2690 } else {
2691 sprintf(buf, dgfmt[count], xtime->wMonth);
2693 } else if (type == 'y') {
2694 if (count == 4) {
2695 sprintf(buf, "%d", xtime->wYear);
2696 } else if (count == 3) {
2697 strcpy(buf, "yyy");
2698 WARN("unknown format, c=%c, n=%d\n", type, count);
2699 } else {
2700 sprintf(buf, dgfmt[count], xtime->wYear % 100);
2702 } else if (type == 'g') {
2703 if (count == 2) {
2704 FIXME("LOCALE_ICALENDARTYPE unimp.\n");
2705 strcpy(buf, "AD");
2706 } else {
2707 strcpy(buf, "g");
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') {
2714 /* 24-hour time */
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') {
2721 if (count == 1) {
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,
2726 (xtime->wHour<12)
2727 ? LOCALE_S1159 : LOCALE_S2359,
2728 buf, sizeof(buf));
2732 /* we need to check the next char in the format string
2733 again, no matter what happened */
2734 inpos--;
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 */
2740 strcat(date, buf);
2741 outpos += buflen;
2742 } else {
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");
2748 return 0;
2751 /* reset the variables we used to keep track of this item */
2752 count = 0;
2753 type = '\0';
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';
2758 break;
2759 } else if (count) {
2760 /* continuing a code for an item */
2761 count +=1;
2762 continue;
2763 } else if (strchr("hHmstyMdg", format[inpos])) {
2764 type = format[inpos];
2765 count = 1;
2766 continue;
2767 } else if (format[inpos] == '\'') {
2768 inquote = 1;
2769 continue;
2770 } else {
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);
2777 return 0;
2781 if (Overflow) {
2782 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2785 /* finish it off with a string terminator */
2786 outpos++;
2787 /* sanity check */
2788 if (outpos > datelen-1) outpos = datelen-1;
2789 date[outpos] = '\0';
2791 TRACE("OLE_GetFormatA returns string '%s', len %d\n",
2792 date, outpos);
2793 return outpos;
2796 /******************************************************************************
2797 * OLE_GetFormatW [INTERNAL]
2799 static INT OLE_GetFormatW(LCID locale, DWORD flags, DWORD tflags,
2800 LPSYSTEMTIME xtime,
2801 LPCWSTR format,
2802 LPWSTR output, INT outlen)
2804 INT inpos, outpos;
2805 int count, type=0, inquote;
2806 int Overflow; /* loop check */
2807 WCHAR buf[40];
2808 int buflen=0;
2809 WCHAR arg0[] = {0}, arg1[] = {'%','d',0};
2810 WCHAR arg2[] = {'%','0','2','d',0};
2811 WCHAR *argarr[3];
2812 int datevars=0, timevars=0;
2814 argarr[0] = arg0;
2815 argarr[1] = arg1;
2816 argarr[2] = arg2;
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);
2825 if(outlen == 0) {
2826 FIXME("outlen = 0, returning 255\n");
2827 return 255;
2830 /* initialize state variables */
2831 inpos = outpos = 0;
2832 count = 0;
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++) {
2839 if (inquote) {
2840 if (format[inpos] == (WCHAR) '\'') {
2841 if (format[inpos+1] == '\'') {
2842 inpos++;
2843 output[outpos++] = '\'';
2844 } else {
2845 inquote = 0;
2846 continue;
2848 } else if (format[inpos] == 0) {
2849 output[outpos++] = 0;
2850 if (outpos > outlen) Overflow = 1;
2851 break; /* normal exit (within a quote) */
2852 } else {
2853 output[outpos++] = format[inpos]; /* copy input */
2854 if (outpos > outlen) {
2855 Overflow = 1;
2856 output[outpos-1] = 0;
2857 break;
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') ) ) {
2870 if (type == 'd') {
2871 if (count == 3) {
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) );
2880 } else {
2881 wsnprintfW(buf, 5, argarr[count], xtime->wDay );
2883 } else if (type == 'M') {
2884 if (count == 4) {
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) );
2892 } else {
2893 wsnprintfW(buf, 5, argarr[count], xtime->wMonth);
2895 } else if (type == 'y') {
2896 if (count == 4) {
2897 wsnprintfW(buf, 6, argarr[1] /* "%d" */,
2898 xtime->wYear);
2899 } else if (count == 3) {
2900 lstrcpynAtoW(buf, "yyy", 5);
2901 } else {
2902 wsnprintfW(buf, 6, argarr[count],
2903 xtime->wYear % 100);
2905 } else if (type == 'g') {
2906 if (count == 2) {
2907 FIXME("LOCALE_ICALENDARTYPE unimplemented\n");
2908 lstrcpynAtoW(buf, "AD", 5);
2909 } else {
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],
2919 xtime->wHour);
2920 } else if (type == 'm' ) {
2921 wsnprintfW(buf, 5, argarr[count],
2922 xtime->wMinute);
2923 } else if (type == 's' ) {
2924 wsnprintfW(buf, 5, argarr[count],
2925 xtime->wSecond);
2926 } else if (type == 't') {
2927 GetLocaleInfoW(locale, (xtime->wHour < 12) ?
2928 LOCALE_S1159 : LOCALE_S2359,
2929 buf, sizeof(buf) );
2930 if (count == 1) {
2931 buf[1] = 0;
2935 /* no matter what happened, we need to check this next
2936 character the next time we loop through */
2937 inpos--;
2939 /* cat buf onto the output */
2940 outlen = lstrlenW(buf);
2941 if (outpos + buflen < outlen) {
2942 lstrcpyW( output + outpos, buf );
2943 outpos += buflen;
2944 } else {
2945 lstrcpynW( output + outpos, buf, outlen - outpos );
2946 Overflow = 1;
2947 break; /* Abnormal exit */
2950 /* reset the variables we used this time */
2951 count = 0;
2952 type = '\0';
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
2956 string */
2957 output[outpos] = 0;
2958 break; /* NORMAL EXIT */
2959 } else if (count) {
2960 /* how we keep track of the middle of a format spec */
2961 count++;
2962 continue;
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];
2973 count = 1;
2974 continue;
2975 } else if (format[inpos] == '\'') {
2976 inquote = 1;
2977 continue;
2978 } else {
2979 /* unquoted literals */
2980 output[outpos++] = format[inpos];
2984 if (Overflow) {
2985 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2986 WARN(" buffer overflow\n");
2989 /* final string terminator and sanity check */
2990 outpos++;
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
3020 * - gg era string
3023 INT WINAPI GetDateFormatA(LCID locale,DWORD flags,
3024 LPSYSTEMTIME xtime,
3025 LPCSTR format, LPSTR date,INT datelen)
3028 char format_buf[40];
3029 LPCSTR thisformat;
3030 SYSTEMTIME t;
3031 LPSYSTEMTIME thistime;
3032 LCID thislocale;
3033 INT ret;
3035 TRACE("(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",
3036 locale,flags,xtime,format,date,datelen);
3038 if (!locale) {
3039 locale = LOCALE_SYSTEM_DEFAULT;
3042 if (locale == LOCALE_SYSTEM_DEFAULT) {
3043 thislocale = GetSystemDefaultLCID();
3044 } else if (locale == LOCALE_USER_DEFAULT) {
3045 thislocale = GetUserDefaultLCID();
3046 } else {
3047 thislocale = locale;
3050 if (xtime == NULL) {
3051 GetSystemTime(&t);
3052 thistime = &t;
3053 } else {
3054 thistime = xtime;
3057 if (format == NULL) {
3058 GetLocaleInfoA(thislocale, ((flags&DATE_LONGDATE)
3059 ? LOCALE_SLONGDATE
3060 : LOCALE_SSHORTDATE),
3061 format_buf, sizeof(format_buf));
3062 thisformat = format_buf;
3063 } else {
3064 thisformat = format;
3068 ret = OLE_GetFormatA(thislocale, flags, 0, thistime, thisformat,
3069 date, datelen);
3072 TRACE(
3073 "GetDateFormat32A() returning %d, with data=%s\n",
3074 ret, date);
3075 return ret;
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,
3087 LPSYSTEMTIME xtime,
3088 LPCWSTR format,
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);
3111 return FALSE;
3114 switch(dwFlags)
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;
3123 return TRUE;
3124 case DATE_LONGDATE:
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;
3129 return TRUE;
3130 default:
3131 FIXME("Unknown date format (%ld)\n", dwFlags);
3132 SetLastError(ERROR_INVALID_PARAMETER);
3133 return FALSE;
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);
3145 return FALSE;
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);
3159 return FALSE;
3162 if(dwFlags)
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;
3172 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);
3183 return FALSE;
3187 /**************************************************************************
3188 * GetNumberFormat32A (KERNEL32.355)
3190 INT WINAPI GetNumberFormatA(LCID locale, DWORD dwflags,
3191 LPCSTR lpValue, const NUMBERFMTA * lpFormat,
3192 LPSTR lpNumberStr, int cchNumber)
3194 LCID thislocale;
3195 UINT thisnumdigits;
3196 UINT thisleadingzero;
3197 UINT thisgrouping[8]={ -1 };
3198 LPCSTR thisdecimalsep;
3199 LPCSTR thisthousandsep;
3200 UINT thisnegativeorder;
3203 LPCSTR sptr;
3204 LPSTR dptr;
3205 char roundbuffer[24]; /* Should be enough */
3206 char *gptr;
3207 int i,j;
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 */
3215 if (!locale) {
3216 locale = LOCALE_SYSTEM_DEFAULT;
3219 if (locale == LOCALE_SYSTEM_DEFAULT) {
3220 thislocale = GetSystemDefaultLCID();
3221 } else if (locale == LOCALE_USER_DEFAULT) {
3222 thislocale = GetUserDefaultLCID();
3223 } else {
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
3248 as usual. */
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';
3259 if (*gptr==';')
3260 gptr++;
3263 /* Take care for repeating group size */
3264 if (thisgrouping[i-1]==0) {
3265 for (j=i-1;j<8;j++)
3266 thisgrouping[j]=thisgrouping[i-2];
3267 lastgroup=7;
3268 } else
3269 lastgroup=i-1;
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);
3286 } else {
3288 thisnumdigits = lpFormat->NumDigits;
3289 thisleadingzero = lpFormat->LeadingZero;
3291 thisgrouping[1] = lpFormat->Grouping;
3292 for (i=2;i<8;i++)
3293 thisgrouping[i]=thisgrouping[i-1]+lpFormat->Grouping;
3294 lastgroup=7;
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 */
3313 sptr=lpValue;
3314 if (*sptr=='-') {
3315 negflag=1;
3316 sptr++;
3318 for (; *sptr=='0'; sptr++) leadingzeros++; /* Ignore leading zeros */
3319 for (; *sptr!='\0'; sptr++) {
3320 if (!dotflag && *sptr=='.') {
3321 dotflag=1;
3322 } else if (*sptr<'0' || *sptr>'9') {
3323 SetLastError(ERROR_INVALID_PARAMETER);
3324 return 0;
3325 } else {
3326 if (dotflag) {
3327 decsize++;
3328 } else {
3329 intsize++;
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);
3346 if (*sptr>='5') {
3347 strcpy(roundbuffer+1,lpValue);
3348 if (negflag) {
3349 *roundbuffer='-';
3350 *(roundbuffer+1)='0';
3351 } else
3352 *roundbuffer='0';
3353 dptr=roundbuffer+(sptr-lpValue); // +1-1
3355 while ( (++*dptr) > '9') {
3356 *(dptr--)='0';
3357 if (*dptr=='.') dptr--;
3359 if ((negflag ? *(roundbuffer+leadingzeros+1) : *(roundbuffer+leadingzeros)) == '1')
3360 intsize++;
3361 sptr=roundbuffer;
3362 } else
3363 sptr=lpValue;
3364 } else
3365 sptr=lpValue;
3367 totalsize=intsize;
3369 if (intsize==0 && (decsize==0 || thisleadingzero))
3370 totalsize++;
3372 if (negflag)
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 */
3385 return totalsize+1;
3386 else
3387 if (cchNumber<totalsize+1) { /* +1 = Null terminator (right?) */
3388 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3389 return 0;
3390 } else {
3393 /* Formatting stuff starts here */
3395 dptr=lpNumberStr;
3397 if (negflag) {
3398 if (thisnegativeorder==0)
3399 *dptr++='(';
3400 else if (thisnegativeorder<=2) {
3401 strcpy(dptr,negative_buf);
3402 dptr+=negsignsize;
3403 if (thisnegativeorder==2)
3404 *dptr++=' ';
3406 sptr++;
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;
3420 j--;
3424 if (decsize>0)
3425 sptr++;
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];
3433 if (negflag) {
3434 if (thisnegativeorder==0)
3435 *dptr++=')';
3436 else if (thisnegativeorder>=3) {
3437 if (thisnegativeorder==4)
3438 *dptr++=' ';
3439 strcpy(dptr,negative_buf);
3440 dptr+=negsignsize;
3441 sptr++;
3445 *dptr='\0';
3448 return totalsize+1;
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)
3468 if (!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();
3478 else
3479 { return locale;
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)
3501 INT WINAPI
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];
3509 LPCSTR thisformat;
3510 SYSTEMTIME t;
3511 LPSYSTEMTIME thistime;
3512 LCID thislocale=0;
3513 DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */
3514 INT ret;
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*/
3526 if (format == NULL)
3527 { if (flags & LOCALE_NOUSEROVERRIDE) /*use system default*/
3528 { thislocale = GetSystemDefaultLCID();
3530 GetLocaleInfoA(thislocale, thisflags, format_buf, sizeof(format_buf));
3531 thisformat = format_buf;
3533 else
3534 { thisformat = format;
3537 if (xtime == NULL) /* NULL means use the current local time*/
3538 { GetLocalTime(&t);
3539 thistime = &t;
3541 else
3542 { thistime = xtime;
3544 ret = OLE_GetFormatA(thislocale, thisflags, flags, thistime, thisformat,
3545 timestr, timelen);
3546 return ret;
3550 /******************************************************************************
3551 * GetTimeFormat32W [KERNEL32.423]
3552 * Makes a Unicode string of the time
3554 INT WINAPI
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];
3562 LPCWSTR thisformat;
3563 SYSTEMTIME t;
3564 LPSYSTEMTIME thistime;
3565 LCID thislocale=0;
3566 DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */
3567 INT ret;
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*/
3580 if (format == NULL)
3581 { if (flags & LOCALE_NOUSEROVERRIDE) /*use system default*/
3582 { thislocale = GetSystemDefaultLCID();
3584 GetLocaleInfoW(thislocale, thisflags, format_buf, 40);
3585 thisformat = format_buf;
3587 else
3588 { thisformat = format;
3591 if (xtime == NULL) /* NULL means use the current local time*/
3592 { GetSystemTime(&t);
3593 thistime = &t;
3595 else
3596 { thistime = xtime;
3599 ret = OLE_GetFormatW(thislocale, thisflags, flags, thistime, thisformat,
3600 timestr, timelen);
3601 return ret;
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);
3611 return FALSE;