Updated, added chapter on configuration and architecture.
[wine] / ole / ole2nls.c
1 /*
2  *      OLE2NLS library
3  *
4  *      Copyright 1995  Martin von Loewis
5  *      Copyright 1998  David Lee Lambert
6  */
7
8 #include <string.h>
9 #include <ctype.h>
10 #include <stdlib.h>
11 #include "winuser.h"
12 #include "heap.h"
13 #include "options.h"
14 #include "winver.h"
15 #include "winnls.h"
16 #include "winreg.h"
17 #include "winerror.h"
18 #include "debugtools.h"
19 #include "crtdll.h"
20 #include "main.h"
21
22 DECLARE_DEBUG_CHANNEL(file)
23 DECLARE_DEBUG_CHANNEL(ole)
24 DECLARE_DEBUG_CHANNEL(string)
25 DECLARE_DEBUG_CHANNEL(win32)
26
27 struct NLS_langlocale {
28         const int lang;
29         struct NLS_localevar {
30                 const int       type;
31                 const char      *val;
32         } locvars[150];
33 };
34
35 static LPVOID lpNLSInfo = NULL;
36
37 #define LANG_BEGIN(l,s) {       MAKELANGID(l,s), {
38
39 #define LOCVAL(type,value)                                      {type,value},
40
41 #define LANG_END                                         }},
42
43 static const struct NLS_langlocale langlocales[] = {
44 /* add languages in numerical order of main language (last two digits)
45  * it is much easier to find the missing holes that way */
46
47 LANG_BEGIN (LANG_CATALAN, SUBLANG_DEFAULT)      /*0x0403*/
48 #include "nls/cat.nls"
49 LANG_END
50
51 LANG_BEGIN (LANG_CZECH, SUBLANG_DEFAULT)        /*0x0405*/
52 #include "nls/cze.nls"
53 LANG_END
54
55 LANG_BEGIN (LANG_DANISH, SUBLANG_DEFAULT)       /*0x0406*/
56 #include "nls/dan.nls"
57 LANG_END
58
59 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN)                /*0x0407*/
60 #include "nls/deu.nls"
61 LANG_END
62 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_SWISS)          /*0x0807*/
63 #include "nls/des.nls"
64 LANG_END
65 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN)       /*0x0C07*/
66 #include "nls/dea.nls"
67 LANG_END
68 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG)     /*0x1007*/
69 #include "nls/del.nls"
70 LANG_END
71 LANG_BEGIN (LANG_GERMAN, SUBLANG_GERMAN_LIECHTENSTEIN)  /*0x1407*/
72 #include "nls/dec.nls"
73 LANG_END
74
75 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_US)           /*0x0409*/
76 #include "nls/enu.nls"
77 LANG_END
78 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_UK)           /*0x0809*/
79 #include "nls/eng.nls"
80 LANG_END
81 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_AUS)          /*0x0C09*/
82 #include "nls/ena.nls"
83 LANG_END
84 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CAN)          /*0x1009*/
85 #include "nls/enc.nls"
86 LANG_END
87 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_NZ)           /*0x1409*/
88 #include "nls/enz.nls"
89 LANG_END
90 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_EIRE)         /*0x1809*/
91 #include "nls/irl.nls"
92 LANG_END
93 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_SAFRICA)      /*0x1C09*/
94 #include "nls/ens.nls"
95 LANG_END
96 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_JAMAICA)      /*0x2009*/
97 #include "nls/enj.nls"
98 LANG_END
99 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_CARRIBEAN)    /*0x2409*/
100 #include "nls/enb.nls"
101 LANG_END
102 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_BELIZE)       /*0x2809*/
103 #include "nls/enl.nls"
104 LANG_END
105 LANG_BEGIN (LANG_ENGLISH, SUBLANG_ENGLISH_TRINIDAD)     /*0x2C09*/
106 #include "nls/ent.nls"
107 LANG_END
108
109 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH)              /*0x040a*/
110 #include "nls/esp.nls"
111 LANG_END
112 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MEXICAN)      /*0x080a*/
113 #include "nls/esm.nls"
114 LANG_END
115 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_MODERN)       /*0x0C0a*/
116 #include "nls/esn.nls"
117 LANG_END
118 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_GUATEMALA)    /*0x100a*/
119 #include "nls/esg.nls"
120 LANG_END
121 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COSTARICA)    /*0x140a*/
122 #include "nls/esc.nls"
123 LANG_END
124 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PANAMA)       /*0x180a*/
125 #include "nls/esa.nls"
126 LANG_END
127 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_DOMINICAN)    /*0x1C0A*/
128 #include "nls/esd.nls"
129 LANG_END
130 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_VENEZUELA)    /*0x200a*/
131 #include "nls/esv.nls"
132 LANG_END
133 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_COLOMBIA)     /*0x240a*/
134 #include "nls/eso.nls"
135 LANG_END
136 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PERU)         /*0x280a*/
137 #include "nls/esr.nls"
138 LANG_END
139 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ARGENTINA)    /*0x2c0a*/
140 #include "nls/ess.nls"
141 LANG_END
142 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_ECUADOR)      /*0x300a*/
143 #include "nls/esf.nls"
144 LANG_END
145 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_CHILE)        /*0x340a*/
146 #include "nls/esl.nls"
147 LANG_END
148 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_URUGUAY)      /*0x380a*/
149 #include "nls/esy.nls"
150 LANG_END
151 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PARAGUAY)     /*0x3c0a*/
152 #include "nls/esz.nls"
153 LANG_END
154 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_BOLIVIA)      /*0x400a*/
155 #include "nls/esb.nls"
156 LANG_END
157 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_EL_SALVADOR)  /*0x440a*/
158 #include "nls/ese.nls"
159 LANG_END
160 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_HONDURAS)     /*0x480a*/
161 #include "nls/esh.nls"
162 LANG_END
163 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_NICARAGUA)    /*0x4c0a*/
164 #include "nls/esi.nls"
165 LANG_END
166 LANG_BEGIN (LANG_SPANISH, SUBLANG_SPANISH_PUERTO_RICO)  /*0x500a*/
167 #include "nls/esu.nls"
168 LANG_END
169
170 LANG_BEGIN (LANG_FINNISH, SUBLANG_DEFAULT)      /*0x040B*/
171 #include "nls/fin.nls"
172 LANG_END
173
174 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH)                /*0x040C*/
175 #include "nls/fra.nls"
176 LANG_END
177 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_BELGIAN)        /*0x080C*/
178 #include "nls/frb.nls"
179 LANG_END
180 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_CANADIAN)       /*0x0C0C*/
181 #include "nls/frc.nls"
182 LANG_END
183 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_SWISS)          /*0x100C*/
184 #include "nls/frs.nls"
185 LANG_END
186 LANG_BEGIN (LANG_FRENCH, SUBLANG_FRENCH_LUXEMBOURG)     /*0x140C*/
187 #include "nls/frl.nls"
188 LANG_END
189
190 LANG_BEGIN (LANG_HUNGARIAN, SUBLANG_DEFAULT)    /*0x040e*/
191 #include "nls/hun.nls"
192 LANG_END
193
194 LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN)              /*0x0410*/
195 #include "nls/ita.nls"
196 LANG_END
197 LANG_BEGIN (LANG_ITALIAN, SUBLANG_ITALIAN_SWISS)        /*0x0810*/
198 #include "nls/its.nls"
199 LANG_END
200
201 LANG_BEGIN (LANG_KOREAN, SUBLANG_KOREAN)        /*0x0412*/
202 #include "nls/kor.nls"
203 LANG_END
204
205 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH)          /*0x0413*/
206 #include "nls/nld.nls"
207 LANG_END
208 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH_BELGIAN)  /*0x0813*/
209 #include "nls/nlb.nls"
210 LANG_END
211 LANG_BEGIN (LANG_DUTCH, SUBLANG_DUTCH_SURINAM)  /*0x0C13*/
212 #include "nls/nls.nls"
213 LANG_END
214
215 LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL)   /*0x0414*/
216 #include "nls/nor.nls"
217 LANG_END
218 LANG_BEGIN (LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK)  /*0x0814*/
219 #include "nls/non.nls"
220 LANG_END
221
222 LANG_BEGIN (LANG_POLISH, SUBLANG_DEFAULT)       /*0x0415*/
223 #include "nls/plk.nls"
224 LANG_END
225
226 LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE_BRAZILIAN)      /*0x0416*/
227 #include "nls/ptb.nls"
228 LANG_END
229 LANG_BEGIN (LANG_PORTUGUESE ,SUBLANG_PORTUGUESE)                /*0x0816*/
230 #include "nls/ptg.nls"
231 LANG_END
232
233 LANG_BEGIN (LANG_RUSSIAN, SUBLANG_DEFAULT)      /*0x419*/
234 #include "nls/rus.nls"
235 LANG_END
236
237 LANG_BEGIN (LANG_SLOVAK, SUBLANG_DEFAULT)       /*0x041b*/
238 #include "nls/sky.nls"
239 LANG_END
240
241 LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH)              /*0x041d*/
242 #include "nls/sve.nls"
243 LANG_END
244 LANG_BEGIN (LANG_SWEDISH, SUBLANG_SWEDISH_FINLAND)      /*0x081d*/
245 #include "nls/svf.nls"
246 LANG_END
247
248 LANG_BEGIN (LANG_THAI, SUBLANG_DEFAULT) /*0x41e*/
249 #include "nls/tha.nls"
250 LANG_END
251
252 LANG_BEGIN (LANG_ESPERANTO, SUBLANG_DEFAULT)    /*0x048f*/
253 #include "nls/esperanto.nls"
254 LANG_END
255
256 LANG_BEGIN (LANG_WALON, SUBLANG_DEFAULT)        /*0x0490*/
257 #include "nls/wal.nls"
258 LANG_END
259             };
260
261
262 /* Locale name to id map. used by EnumSystemLocales, GetLocaleInfoA 
263  * MUST contain all #defines from winnls.h
264  * last entry has NULL name, 0 id.
265  */ 
266 #define LOCALE_ENTRY(x) {#x,LOCALE_##x}
267 static struct tagLOCALE_NAME2ID {
268         char    *name;
269         DWORD   id;
270 } locale_name2id[]= {
271         LOCALE_ENTRY(ILANGUAGE),
272         LOCALE_ENTRY(SLANGUAGE),
273         LOCALE_ENTRY(SENGLANGUAGE),
274         LOCALE_ENTRY(SABBREVLANGNAME),
275         LOCALE_ENTRY(SNATIVELANGNAME),
276         LOCALE_ENTRY(ICOUNTRY),
277         LOCALE_ENTRY(SCOUNTRY),
278         LOCALE_ENTRY(SENGCOUNTRY),
279         LOCALE_ENTRY(SABBREVCTRYNAME),
280         LOCALE_ENTRY(SNATIVECTRYNAME),
281         LOCALE_ENTRY(IDEFAULTLANGUAGE),
282         LOCALE_ENTRY(IDEFAULTCOUNTRY),
283         LOCALE_ENTRY(IDEFAULTCODEPAGE),
284         LOCALE_ENTRY(IDEFAULTANSICODEPAGE),
285         LOCALE_ENTRY(IDEFAULTMACCODEPAGE),
286         LOCALE_ENTRY(SLIST),
287         LOCALE_ENTRY(IMEASURE),
288         LOCALE_ENTRY(SDECIMAL),
289         LOCALE_ENTRY(STHOUSAND),
290         LOCALE_ENTRY(SGROUPING),
291         LOCALE_ENTRY(IDIGITS),
292         LOCALE_ENTRY(ILZERO),
293         LOCALE_ENTRY(INEGNUMBER),
294         LOCALE_ENTRY(SNATIVEDIGITS),
295         LOCALE_ENTRY(SCURRENCY),
296         LOCALE_ENTRY(SINTLSYMBOL),
297         LOCALE_ENTRY(SMONDECIMALSEP),
298         LOCALE_ENTRY(SMONTHOUSANDSEP),
299         LOCALE_ENTRY(SMONGROUPING),
300         LOCALE_ENTRY(ICURRDIGITS),
301         LOCALE_ENTRY(IINTLCURRDIGITS),
302         LOCALE_ENTRY(ICURRENCY),
303         LOCALE_ENTRY(INEGCURR),
304         LOCALE_ENTRY(SDATE),
305         LOCALE_ENTRY(STIME),
306         LOCALE_ENTRY(SSHORTDATE),
307         LOCALE_ENTRY(SLONGDATE),
308         LOCALE_ENTRY(STIMEFORMAT),
309         LOCALE_ENTRY(IDATE),
310         LOCALE_ENTRY(ILDATE),
311         LOCALE_ENTRY(ITIME),
312         LOCALE_ENTRY(ITIMEMARKPOSN),
313         LOCALE_ENTRY(ICENTURY),
314         LOCALE_ENTRY(ITLZERO),
315         LOCALE_ENTRY(IDAYLZERO),
316         LOCALE_ENTRY(IMONLZERO),
317         LOCALE_ENTRY(S1159),
318         LOCALE_ENTRY(S2359),
319         LOCALE_ENTRY(ICALENDARTYPE),
320         LOCALE_ENTRY(IOPTIONALCALENDAR),
321         LOCALE_ENTRY(IFIRSTDAYOFWEEK),
322         LOCALE_ENTRY(IFIRSTWEEKOFYEAR),
323         LOCALE_ENTRY(SDAYNAME1),
324         LOCALE_ENTRY(SDAYNAME2),
325         LOCALE_ENTRY(SDAYNAME3),
326         LOCALE_ENTRY(SDAYNAME4),
327         LOCALE_ENTRY(SDAYNAME5),
328         LOCALE_ENTRY(SDAYNAME6),
329         LOCALE_ENTRY(SDAYNAME7),
330         LOCALE_ENTRY(SABBREVDAYNAME1),
331         LOCALE_ENTRY(SABBREVDAYNAME2),
332         LOCALE_ENTRY(SABBREVDAYNAME3),
333         LOCALE_ENTRY(SABBREVDAYNAME4),
334         LOCALE_ENTRY(SABBREVDAYNAME5),
335         LOCALE_ENTRY(SABBREVDAYNAME6),
336         LOCALE_ENTRY(SABBREVDAYNAME7),
337         LOCALE_ENTRY(SMONTHNAME1),
338         LOCALE_ENTRY(SMONTHNAME2),
339         LOCALE_ENTRY(SMONTHNAME3),
340         LOCALE_ENTRY(SMONTHNAME4),
341         LOCALE_ENTRY(SMONTHNAME5),
342         LOCALE_ENTRY(SMONTHNAME6),
343         LOCALE_ENTRY(SMONTHNAME7),
344         LOCALE_ENTRY(SMONTHNAME8),
345         LOCALE_ENTRY(SMONTHNAME9),
346         LOCALE_ENTRY(SMONTHNAME10),
347         LOCALE_ENTRY(SMONTHNAME11),
348         LOCALE_ENTRY(SMONTHNAME12),
349         LOCALE_ENTRY(SMONTHNAME13),
350         LOCALE_ENTRY(SABBREVMONTHNAME1),
351         LOCALE_ENTRY(SABBREVMONTHNAME2),
352         LOCALE_ENTRY(SABBREVMONTHNAME3),
353         LOCALE_ENTRY(SABBREVMONTHNAME4),
354         LOCALE_ENTRY(SABBREVMONTHNAME5),
355         LOCALE_ENTRY(SABBREVMONTHNAME6),
356         LOCALE_ENTRY(SABBREVMONTHNAME7),
357         LOCALE_ENTRY(SABBREVMONTHNAME8),
358         LOCALE_ENTRY(SABBREVMONTHNAME9),
359         LOCALE_ENTRY(SABBREVMONTHNAME10),
360         LOCALE_ENTRY(SABBREVMONTHNAME11),
361         LOCALE_ENTRY(SABBREVMONTHNAME12),
362         LOCALE_ENTRY(SABBREVMONTHNAME13),
363         LOCALE_ENTRY(SPOSITIVESIGN),
364         LOCALE_ENTRY(SNEGATIVESIGN),
365         LOCALE_ENTRY(IPOSSIGNPOSN),
366         LOCALE_ENTRY(INEGSIGNPOSN),
367         LOCALE_ENTRY(IPOSSYMPRECEDES),
368         LOCALE_ENTRY(IPOSSEPBYSPACE),
369         LOCALE_ENTRY(INEGSYMPRECEDES),
370         LOCALE_ENTRY(INEGSEPBYSPACE),
371         LOCALE_ENTRY(FONTSIGNATURE),
372         LOCALE_ENTRY(SISO639LANGNAME),
373         LOCALE_ENTRY(SISO3166CTRYNAME),
374         {NULL,0},
375 };
376
377 const struct map_lcid2str {
378         LCID            langid;
379         const char      *langname;
380 } languages[]={
381         {0x0401,"Arabic (Saudi Arabia)"},
382         {0x0801,"Arabic (Iraq)"},
383         {0x0c01,"Arabic (Egypt)"},
384         {0x1001,"Arabic (Libya)"},
385         {0x1401,"Arabic (Algeria)"},
386         {0x1801,"Arabic (Morocco)"},
387         {0x1c01,"Arabic (Tunisia)"},
388         {0x2001,"Arabic (Oman)"},
389         {0x2401,"Arabic (Yemen)"},
390         {0x2801,"Arabic (Syria)"},
391         {0x2c01,"Arabic (Jordan)"},
392         {0x3001,"Arabic (Lebanon)"},
393         {0x3401,"Arabic (Kuwait)"},
394         {0x3801,"Arabic (United Arab Emirates)"},
395         {0x3c01,"Arabic (Bahrain)"},
396         {0x4001,"Arabic (Qatar)"},
397         {0x0402,"Bulgarian"},
398         {0x0403,"Catalan"},
399         {0x0404,"Chinese (Taiwan)"},
400         {0x0804,"Chinese (People's Republic of China)"},
401         {0x0c04,"Chinese (Hong Kong)"},
402         {0x1004,"Chinese (Singapore)"},
403         {0x1404,"Chinese (Macau)"},
404         {0x0405,"Czech"},
405         {0x0406,"Danish"},
406         {0x0407,"German (Germany)"},
407         {0x0807,"German (Switzerland)"},
408         {0x0c07,"German (Austria)"},
409         {0x1007,"German (Luxembourg)"},
410         {0x1407,"German (Liechtenstein)"},
411         {0x0408,"Greek"},
412         {0x0409,"English (United States)"},
413         {0x0809,"English (United Kingdom)"},
414         {0x0c09,"English (Australia)"},
415         {0x1009,"English (Canada)"},
416         {0x1409,"English (New Zealand)"},
417         {0x1809,"English (Ireland)"},
418         {0x1c09,"English (South Africa)"},
419         {0x2009,"English (Jamaica)"},
420         {0x2409,"English (Caribbean)"},
421         {0x2809,"English (Belize)"},
422         {0x2c09,"English (Trinidad)"},
423         {0x3009,"English (Zimbabwe)"},
424         {0x3409,"English (Philippines)"},
425         {0x040a,"Spanish (Spain, traditional sorting)"},
426         {0x080a,"Spanish (Mexico)"},
427         {0x0c0a,"Spanish (Spain, international sorting)"},
428         {0x100a,"Spanish (Guatemala)"},
429         {0x140a,"Spanish (Costa Rica)"},
430         {0x180a,"Spanish (Panama)"},
431         {0x1c0a,"Spanish (Dominican Republic)"},
432         {0x200a,"Spanish (Venezuela)"},
433         {0x240a,"Spanish (Colombia)"},
434         {0x280a,"Spanish (Peru)"},
435         {0x2c0a,"Spanish (Argentina)"},
436         {0x300a,"Spanish (Ecuador)"},
437         {0x340a,"Spanish (Chile)"},
438         {0x380a,"Spanish (Uruguay)"},
439         {0x3c0a,"Spanish (Paraguay)"},
440         {0x400a,"Spanish (Bolivia)"},
441         {0x440a,"Spanish (El Salvador)"},
442         {0x480a,"Spanish (Honduras)"},
443         {0x4c0a,"Spanish (Nicaragua)"},
444         {0x500a,"Spanish (Puerto Rico)"},
445         {0x040b,"Finnish"},
446         {0x040c,"French (France)"},
447         {0x080c,"French (Belgium)"},
448         {0x0c0c,"French (Canada)"},
449         {0x100c,"French (Switzerland)"},
450         {0x140c,"French (Luxembourg)"},
451         {0x180c,"French (Monaco)"},
452         {0x040d,"Hebrew"},
453         {0x040e,"Hungarian"},
454         {0x040f,"Icelandic"},
455         {0x0410,"Italian (Italy)"},
456         {0x0810,"Italian (Switzerland)"},
457         {0x0411,"Japanese"},
458         {0x0412,"Korean (Wansung)"},
459         {0x0812,"Korean (Johab)"},
460         {0x0413,"Dutch (Netherlands)"},
461         {0x0813,"Dutch (Belgium)"},
462         {0x0414,"Norwegian (Bokmal)"},
463         {0x0814,"Norwegian (Nynorsk)"},
464         {0x0415,"Polish"},
465         {0x0416,"Portuguese (Brazil)"},
466         {0x0816,"Portuguese (Portugal)"},
467         {0x0417,"Rhaeto Romanic"},
468         {0x0418,"Romanian"},
469         {0x0818,"Moldavian"},
470         {0x0419,"Russian (Russia)"},
471         {0x0819,"Russian (Moldavia)"},
472         {0x041a,"Croatian"},
473         {0x081a,"Serbian (latin)"},
474         {0x0c1a,"Serbian (cyrillic)"},
475         {0x041b,"Slovak"},
476         {0x041c,"Albanian"},
477         {0x041d,"Swedish (Sweden)"},
478         {0x081d,"Swedish (Finland)"},
479         {0x041e,"Thai"},
480         {0x041f,"Turkish"},
481         {0x0420,"Urdu"},
482         {0x0421,"Indonesian"},
483         {0x0422,"Ukrainian"},
484         {0x0423,"Belarusian"},
485         {0x0424,"Slovene"},
486         {0x0425,"Estonian"},
487         {0x0426,"Latvian"},
488         {0x0427,"Lithuanian (modern)"},
489         {0x0827,"Lithuanian (classic)"},
490         {0x0428,"Maori"},
491         {0x0429,"Farsi"},
492         {0x042a,"Vietnamese"},
493         {0x042b,"Armenian"},
494         {0x042c,"Azeri (latin)"},
495         {0x082c,"Azeri (cyrillic)"},
496         {0x042d,"Basque"},
497         {0x042e,"Sorbian"},
498         {0x042f,"Macedonian"},
499         {0x0430,"Sutu"},
500         {0x0431,"Tsonga"},
501         {0x0432,"Tswana"},
502         {0x0433,"Venda"},
503         {0x0434,"Xhosa"},
504         {0x0435,"Zulu"},
505         {0x0436,"Afrikaans"},
506         {0x0437,"Georgian"},
507         {0x0438,"Faeroese"},
508         {0x0439,"Hindi"},
509         {0x043a,"Maltese"},
510         {0x043b,"Saami"},
511         {0x043c,"Irish gaelic"},
512         {0x083c,"Scottish gaelic"},
513         {0x043e,"Malay (Malaysia)"},
514         {0x083e,"Malay (Brunei Darussalam)"},
515         {0x043f,"Kazak"},
516         {0x0441,"Swahili"},
517         {0x0443,"Uzbek (latin)"},
518         {0x0843,"Uzbek (cyrillic)"},
519         {0x0444,"Tatar"},
520         {0x0445,"Bengali"},
521         {0x0446,"Punjabi"},
522         {0x0447,"Gujarati"},
523         {0x0448,"Oriya"},
524         {0x0449,"Tamil"},
525         {0x044a,"Telugu"},
526         {0x044b,"Kannada"},
527         {0x044c,"Malayalam"},
528         {0x044d,"Assamese"},
529         {0x044e,"Marathi"},
530         {0x044f,"Sanskrit"},
531         {0x0457,"Konkani"},
532         {0x048f,"Esperanto"}, /* Non official */
533         {0x0490,"Walon"}, /* Non official */
534         {0x0000,"Unknown"}
535     }, languages_de[]={
536         {0x0401,"Arabic"},
537         {0x0402,"Bulgarisch"},
538         {0x0403,"Katalanisch"},
539         {0x0404,"Traditionales Chinesisch"},
540         {0x0405,"Tschecisch"},
541         {0x0406,"Dänisch"},
542         {0x0407,"Deutsch"},
543         {0x0408,"Griechisch"},
544         {0x0409,"Amerikanisches Englisch"},
545         {0x040A,"Kastilisches Spanisch"},
546         {0x040B,"Finnisch"},
547         {0x040C,"Franzvsisch"},
548         {0x040D,"Hebrdisch"},
549         {0x040E,"Ungarisch"},
550         {0x040F,"Isldndisch"},
551         {0x0410,"Italienisch"},
552         {0x0411,"Japanisch"},
553         {0x0412,"Koreanisch"},
554         {0x0413,"Niederldndisch"},
555         {0x0414,"Norwegisch-Bokmal"},
556         {0x0415,"Polnisch"},
557         {0x0416,"Brasilianisches Portugiesisch"},
558         {0x0417,"Rdtoromanisch"},
559         {0x0418,"Rumdnisch"},
560         {0x0419,"Russisch"},
561         {0x041A,"Kroatoserbisch (lateinisch)"},
562         {0x041B,"Slowenisch"},
563         {0x041C,"Albanisch"},
564         {0x041D,"Schwedisch"},
565         {0x041E,"Thai"},
566         {0x041F,"Türkisch"},
567         {0x0420,"Urdu"},
568         {0x0421,"Bahasa"},
569         {0x0804,"Vereinfachtes Chinesisch"},
570         {0x0807,"Schweizerdeutsch"},
571         {0x0809,"Britisches Englisch"},
572         {0x080A,"Mexikanisches Spanisch"},
573         {0x080C,"Belgisches Franzvsisch"},
574         {0x0810,"Schweizerisches Italienisch"},
575         {0x0813,"Belgisches Niederldndisch"},
576         {0x0814,"Norgwegisch-Nynorsk"},
577         {0x0816,"Portugiesisch"},
578         {0x081A,"Serbokratisch (kyrillisch)"},
579         {0x0C1C,"Kanadisches Franzvsisch"},
580         {0x100C,"Schweizerisches Franzvsisch"},
581         {0x0000,"Unbekannt"},
582 };
583
584 /***********************************************************************
585  *           GetUserDefaultLCID       (OLE2NLS.1)
586  */
587 LCID WINAPI GetUserDefaultLCID()
588 {
589         return MAKELCID( GetUserDefaultLangID() , SORT_DEFAULT );
590 }
591
592 /***********************************************************************
593  *         GetSystemDefaultLCID       (OLE2NLS.2)
594  */
595 LCID WINAPI GetSystemDefaultLCID()
596 {
597         return GetUserDefaultLCID();
598 }
599
600 /***********************************************************************
601  *         GetUserDefaultLangID       (OLE2NLS.3)
602  */
603 LANGID WINAPI GetUserDefaultLangID()
604 {
605         /* caching result, if defined from environment, which should (?) not change during a WINE session */
606         static  LANGID  userLCID = 0;
607         if (Options.language) {
608                 return Languages[Options.language].langid;
609         }
610
611         if (userLCID == 0) {
612                 char *buf=NULL;
613                 char *lang,*country,*charset,*dialect,*next;
614                 int     ret=0;
615                 
616                 buf=getenv("LANGUAGE");
617                 if (!buf) buf=getenv("LANG");
618                 if (!buf) buf=getenv("LC_ALL");
619                 if (!buf) buf=getenv("LC_MESSAGES");
620                 if (!buf) buf=getenv("LC_CTYPE");
621                 if (!buf) return userLCID = MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT );
622                 
623                 if (!strcmp(buf,"POSIX") || !strcmp(buf,"C")) {
624                         return MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT );
625                 }
626                 
627                 lang=buf;
628                 
629                 do {
630                         next=strchr(lang,':'); if (next) *next++='\0';
631                         dialect=strchr(lang,'@'); if (dialect) *dialect++='\0';
632                         charset=strchr(lang,'.'); if (charset) *charset++='\0';
633                         country=strchr(lang,'_'); if (country) *country++='\0';
634                         
635                         ret=MAIN_GetLanguageID(lang, country, charset, dialect);
636                         
637                         lang=next;
638                         
639                 } while (lang && !ret);
640                 
641                 /* FIXME : are strings returned by getenv() to be free()'ed ? */
642                 userLCID = (LANGID)ret;
643         }
644         return userLCID;
645 }
646
647 /***********************************************************************
648  *         GetSystemDefaultLangID     (OLE2NLS.4)
649  */
650 LANGID WINAPI GetSystemDefaultLangID()
651 {
652         return GetUserDefaultLangID();
653 }
654
655 /******************************************************************************
656  *              GetLocaleInfo16 [OLE2NLS.5]
657  * Is the last parameter really WORD for Win16?
658  */
659 INT16 WINAPI GetLocaleInfo16(LCID lcid,LCTYPE LCType,LPSTR buf,INT16 len)
660 {
661         return GetLocaleInfoA(lcid,LCType,buf,len);
662 }
663 /******************************************************************************
664  * ConvertDefaultLocale32 [KERNEL32.147]
665  */
666 LCID WINAPI ConvertDefaultLocale32 (LCID lcid)
667 {       switch (lcid)
668         {  case LOCALE_SYSTEM_DEFAULT:
669              return GetSystemDefaultLCID();
670            case LOCALE_USER_DEFAULT:
671              return GetUserDefaultLCID();
672            case 0:
673              return MAKELCID (LANG_NEUTRAL, SUBLANG_NEUTRAL);
674         }  
675         return MAKELANGID( PRIMARYLANGID(lcid), SUBLANG_NEUTRAL);
676 }
677 /******************************************************************************
678  * GetLocaleInfo32A [KERNEL32.342]
679  *
680  * NOTES 
681  *  LANG_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
682  *
683  *  MS online documentation states that the string returned is NULL terminated
684  *  except for LOCALE_FONTSIGNATURE  which "will return a non-NULL
685  *  terminated string".
686  */
687 INT WINAPI GetLocaleInfoA(LCID lcid,LCTYPE LCType,LPSTR buf,INT len)
688 {
689   LPCSTR  retString;
690         int     found,i;
691         int     lang=0;
692
693   TRACE_(ole)("(lcid=0x%lx,lctype=0x%lx,%p,%x)\n",lcid,LCType,buf,len);
694
695   if (len && (! buf) ) {
696     SetLastError(ERROR_INSUFFICIENT_BUFFER);
697                 return 0;
698         }
699
700         if (lcid ==0 || lcid == LANG_SYSTEM_DEFAULT || (LCType & LOCALE_NOUSEROVERRIDE) )       /* 0x00, 0x400 */
701         {
702             lcid = GetSystemDefaultLCID();
703         } 
704         else if (lcid == LANG_USER_DEFAULT) /*0x800*/
705         {
706             lcid = GetUserDefaultLCID();
707         }
708         LCType &= ~(LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP);
709
710         /* As an option, we could obtain the value from win.ini.
711            This would not match the Wine compile-time option.
712            Also, not all identifiers are available from win.ini */
713         retString=0;
714         /* If we are through all of this, retLen should not be zero anymore.
715            If it is, the value is not supported */
716         i=0;
717         while (locale_name2id[i].name!=NULL) {
718                 if (LCType == locale_name2id[i].id) {
719                         retString = locale_name2id[i].name;
720                         break;
721                 }
722                 i++;
723         }
724         if (!retString) {
725       FIXME_(ole)("Unkown LC type %lX\n",LCType);
726                 return 0;
727         }
728
729     found=0;lang=lcid;
730     for (i=0;(i<3 && !found);i++) {
731       int j;
732
733       for (j=0;j<sizeof(langlocales)/sizeof(langlocales[0]);j++) {
734         if (langlocales[j].lang == lang) {
735           int k;
736
737           for (k=0;k<sizeof(langlocales[j].locvars)/sizeof(langlocales[j].locvars[0]) && (langlocales[j].locvars[k].type);k++) {
738             if (langlocales[j].locvars[k].type == LCType) {
739               found = 1;
740               retString = langlocales[j].locvars[k].val;
741           break;
742             }
743           }
744           if (found)
745             break;
746         }
747       }
748           /* language not found, try without a sublanguage*/
749           if (i==1) lang=MAKELANGID( PRIMARYLANGID(lang), SUBLANG_DEFAULT);
750           /* mask the LC Value */
751           if (i==2) LCType &= 0xfff;
752     }
753
754     if(!found) {
755       ERR_(ole)("'%s' not supported for your language (%04X).\n",
756                         retString,(WORD)lcid);
757                 SetLastError(ERROR_INVALID_PARAMETER);
758                 return 0;                       
759         }
760     /* a FONTSIGNATURE is not a string, just 6 DWORDs  */
761     if (LCType == LOCALE_FONTSIGNATURE) {
762         if (len)
763             memcpy(buf, retString, (len<=sizeof(FONTSIGNATURE))?len:sizeof(FONTSIGNATURE));
764         return sizeof(FONTSIGNATURE);
765     }
766     /* if len=0 return only the length, don't touch the buffer*/
767     if (len) lstrcpynA(buf,retString,len);
768     return strlen(retString)+1;
769 }
770
771 /******************************************************************************
772  *              GetLocaleInfo32W        [KERNEL32.343]
773  *
774  * NOTES
775  *  MS documentation states that len "specifies the size, in bytes (ANSI version)
776  *  or characters (Unicode version), of" wbuf. Thus the number returned is
777  *  the same between GetLocaleInfo32W and GetLocaleInfo32A.
778  */
779 INT WINAPI GetLocaleInfoW(LCID lcid,LCTYPE LCType,LPWSTR wbuf,INT len)
780 {       WORD wlen;
781         LPSTR abuf;
782         
783         if (len && (! wbuf) )
784         { SetLastError(ERROR_INSUFFICIENT_BUFFER);
785           return 0;
786         }
787
788         abuf = (LPSTR)HeapAlloc(GetProcessHeap(),0,len);
789         wlen = GetLocaleInfoA(lcid, LCType, abuf, len);
790
791         if (wlen && len)        /* if len=0 return only the length*/
792           lstrcpynAtoW(wbuf,abuf,len);
793
794         HeapFree(GetProcessHeap(),0,abuf);
795         return wlen;
796 }
797
798 /******************************************************************************
799  *              SetLocaleInfoA  [KERNEL32.656]
800  */
801 BOOL16 WINAPI SetLocaleInfoA(DWORD lcid, DWORD lctype, LPCSTR data)
802 {
803     FIXME_(ole)("(%ld,%ld,%s): stub\n",lcid,lctype,data);
804     return TRUE;
805 }
806
807 /******************************************************************************
808  *              IsValidLocale   [KERNEL32.489]
809  */
810 BOOL WINAPI IsValidLocale(LCID lcid,DWORD flags)
811 {
812         /* we support ANY language. Well, at least say that...*/
813         return TRUE;
814 }
815
816 /******************************************************************************
817  *              EnumSystemLocales32W    [KERNEL32.209]
818  */
819 BOOL WINAPI EnumSystemLocalesW( LOCALE_ENUMPROCW lpfnLocaleEnum,
820                                     DWORD flags )
821 {
822         int     i;
823         BOOL    ret;
824         WCHAR   buffer[200];
825         HKEY    xhkey;
826
827         TRACE_(win32)("(%p,%08lx)\n",lpfnLocaleEnum,flags );
828         /* see if we can reuse the Win95 registry entries.... */
829         if (ERROR_SUCCESS==RegOpenKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\control\\Nls\\Locale\\",&xhkey)) {
830                 i=0;
831                 while (1) {
832                         if (ERROR_SUCCESS!=RegEnumKeyW(xhkey,i,buffer,sizeof(buffer)))
833                                 break;
834                         if (!lpfnLocaleEnum(buffer))
835                                 break;
836                         i++;
837                 }
838                 RegCloseKey(xhkey);
839                 return TRUE;
840         }
841
842         i=0;
843         while (languages[i].langid!=0)
844         {
845             LPWSTR cp;
846             char   xbuffer[10];
847         
848             sprintf(xbuffer,"%08lx",(DWORD)languages[i].langid);
849
850             cp = HEAP_strdupAtoW( GetProcessHeap(), 0, xbuffer );
851             ret = lpfnLocaleEnum(cp);
852             HeapFree( GetProcessHeap(), 0, cp );
853             if (!ret) break;
854             i++;
855         }
856         return TRUE;
857 }
858
859 /******************************************************************************
860  *              EnumSystemLocales32A    [KERNEL32.208]
861  */
862 BOOL WINAPI EnumSystemLocalesA(LOCALE_ENUMPROCA lpfnLocaleEnum,
863                                    DWORD flags)
864 {
865         int     i;
866         CHAR    buffer[200];
867         HKEY    xhkey;
868
869         TRACE_(win32)("(%p,%08lx)\n",
870                 lpfnLocaleEnum,flags
871         );
872         if (ERROR_SUCCESS==RegOpenKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\control\\Nls\\Locale\\",&xhkey)) {
873                 i=0;
874                 while (1) {
875                         if (ERROR_SUCCESS!=RegEnumKeyA(xhkey,i,buffer,sizeof(buffer)))
876                                 break;
877                         if (!lpfnLocaleEnum(buffer))
878                                 break;
879                         i++;
880                 }
881                 RegCloseKey(xhkey);
882                 return TRUE;
883         }
884         i=0;
885         while (languages[i].langid!=0) {
886                 sprintf(buffer,"%08lx",(DWORD)languages[i].langid);
887                 if (!lpfnLocaleEnum(buffer))
888                         break;
889                 i++;
890         }
891         return TRUE;
892 }
893
894 static const unsigned char CT_CType2_LUT[] = {
895   C2_NOTAPPLICABLE, /*   -   0 */
896   C2_NOTAPPLICABLE, /*   -   1 */
897   C2_NOTAPPLICABLE, /*   -   2 */
898   C2_NOTAPPLICABLE, /*   -   3 */
899   C2_NOTAPPLICABLE, /*   -   4 */
900   C2_NOTAPPLICABLE, /*   -   5 */
901   C2_NOTAPPLICABLE, /*   -   6 */
902   C2_NOTAPPLICABLE, /*   -   7 */
903   C2_NOTAPPLICABLE, /*   -   8 */
904   C2_SEGMENTSEPARATOR, /*   -   9 */
905   C2_NOTAPPLICABLE, /*   -  10 */
906   C2_NOTAPPLICABLE, /*   -  11 */
907   C2_NOTAPPLICABLE, /*   -  12 */
908   C2_NOTAPPLICABLE, /*   -  13 */
909   C2_NOTAPPLICABLE, /*   -  14 */
910   C2_NOTAPPLICABLE, /*   -  15 */
911   C2_NOTAPPLICABLE, /*   -  16 */
912   C2_NOTAPPLICABLE, /*   -  17 */
913   C2_NOTAPPLICABLE, /*   -  18 */
914   C2_NOTAPPLICABLE, /*   -  19 */
915   C2_NOTAPPLICABLE, /*   -  20 */
916   C2_NOTAPPLICABLE, /*   -  21 */
917   C2_NOTAPPLICABLE, /*   -  22 */
918   C2_NOTAPPLICABLE, /*   -  23 */
919   C2_NOTAPPLICABLE, /*   -  24 */
920   C2_NOTAPPLICABLE, /*   -  25 */
921   C2_NOTAPPLICABLE, /*   -  26 */
922   C2_NOTAPPLICABLE, /*   -  27 */
923   C2_NOTAPPLICABLE, /*   -  28 */
924   C2_NOTAPPLICABLE, /*   -  29 */
925   C2_NOTAPPLICABLE, /*   -  30 */
926   C2_NOTAPPLICABLE, /*   -  31 */
927   C2_WHITESPACE, /*   -  32 */
928   C2_OTHERNEUTRAL, /* ! -  33 */
929   C2_OTHERNEUTRAL, /* " -  34 */ /* " */
930   C2_EUROPETERMINATOR, /* # -  35 */
931   C2_EUROPETERMINATOR, /* $ -  36 */
932   C2_EUROPETERMINATOR, /* % -  37 */
933   C2_LEFTTORIGHT, /* & -  38 */
934   C2_OTHERNEUTRAL, /* ' -  39 */
935   C2_OTHERNEUTRAL, /* ( -  40 */
936   C2_OTHERNEUTRAL, /* ) -  41 */
937   C2_OTHERNEUTRAL, /* * -  42 */
938   C2_EUROPETERMINATOR, /* + -  43 */
939   C2_COMMONSEPARATOR, /* , -  44 */
940   C2_EUROPETERMINATOR, /* - -  45 */
941   C2_EUROPESEPARATOR, /* . -  46 */
942   C2_EUROPESEPARATOR, /* / -  47 */
943   C2_EUROPENUMBER, /* 0 -  48 */
944   C2_EUROPENUMBER, /* 1 -  49 */
945   C2_EUROPENUMBER, /* 2 -  50 */
946   C2_EUROPENUMBER, /* 3 -  51 */
947   C2_EUROPENUMBER, /* 4 -  52 */
948   C2_EUROPENUMBER, /* 5 -  53 */
949   C2_EUROPENUMBER, /* 6 -  54 */
950   C2_EUROPENUMBER, /* 7 -  55 */
951   C2_EUROPENUMBER, /* 8 -  56 */
952   C2_EUROPENUMBER, /* 9 -  57 */
953   C2_COMMONSEPARATOR, /* : -  58 */
954   C2_OTHERNEUTRAL, /* ; -  59 */
955   C2_OTHERNEUTRAL, /* < -  60 */
956   C2_OTHERNEUTRAL, /* = -  61 */
957   C2_OTHERNEUTRAL, /* > -  62 */
958   C2_OTHERNEUTRAL, /* ? -  63 */
959   C2_LEFTTORIGHT, /* @ -  64 */
960   C2_LEFTTORIGHT, /* A -  65 */
961   C2_LEFTTORIGHT, /* B -  66 */
962   C2_LEFTTORIGHT, /* C -  67 */
963   C2_LEFTTORIGHT, /* D -  68 */
964   C2_LEFTTORIGHT, /* E -  69 */
965   C2_LEFTTORIGHT, /* F -  70 */
966   C2_LEFTTORIGHT, /* G -  71 */
967   C2_LEFTTORIGHT, /* H -  72 */
968   C2_LEFTTORIGHT, /* I -  73 */
969   C2_LEFTTORIGHT, /* J -  74 */
970   C2_LEFTTORIGHT, /* K -  75 */
971   C2_LEFTTORIGHT, /* L -  76 */
972   C2_LEFTTORIGHT, /* M -  77 */
973   C2_LEFTTORIGHT, /* N -  78 */
974   C2_LEFTTORIGHT, /* O -  79 */
975   C2_LEFTTORIGHT, /* P -  80 */
976   C2_LEFTTORIGHT, /* Q -  81 */
977   C2_LEFTTORIGHT, /* R -  82 */
978   C2_LEFTTORIGHT, /* S -  83 */
979   C2_LEFTTORIGHT, /* T -  84 */
980   C2_LEFTTORIGHT, /* U -  85 */
981   C2_LEFTTORIGHT, /* V -  86 */
982   C2_LEFTTORIGHT, /* W -  87 */
983   C2_LEFTTORIGHT, /* X -  88 */
984   C2_LEFTTORIGHT, /* Y -  89 */
985   C2_LEFTTORIGHT, /* Z -  90 */
986   C2_OTHERNEUTRAL, /* [ -  91 */
987   C2_OTHERNEUTRAL, /* \ -  92 */
988   C2_OTHERNEUTRAL, /* ] -  93 */
989   C2_OTHERNEUTRAL, /* ^ -  94 */
990   C2_OTHERNEUTRAL, /* _ -  95 */
991   C2_OTHERNEUTRAL, /* ` -  96 */
992   C2_LEFTTORIGHT, /* a -  97 */
993   C2_LEFTTORIGHT, /* b -  98 */
994   C2_LEFTTORIGHT, /* c -  99 */
995   C2_LEFTTORIGHT, /* d - 100 */
996   C2_LEFTTORIGHT, /* e - 101 */
997   C2_LEFTTORIGHT, /* f - 102 */
998   C2_LEFTTORIGHT, /* g - 103 */
999   C2_LEFTTORIGHT, /* h - 104 */
1000   C2_LEFTTORIGHT, /* i - 105 */
1001   C2_LEFTTORIGHT, /* j - 106 */
1002   C2_LEFTTORIGHT, /* k - 107 */
1003   C2_LEFTTORIGHT, /* l - 108 */
1004   C2_LEFTTORIGHT, /* m - 109 */
1005   C2_LEFTTORIGHT, /* n - 110 */
1006   C2_LEFTTORIGHT, /* o - 111 */
1007   C2_LEFTTORIGHT, /* p - 112 */
1008   C2_LEFTTORIGHT, /* q - 113 */
1009   C2_LEFTTORIGHT, /* r - 114 */
1010   C2_LEFTTORIGHT, /* s - 115 */
1011   C2_LEFTTORIGHT, /* t - 116 */
1012   C2_LEFTTORIGHT, /* u - 117 */
1013   C2_LEFTTORIGHT, /* v - 118 */
1014   C2_LEFTTORIGHT, /* w - 119 */
1015   C2_LEFTTORIGHT, /* x - 120 */
1016   C2_LEFTTORIGHT, /* y - 121 */
1017   C2_LEFTTORIGHT, /* z - 122 */
1018   C2_OTHERNEUTRAL, /* { - 123 */
1019   C2_OTHERNEUTRAL, /* | - 124 */
1020   C2_OTHERNEUTRAL, /* } - 125 */
1021   C2_OTHERNEUTRAL, /* ~ - 126 */
1022   C2_NOTAPPLICABLE, /* \7f - 127 */
1023   C2_NOTAPPLICABLE, /* \80 - 128 */
1024   C2_NOTAPPLICABLE, /* \81 - 129 */
1025   C2_OTHERNEUTRAL, /* \82 - 130 */
1026   C2_LEFTTORIGHT, /* \83 - 131 */
1027   C2_OTHERNEUTRAL, /* \84 - 132 */
1028   C2_OTHERNEUTRAL, /* \85 - 133 */
1029   C2_OTHERNEUTRAL, /* \86 - 134 */
1030   C2_OTHERNEUTRAL, /* \87 - 135 */
1031   C2_LEFTTORIGHT, /* \88 - 136 */
1032   C2_EUROPETERMINATOR, /* \89 - 137 */
1033   C2_LEFTTORIGHT, /* \8a - 138 */
1034   C2_OTHERNEUTRAL, /* \8b - 139 */
1035   C2_LEFTTORIGHT, /* \8c - 140 */
1036   C2_NOTAPPLICABLE, /* \8d - 141 */
1037   C2_NOTAPPLICABLE, /* \8e - 142 */
1038   C2_NOTAPPLICABLE, /* \8f - 143 */
1039   C2_NOTAPPLICABLE, /* \90 - 144 */
1040   C2_OTHERNEUTRAL, /* \91 - 145 */
1041   C2_OTHERNEUTRAL, /* \92 - 146 */
1042   C2_OTHERNEUTRAL, /* \93 - 147 */
1043   C2_OTHERNEUTRAL, /* \94 - 148 */
1044   C2_OTHERNEUTRAL, /* \95 - 149 */
1045   C2_OTHERNEUTRAL, /* \96 - 150 */
1046   C2_OTHERNEUTRAL, /* \97 - 151 */
1047   C2_LEFTTORIGHT, /* \98 - 152 */
1048   C2_OTHERNEUTRAL, /* \99 - 153 */
1049   C2_LEFTTORIGHT, /* \9a - 154 */
1050   C2_OTHERNEUTRAL, /* \9b - 155 */
1051   C2_LEFTTORIGHT, /* \9c - 156 */
1052   C2_NOTAPPLICABLE, /* \9d - 157 */
1053   C2_NOTAPPLICABLE, /* \9e - 158 */
1054   C2_LEFTTORIGHT, /* \9f - 159 */
1055   C2_WHITESPACE, /*   - 160 */
1056   C2_OTHERNEUTRAL, /* ¡ - 161 */
1057   C2_EUROPETERMINATOR, /* ¢ - 162 */
1058   C2_EUROPETERMINATOR, /* £ - 163 */
1059   C2_EUROPETERMINATOR, /* ¤ - 164 */
1060   C2_EUROPETERMINATOR, /* ¥ - 165 */
1061   C2_OTHERNEUTRAL, /* ¦ - 166 */
1062   C2_OTHERNEUTRAL, /* § - 167 */
1063   C2_OTHERNEUTRAL, /* ¨ - 168 */
1064   C2_OTHERNEUTRAL, /* © - 169 */
1065   C2_OTHERNEUTRAL, /* ª - 170 */
1066   C2_OTHERNEUTRAL, /* « - 171 */
1067   C2_OTHERNEUTRAL, /* ¬ - 172 */
1068   C2_OTHERNEUTRAL, /* ­ - 173 */
1069   C2_OTHERNEUTRAL, /* ® - 174 */
1070   C2_OTHERNEUTRAL, /* ¯ - 175 */
1071   C2_EUROPETERMINATOR, /* ° - 176 */
1072   C2_EUROPETERMINATOR, /* ± - 177 */
1073   C2_EUROPENUMBER, /* ² - 178 */
1074   C2_EUROPENUMBER, /* ³ - 179 */
1075   C2_OTHERNEUTRAL, /* ´ - 180 */
1076   C2_OTHERNEUTRAL, /* µ - 181 */
1077   C2_OTHERNEUTRAL, /* ¶ - 182 */
1078   C2_OTHERNEUTRAL, /* · - 183 */
1079   C2_OTHERNEUTRAL, /* ¸ - 184 */
1080   C2_EUROPENUMBER, /* ¹ - 185 */
1081   C2_OTHERNEUTRAL, /* º - 186 */
1082   C2_OTHERNEUTRAL, /* » - 187 */
1083   C2_OTHERNEUTRAL, /* ¼ - 188 */
1084   C2_OTHERNEUTRAL, /* ½ - 189 */
1085   C2_OTHERNEUTRAL, /* ¾ - 190 */
1086   C2_OTHERNEUTRAL, /* ¿ - 191 */
1087   C2_LEFTTORIGHT, /* À - 192 */
1088   C2_LEFTTORIGHT, /* Á - 193 */
1089   C2_LEFTTORIGHT, /* Â - 194 */
1090   C2_LEFTTORIGHT, /* Ã - 195 */
1091   C2_LEFTTORIGHT, /* Ä - 196 */
1092   C2_LEFTTORIGHT, /* Å - 197 */
1093   C2_LEFTTORIGHT, /* Æ - 198 */
1094   C2_LEFTTORIGHT, /* Ç - 199 */
1095   C2_LEFTTORIGHT, /* È - 200 */
1096   C2_LEFTTORIGHT, /* É - 201 */
1097   C2_LEFTTORIGHT, /* Ê - 202 */
1098   C2_LEFTTORIGHT, /* Ë - 203 */
1099   C2_LEFTTORIGHT, /* Ì - 204 */
1100   C2_LEFTTORIGHT, /* Í - 205 */
1101   C2_LEFTTORIGHT, /* Î - 206 */
1102   C2_LEFTTORIGHT, /* Ï - 207 */
1103   C2_LEFTTORIGHT, /* Ð - 208 */
1104   C2_LEFTTORIGHT, /* Ñ - 209 */
1105   C2_LEFTTORIGHT, /* Ò - 210 */
1106   C2_LEFTTORIGHT, /* Ó - 211 */
1107   C2_LEFTTORIGHT, /* Ô - 212 */
1108   C2_LEFTTORIGHT, /* Õ - 213 */
1109   C2_LEFTTORIGHT, /* Ö - 214 */
1110   C2_OTHERNEUTRAL, /* × - 215 */
1111   C2_LEFTTORIGHT, /* Ø - 216 */
1112   C2_LEFTTORIGHT, /* Ù - 217 */
1113   C2_LEFTTORIGHT, /* Ú - 218 */
1114   C2_LEFTTORIGHT, /* Û - 219 */
1115   C2_LEFTTORIGHT, /* Ü - 220 */
1116   C2_LEFTTORIGHT, /* Ý - 221 */
1117   C2_LEFTTORIGHT, /* Þ - 222 */
1118   C2_LEFTTORIGHT, /* ß - 223 */
1119   C2_LEFTTORIGHT, /* à - 224 */
1120   C2_LEFTTORIGHT, /* á - 225 */
1121   C2_LEFTTORIGHT, /* â - 226 */
1122   C2_LEFTTORIGHT, /* ã - 227 */
1123   C2_LEFTTORIGHT, /* ä - 228 */
1124   C2_LEFTTORIGHT, /* å - 229 */
1125   C2_LEFTTORIGHT, /* æ - 230 */
1126   C2_LEFTTORIGHT, /* ç - 231 */
1127   C2_LEFTTORIGHT, /* è - 232 */
1128   C2_LEFTTORIGHT, /* é - 233 */
1129   C2_LEFTTORIGHT, /* ê - 234 */
1130   C2_LEFTTORIGHT, /* ë - 235 */
1131   C2_LEFTTORIGHT, /* ì - 236 */
1132   C2_LEFTTORIGHT, /* í - 237 */
1133   C2_LEFTTORIGHT, /* î - 238 */
1134   C2_LEFTTORIGHT, /* ï - 239 */
1135   C2_LEFTTORIGHT, /* ð - 240 */
1136   C2_LEFTTORIGHT, /* ñ - 241 */
1137   C2_LEFTTORIGHT, /* ò - 242 */
1138   C2_LEFTTORIGHT, /* ó - 243 */
1139   C2_LEFTTORIGHT, /* ô - 244 */
1140   C2_LEFTTORIGHT, /* õ - 245 */
1141   C2_LEFTTORIGHT, /* ö - 246 */
1142   C2_OTHERNEUTRAL, /* ÷ - 247 */
1143   C2_LEFTTORIGHT, /* ø - 248 */
1144   C2_LEFTTORIGHT, /* ù - 249 */
1145   C2_LEFTTORIGHT, /* ú - 250 */
1146   C2_LEFTTORIGHT, /* û - 251 */
1147   C2_LEFTTORIGHT, /* ü - 252 */
1148   C2_LEFTTORIGHT, /* ý - 253 */
1149   C2_LEFTTORIGHT, /* þ - 254 */
1150   C2_LEFTTORIGHT /* ÿ - 255 */
1151 };
1152
1153 const WORD OLE2NLS_CT_CType3_LUT[] = { 
1154   0x0000, /*   -   0 */
1155   0x0000, /*   -   1 */
1156   0x0000, /*   -   2 */
1157   0x0000, /*   -   3 */
1158   0x0000, /*   -   4 */
1159   0x0000, /*   -   5 */
1160   0x0000, /*   -   6 */
1161   0x0000, /*   -   7 */
1162   0x0000, /*   -   8 */
1163   0x0008, /*   -   9 */
1164   0x0008, /*   -  10 */
1165   0x0008, /*   -  11 */
1166   0x0008, /*   -  12 */
1167   0x0008, /*   -  13 */
1168   0x0000, /*   -  14 */
1169   0x0000, /*   -  15 */
1170   0x0000, /*   -  16 */
1171   0x0000, /*   -  17 */
1172   0x0000, /*   -  18 */
1173   0x0000, /*   -  19 */
1174   0x0000, /*   -  20 */
1175   0x0000, /*   -  21 */
1176   0x0000, /*   -  22 */
1177   0x0000, /*   -  23 */
1178   0x0000, /*   -  24 */
1179   0x0000, /*   -  25 */
1180   0x0000, /*   -  26 */
1181   0x0000, /*   -  27 */
1182   0x0000, /*   -  28 */
1183   0x0000, /*   -  29 */
1184   0x0000, /*   -  30 */
1185   0x0000, /*   -  31 */
1186   0x0048, /*   -  32 */
1187   0x0048, /* ! -  33 */
1188   0x0448, /* " -  34 */ /* " */
1189   0x0048, /* # -  35 */
1190   0x0448, /* $ -  36 */
1191   0x0048, /* % -  37 */
1192   0x0048, /* & -  38 */
1193   0x0440, /* ' -  39 */
1194   0x0048, /* ( -  40 */
1195   0x0048, /* ) -  41 */
1196   0x0048, /* * -  42 */
1197   0x0048, /* + -  43 */
1198   0x0048, /* , -  44 */
1199   0x0440, /* - -  45 */
1200   0x0048, /* . -  46 */
1201   0x0448, /* / -  47 */
1202   0x0040, /* 0 -  48 */
1203   0x0040, /* 1 -  49 */
1204   0x0040, /* 2 -  50 */
1205   0x0040, /* 3 -  51 */
1206   0x0040, /* 4 -  52 */
1207   0x0040, /* 5 -  53 */
1208   0x0040, /* 6 -  54 */
1209   0x0040, /* 7 -  55 */
1210   0x0040, /* 8 -  56 */
1211   0x0040, /* 9 -  57 */
1212   0x0048, /* : -  58 */
1213   0x0048, /* ; -  59 */
1214   0x0048, /* < -  60 */
1215   0x0448, /* = -  61 */
1216   0x0048, /* > -  62 */
1217   0x0048, /* ? -  63 */
1218   0x0448, /* @ -  64 */
1219   0x8040, /* A -  65 */
1220   0x8040, /* B -  66 */
1221   0x8040, /* C -  67 */
1222   0x8040, /* D -  68 */
1223   0x8040, /* E -  69 */
1224   0x8040, /* F -  70 */
1225   0x8040, /* G -  71 */
1226   0x8040, /* H -  72 */
1227   0x8040, /* I -  73 */
1228   0x8040, /* J -  74 */
1229   0x8040, /* K -  75 */
1230   0x8040, /* L -  76 */
1231   0x8040, /* M -  77 */
1232   0x8040, /* N -  78 */
1233   0x8040, /* O -  79 */
1234   0x8040, /* P -  80 */
1235   0x8040, /* Q -  81 */
1236   0x8040, /* R -  82 */
1237   0x8040, /* S -  83 */
1238   0x8040, /* T -  84 */
1239   0x8040, /* U -  85 */
1240   0x8040, /* V -  86 */
1241   0x8040, /* W -  87 */
1242   0x8040, /* X -  88 */
1243   0x8040, /* Y -  89 */
1244   0x8040, /* Z -  90 */
1245   0x0048, /* [ -  91 */
1246   0x0448, /* \ -  92 */
1247   0x0048, /* ] -  93 */
1248   0x0448, /* ^ -  94 */
1249   0x0448, /* _ -  95 */
1250   0x0448, /* ` -  96 */
1251   0x8040, /* a -  97 */
1252   0x8040, /* b -  98 */
1253   0x8040, /* c -  99 */
1254   0x8040, /* d - 100 */
1255   0x8040, /* e - 101 */
1256   0x8040, /* f - 102 */
1257   0x8040, /* g - 103 */
1258   0x8040, /* h - 104 */
1259   0x8040, /* i - 105 */
1260   0x8040, /* j - 106 */
1261   0x8040, /* k - 107 */
1262   0x8040, /* l - 108 */
1263   0x8040, /* m - 109 */
1264   0x8040, /* n - 110 */
1265   0x8040, /* o - 111 */
1266   0x8040, /* p - 112 */
1267   0x8040, /* q - 113 */
1268   0x8040, /* r - 114 */
1269   0x8040, /* s - 115 */
1270   0x8040, /* t - 116 */
1271   0x8040, /* u - 117 */
1272   0x8040, /* v - 118 */
1273   0x8040, /* w - 119 */
1274   0x8040, /* x - 120 */
1275   0x8040, /* y - 121 */
1276   0x8040, /* z - 122 */
1277   0x0048, /* { - 123 */
1278   0x0048, /* | - 124 */
1279   0x0048, /* } - 125 */
1280   0x0448, /* ~ - 126 */
1281   0x0000, /* \7f - 127 */
1282   0x0000, /* \80 - 128 */
1283   0x0000, /* \81 - 129 */
1284   0x0008, /* \82 - 130 */
1285   0x8000, /* \83 - 131 */
1286   0x0008, /* \84 - 132 */
1287   0x0008, /* \85 - 133 */
1288   0x0008, /* \86 - 134 */
1289   0x0008, /* \87 - 135 */
1290   0x0001, /* \88 - 136 */
1291   0x0008, /* \89 - 137 */
1292   0x8003, /* \8a - 138 */
1293   0x0008, /* \8b - 139 */
1294   0x8000, /* \8c - 140 */
1295   0x0000, /* \8d - 141 */
1296   0x0000, /* \8e - 142 */
1297   0x0000, /* \8f - 143 */
1298   0x0000, /* \90 - 144 */
1299   0x0088, /* \91 - 145 */
1300   0x0088, /* \92 - 146 */
1301   0x0088, /* \93 - 147 */
1302   0x0088, /* \94 - 148 */
1303   0x0008, /* \95 - 149 */
1304   0x0400, /* \96 - 150 */
1305   0x0400, /* \97 - 151 */
1306   0x0408, /* \98 - 152 */
1307   0x0000, /* \99 - 153 */
1308   0x8003, /* \9a - 154 */
1309   0x0008, /* \9b - 155 */
1310   0x8000, /* \9c - 156 */
1311   0x0000, /* \9d - 157 */
1312   0x0000, /* \9e - 158 */
1313   0x8003, /* \9f - 159 */
1314   0x0008, /*   - 160 */
1315   0x0008, /* ¡ - 161 */
1316   0x0048, /* ¢ - 162 */
1317   0x0048, /* £ - 163 */
1318   0x0008, /* ¤ - 164 */
1319   0x0048, /* ¥ - 165 */
1320   0x0048, /* ¦ - 166 */
1321   0x0008, /* § - 167 */
1322   0x0408, /* ¨ - 168 */
1323   0x0008, /* © - 169 */
1324   0x0400, /* ª - 170 */
1325   0x0008, /* « - 171 */
1326   0x0048, /* ¬ - 172 */
1327   0x0408, /* ­ - 173 */
1328   0x0008, /* ® - 174 */
1329   0x0448, /* ¯ - 175 */
1330   0x0008, /* ° - 176 */
1331   0x0008, /* ± - 177 */
1332   0x0000, /* ² - 178 */
1333   0x0000, /* ³ - 179 */
1334   0x0408, /* ´ - 180 */
1335   0x0008, /* µ - 181 */
1336   0x0008, /* ¶ - 182 */
1337   0x0008, /* · - 183 */
1338   0x0408, /* ¸ - 184 */
1339   0x0000, /* ¹ - 185 */
1340   0x0400, /* º - 186 */
1341   0x0008, /* » - 187 */
1342   0x0000, /* ¼ - 188 */
1343   0x0000, /* ½ - 189 */
1344   0x0000, /* ¾ - 190 */
1345   0x0008, /* ¿ - 191 */
1346   0x8003, /* À - 192 */
1347   0x8003, /* Á - 193 */
1348   0x8003, /* Â - 194 */
1349   0x8003, /* Ã - 195 */
1350   0x8003, /* Ä - 196 */
1351   0x8003, /* Å - 197 */
1352   0x8000, /* Æ - 198 */
1353   0x8003, /* Ç - 199 */
1354   0x8003, /* È - 200 */
1355   0x8003, /* É - 201 */
1356   0x8003, /* Ê - 202 */
1357   0x8003, /* Ë - 203 */
1358   0x8003, /* Ì - 204 */
1359   0x8003, /* Í - 205 */
1360   0x8003, /* Î - 206 */
1361   0x8003, /* Ï - 207 */
1362   0x8000, /* Ð - 208 */
1363   0x8003, /* Ñ - 209 */
1364   0x8003, /* Ò - 210 */
1365   0x8003, /* Ó - 211 */
1366   0x8003, /* Ô - 212 */
1367   0x8003, /* Õ - 213 */
1368   0x8003, /* Ö - 214 */
1369   0x0008, /* × - 215 */
1370   0x8003, /* Ø - 216 */
1371   0x8003, /* Ù - 217 */
1372   0x8003, /* Ú - 218 */
1373   0x8003, /* Û - 219 */
1374   0x8003, /* Ü - 220 */
1375   0x8003, /* Ý - 221 */
1376   0x8000, /* Þ - 222 */
1377   0x8000, /* ß - 223 */
1378   0x8003, /* à - 224 */
1379   0x8003, /* á - 225 */
1380   0x8003, /* â - 226 */
1381   0x8003, /* ã - 227 */
1382   0x8003, /* ä - 228 */
1383   0x8003, /* å - 229 */
1384   0x8000, /* æ - 230 */
1385   0x8003, /* ç - 231 */
1386   0x8003, /* è - 232 */
1387   0x8003, /* é - 233 */
1388   0x8003, /* ê - 234 */
1389   0x8003, /* ë - 235 */
1390   0x8003, /* ì - 236 */
1391   0x8003, /* í - 237 */
1392   0x8003, /* î - 238 */
1393   0x8003, /* ï - 239 */
1394   0x8000, /* ð - 240 */
1395   0x8003, /* ñ - 241 */
1396   0x8003, /* ò - 242 */
1397   0x8003, /* ó - 243 */
1398   0x8003, /* ô - 244 */
1399   0x8003, /* õ - 245 */
1400   0x8003, /* ö - 246 */
1401   0x0008, /* ÷ - 247 */
1402   0x8003, /* ø - 248 */
1403   0x8003, /* ù - 249 */
1404   0x8003, /* ú - 250 */
1405   0x8003, /* û - 251 */
1406   0x8003, /* ü - 252 */
1407   0x8003, /* ý - 253 */
1408   0x8000, /* þ - 254 */
1409   0x8003  /* ÿ - 255 */
1410 };
1411
1412 /******************************************************************************
1413  *              GetStringType16 [OLE2NLS.7]
1414  */
1415 BOOL16 WINAPI GetStringType16(LCID locale,DWORD dwInfoType,LPCSTR src,
1416                               INT16 cchSrc,LPWORD chartype)
1417 {
1418         return GetStringTypeExA(locale,dwInfoType,src,cchSrc,chartype);
1419 }
1420 /******************************************************************************
1421  *              GetStringType32A        [KERNEL32.396]
1422  */
1423 BOOL WINAPI GetStringTypeA(LCID locale,DWORD dwInfoType,LPCSTR src,
1424                                INT cchSrc,LPWORD chartype)
1425 {
1426         return GetStringTypeExA(locale,dwInfoType,src,cchSrc,chartype);
1427 }
1428
1429 /******************************************************************************
1430  *              GetStringTypeEx32A      [KERNEL32.397]
1431  *
1432  * FIXME: Ignores the locale.
1433  */
1434 BOOL WINAPI GetStringTypeExA(LCID locale,DWORD dwInfoType,LPCSTR src,
1435                                  INT cchSrc,LPWORD chartype)
1436 {
1437         int     i;
1438         
1439         if ((src==NULL) || (chartype==NULL) || (src==(LPSTR)chartype))
1440         {
1441           SetLastError(ERROR_INVALID_PARAMETER);
1442           return FALSE;
1443         }
1444
1445         if (cchSrc==-1)
1446           cchSrc=lstrlenA(src)+1;
1447           
1448         switch (dwInfoType) {
1449         case CT_CTYPE1:
1450           for (i=0;i<cchSrc;i++) 
1451           {
1452             chartype[i] = 0;
1453             if (isdigit(src[i])) chartype[i]|=C1_DIGIT;
1454             if (isalpha(src[i])) chartype[i]|=C1_ALPHA;
1455             if (islower(src[i])) chartype[i]|=C1_LOWER;
1456             if (isupper(src[i])) chartype[i]|=C1_UPPER;
1457             if (isspace(src[i])) chartype[i]|=C1_SPACE;
1458             if (ispunct(src[i])) chartype[i]|=C1_PUNCT;
1459             if (iscntrl(src[i])) chartype[i]|=C1_CNTRL;
1460 /* FIXME: isblank() is a GNU extension */
1461 /*              if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1462             if ((src[i] == ' ') || (src[i] == '\t')) chartype[i]|=C1_BLANK;
1463             /* C1_XDIGIT */
1464         }
1465         return TRUE;
1466
1467         case CT_CTYPE2:
1468           for (i=0;i<cchSrc;i++) 
1469           {
1470             chartype[i]=(WORD)CT_CType2_LUT[i];
1471           }
1472           return TRUE;
1473
1474         case CT_CTYPE3:
1475           for (i=0;i<cchSrc;i++) 
1476           {
1477             chartype[i]=OLE2NLS_CT_CType3_LUT[i];
1478           }
1479           return TRUE;
1480
1481         default:
1482           ERR_(ole)("Unknown dwInfoType:%ld\n",dwInfoType);
1483           return FALSE;
1484         }
1485 }
1486
1487 /******************************************************************************
1488  *              GetStringType32W        [KERNEL32.399]
1489  *
1490  * NOTES
1491  * Yes, this is missing LCID locale. MS fault.
1492  */
1493 BOOL WINAPI GetStringTypeW(DWORD dwInfoType,LPCWSTR src,INT cchSrc,
1494                                LPWORD chartype)
1495 {
1496         return GetStringTypeExW(0/*defaultlocale*/,dwInfoType,src,cchSrc,chartype);
1497 }
1498
1499 /******************************************************************************
1500  *              GetStringTypeEx32W      [KERNEL32.398]
1501  *
1502  * FIXME: unicode chars are assumed chars
1503  */
1504 BOOL WINAPI GetStringTypeExW(LCID locale,DWORD dwInfoType,LPCWSTR src,
1505                                  INT cchSrc,LPWORD chartype)
1506 {
1507         int     i;
1508
1509
1510         if (cchSrc==-1)
1511           cchSrc=lstrlenW(src)+1;
1512         
1513         switch (dwInfoType) {
1514         case CT_CTYPE2:
1515                 FIXME_(ole)("CT_CTYPE2 not supported.\n");
1516                 return FALSE;
1517         case CT_CTYPE3:
1518                 FIXME_(ole)("CT_CTYPE3 not supported.\n");
1519                 return FALSE;
1520         default:break;
1521         }
1522         for (i=0;i<cchSrc;i++) {
1523                 chartype[i] = 0;
1524                 if (isdigit(src[i])) chartype[i]|=C1_DIGIT;
1525                 if (isalpha(src[i])) chartype[i]|=C1_ALPHA;
1526                 if (islower(src[i])) chartype[i]|=C1_LOWER;
1527                 if (isupper(src[i])) chartype[i]|=C1_UPPER;
1528                 if (isspace(src[i])) chartype[i]|=C1_SPACE;
1529                 if (ispunct(src[i])) chartype[i]|=C1_PUNCT;
1530                 if (iscntrl(src[i])) chartype[i]|=C1_CNTRL;
1531 /* FIXME: isblank() is a GNU extension */
1532 /*              if (isblank(src[i])) chartype[i]|=C1_BLANK; */
1533                 if ((src[i] == ' ') || (src[i] == '\t')) chartype[i]|=C1_BLANK;
1534                 /* C1_XDIGIT */
1535         }
1536         return TRUE;
1537 }
1538
1539 /*****************************************************************
1540  * WINE_GetLanguageName   [internal] 
1541  */
1542 static LPCSTR WINE_GetLanguageName( UINT langid )
1543 {
1544     int i;
1545     for ( i = 0; languages[i].langid != 0; i++ )
1546         if ( langid == languages[i].langid )
1547             break;
1548
1549     return languages[i].langname;
1550 }
1551
1552 /***********************************************************************
1553  *           VerLanguageNameA              [KERNEL32.709][VERSION.9]
1554  */
1555 DWORD WINAPI VerLanguageNameA( UINT wLang, LPSTR szLang, UINT nSize )
1556 {
1557     char    buffer[80];
1558     LPCSTR  name;
1559     DWORD   result;
1560
1561     /*
1562      * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1563      * from the registry.
1564      */
1565
1566     sprintf( buffer,
1567              "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1568              wLang );
1569
1570     result = RegQueryValueA( HKEY_LOCAL_MACHINE, buffer, szLang, (LPDWORD)&nSize );
1571     if ( result == ERROR_SUCCESS || result == ERROR_MORE_DATA )
1572         return nSize;
1573
1574     /*
1575      * If that fails, use the internal table
1576      */
1577
1578     name = WINE_GetLanguageName( wLang );
1579     lstrcpynA( szLang, name, nSize );
1580     return lstrlenA( name );
1581 }
1582
1583 /***********************************************************************
1584  *           VerLanguageNameW              [KERNEL32.710][VERSION.10]
1585  */
1586 DWORD WINAPI VerLanguageNameW( UINT wLang, LPWSTR szLang, UINT nSize )
1587 {
1588     char    buffer[80];
1589     LPWSTR  keyname;
1590     LPCSTR  name;
1591     DWORD   result;
1592
1593     /*
1594      * First, check \System\CurrentControlSet\control\Nls\Locale\<langid>
1595      * from the registry.
1596      */
1597
1598     sprintf( buffer,
1599              "\\System\\CurrentControlSet\\control\\Nls\\Locale\\%08x",
1600              wLang );
1601
1602     keyname = HEAP_strdupAtoW( GetProcessHeap(), 0, buffer );
1603     result = RegQueryValueW( HKEY_LOCAL_MACHINE, keyname, szLang, (LPDWORD)&nSize );
1604     HeapFree( GetProcessHeap(), 0, keyname );
1605
1606     if ( result == ERROR_SUCCESS || result == ERROR_MORE_DATA )
1607         return nSize;
1608
1609     /*
1610      * If that fails, use the internal table
1611      */
1612
1613     name = WINE_GetLanguageName( wLang );
1614     lstrcpynAtoW( szLang, name, nSize );
1615     return lstrlenA( name );
1616 }
1617
1618  
1619 static const unsigned char LCM_Unicode_LUT[] = {
1620   6      ,   3, /*   -   1 */  
1621   6      ,   4, /*   -   2 */  
1622   6      ,   5, /*   -   3 */  
1623   6      ,   6, /*   -   4 */  
1624   6      ,   7, /*   -   5 */  
1625   6      ,   8, /*   -   6 */  
1626   6      ,   9, /*   -   7 */  
1627   6      ,  10, /*   -   8 */  
1628   7      ,   5, /*   -   9 */  
1629   7      ,   6, /*   -  10 */  
1630   7      ,   7, /*   -  11 */  
1631   7      ,   8, /*   -  12 */  
1632   7      ,   9, /*   -  13 */  
1633   6      ,  11, /*   -  14 */  
1634   6      ,  12, /*   -  15 */  
1635   6      ,  13, /*   -  16 */  
1636   6      ,  14, /*   -  17 */  
1637   6      ,  15, /*   -  18 */  
1638   6      ,  16, /*   -  19 */  
1639   6      ,  17, /*   -  20 */  
1640   6      ,  18, /*   -  21 */  
1641   6      ,  19, /*   -  22 */  
1642   6      ,  20, /*   -  23 */  
1643   6      ,  21, /*   -  24 */  
1644   6      ,  22, /*   -  25 */  
1645   6      ,  23, /*   -  26 */  
1646   6      ,  24, /*   -  27 */  
1647   6      ,  25, /*   -  28 */  
1648   6      ,  26, /*   -  29 */  
1649   6      ,  27, /*   -  30 */  
1650   6      ,  28, /*   -  31 */  
1651   7      ,   2, /*   -  32 */
1652   7      ,  28, /* ! -  33 */
1653   7      ,  29, /* " -  34 */ /* " */
1654   7      ,  31, /* # -  35 */
1655   7      ,  33, /* $ -  36 */
1656   7      ,  35, /* % -  37 */
1657   7      ,  37, /* & -  38 */
1658   6      , 128, /* ' -  39 */
1659   7      ,  39, /* ( -  40 */
1660   7      ,  42, /* ) -  41 */
1661   7      ,  45, /* * -  42 */
1662   8      ,   3, /* + -  43 */
1663   7      ,  47, /* , -  44 */
1664   6      , 130, /* - -  45 */
1665   7      ,  51, /* . -  46 */
1666   7      ,  53, /* / -  47 */
1667  12      ,   3, /* 0 -  48 */
1668  12      ,  33, /* 1 -  49 */
1669  12      ,  51, /* 2 -  50 */
1670  12      ,  70, /* 3 -  51 */
1671  12      ,  88, /* 4 -  52 */
1672  12      , 106, /* 5 -  53 */
1673  12      , 125, /* 6 -  54 */
1674  12      , 144, /* 7 -  55 */
1675  12      , 162, /* 8 -  56 */
1676  12      , 180, /* 9 -  57 */
1677   7      ,  55, /* : -  58 */
1678   7      ,  58, /* ; -  59 */
1679   8      ,  14, /* < -  60 */
1680   8      ,  18, /* = -  61 */
1681   8      ,  20, /* > -  62 */
1682   7      ,  60, /* ? -  63 */
1683   7      ,  62, /* @ -  64 */
1684  14      ,   2, /* A -  65 */
1685  14      ,   9, /* B -  66 */
1686  14      ,  10, /* C -  67 */
1687  14      ,  26, /* D -  68 */
1688  14      ,  33, /* E -  69 */
1689  14      ,  35, /* F -  70 */
1690  14      ,  37, /* G -  71 */
1691  14      ,  44, /* H -  72 */
1692  14      ,  50, /* I -  73 */
1693  14      ,  53, /* J -  74 */
1694  14      ,  54, /* K -  75 */
1695  14      ,  72, /* L -  76 */
1696  14      ,  81, /* M -  77 */
1697  14      , 112, /* N -  78 */
1698  14      , 124, /* O -  79 */
1699  14      , 126, /* P -  80 */
1700  14      , 137, /* Q -  81 */
1701  14      , 138, /* R -  82 */
1702  14      , 145, /* S -  83 */
1703  14      , 153, /* T -  84 */
1704  14      , 159, /* U -  85 */
1705  14      , 162, /* V -  86 */
1706  14      , 164, /* W -  87 */
1707  14      , 166, /* X -  88 */
1708  14      , 167, /* Y -  89 */
1709  14      , 169, /* Z -  90 */
1710   7      ,  63, /* [ -  91 */
1711   7      ,  65, /* \ -  92 */
1712   7      ,  66, /* ] -  93 */
1713   7      ,  67, /* ^ -  94 */
1714   7      ,  68, /* _ -  95 */
1715   7      ,  72, /* ` -  96 */
1716  14      ,   2, /* a -  97 */
1717  14      ,   9, /* b -  98 */
1718  14      ,  10, /* c -  99 */
1719  14      ,  26, /* d - 100 */
1720  14      ,  33, /* e - 101 */
1721  14      ,  35, /* f - 102 */
1722  14      ,  37, /* g - 103 */
1723  14      ,  44, /* h - 104 */
1724  14      ,  50, /* i - 105 */
1725  14      ,  53, /* j - 106 */
1726  14      ,  54, /* k - 107 */
1727  14      ,  72, /* l - 108 */
1728  14      ,  81, /* m - 109 */
1729  14      , 112, /* n - 110 */
1730  14      , 124, /* o - 111 */
1731  14      , 126, /* p - 112 */
1732  14      , 137, /* q - 113 */
1733  14      , 138, /* r - 114 */
1734  14      , 145, /* s - 115 */
1735  14      , 153, /* t - 116 */
1736  14      , 159, /* u - 117 */
1737  14      , 162, /* v - 118 */
1738  14      , 164, /* w - 119 */
1739  14      , 166, /* x - 120 */
1740  14      , 167, /* y - 121 */
1741  14      , 169, /* z - 122 */
1742   7      ,  74, /* { - 123 */
1743   7      ,  76, /* | - 124 */
1744   7      ,  78, /* } - 125 */
1745   7      ,  80, /* ~ - 126 */
1746   6      ,  29, /* \7f - 127 */
1747   6      ,  30, /* \80 - 128 */
1748   6      ,  31, /* \81 - 129 */
1749   7      , 123, /* \82 - 130 */
1750  14      ,  35, /* \83 - 131 */
1751   7      , 127, /* \84 - 132 */
1752  10      ,  21, /* \85 - 133 */
1753  10      ,  15, /* \86 - 134 */
1754  10      ,  16, /* \87 - 135 */
1755   7      ,  67, /* \88 - 136 */
1756  10      ,  22, /* \89 - 137 */
1757  14      , 145, /* \8a - 138 */
1758   7      , 136, /* \8b - 139 */
1759  14 + 16 , 124, /* \8c - 140 */
1760   6      ,  43, /* \8d - 141 */
1761   6      ,  44, /* \8e - 142 */
1762   6      ,  45, /* \8f - 143 */
1763   6      ,  46, /* \90 - 144 */
1764   7      , 121, /* \91 - 145 */
1765   7      , 122, /* \92 - 146 */
1766   7      , 125, /* \93 - 147 */
1767   7      , 126, /* \94 - 148 */
1768  10      ,  17, /* \95 - 149 */
1769   6      , 137, /* \96 - 150 */
1770   6      , 139, /* \97 - 151 */
1771   7      ,  93, /* \98 - 152 */
1772  14      , 156, /* \99 - 153 */
1773  14      , 145, /* \9a - 154 */
1774   7      , 137, /* \9b - 155 */
1775  14 + 16 , 124, /* \9c - 156 */
1776   6      ,  59, /* \9d - 157 */
1777   6      ,  60, /* \9e - 158 */
1778  14      , 167, /* \9f - 159 */
1779   7      ,   4, /*   - 160 */
1780   7      ,  81, /* ¡ - 161 */
1781  10      ,   2, /* ¢ - 162 */
1782  10      ,   3, /* £ - 163 */
1783  10      ,   4, /* ¤ - 164 */
1784  10      ,   5, /* ¥ - 165 */
1785   7      ,  82, /* ¦ - 166 */
1786  10      ,   6, /* § - 167 */
1787   7      ,  83, /* ¨ - 168 */
1788  10      ,   7, /* © - 169 */
1789  14      ,   2, /* ª - 170 */
1790   8      ,  24, /* « - 171 */
1791  10      ,   8, /* ¬ - 172 */
1792   6      , 131, /* ­ - 173 */
1793  10      ,   9, /* ® - 174 */
1794   7      ,  84, /* ¯ - 175 */
1795  10      ,  10, /* ° - 176 */
1796   8      ,  23, /* ± - 177 */
1797  12      ,  51, /* ² - 178 */
1798  12      ,  70, /* ³ - 179 */
1799   7      ,  85, /* ´ - 180 */
1800  10      ,  11, /* µ - 181 */
1801  10      ,  12, /* ¶ - 182 */
1802  10      ,  13, /* · - 183 */
1803   7      ,  86, /* ¸ - 184 */
1804  12      ,  33, /* ¹ - 185 */
1805  14      , 124, /* º - 186 */
1806   8      ,  26, /* » - 187 */
1807  12      ,  21, /* ¼ - 188 */
1808  12      ,  25, /* ½ - 189 */
1809  12      ,  29, /* ¾ - 190 */
1810   7      ,  87, /* ¿ - 191 */
1811  14      ,   2, /* À - 192 */
1812  14      ,   2, /* Á - 193 */
1813  14      ,   2, /* Â - 194 */
1814  14      ,   2, /* Ã - 195 */
1815  14      ,   2, /* Ä - 196 */
1816  14      ,   2, /* Å - 197 */
1817  14 + 16 ,   2, /* Æ - 198 */
1818  14      ,  10, /* Ç - 199 */
1819  14      ,  33, /* È - 200 */
1820  14      ,  33, /* É - 201 */
1821  14      ,  33, /* Ê - 202 */
1822  14      ,  33, /* Ë - 203 */
1823  14      ,  50, /* Ì - 204 */
1824  14      ,  50, /* Í - 205 */
1825  14      ,  50, /* Î - 206 */
1826  14      ,  50, /* Ï - 207 */
1827  14      ,  26, /* Ð - 208 */
1828  14      , 112, /* Ñ - 209 */
1829  14      , 124, /* Ò - 210 */
1830  14      , 124, /* Ó - 211 */
1831  14      , 124, /* Ô - 212 */
1832  14      , 124, /* Õ - 213 */
1833  14      , 124, /* Ö - 214 */
1834   8      ,  28, /* × - 215 */
1835  14      , 124, /* Ø - 216 */
1836  14      , 159, /* Ù - 217 */
1837  14      , 159, /* Ú - 218 */
1838  14      , 159, /* Û - 219 */
1839  14      , 159, /* Ü - 220 */
1840  14      , 167, /* Ý - 221 */
1841  14 + 32 , 153, /* Þ - 222 */
1842  14 + 48 , 145, /* ß - 223 */
1843  14      ,   2, /* à - 224 */
1844  14      ,   2, /* á - 225 */
1845  14      ,   2, /* â - 226 */
1846  14      ,   2, /* ã - 227 */
1847  14      ,   2, /* ä - 228 */
1848  14      ,   2, /* å - 229 */
1849  14 + 16 ,   2, /* æ - 230 */
1850  14      ,  10, /* ç - 231 */
1851  14      ,  33, /* è - 232 */
1852  14      ,  33, /* é - 233 */
1853  14      ,  33, /* ê - 234 */
1854  14      ,  33, /* ë - 235 */
1855  14      ,  50, /* ì - 236 */
1856  14      ,  50, /* í - 237 */
1857  14      ,  50, /* î - 238 */
1858  14      ,  50, /* ï - 239 */
1859  14      ,  26, /* ð - 240 */
1860  14      , 112, /* ñ - 241 */
1861  14      , 124, /* ò - 242 */
1862  14      , 124, /* ó - 243 */
1863  14      , 124, /* ô - 244 */
1864  14      , 124, /* õ - 245 */
1865  14      , 124, /* ö - 246 */
1866   8      ,  29, /* ÷ - 247 */
1867  14      , 124, /* ø - 248 */
1868  14      , 159, /* ù - 249 */
1869  14      , 159, /* ú - 250 */
1870  14      , 159, /* û - 251 */
1871  14      , 159, /* ü - 252 */
1872  14      , 167, /* ý - 253 */
1873  14 + 32 , 153, /* þ - 254 */
1874  14      , 167  /* ÿ - 255 */ };
1875
1876 static const unsigned char LCM_Unicode_LUT_2[] = { 33, 44, 145 };
1877
1878 #define LCM_Diacritic_Start 131
1879
1880 static const unsigned char LCM_Diacritic_LUT[] = { 
1881 123,  /* \83 - 131 */
1882   2,  /* \84 - 132 */
1883   2,  /* \85 - 133 */
1884   2,  /* \86 - 134 */
1885   2,  /* \87 - 135 */
1886   3,  /* \88 - 136 */
1887   2,  /* \89 - 137 */
1888  20,  /* \8a - 138 */
1889   2,  /* \8b - 139 */
1890   2,  /* \8c - 140 */
1891   2,  /* \8d - 141 */
1892   2,  /* \8e - 142 */
1893   2,  /* \8f - 143 */
1894   2,  /* \90 - 144 */
1895   2,  /* \91 - 145 */
1896   2,  /* \92 - 146 */
1897   2,  /* \93 - 147 */
1898   2,  /* \94 - 148 */
1899   2,  /* \95 - 149 */
1900   2,  /* \96 - 150 */
1901   2,  /* \97 - 151 */
1902   2,  /* \98 - 152 */
1903   2,  /* \99 - 153 */
1904  20,  /* \9a - 154 */
1905   2,  /* \9b - 155 */
1906   2,  /* \9c - 156 */
1907   2,  /* \9d - 157 */
1908   2,  /* \9e - 158 */
1909  19,  /* \9f - 159 */
1910   2,  /*   - 160 */
1911   2,  /* ¡ - 161 */
1912   2,  /* ¢ - 162 */
1913   2,  /* £ - 163 */
1914   2,  /* ¤ - 164 */
1915   2,  /* ¥ - 165 */
1916   2,  /* ¦ - 166 */
1917   2,  /* § - 167 */
1918   2,  /* ¨ - 168 */
1919   2,  /* © - 169 */
1920   3,  /* ª - 170 */
1921   2,  /* « - 171 */
1922   2,  /* ¬ - 172 */
1923   2,  /* ­ - 173 */
1924   2,  /* ® - 174 */
1925   2,  /* ¯ - 175 */
1926   2,  /* ° - 176 */
1927   2,  /* ± - 177 */
1928   2,  /* ² - 178 */
1929   2,  /* ³ - 179 */
1930   2,  /* ´ - 180 */
1931   2,  /* µ - 181 */
1932   2,  /* ¶ - 182 */
1933   2,  /* · - 183 */
1934   2,  /* ¸ - 184 */
1935   2,  /* ¹ - 185 */
1936   3,  /* º - 186 */
1937   2,  /* » - 187 */
1938   2,  /* ¼ - 188 */
1939   2,  /* ½ - 189 */
1940   2,  /* ¾ - 190 */
1941   2,  /* ¿ - 191 */
1942  15,  /* À - 192 */
1943  14,  /* Á - 193 */
1944  18,  /* Â - 194 */
1945  25,  /* Ã - 195 */
1946  19,  /* Ä - 196 */
1947  26,  /* Å - 197 */
1948   2,  /* Æ - 198 */
1949  28,  /* Ç - 199 */
1950  15,  /* È - 200 */
1951  14,  /* É - 201 */
1952  18,  /* Ê - 202 */
1953  19,  /* Ë - 203 */
1954  15,  /* Ì - 204 */
1955  14,  /* Í - 205 */
1956  18,  /* Î - 206 */
1957  19,  /* Ï - 207 */
1958 104,  /* Ð - 208 */
1959  25,  /* Ñ - 209 */
1960  15,  /* Ò - 210 */
1961  14,  /* Ó - 211 */
1962  18,  /* Ô - 212 */
1963  25,  /* Õ - 213 */
1964  19,  /* Ö - 214 */
1965   2,  /* × - 215 */
1966  33,  /* Ø - 216 */
1967  15,  /* Ù - 217 */
1968  14,  /* Ú - 218 */
1969  18,  /* Û - 219 */
1970  19,  /* Ü - 220 */
1971  14,  /* Ý - 221 */
1972   2,  /* Þ - 222 */
1973   2,  /* ß - 223 */
1974  15,  /* à - 224 */
1975  14,  /* á - 225 */
1976  18,  /* â - 226 */
1977  25,  /* ã - 227 */
1978  19,  /* ä - 228 */
1979  26,  /* å - 229 */
1980   2,  /* æ - 230 */
1981  28,  /* ç - 231 */
1982  15,  /* è - 232 */
1983  14,  /* é - 233 */
1984  18,  /* ê - 234 */
1985  19,  /* ë - 235 */
1986  15,  /* ì - 236 */
1987  14,  /* í - 237 */
1988  18,  /* î - 238 */
1989  19,  /* ï - 239 */
1990 104,  /* ð - 240 */
1991  25,  /* ñ - 241 */
1992  15,  /* ò - 242 */
1993  14,  /* ó - 243 */
1994  18,  /* ô - 244 */
1995  25,  /* õ - 245 */
1996  19,  /* ö - 246 */
1997   2,  /* ÷ - 247 */
1998  33,  /* ø - 248 */
1999  15,  /* ù - 249 */
2000  14,  /* ú - 250 */
2001  18,  /* û - 251 */
2002  19,  /* ü - 252 */
2003  14,  /* ý - 253 */
2004   2,  /* þ - 254 */
2005  19,  /* ÿ - 255 */
2006 } ;
2007
2008 /******************************************************************************
2009  * OLE2NLS_isPunctuation [INTERNAL]
2010  */
2011 static int OLE2NLS_isPunctuation(unsigned char c) 
2012 {
2013   /* "punctuation character" in this context is a character which is 
2014      considered "less important" during word sort comparison.
2015      See LCMapString implementation for the precise definition 
2016      of "less important". */
2017
2018   return (LCM_Unicode_LUT[-2+2*c]==6);
2019 }
2020
2021 /******************************************************************************
2022  * OLE2NLS_isNonSpacing [INTERNAL]
2023  */
2024 static int OLE2NLS_isNonSpacing(unsigned char c) 
2025 {
2026   /* This function is used by LCMapString32A.  Characters 
2027      for which it returns true are ignored when mapping a
2028      string with NORM_IGNORENONSPACE */
2029   return ((c==136) || (c==170) || (c==186));
2030 }
2031
2032 /******************************************************************************
2033  * OLE2NLS_isSymbol [INTERNAL]
2034  */
2035 static int OLE2NLS_isSymbol(unsigned char c) 
2036 {
2037   /* This function is used by LCMapString32A.  Characters 
2038      for which it returns true are ignored when mapping a
2039      string with NORM_IGNORESYMBOLS */
2040   return ( (c!=0) && !IsCharAlphaNumericA(c) );
2041 }
2042
2043 /******************************************************************************
2044  *              identity        [Internal]
2045  */
2046 static int identity(int c)
2047 {
2048   return c;
2049 }
2050
2051 /*************************************************************************
2052  *              LCMapString32A                [KERNEL32.492]
2053  *
2054  * Convert a string, or generate a sort key from it.
2055  *
2056  * If (mapflags & LCMAP_SORTKEY), the function will generate
2057  * a sort key for the source string.  Else, it will convert it
2058  * accordingly to the flags LCMAP_UPPERCASE, LCMAP_LOWERCASE,...
2059  *
2060  * RETURNS
2061  *    Error : 0.
2062  *    Success : length of the result string.
2063  *
2064  * NOTES
2065  *    If called with scrlen = -1, the function will compute the length
2066  *      of the 0-terminated string strsrc by itself.      
2067  * 
2068  *    If called with dstlen = 0, returns the buffer length that 
2069  *      would be required.
2070  *
2071  *    NORM_IGNOREWIDTH means to compare ASCII and wide characters
2072  *    as if they are equal.  
2073  *    In the only code page implemented so far, there may not be
2074  *    wide characters in strings passed to LCMapString32A,
2075  *    so there is nothing to be done for this flag.
2076  */
2077 INT WINAPI LCMapStringA(
2078         LCID lcid /* locale identifier created with MAKELCID; 
2079                      LOCALE_SYSTEM_DEFAULT and LOCALE_USER_DEFAULT are 
2080                      predefined values. */,
2081         DWORD mapflags /* flags */,
2082         LPCSTR srcstr  /* source buffer */,
2083         INT srclen   /* source length */,
2084         LPSTR dststr   /* destination buffer */,
2085         INT dstlen   /* destination buffer length */) 
2086 {
2087   int i;
2088
2089   TRACE_(string)("(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
2090         lcid,mapflags,srcstr,srclen,dststr,dstlen);
2091
2092   if ( ((dstlen!=0) && (dststr==NULL)) || (srcstr==NULL) )
2093   {
2094     ERR_(ole)("(src=%s,dest=%s): Invalid NULL string\n", srcstr, dststr);
2095     SetLastError(ERROR_INVALID_PARAMETER);
2096     return 0;
2097   }
2098   if (srclen == -1) 
2099     srclen = lstrlenA(srcstr) + 1 ;    /* (include final '\0') */
2100
2101 #define LCMAPSTRINGA_SUPPORTED_FLAGS (LCMAP_UPPERCASE     | \
2102                                         LCMAP_LOWERCASE     | \
2103                                         LCMAP_SORTKEY       | \
2104                                         NORM_IGNORECASE     | \
2105                                         NORM_IGNORENONSPACE | \
2106                                         SORT_STRINGSORT     | \
2107                                         NORM_IGNOREWIDTH    | \
2108                                         NORM_IGNOREKANATYPE)
2109   /* FIXME: as long as we don't support Kanakana nor Hirigana 
2110    * characters, we can support NORM_IGNOREKANATYPE
2111    */
2112   if (mapflags & ~LCMAPSTRINGA_SUPPORTED_FLAGS)
2113   {
2114     FIXME_(string)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2115           "unimplemented flags: 0x%08lx\n",
2116           lcid,
2117           mapflags,
2118           srcstr,
2119           srclen,
2120           dststr,
2121           dstlen,
2122           mapflags & ~LCMAPSTRINGA_SUPPORTED_FLAGS
2123      );
2124   }
2125
2126   if ( !(mapflags & LCMAP_SORTKEY) )
2127   {
2128     int i,j;
2129     int (*f)(int) = identity; 
2130     int flag_ignorenonspace = mapflags & NORM_IGNORENONSPACE;
2131     int flag_ignoresymbols = mapflags & NORM_IGNORESYMBOLS;
2132
2133     if (flag_ignorenonspace || flag_ignoresymbols)
2134     {
2135       /* For some values of mapflags, the length of the resulting 
2136          string is not known at this point.  Windows does map the string
2137          and does not SetLastError ERROR_INSUFFICIENT_BUFFER in
2138          these cases. */
2139       if (dstlen==0)
2140       {
2141         /* Compute required length */
2142         for (i=j=0; i < srclen; i++)
2143         {
2144           if ( !(flag_ignorenonspace && OLE2NLS_isNonSpacing(srcstr[i]))
2145                && !(flag_ignoresymbols && OLE2NLS_isSymbol(srcstr[i])) )
2146             j++;
2147         }
2148         return j;
2149       }
2150     }
2151     else
2152     {
2153       if (dstlen==0)
2154         return srclen;  
2155       if (dstlen<srclen) 
2156            {
2157              SetLastError(ERROR_INSUFFICIENT_BUFFER);
2158              return 0;
2159            }
2160     }
2161     if (mapflags & LCMAP_UPPERCASE)
2162       f = toupper;
2163     else if (mapflags & LCMAP_LOWERCASE)
2164       f = tolower;
2165     /* FIXME: NORM_IGNORENONSPACE requires another conversion */
2166     for (i=j=0; (i<srclen) && (j<dstlen) ; i++)
2167     {
2168       if ( !(flag_ignorenonspace && OLE2NLS_isNonSpacing(srcstr[i]))
2169            && !(flag_ignoresymbols && OLE2NLS_isSymbol(srcstr[i])) )
2170       {
2171         dststr[j] = (CHAR) f(srcstr[i]);
2172         j++;
2173       }
2174     }
2175     return j;
2176   }
2177
2178   /* else ... (mapflags & LCMAP_SORTKEY)  */
2179   {
2180     int unicode_len=0;
2181     int case_len=0;
2182     int diacritic_len=0;
2183     int delayed_punctuation_len=0;
2184     char *case_component;
2185     char *diacritic_component;
2186     char *delayed_punctuation_component;
2187     int room,count;
2188     int flag_stringsort = mapflags & SORT_STRINGSORT;
2189
2190     /* compute how much room we will need */
2191     for (i=0;i<srclen;i++)
2192     {
2193       int ofs;
2194       unsigned char source_char = srcstr[i];
2195       if (source_char!='\0') 
2196       {
2197         if (flag_stringsort || !OLE2NLS_isPunctuation(source_char))
2198         {
2199           unicode_len++;
2200           if ( LCM_Unicode_LUT[-2+2*source_char] & ~15 )
2201             unicode_len++;             /* double letter */
2202         }
2203         else
2204         {
2205           delayed_punctuation_len++;
2206         }         
2207       }
2208           
2209       if (isupper(source_char))
2210         case_len=unicode_len; 
2211
2212       ofs = source_char - LCM_Diacritic_Start;
2213       if ((ofs>=0) && (LCM_Diacritic_LUT[ofs]!=2))
2214         diacritic_len=unicode_len;
2215     }
2216
2217     if (mapflags & NORM_IGNORECASE)
2218       case_len=0;                   
2219     if (mapflags & NORM_IGNORENONSPACE)
2220       diacritic_len=0;
2221
2222     room =  2 * unicode_len              /* "unicode" component */
2223       +     diacritic_len                /* "diacritic" component */
2224       +     case_len                     /* "case" component */
2225       +     4 * delayed_punctuation_len  /* punctuation in word sort mode */
2226       +     4                            /* four '\1' separators */
2227       +     1  ;                         /* terminal '\0' */
2228     if (dstlen==0)
2229       return room;      
2230     else if (dstlen<room)
2231     {
2232       SetLastError(ERROR_INSUFFICIENT_BUFFER);
2233       return 0;
2234     }
2235
2236     /*FIXME the Pointercheck should not be nessesary */
2237     if (IsBadWritePtr (dststr,room))
2238     { ERR_(string)("bad destination buffer (dststr) : %p,%d\n",dststr,dstlen);
2239       SetLastError(ERROR_INSUFFICIENT_BUFFER);
2240       return 0;
2241     }
2242
2243     /* locate each component, write separators */
2244     diacritic_component = dststr + 2*unicode_len ;
2245     *diacritic_component++ = '\1'; 
2246     case_component = diacritic_component + diacritic_len ;
2247     *case_component++ = '\1'; 
2248     delayed_punctuation_component = case_component + case_len ;
2249     *delayed_punctuation_component++ = '\1';
2250     *delayed_punctuation_component++ = '\1';
2251
2252     /* read source string char by char, write 
2253        corresponding weight in each component. */
2254     for (i=0,count=0;i<srclen;i++)
2255     {
2256       unsigned char source_char=srcstr[i];
2257       if (source_char!='\0') 
2258       {
2259         int type,longcode;
2260         type = LCM_Unicode_LUT[-2+2*source_char];
2261         longcode = type >> 4;
2262         type &= 15;
2263         if (!flag_stringsort && OLE2NLS_isPunctuation(source_char)) 
2264         {
2265           UINT16 encrypted_location = (1<<15) + 7 + 4*count;
2266           *delayed_punctuation_component++ = (unsigned char) (encrypted_location>>8);
2267           *delayed_punctuation_component++ = (unsigned char) (encrypted_location&255);
2268                      /* big-endian is used here because it lets string comparison be
2269                         compatible with numerical comparison */
2270
2271           *delayed_punctuation_component++ = type;
2272           *delayed_punctuation_component++ = LCM_Unicode_LUT[-1+2*source_char];  
2273                      /* assumption : a punctuation character is never a 
2274                         double or accented letter */
2275         }
2276         else
2277         {
2278           dststr[2*count] = type;
2279           dststr[2*count+1] = LCM_Unicode_LUT[-1+2*source_char];  
2280           if (longcode)
2281           {
2282             if (count<case_len)
2283               case_component[count] = ( isupper(source_char) ? 18 : 2 ) ;
2284             if (count<diacritic_len)
2285               diacritic_component[count] = 2; /* assumption: a double letter
2286                                                  is never accented */
2287             count++;
2288             
2289             dststr[2*count] = type;
2290             dststr[2*count+1] = *(LCM_Unicode_LUT_2 - 1 + longcode); 
2291             /* 16 in the first column of LCM_Unicode_LUT  -->  longcode = 1 
2292                32 in the first column of LCM_Unicode_LUT  -->  longcode = 2 
2293                48 in the first column of LCM_Unicode_LUT  -->  longcode = 3 */
2294           }
2295
2296           if (count<case_len)
2297             case_component[count] = ( isupper(source_char) ? 18 : 2 ) ;
2298           if (count<diacritic_len)
2299           {
2300             int ofs = source_char - LCM_Diacritic_Start;
2301             diacritic_component[count] = (ofs>=0 ? LCM_Diacritic_LUT[ofs] : 2);
2302           }
2303           count++;
2304         }
2305       }
2306     }
2307     dststr[room-1] = '\0';
2308     return room;
2309   }
2310 }
2311                      
2312 /*************************************************************************
2313  *              LCMapString32W                [KERNEL32.493]
2314  *
2315  * Convert a string, or generate a sort key from it.
2316  *
2317  * NOTE
2318  *
2319  * See LCMapString32A for documentation
2320  */
2321 INT WINAPI LCMapStringW(
2322         LCID lcid,DWORD mapflags,LPCWSTR srcstr,INT srclen,LPWSTR dststr,
2323         INT dstlen)
2324 {
2325   int i;
2326  
2327   TRACE_(string)("(0x%04lx,0x%08lx,%p,%d,%p,%d)\n",
2328         lcid,mapflags,srcstr,srclen,dststr,dstlen);
2329
2330   if ( ((dstlen!=0) && (dststr==NULL)) || (srcstr==NULL) )
2331   {
2332     ERR_(ole)("(src=%p,dst=%p): Invalid NULL string\n", srcstr, dststr);
2333     SetLastError(ERROR_INVALID_PARAMETER);
2334     return 0;
2335   }
2336   if (srclen==-1) 
2337     srclen = lstrlenW(srcstr)+1;
2338   if (mapflags & LCMAP_SORTKEY) 
2339   {
2340     FIXME_(string)("(0x%04lx,0x%08lx,%p,%d,%p,%d): "
2341           "unimplemented flags: 0x%08lx\n",
2342           lcid,mapflags,srcstr,srclen,dststr,dstlen,mapflags);
2343     return 0;
2344   }
2345   else
2346   {
2347     int (*f)(int)=identity; 
2348
2349     if (dstlen==0)
2350       return srclen;  
2351     if (dstlen<srclen) {
2352       SetLastError(ERROR_INSUFFICIENT_BUFFER);
2353       return 0;
2354     }
2355     if (mapflags & LCMAP_UPPERCASE)
2356       f = toupper;
2357     else if (mapflags & LCMAP_LOWERCASE)
2358       f = tolower;
2359     for (i=0; i < srclen; i++)
2360       dststr[i] = (WCHAR) f(srcstr[i]);
2361     return srclen;
2362   }
2363 }
2364
2365 /***********************************************************************
2366  *           CompareString16       (OLE2NLS.8)
2367  */
2368 UINT16 WINAPI CompareString16(DWORD lcid,DWORD fdwStyle,
2369                               LPCSTR s1,DWORD l1,LPCSTR s2,DWORD l2)
2370 {
2371         return (UINT16)CompareStringA(lcid,fdwStyle,s1,l1,s2,l2);
2372 }
2373
2374 /******************************************************************************
2375  *              CompareString32A        [KERNEL32.143]
2376  * Compares two strings using locale
2377  *
2378  * RETURNS
2379  *
2380  * success: CSTR_LESS_THAN, CSTR_EQUAL, CSTR_GREATER_THAN
2381  * failure: 0
2382  *
2383  * NOTES
2384  *
2385  * Defaults to a word sort, but uses a string sort if
2386  * SORT_STRINGSORT is set.
2387  * Calls SetLastError for ERROR_INVALID_FLAGS, ERROR_INVALID_PARAMETER.
2388  * 
2389  * BUGS
2390  *
2391  * This implementation ignores the locale
2392  *
2393  * FIXME
2394  * 
2395  * Quite inefficient.
2396  */
2397 UINT WINAPI CompareStringA(
2398     DWORD lcid,     /* locale ID */
2399     DWORD fdwStyle, /* comparison-style options */
2400     LPCSTR s1,      /* first string */
2401     DWORD l1,       /* length of first string */
2402     LPCSTR s2,      /* second string */
2403     DWORD l2)       /* length of second string */
2404 {
2405   int mapstring_flags;
2406   int len1,len2;
2407   int result;
2408   LPSTR sk1,sk2;
2409   TRACE_(ole)("%s and %s\n",
2410         debugstr_a (s1), debugstr_a (s2));
2411
2412   if ( (s1==NULL) || (s2==NULL) )
2413   {    
2414     ERR_(ole)("(s1=%s,s2=%s): Invalid NULL string\n", s1, s2);
2415     SetLastError(ERROR_INVALID_PARAMETER);
2416     return 0;
2417   }
2418
2419   if(fdwStyle & NORM_IGNORESYMBOLS)
2420     FIXME_(ole)("IGNORESYMBOLS not supported\n");
2421         
2422   mapstring_flags = LCMAP_SORTKEY | fdwStyle ;
2423   len1 = LCMapStringA(lcid,mapstring_flags,s1,l1,NULL,0);
2424   len2 = LCMapStringA(lcid,mapstring_flags,s2,l2,NULL,0);
2425
2426   if ((len1==0)||(len2==0))
2427     return 0;     /* something wrong happened */
2428
2429   sk1 = (LPSTR)HeapAlloc(GetProcessHeap(),0,len1);
2430   sk2 = (LPSTR)HeapAlloc(GetProcessHeap(),0,len2);
2431   if ( (!LCMapStringA(lcid,mapstring_flags,s1,l1,sk1,len1))
2432          || (!LCMapStringA(lcid,mapstring_flags,s2,l2,sk2,len2)) )
2433   {
2434     ERR_(ole)("Bug in LCmapString32A.\n");
2435     result = 0;
2436   }
2437   else
2438   {
2439     /* strcmp doesn't necessarily return -1, 0, or 1 */
2440     result = strcmp(sk1,sk2);
2441   }
2442   HeapFree(GetProcessHeap(),0,sk1);
2443   HeapFree(GetProcessHeap(),0,sk2);
2444
2445   if (result < 0)
2446     return 1;
2447   if (result == 0)
2448     return 2;
2449
2450   /* must be greater, if we reach this point */
2451   return 3;
2452 }
2453
2454 /******************************************************************************
2455  *              CompareString32W        [KERNEL32.144]
2456  * This implementation ignores the locale
2457  * FIXME :  Does only string sort.  Should
2458  * be reimplemented the same way as CompareString32A.
2459  */
2460 UINT WINAPI CompareStringW(DWORD lcid, DWORD fdwStyle, 
2461                                LPCWSTR s1, DWORD l1, LPCWSTR s2,DWORD l2)
2462 {
2463         int len,ret;
2464         if(fdwStyle & NORM_IGNORENONSPACE)
2465                 FIXME_(ole)("IGNORENONSPACE not supprted\n");
2466         if(fdwStyle & NORM_IGNORESYMBOLS)
2467                 FIXME_(ole)("IGNORESYMBOLS not supported\n");
2468
2469         /* Is strcmp defaulting to string sort or to word sort?? */
2470         /* FIXME: Handle NORM_STRINGSORT */
2471         l1 = (l1==-1)?lstrlenW(s1):l1;
2472         l2 = (l2==-1)?lstrlenW(s2):l2;
2473         len = l1<l2 ? l1:l2;
2474         ret = (fdwStyle & NORM_IGNORECASE) ?
2475                 CRTDLL__wcsnicmp(s1,s2,len) : CRTDLL_wcsncmp(s1,s2,len);
2476         /* not equal, return 1 or 3 */
2477         if(ret!=0) return ret+2;
2478         /* same len, return 2 */
2479         if(l1==l2) return 2;
2480         /* the longer one is lexically greater */
2481         return (l1<l2)? 1 : 3;
2482 }
2483
2484 /******************************************************************************
2485  *      RegisterNLSInfoChanged  [OLE2NLS.10]
2486  */
2487 BOOL16 WINAPI RegisterNLSInfoChanged16(LPVOID/*FIXME*/ lpNewNLSInfo)
2488 {
2489         FIXME_(ole)("Fully implemented, but doesn't effect anything.\n");
2490
2491         if (!lpNewNLSInfo)
2492         {
2493                 lpNLSInfo = NULL;
2494                 return TRUE;
2495         }
2496         else
2497         {
2498                 if (!lpNLSInfo)
2499                 {
2500                         lpNLSInfo = lpNewNLSInfo;
2501                         return TRUE;
2502                 }
2503         }
2504
2505         return FALSE; /* ptr not set */
2506
2507
2508 /******************************************************************************
2509  *              OLE_GetFormatA  [Internal]
2510  *
2511  * FIXME
2512  *    If datelen == 0, it should return the reguired string length.
2513  *
2514  This function implements stuff for GetDateFormat() and 
2515  GetTimeFormat().
2516
2517   d    single-digit (no leading zero) day (of month)
2518   dd   two-digit day (of month)
2519   ddd  short day-of-week name
2520   dddd long day-of-week name
2521   M    single-digit month
2522   MM   two-digit month
2523   MMM  short month name
2524   MMMM full month name
2525   y    two-digit year, no leading 0
2526   yy   two-digit year
2527   yyyy four-digit year
2528   gg   era string
2529   h    hours with no leading zero (12-hour)
2530   hh   hours with full two digits
2531   H    hours with no leading zero (24-hour)
2532   HH   hours with full two digits
2533   m    minutes with no leading zero
2534   mm   minutes with full two digits
2535   s    seconds with no leading zero
2536   ss   seconds with full two digits
2537   t    time marker (A or P)
2538   tt   time marker (AM, PM)
2539   ''   used to quote literal characters
2540   ''   (within a quoted string) indicates a literal '
2541
2542  These functions REQUIRE valid locale, date,  and format. 
2543  */
2544 static INT OLE_GetFormatA(LCID locale,
2545                             DWORD flags,
2546                             DWORD tflags,
2547                             LPSYSTEMTIME xtime,
2548                             LPCSTR _format,     /*in*/
2549                             LPSTR date,         /*out*/
2550                             INT datelen)
2551 {
2552    INT inpos, outpos;
2553    int count, type, inquote, Overflow;
2554    char buf[40];
2555    char format[40];
2556    char * pos;
2557    int buflen;
2558
2559    const char * _dgfmt[] = { "%d", "%02d" };
2560    const char ** dgfmt = _dgfmt - 1; 
2561
2562    /* report, for debugging */
2563    TRACE_(ole)("(0x%lx,0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt=%p \'%s\' , %p, len=%d)\n",
2564          locale, flags, tflags,
2565          xtime->wDay, xtime->wHour, xtime->wMinute, xtime->wSecond,
2566          _format, _format, date, datelen);
2567   
2568    if(datelen == 0) {
2569      FIXME_(ole)("datelen = 0, returning 255\n");
2570      return 255;
2571    }
2572
2573    /* initalize state variables and output buffer */
2574    inpos = outpos = 0;
2575    count = 0; inquote = 0; Overflow = 0;
2576    type = '\0';
2577    date[0] = buf[0] = '\0';
2578       
2579    strcpy(format,_format);
2580
2581    /* alter the formatstring, while it works for all languages now in wine
2582    its possible that it fails when the time looks like ss:mm:hh as example*/   
2583    if (tflags & (TIME_NOMINUTESORSECONDS))
2584    { if ((pos = strstr ( format, ":mm")))
2585      { memcpy ( pos, pos+3, strlen(format)-(pos-format)-2 );
2586      }
2587    }
2588    if (tflags & (TIME_NOSECONDS))
2589    { if ((pos = strstr ( format, ":ss")))
2590      { memcpy ( pos, pos+3, strlen(format)-(pos-format)-2 );
2591      }
2592    }
2593    
2594    for (inpos = 0;; inpos++) {
2595       /* 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]); */
2596       if (inquote) {
2597          if (format[inpos] == '\'') {
2598             if (format[inpos+1] == '\'') {
2599                inpos += 1;
2600                date[outpos++] = '\'';
2601             } else {
2602                inquote = 0;
2603                continue; /* we did nothing to the output */
2604             }
2605          } else if (format[inpos] == '\0') {
2606             date[outpos++] = '\0';
2607             if (outpos > datelen) Overflow = 1;
2608             break;
2609          } else {
2610             date[outpos++] = format[inpos];
2611             if (outpos > datelen) {
2612                Overflow = 1;
2613                date[outpos-1] = '\0'; /* this is the last place where
2614                                          it's safe to write */
2615                break;
2616             }
2617          }
2618       } else if (  (count && (format[inpos] != type))
2619                    || count == 4
2620                    || (count == 2 && strchr("ghHmst", type)) )
2621        {
2622             if         (type == 'd') {
2623                if        (count == 4) {
2624                   GetLocaleInfoA(locale,
2625                                    LOCALE_SDAYNAME1
2626                                    + xtime->wDayOfWeek - 1,
2627                                    buf, sizeof(buf));
2628                } else if (count == 3) {
2629                            GetLocaleInfoA(locale, 
2630                                             LOCALE_SABBREVDAYNAME1 
2631                                             + xtime->wDayOfWeek - 1,
2632                                             buf, sizeof(buf));
2633                       } else {
2634                   sprintf(buf, dgfmt[count], xtime->wDay);
2635                }
2636             } else if (type == 'M') {
2637                if (count == 3) {
2638                   GetLocaleInfoA(locale, 
2639                                    LOCALE_SABBREVMONTHNAME1
2640                                    + xtime->wMonth - 1,
2641                                    buf, sizeof(buf));
2642                } else if (count == 4) {
2643                   GetLocaleInfoA(locale,
2644                                    LOCALE_SMONTHNAME1
2645                                    + xtime->wMonth - 1,
2646                                    buf, sizeof(buf));
2647                  } else {
2648                   sprintf(buf, dgfmt[count], xtime->wMonth);
2649                }
2650             } else if (type == 'y') {
2651                if (count == 4) {
2652                       sprintf(buf, "%d", xtime->wYear);
2653                } else if (count == 3) {
2654                   strcpy(buf, "yyy");
2655                   WARN_(ole)("unknown format, c=%c, n=%d\n",  type, count);
2656                  } else {
2657                   sprintf(buf, dgfmt[count], xtime->wYear % 100);
2658                }
2659             } else if (type == 'g') {
2660                if        (count == 2) {
2661                   FIXME_(ole)("LOCALE_ICALENDARTYPE unimp.\n");
2662                   strcpy(buf, "AD");
2663             } else {
2664                   strcpy(buf, "g");
2665                   WARN_(ole)("unknown format, c=%c, n=%d\n", type, count);
2666                }
2667             } else if (type == 'h') {
2668                /* gives us hours 1:00 -- 12:00 */
2669                sprintf(buf, dgfmt[count], (xtime->wHour-1)%12 +1);
2670             } else if (type == 'H') {
2671                /* 24-hour time */
2672                sprintf(buf, dgfmt[count], xtime->wHour);
2673             } else if ( type == 'm') {
2674                sprintf(buf, dgfmt[count], xtime->wMinute);
2675             } else if ( type == 's') {
2676                sprintf(buf, dgfmt[count], xtime->wSecond);
2677             } else if (type == 't') {
2678                if        (count == 1) {
2679                   sprintf(buf, "%c", (xtime->wHour < 12) ? 'A' : 'P');
2680                } else if (count == 2) {
2681                   /* sprintf(buf, "%s", (xtime->wHour < 12) ? "AM" : "PM"); */
2682                   GetLocaleInfoA(locale,
2683                                    (xtime->wHour<12) 
2684                                    ? LOCALE_S1159 : LOCALE_S2359,
2685                                    buf, sizeof(buf));
2686                }
2687             };
2688
2689             /* we need to check the next char in the format string 
2690                again, no matter what happened */
2691             inpos--;
2692             
2693             /* add the contents of buf to the output */
2694             buflen = strlen(buf);
2695             if (outpos + buflen < datelen) {
2696                date[outpos] = '\0'; /* for strcat to hook onto */
2697                  strcat(date, buf);
2698                outpos += buflen;
2699             } else {
2700                date[outpos] = '\0';
2701                strncat(date, buf, datelen - outpos);
2702                  date[datelen - 1] = '\0';
2703                  SetLastError(ERROR_INSUFFICIENT_BUFFER);
2704                WARN_(ole)("insufficient buffer\n");
2705                  return 0;
2706             }
2707
2708             /* reset the variables we used to keep track of this item */
2709             count = 0;
2710             type = '\0';
2711          } else if (format[inpos] == '\0') {
2712             /* we can't check for this at the loop-head, because
2713                that breaks the printing of the last format-item */
2714             date[outpos] = '\0';
2715             break;
2716          } else if (count) {
2717             /* continuing a code for an item */
2718             count +=1;
2719             continue;
2720          } else if (strchr("hHmstyMdg", format[inpos])) {
2721             type = format[inpos];
2722             count = 1;
2723             continue;
2724          } else if (format[inpos] == '\'') {
2725             inquote = 1;
2726             continue;
2727        } else {
2728             date[outpos++] = format[inpos];
2729          }
2730       /* now deal with a possible buffer overflow */
2731       if (outpos >= datelen) {
2732        date[datelen - 1] = '\0';
2733        SetLastError(ERROR_INSUFFICIENT_BUFFER);
2734        return 0;
2735       }
2736    }
2737    
2738    if (Overflow) {
2739       SetLastError(ERROR_INSUFFICIENT_BUFFER);
2740    };
2741
2742    /* finish it off with a string terminator */
2743    outpos++;
2744    /* sanity check */
2745    if (outpos > datelen-1) outpos = datelen-1;
2746    date[outpos] = '\0';
2747    
2748    TRACE_(ole)("OLE_GetFormatA returns string '%s', len %d\n",
2749                date, outpos);
2750    return outpos;
2751 }
2752
2753 /******************************************************************************
2754  * OLE_GetFormatW [INTERNAL]
2755  */
2756 static INT OLE_GetFormatW(LCID locale, DWORD flags, DWORD tflags,
2757                             LPSYSTEMTIME xtime,
2758                             LPCWSTR format,
2759                             LPWSTR output, INT outlen)
2760 {
2761    INT   inpos, outpos;
2762    int     count, type=0, inquote;
2763    int     Overflow; /* loop check */
2764    WCHAR   buf[40];
2765    int     buflen=0;
2766    WCHAR   arg0[] = {0}, arg1[] = {'%','d',0};
2767    WCHAR   arg2[] = {'%','0','2','d',0};
2768    WCHAR  *argarr[3];
2769    int     datevars=0, timevars=0;
2770
2771    argarr[0] = arg0;
2772    argarr[1] = arg1;
2773    argarr[2] = arg2;
2774
2775    /* make a debug report */
2776    TRACE_(ole)("args: 0x%lx, 0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt:%s (at %p), "
2777               "%p with max len %d\n",
2778          locale, flags, tflags,
2779          xtime->wDay, xtime->wHour, xtime->wMinute, xtime->wSecond,
2780          debugstr_w(format), format, output, outlen);
2781    
2782    if(outlen == 0) {
2783      FIXME_(ole)("outlen = 0, returning 255\n");
2784      return 255;
2785    }
2786
2787    /* initialize state variables */
2788    inpos = outpos = 0;
2789    count = 0;
2790    inquote = Overflow = 0;
2791    /* this is really just a sanity check */
2792    output[0] = buf[0] = 0;
2793    
2794    /* this loop is the core of the function */
2795    for (inpos = 0; /* we have several break points */ ; inpos++) {
2796       if (inquote) {
2797          if (format[inpos] == (WCHAR) '\'') {
2798             if (format[inpos+1] == '\'') {
2799                inpos++;
2800                output[outpos++] = '\'';
2801             } else {
2802                inquote = 0;
2803                continue;
2804             }
2805          } else if (format[inpos] == 0) {
2806             output[outpos++] = 0;
2807             if (outpos > outlen) Overflow = 1;
2808             break;  /*  normal exit (within a quote) */
2809          } else {
2810             output[outpos++] = format[inpos]; /* copy input */
2811             if (outpos > outlen) {
2812                Overflow = 1;
2813                output[outpos-1] = 0; 
2814                break;
2815             }
2816          }
2817       } else if (  (count && (format[inpos] != type))
2818                    || ( (count==4 && type =='y') ||
2819                         (count==4 && type =='M') ||
2820                         (count==4 && type =='d') ||
2821                         (count==2 && type =='g') ||
2822                         (count==2 && type =='h') ||
2823                         (count==2 && type =='H') ||
2824                         (count==2 && type =='m') ||
2825                         (count==2 && type =='s') ||
2826                         (count==2 && type =='t') )  ) {
2827          if        (type == 'd') {
2828             if        (count == 3) {
2829                GetLocaleInfoW(locale,
2830                              LOCALE_SDAYNAME1 + xtime->wDayOfWeek -1,
2831                              buf, sizeof(buf)/sizeof(WCHAR) );
2832             } else if (count == 3) {
2833                GetLocaleInfoW(locale,
2834                                 LOCALE_SABBREVDAYNAME1 +
2835                                 xtime->wDayOfWeek -1,
2836                                 buf, sizeof(buf)/sizeof(WCHAR) );
2837             } else {
2838                wsnprintfW(buf, 5, argarr[count], xtime->wDay );
2839             };
2840          } else if (type == 'M') {
2841             if        (count == 4) {
2842                GetLocaleInfoW(locale,  LOCALE_SMONTHNAME1 +
2843                                 xtime->wMonth -1, buf,
2844                                 sizeof(buf)/sizeof(WCHAR) );
2845             } else if (count == 3) {
2846                GetLocaleInfoW(locale,  LOCALE_SABBREVMONTHNAME1 +
2847                                 xtime->wMonth -1, buf,
2848                                 sizeof(buf)/sizeof(WCHAR) );
2849             } else {
2850                wsnprintfW(buf, 5, argarr[count], xtime->wMonth);
2851             }
2852          } else if (type == 'y') {
2853             if        (count == 4) {
2854                wsnprintfW(buf, 6, argarr[1] /* "%d" */,
2855                          xtime->wYear);
2856             } else if (count == 3) {
2857                lstrcpynAtoW(buf, "yyy", 5);
2858             } else {
2859                wsnprintfW(buf, 6, argarr[count],
2860                             xtime->wYear % 100);
2861             }
2862          } else if (type == 'g') {
2863             if        (count == 2) {
2864                FIXME_(ole)("LOCALE_ICALENDARTYPE unimplemented\n");
2865                lstrcpynAtoW(buf, "AD", 5);
2866             } else {
2867                /* Win API sez we copy it verbatim */
2868                lstrcpynAtoW(buf, "g", 5);
2869             }
2870          } else if (type == 'h') {
2871             /* hours 1:00-12:00 --- is this right? */
2872             wsnprintfW(buf, 5, argarr[count], 
2873                          (xtime->wHour-1)%12 +1);
2874          } else if (type == 'H') {
2875             wsnprintfW(buf, 5, argarr[count], 
2876                          xtime->wHour);
2877          } else if (type == 'm' ) {
2878             wsnprintfW(buf, 5, argarr[count],
2879                          xtime->wMinute);
2880          } else if (type == 's' ) {
2881             wsnprintfW(buf, 5, argarr[count],
2882                          xtime->wSecond);
2883          } else if (type == 't') {
2884             GetLocaleInfoW(locale, (xtime->wHour < 12) ?
2885                              LOCALE_S1159 : LOCALE_S2359,
2886                              buf, sizeof(buf) );
2887             if        (count == 1) {
2888                buf[1] = 0;
2889             }
2890 }
2891
2892          /* no matter what happened,  we need to check this next 
2893             character the next time we loop through */
2894          inpos--;
2895
2896          /* cat buf onto the output */
2897          outlen = lstrlenW(buf);
2898          if (outpos + buflen < outlen) {
2899             lstrcpyW( output + outpos, buf );
2900             outpos += buflen;
2901          } else {
2902             lstrcpynW( output + outpos, buf, outlen - outpos );
2903             Overflow = 1;
2904             break; /* Abnormal exit */
2905          }
2906
2907          /* reset the variables we used this time */
2908          count = 0;
2909          type = '\0';
2910       } else if (format[inpos] == 0) {
2911          /* we can't check for this at the beginning,  because that 
2912          would keep us from printing a format spec that ended the 
2913          string */
2914          output[outpos] = 0;
2915          break;  /*  NORMAL EXIT  */
2916       } else if (count) {
2917          /* how we keep track of the middle of a format spec */
2918          count++;
2919          continue;
2920       } else if ( (datevars && (format[inpos]=='d' ||
2921                                 format[inpos]=='M' ||
2922                                 format[inpos]=='y' ||
2923                                 format[inpos]=='g')  ) ||
2924                   (timevars && (format[inpos]=='H' ||
2925                                 format[inpos]=='h' ||
2926                                 format[inpos]=='m' ||
2927                                 format[inpos]=='s' ||
2928                                 format[inpos]=='t') )    ) {
2929          type = format[inpos];
2930          count = 1;
2931          continue;
2932       } else if (format[inpos] == '\'') {
2933          inquote = 1;
2934          continue;
2935       } else {
2936          /* unquoted literals */
2937          output[outpos++] = format[inpos];
2938       }
2939    }
2940
2941    if (Overflow) {
2942       SetLastError(ERROR_INSUFFICIENT_BUFFER);
2943       WARN_(ole)(" buffer overflow\n");
2944    };
2945
2946    /* final string terminator and sanity check */
2947    outpos++;
2948    if (outpos > outlen-1) outpos = outlen-1;
2949    output[outpos] = '0';
2950
2951    TRACE_(ole)(" returning %s\n", debugstr_w(output));
2952         
2953    return (!Overflow) ? outlen : 0;
2954    
2955 }
2956
2957
2958 /******************************************************************************
2959  *              GetDateFormat32A        [KERNEL32.310]
2960  * Makes an ASCII string of the date
2961  *
2962  * This function uses format to format the date,  or,  if format
2963  * is NULL, uses the default for the locale.  format is a string
2964  * of literal fields and characters as follows:
2965  *
2966  * - d    single-digit (no leading zero) day (of month)
2967  * - dd   two-digit day (of month)
2968  * - ddd  short day-of-week name
2969  * - dddd long day-of-week name
2970  * - M    single-digit month
2971  * - MM   two-digit month
2972  * - MMM  short month name
2973  * - MMMM full month name
2974  * - y    two-digit year, no leading 0
2975  * - yy   two-digit year
2976  * - yyyy four-digit year
2977  * - gg   era string
2978  *
2979  */
2980 INT WINAPI GetDateFormatA(LCID locale,DWORD flags,
2981                               LPSYSTEMTIME xtime,
2982                               LPCSTR format, LPSTR date,INT datelen) 
2983 {
2984    
2985   char format_buf[40];
2986   LPCSTR thisformat;
2987   SYSTEMTIME t;
2988   LPSYSTEMTIME thistime;
2989   LCID thislocale;
2990   INT ret;
2991
2992   TRACE_(ole)("(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",
2993               locale,flags,xtime,format,date,datelen);
2994   
2995   if (!locale) {
2996      locale = LOCALE_SYSTEM_DEFAULT;
2997      };
2998   
2999   if (locale == LOCALE_SYSTEM_DEFAULT) {
3000      thislocale = GetSystemDefaultLCID();
3001   } else if (locale == LOCALE_USER_DEFAULT) {
3002      thislocale = GetUserDefaultLCID();
3003   } else {
3004      thislocale = locale;
3005    };
3006
3007   if (xtime == NULL) {
3008      GetSystemTime(&t);
3009      thistime = &t;
3010   } else {
3011      thistime = xtime;
3012   };
3013
3014   if (format == NULL) {
3015      GetLocaleInfoA(thislocale, ((flags&DATE_LONGDATE) 
3016                                    ? LOCALE_SLONGDATE
3017                                    : LOCALE_SSHORTDATE),
3018                       format_buf, sizeof(format_buf));
3019      thisformat = format_buf;
3020   } else {
3021      thisformat = format;
3022   };
3023
3024   
3025   ret = OLE_GetFormatA(thislocale, flags, 0, thistime, thisformat, 
3026                        date, datelen);
3027   
3028
3029    TRACE_(ole)(
3030                "GetDateFormat32A() returning %d, with data=%s\n",
3031                ret, date);
3032   return ret;
3033 }
3034
3035 /******************************************************************************
3036  *              GetDateFormat32W        [KERNEL32.311]
3037  * Makes a Unicode string of the date
3038  *
3039  * Acts the same as GetDateFormat32A(),  except that it's Unicode.
3040  * Accepts & returns sizes as counts of Unicode characters.
3041  *
3042  */
3043 INT WINAPI GetDateFormatW(LCID locale,DWORD flags,
3044                               LPSYSTEMTIME xtime,
3045                               LPCWSTR format,
3046                               LPWSTR date, INT datelen)
3047 {
3048    unsigned short datearr[] = {'1','9','9','4','-','1','-','1',0};
3049
3050    FIXME_(ole)("STUB (should call OLE_GetFormatW)\n");   
3051    lstrcpynW(date, datearr, datelen);
3052    return (  datelen < 9) ? datelen : 9;
3053    
3054    
3055 }
3056
3057 /**************************************************************************
3058  *              EnumDateFormats32A      (KERNEL32.198)
3059  */
3060 BOOL WINAPI EnumDateFormatsA(
3061   DATEFMT_ENUMPROCA lpDateFmtEnumProc, LCID Locale,  DWORD dwFlags)
3062 {
3063   FIXME_(ole)("Only US English supported\n");
3064
3065   if(!lpDateFmtEnumProc)
3066     {
3067       SetLastError(ERROR_INVALID_PARAMETER);
3068       return FALSE;
3069     }
3070
3071   switch(dwFlags)
3072     {
3073       case DATE_SHORTDATE:
3074         if(!(*lpDateFmtEnumProc)("M/d/yy")) return TRUE;
3075         if(!(*lpDateFmtEnumProc)("M/d/yyyy")) return TRUE;
3076         if(!(*lpDateFmtEnumProc)("MM/dd/yy")) return TRUE;
3077         if(!(*lpDateFmtEnumProc)("MM/dd/yyyy")) return TRUE;
3078         if(!(*lpDateFmtEnumProc)("yy/MM/dd")) return TRUE;
3079         if(!(*lpDateFmtEnumProc)("dd-MMM-yy")) return TRUE;
3080         return TRUE;
3081       case DATE_LONGDATE:
3082         if(!(*lpDateFmtEnumProc)("dddd, MMMM dd, yyyy")) return TRUE;
3083         if(!(*lpDateFmtEnumProc)("MMMM dd, yyyy")) return TRUE;
3084         if(!(*lpDateFmtEnumProc)("dddd, dd MMMM, yyyy")) return TRUE;
3085         if(!(*lpDateFmtEnumProc)("dd MMMM, yyyy")) return TRUE;
3086         return TRUE;
3087       default:
3088         FIXME_(ole)("Unknown date format (%ld)\n", dwFlags); 
3089         SetLastError(ERROR_INVALID_PARAMETER);
3090         return FALSE;
3091     }
3092 }
3093
3094 /**************************************************************************
3095  *              EnumDateFormats32W      (KERNEL32.199)
3096  */
3097 BOOL WINAPI EnumDateFormatsW(
3098   DATEFMT_ENUMPROCW lpDateFmtEnumProc, LCID Locale, DWORD dwFlags)
3099 {
3100   FIXME_(ole)("(%p, %ld, %ld): stub\n", lpDateFmtEnumProc, Locale, dwFlags);
3101   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3102   return FALSE;
3103 }
3104
3105 /**************************************************************************
3106  *              EnumTimeFormats32A      (KERNEL32.210)
3107  */
3108 BOOL WINAPI EnumTimeFormatsA(
3109   TIMEFMT_ENUMPROCA lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags)
3110 {
3111   FIXME_(ole)("Only US English supported\n");
3112
3113   if(!lpTimeFmtEnumProc)
3114     {
3115       SetLastError(ERROR_INVALID_PARAMETER);
3116       return FALSE;
3117     }
3118
3119   if(dwFlags)
3120     {
3121       FIXME_(ole)("Unknown time format (%ld)\n", dwFlags); 
3122     }
3123   
3124   if(!(*lpTimeFmtEnumProc)("h:mm:ss tt")) return TRUE;
3125   if(!(*lpTimeFmtEnumProc)("hh:mm:ss tt")) return TRUE;
3126   if(!(*lpTimeFmtEnumProc)("H:mm:ss")) return TRUE;
3127   if(!(*lpTimeFmtEnumProc)("HH:mm:ss")) return TRUE;
3128
3129   return TRUE;
3130 }
3131
3132 /**************************************************************************
3133  *              EnumTimeFormats32W      (KERNEL32.211)
3134  */
3135 BOOL WINAPI EnumTimeFormatsW(
3136   TIMEFMT_ENUMPROCW lpTimeFmtEnumProc, LCID Locale, DWORD dwFlags)
3137 {
3138   FIXME_(ole)("(%p,%ld,%ld): stub\n", lpTimeFmtEnumProc, Locale, dwFlags);
3139   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3140   return FALSE;
3141 }
3142
3143 /**************************************************************************
3144  *              GetNumberFormat32A      (KERNEL32.355)
3145  */
3146 INT WINAPI GetNumberFormatA(LCID locale, DWORD dwflags,
3147                                LPCSTR lpvalue,   const NUMBERFMTA * lpFormat,
3148                                LPSTR lpNumberStr, int cchNumber)
3149 {
3150  FIXME_(file)("%s: stub, no reformating done\n",lpvalue);
3151
3152  lstrcpynA( lpNumberStr, lpvalue, cchNumber );
3153  return cchNumber? lstrlenA( lpNumberStr ) : 0;
3154 }
3155 /**************************************************************************
3156  *              GetNumberFormat32W      (KERNEL32.xxx)
3157  */
3158 INT WINAPI GetNumberFormatW(LCID locale, DWORD dwflags,
3159                                LPCWSTR lpvalue,  const NUMBERFMTW * lpFormat,
3160                                LPWSTR lpNumberStr, int cchNumber)
3161 {
3162  FIXME_(file)("%s: stub, no reformating done\n",debugstr_w(lpvalue));
3163
3164  lstrcpynW( lpNumberStr, lpvalue, cchNumber );
3165  return cchNumber? lstrlenW( lpNumberStr ) : 0;
3166 }
3167 /******************************************************************************
3168  *              OLE2NLS_CheckLocale     [intern]
3169  */ 
3170 static LCID OLE2NLS_CheckLocale (LCID locale)
3171 {
3172         if (!locale) 
3173         { locale = LOCALE_SYSTEM_DEFAULT;
3174         }
3175   
3176         if (locale == LOCALE_SYSTEM_DEFAULT) 
3177         { return GetSystemDefaultLCID();
3178         } 
3179         else if (locale == LOCALE_USER_DEFAULT) 
3180         { return GetUserDefaultLCID();
3181         }
3182         else
3183         { return locale;
3184         }
3185 }
3186 /******************************************************************************
3187  *              GetTimeFormat32A        [KERNEL32.422]
3188  * Makes an ASCII string of the time
3189  *
3190  * Formats date according to format,  or locale default if format is
3191  * NULL. The format consists of literal characters and fields as follows:
3192  *
3193  * h  hours with no leading zero (12-hour)
3194  * hh hours with full two digits
3195  * H  hours with no leading zero (24-hour)
3196  * HH hours with full two digits
3197  * m  minutes with no leading zero
3198  * mm minutes with full two digits
3199  * s  seconds with no leading zero
3200  * ss seconds with full two digits
3201  * t  time marker (A or P)
3202  * tt time marker (AM, PM)
3203  *
3204  */
3205 INT WINAPI 
3206 GetTimeFormatA(LCID locale,        /* in  */
3207                  DWORD flags,        /* in  */
3208                  LPSYSTEMTIME xtime, /* in  */ 
3209                  LPCSTR format,      /* in  */
3210                  LPSTR timestr,      /* out */
3211                  INT timelen       /* in  */) 
3212 { char format_buf[40];
3213   LPCSTR thisformat;
3214   SYSTEMTIME t;
3215   LPSYSTEMTIME thistime;
3216   LCID thislocale=0;
3217   DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */
3218   INT ret;
3219     
3220   TRACE_(ole)("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale,flags,xtime,format,timestr,timelen);
3221
3222   thislocale = OLE2NLS_CheckLocale ( locale );
3223
3224   if ( flags & (TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT ))
3225   { FIXME_(ole)("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3226   }
3227   
3228   flags &= (TIME_NOSECONDS | TIME_NOMINUTESORSECONDS); /* mask for OLE_GetFormatA*/
3229
3230   if (format == NULL) 
3231   { if (flags & LOCALE_NOUSEROVERRIDE)  /*use system default*/
3232     { thislocale = GetSystemDefaultLCID();
3233     }
3234     GetLocaleInfoA(thislocale, thisflags, format_buf, sizeof(format_buf));
3235     thisformat = format_buf;
3236   }
3237   else 
3238   { thisformat = format;
3239   }
3240   
3241   if (xtime == NULL) /* NULL means use the current local time*/
3242   { GetLocalTime(&t);
3243     thistime = &t;
3244   } 
3245   else
3246   { thistime = xtime;
3247   }
3248   ret = OLE_GetFormatA(thislocale, thisflags, flags, thistime, thisformat,
3249                          timestr, timelen);
3250   return ret;
3251 }
3252
3253
3254 /******************************************************************************
3255  *              GetTimeFormat32W        [KERNEL32.423]
3256  * Makes a Unicode string of the time
3257  */
3258 INT WINAPI 
3259 GetTimeFormatW(LCID locale,        /* in  */
3260                  DWORD flags,        /* in  */
3261                  LPSYSTEMTIME xtime, /* in  */ 
3262                  LPCWSTR format,     /* in  */
3263                  LPWSTR timestr,     /* out */
3264                  INT timelen       /* in  */) 
3265 {       WCHAR format_buf[40];
3266         LPCWSTR thisformat;
3267         SYSTEMTIME t;
3268         LPSYSTEMTIME thistime;
3269         LCID thislocale=0;
3270         DWORD thisflags=LOCALE_STIMEFORMAT; /* standart timeformat */
3271         INT ret;
3272             
3273         TRACE_(ole)("GetTimeFormat(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",locale,flags,
3274         xtime,debugstr_w(format),timestr,timelen);
3275
3276         thislocale = OLE2NLS_CheckLocale ( locale );
3277
3278         if ( flags & (TIME_NOTIMEMARKER | TIME_FORCE24HOURFORMAT ))
3279         { FIXME_(ole)("TIME_NOTIMEMARKER or TIME_FORCE24HOURFORMAT not implemented\n");
3280         }
3281   
3282         flags &= (TIME_NOSECONDS | TIME_NOMINUTESORSECONDS); /* mask for OLE_GetFormatA*/
3283
3284         if (format == NULL) 
3285         { if (flags & LOCALE_NOUSEROVERRIDE)  /*use system default*/
3286           { thislocale = GetSystemDefaultLCID();
3287           }
3288           GetLocaleInfoW(thislocale, thisflags, format_buf, 40);
3289           thisformat = format_buf;
3290         }         
3291         else 
3292         { thisformat = format;
3293         }
3294  
3295         if (xtime == NULL) /* NULL means use the current local time*/
3296         { GetSystemTime(&t);
3297           thistime = &t;
3298         } 
3299         else
3300         { thistime = xtime;
3301         }
3302
3303         ret = OLE_GetFormatW(thislocale, thisflags, flags, thistime, thisformat,
3304                          timestr, timelen);
3305         return ret;
3306 }
3307
3308 /******************************************************************************
3309  *              EnumCalendarInfoA       [KERNEL32.196]
3310  */
3311 BOOL WINAPI EnumCalendarInfoA(
3312         CALINFO_ENUMPROCA calinfoproc,LCID locale,CALID calendar,CALTYPE caltype
3313 ) {
3314         FIXME_(ole)("(%p,0x%04lx,0x%08lx,0x%08lx),stub!\n",calinfoproc,locale,calendar,caltype);
3315         return FALSE;
3316 }