Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbeyj@wpi.edu>
[wine] / win32 / code_page.c
1 /*
2  * Win32 kernel functions
3  *
4  * Copyright 1995 Martin von Loewis and Cameron Heide
5  */
6
7 #include <stdlib.h>
8 #include "winerror.h"
9 #include "winnls.h"
10 #include "heap.h"
11 #include "debugtools.h"
12
13 DEFAULT_DEBUG_CHANNEL(win32)
14
15
16 /******************************************************************************
17  * GetACP [KERNEL32.276]  Gets current ANSI code-page identifier.
18  *
19  * RETURNS
20  *    Current ANSI code-page identifier, default if no current defined
21  */
22 UINT WINAPI GetACP(void)
23 {
24     /* This introduces too many messages */
25 /*    FIXME(win32, "(void): stub\n"); */
26     return 1252;    /* Windows 3.1 ISO Latin */
27 }
28
29
30 /***********************************************************************
31  *           GetCPInfo            (KERNEL32.154)
32  */
33 BOOL WINAPI GetCPInfo( UINT codepage, LPCPINFO cpinfo )
34 {
35     cpinfo->DefaultChar[0] = '?';
36     switch (codepage)
37     {
38     case 932 : /* Shift JIS (japan) */
39         cpinfo->MaxCharSize = 2;
40         cpinfo->LeadByte[0]= 0x81; cpinfo->LeadByte[1] = 0x9F;
41         cpinfo->LeadByte[2]= 0xE0; cpinfo->LeadByte[3] = 0xFC;
42         cpinfo->LeadByte[4]= 0x00; cpinfo->LeadByte[5] = 0x00;
43         break;
44     case 936 : /* GB2312 (Chinese) */
45     case 949 : /* KSC5601-1987 (Korean) */
46     case 950 : /* BIG5 (Chinese) */
47         cpinfo->MaxCharSize = 2;
48         cpinfo->LeadByte[0]= 0x81; cpinfo->LeadByte[1] = 0xFE;
49         cpinfo->LeadByte[2]= 0x00; cpinfo->LeadByte[3] = 0x00;
50         break;
51     case 1361 : /* Johab (Korean) */
52         cpinfo->MaxCharSize = 2;
53         cpinfo->LeadByte[0]= 0x84; cpinfo->LeadByte[1] = 0xD3;
54         cpinfo->LeadByte[2]= 0xD8; cpinfo->LeadByte[3] = 0xDE;
55         cpinfo->LeadByte[4]= 0xE0; cpinfo->LeadByte[5] = 0xF9;
56         cpinfo->LeadByte[6]= 0x00; cpinfo->LeadByte[7] = 0x00;
57         break;
58     default :
59         cpinfo->MaxCharSize = 1;
60         cpinfo->LeadByte[0]= 0x00; cpinfo->LeadByte[1] = 0x00;
61         break;
62     }
63     return 1;
64 }
65
66 /***********************************************************************
67  *              GetOEMCP                (KERNEL32.248)
68  */
69 UINT WINAPI GetOEMCP(void)
70 {
71     return 437;    /* MS-DOS United States */
72 }
73
74 /***********************************************************************
75  *           IsValidCodePage   (KERNEL32.360)
76  */
77 BOOL WINAPI IsValidCodePage(UINT CodePage)
78 {
79     switch ( CodePage )
80     {
81     case 1252 :
82     case 437 :
83         return TRUE;
84     default :
85         return FALSE;
86     }
87 }
88
89
90 /***********************************************************************
91  *              MultiByteToWideChar                (KERNEL32.534)
92  *
93  * PARAMS
94  *   page [in]   Codepage character set to convert from
95  *   flags [in]  Character mapping flags
96  *   src [in]     Source string buffer
97  *   srclen [in]  Length of source string buffer
98  *   dst [in]     Destination buffer
99  *   dstlen [in]  Length of destination buffer
100  *
101  * NOTES
102  *   The returned length includes the null terminator character.
103  *
104  * RETURNS
105  *   Success: If dstlen > 0, number of characters written to destination
106  *            buffer.  If dstlen == 0, number of characters needed to do
107  *            conversion.
108  *   Failure: 0. Occurs if not enough space is available.
109  *
110  * ERRORS
111  *   ERROR_INSUFFICIENT_BUFFER
112  *   ERROR_INVALID_FLAGS (not yet implemented)
113  *   ERROR_INVALID_PARAMETER (not yet implemented)
114  *
115  * BUGS
116  *   Does not properly handle codepage conversions.
117  *   Does not properly handle flags.
118  *
119  */
120 INT WINAPI MultiByteToWideChar(UINT page, DWORD flags,
121                                  LPCSTR src, INT srclen,
122                                  LPWSTR dst, INT dstlen)
123 {
124     int ret;
125
126     if (srclen == -1)
127         srclen = lstrlenA(src)+1;
128     if (!dstlen || !dst)
129         return srclen;
130
131     ret = srclen;
132     while (srclen && dstlen) {
133         *dst = (WCHAR)(unsigned char)*src;
134         dst++;    src++;
135         dstlen--; srclen--;
136     }
137     if (!dstlen && srclen) {
138         SetLastError(ERROR_INSUFFICIENT_BUFFER);
139         return 0;
140     }
141     return ret;
142 }
143
144 /***********************************************************************
145  *              WideCharToMultiByte                (KERNEL32.727)
146  *
147  * PARAMS
148  *   page [in]    Codepage character set to convert to
149  *   flags [in]   Character mapping flags
150  *   src [in]     Source string buffer
151  *   srclen [in]  Length of source string buffer
152  *   dst [in]     Destination buffer
153  *   dstlen [in]  Length of destination buffer
154  *   defchar [in] Default character to use for conversion if no exact
155  *                  conversion can be made
156  *   used [out]   Set if default character was used in the conversion
157  *
158  * NOTES
159  *   The returned length includes the null terminator character.
160  *
161  * RETURNS
162  *   Success: If dstlen > 0, number of characters written to destination
163  *            buffer.  If dstlen == 0, number of characters needed to do
164  *            conversion.
165  *   Failure: 0. Occurs if not enough space is available.
166  *
167  * ERRORS
168  *   ERROR_INSUFFICIENT_BUFFER
169  *   ERROR_INVALID_FLAGS (not yet implemented)
170  *
171  * BUGS
172  *   Does not properly handle codepage conversions.
173  *   Does not properly handle flags.
174  *
175  */
176 INT WINAPI WideCharToMultiByte(UINT page, DWORD flags, LPCWSTR src,
177                                  INT srclen,LPSTR dst, INT dstlen,
178                                  LPCSTR defchar, BOOL *used)
179 {
180     int count = 0;
181     int eos = 0;
182     int care_for_eos=0;
183     int dont_copy= (dstlen==0);
184
185     if ((!src) || ((!dst) && (!dont_copy)) )
186     {   SetLastError(ERROR_INVALID_PARAMETER);
187         return 0;
188     }
189     
190     if (page!=GetACP() && page!=CP_OEMCP && page!=CP_ACP)
191         FIXME("Conversion in CP %d not supported\n",page);
192 #if 0
193     if (flags)
194         FIXME("flags %lx not supported\n",flags);
195 #endif
196     if(used)
197         *used=0;
198     if (srclen == -1)
199       {
200         srclen = lstrlenW(src)+1;
201          care_for_eos=1;
202       }
203     while(srclen && (dont_copy || dstlen))
204     {
205         if(!dont_copy){
206             if(*src<256)
207                 *dst = *src;
208             else
209             {
210                 /* ??? The WC_DEFAULTCHAR flag only gets used in
211                  * combination with the WC_COMPOSITECHECK flag or at
212                  * least this is what it seems from using the function
213                  * on NT4.0 in combination with reading the documentation.
214                  */
215                 *dst = defchar ? *defchar : '?';
216                 if(used)*used=1;
217             }
218             dstlen--;
219             dst++;
220         }
221         count++;
222         srclen--;
223         if((!*src) && care_for_eos) {
224             eos = 1;
225             break;
226         }
227         src++;
228     }
229     if (dont_copy)
230         return count;
231
232     if (!eos && srclen > 0) {
233         SetLastError(ERROR_INSUFFICIENT_BUFFER);
234         return 0;
235     }
236     return count;
237 }
238
239
240 /***********************************************************************
241  *           IsDBCSLeadByteEx   (KERNEL32.359)
242  */
243 BOOL WINAPI IsDBCSLeadByteEx( UINT codepage, BYTE testchar )
244 {
245     CPINFO cpinfo;
246     int i;
247
248     GetCPInfo(codepage, &cpinfo);
249     for (i = 0 ; i < sizeof(cpinfo.LeadByte)/sizeof(cpinfo.LeadByte[0]); i+=2)
250     {
251         if (cpinfo.LeadByte[i] == 0)
252             return FALSE;
253         if (cpinfo.LeadByte[i] <= testchar && testchar <= cpinfo.LeadByte[i+1])
254             return TRUE;
255     }
256     return FALSE;
257 }
258
259
260 /***********************************************************************
261  *           IsDBCSLeadByte16   (KERNEL.207)
262  */
263 BOOL16 WINAPI IsDBCSLeadByte16( BYTE testchar )
264 {
265     return IsDBCSLeadByteEx(GetACP(), testchar);
266 }
267
268
269 /***********************************************************************
270  *           IsDBCSLeadByte32   (KERNEL32.358)
271  */
272 BOOL WINAPI IsDBCSLeadByte( BYTE testchar )
273 {
274     return IsDBCSLeadByteEx(GetACP(), testchar);
275 }
276
277
278 /***********************************************************************
279  *              EnumSystemCodePages32A                (KERNEL32.92)
280  */
281 BOOL WINAPI EnumSystemCodePagesA(CODEPAGE_ENUMPROCA lpfnCodePageEnum,DWORD flags)
282 {
283         TRACE("(%p,%08lx)\n",lpfnCodePageEnum,flags);
284         lpfnCodePageEnum("437");
285         return TRUE;
286 }
287
288 /***********************************************************************
289  *              EnumSystemCodePages32W                (KERNEL32.93)
290  */
291 BOOL WINAPI EnumSystemCodePagesW( CODEPAGE_ENUMPROCW lpfnCodePageEnum,
292                                       DWORD flags)
293 {
294     WCHAR       *cp;
295     TRACE("(%p,%08lx)\n",lpfnCodePageEnum,flags );
296
297     cp = HEAP_strdupAtoW( GetProcessHeap(), 0, "437" );
298     lpfnCodePageEnum(cp);
299     HeapFree( GetProcessHeap(), 0, cp );
300     return TRUE;
301 }