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