The API for WideCharToMultiByte says that the src-string has only to be
[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 care_for_eos=0;
182     int dont_copy= (dstlen==0);
183
184     if ((!src) | ((!dst) && (!dont_copy)) )
185     {   SetLastError(ERROR_INVALID_PARAMETER);
186         return 0;
187     }
188     
189     if (page!=GetACP() && page!=CP_OEMCP && page!=CP_ACP)
190         FIXME(win32,"Conversion in CP %d not supported\n",page);
191 #if 0
192     if (flags)
193         FIXME(win32,"flags %lx not supported\n",flags);
194 #endif
195     if(used)
196         *used=0;
197     if (srclen == -1)
198       {
199         srclen = lstrlen32W(src)+1;
200          care_for_eos=1;
201       }
202     while(srclen && (dont_copy || dstlen))
203     {
204         if(!dont_copy){
205             if(*src<256)
206                 *dst = *src;
207             else
208             {
209                 /* ??? The WC_DEFAULTCHAR flag only gets used in
210                  * combination with the WC_COMPOSITECHECK flag or at
211                  * least this is what it seems from using the function
212                  * on NT4.0 in combination with reading the documentation.
213                  */
214                 *dst = defchar ? *defchar : '?';
215                 if(used)*used=1;
216             }
217             dstlen--;
218             dst++;
219         }
220         count++;
221         srclen--;
222         if((!*src) && care_for_eos) {
223             eos = 1;
224             break;
225         }
226         src++;
227     }
228     if (dont_copy)
229         return count;
230
231     if (!eos && srclen > 0) {
232         SetLastError(ERROR_INSUFFICIENT_BUFFER);
233         return 0;
234     }
235     return count;
236 }
237
238
239 /***********************************************************************
240  *           IsDBCSLeadByteEx   (KERNEL32.359)
241  */
242 BOOL32 WINAPI IsDBCSLeadByteEx( UINT32 codepage, BYTE testchar )
243 {
244     CPINFO cpinfo;
245     int i;
246
247     GetCPInfo(codepage, &cpinfo);
248     for (i = 0 ; i < sizeof(cpinfo.LeadByte)/sizeof(cpinfo.LeadByte[0]); i+=2)
249     {
250         if (cpinfo.LeadByte[i] == 0)
251             return FALSE;
252         if (cpinfo.LeadByte[i] <= testchar && testchar <= cpinfo.LeadByte[i+1])
253             return TRUE;
254     }
255     return FALSE;
256 }
257
258
259 /***********************************************************************
260  *           IsDBCSLeadByte16   (KERNEL.207)
261  */
262 BOOL16 WINAPI IsDBCSLeadByte16( BYTE testchar )
263 {
264     return IsDBCSLeadByteEx(GetACP(), testchar);
265 }
266
267
268 /***********************************************************************
269  *           IsDBCSLeadByte32   (KERNEL32.358)
270  */
271 BOOL32 WINAPI IsDBCSLeadByte32( BYTE testchar )
272 {
273     return IsDBCSLeadByteEx(GetACP(), testchar);
274 }
275
276
277 /***********************************************************************
278  *              EnumSystemCodePages32A                (KERNEL32.92)
279  */
280 BOOL32 WINAPI EnumSystemCodePages32A(CODEPAGE_ENUMPROC32A lpfnCodePageEnum,DWORD flags)
281 {
282         TRACE(win32,"(%p,%08lx)\n",lpfnCodePageEnum,flags);
283         lpfnCodePageEnum("437");
284         return TRUE;
285 }
286
287 /***********************************************************************
288  *              EnumSystemCodePages32W                (KERNEL32.93)
289  */
290 BOOL32 WINAPI EnumSystemCodePages32W( CODEPAGE_ENUMPROC32W lpfnCodePageEnum,
291                                       DWORD flags)
292 {
293     WCHAR       *cp;
294     TRACE(win32,"(%p,%08lx)\n",lpfnCodePageEnum,flags );
295
296     cp = HEAP_strdupAtoW( GetProcessHeap(), 0, "437" );
297     lpfnCodePageEnum(cp);
298     HeapFree( GetProcessHeap(), 0, cp );
299     return TRUE;
300 }