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