d4116b4c5dd1a2596eaca5a53739d31afc2af042
[reactos.git] / lib / kernel32 / misc / mbchars.c
1 /* $Id$
2  *
3  */
4 #include <windows.h>
5
6
7 /**********************************************************************
8  * NAME                         PRIVATE
9  *  IsInstalledCP@4
10  *
11  * RETURN VALUE
12  *  TRUE if CodePage is installed in the system.
13  */
14 static
15 BOOL
16 STDCALL
17 IsInstalledCP(UINT CodePage)
18 {
19     /* FIXME */
20     return TRUE;
21 }
22
23
24 /**********************************************************************
25  * NAME                         EXPORTED
26  *  MultiByteToWideChar@24
27  *
28  * ARGUMENTS
29  *  CodePage
30  *      CP_ACP      ANSI code page
31  *      CP_MACCP    Macintosh code page
32  *      CP_OEMCP    OEM code page
33  *      (UINT)      Any installed code page
34  *
35  *  dwFlags
36  *      MB_PRECOMPOSED
37  *      MB_COMPOSITE
38  *      MB_ERR_INVALID_CHARS
39  *      MB_USEGLYPHCHARS
40  *
41  *  lpMultiByteStr
42  *      Input buffer;
43  *
44  *  cchMultiByte
45  *      Size of MultiByteStr, or -1 if MultiByteStr is
46  *      NULL terminated;
47  *
48  *  lpWideCharStr
49  *      Output buffer;
50  *
51  *  cchWideChar
52  *      Size (in WCHAR unit) of WideCharStr, or 0
53  *      if the caller just wants to know how large
54  *      WideCharStr should be for a successful
55  *      conversion.
56  *
57  * RETURN VALUE
58  *  0 on error; otherwise the number of WCHAR written
59  *  in the WideCharStr buffer.
60  *
61  * NOTE
62  *  A raw converter for now. It assumes lpMultiByteStr is
63  *  NEVER multi-byte (that is each input character is
64  *  8-bit ASCII) and is ALWAYS NULL terminated.
65  *  FIXME-FIXME-FIXME-FIXME
66  *
67  * @implemented
68  */
69 INT
70 STDCALL
71 MultiByteToWideChar(
72     UINT    CodePage,
73     DWORD   dwFlags,
74     LPCSTR  lpMultiByteStr,
75     int     cchMultiByte,
76     LPWSTR  lpWideCharStr,
77     int     cchWideChar)
78 {
79     int InStringLength = 0;
80     PCHAR   r;
81     PWCHAR  w;
82     int cchConverted;
83
84     /*
85      * Check the parameters.
86      */
87     if (/* --- CODE PAGE --- */
88         (  (CP_ACP != CodePage)
89                 && (CP_MACCP != CodePage)
90                 && (CP_OEMCP != CodePage)
91                 && (FALSE == IsInstalledCP(CodePage)) )
92         /* --- FLAGS --- */
93         || (dwFlags & ~(MB_PRECOMPOSED | MB_COMPOSITE |
94                         MB_ERR_INVALID_CHARS | MB_USEGLYPHCHARS))
95         /* --- INPUT BUFFER --- */
96         || (NULL == lpMultiByteStr)  )
97     {
98         SetLastError (ERROR_INVALID_PARAMETER);
99         return 0;
100     }
101     /*
102      * Compute the input buffer length.
103      */
104     //if (-1 == cchMultiByte)
105     if (cchMultiByte < 0)
106     {
107         InStringLength = lstrlenA(lpMultiByteStr) + 1;
108     }
109     else
110     {
111         InStringLength = cchMultiByte;
112     }
113     /*
114      * Does caller query for output
115      * buffer size?
116      */
117     if (0 == cchWideChar)
118     {
119         //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
120         return InStringLength;
121     }
122     /*
123      * Is space provided for the translated
124      * string enough?
125      */
126     if (cchWideChar < InStringLength)
127     {
128         SetLastError(ERROR_INSUFFICIENT_BUFFER);
129         return 0;
130     }
131     /*
132      * Raw 8- to 16-bit conversion.
133      */
134     for (cchConverted = 0,
135         r = (PCHAR)lpMultiByteStr,
136         w = (PWCHAR)lpWideCharStr;
137
138         cchConverted < InStringLength;
139
140         r++,
141         w++,
142         cchConverted++)
143     {
144         *w = (WCHAR)*r;
145     }
146     /*
147      * Return how many characters we
148      * wrote in the output buffer.
149      */
150     //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
151     return cchConverted;
152 }
153
154
155 /**********************************************************************
156  * NAME                         EXPORTED
157  *  WideCharToMultiByte@32
158  * 
159  *  Not yet implemented complete (without NLS so far)
160  *
161  * ARGUMENTS
162  *  CodePage
163  *      CP_ACP ANSI code page 
164  *      CP_MACCP Macintosh code page 
165  *      CP_OEMCP OEM code page 
166  *      CP_SYMBOL Symbol code page (42) 
167  *      CP_THREAD_ACP Current thread's ANSI code page 
168  *      CP_UTF7 Translate using UTF-7 
169  *      CP_UTF8 Translate using UTF-8 
170  *      (UINT)      Any installed code page
171  *
172  *  dwFlags
173  *      WC_NO_BEST_FIT_CHARS    
174  *      WC_COMPOSITECHECK Convert composite characters to precomposed characters. 
175  *      WC_DISCARDNS Discard nonspacing characters during conversion. 
176  *      WC_SEPCHARS Generate separate characters during conversion. This is the default conversion behavior. 
177  *      WC_DEFAULTCHAR Replace exceptions with the default character during conversion. 
178  *
179  *  lpWideCharStr 
180  *      Points to the wide-character string to be converted. 
181  *
182  *  cchWideChar
183  *      Size (in WCHAR unit) of WideCharStr, or 0
184  *      if the caller just wants to know how large
185  *      WideCharStr should be for a successful
186  *      conversion.
187  *  lpMultiByteStr 
188  *      Points to the buffer to receive the translated string. 
189  *  cchMultiByte 
190  *      Specifies the size in bytes of the buffer pointed to by the 
191  *      lpMultiByteStr parameter. If this value is zero, the function 
192  *      returns the number of bytes required for the buffer. 
193  *  lpDefaultChar 
194  *      Points to the character used if a wide character cannot be 
195  *      represented in the specified code page. If this parameter is 
196  *      NULL, a system default value is used. 
197         FIXME: ignored
198  *  lpUsedDefaultChar 
199  *      Points to a flag that indicates whether a default character was used. 
200  *      This parameter may be NULL. 
201         FIXME: allways set to FALSE.
202  *
203  *
204  *
205  * RETURN VALUE
206  *  0 on error; otherwise the number of bytes written
207  *  in the lpMultiByteStr buffer. Or the number of
208  *  bytes needed for the lpMultiByteStr buffer if cchMultiByte is zero.
209  *
210  * NOTE
211  *  A raw converter for now. It just cuts off the upper 9 Bit.
212  *  So the MBCS-string does not contain any LeadCharacters
213  *  FIXME - FIXME - FIXME - FIXME
214  *
215  * @implemented
216  */
217 int
218 STDCALL
219 WideCharToMultiByte(
220     UINT    CodePage,
221     DWORD   dwFlags,
222     LPCWSTR lpWideCharStr,
223     int     cchWideChar,
224     LPSTR   lpMultiByteStr,
225     int     cchMultiByte,
226     LPCSTR  lpDefaultChar,
227     LPBOOL  lpUsedDefaultChar
228     )
229 {
230     int wi, di;  // wide counter, dbcs byte count
231
232     /*
233      * Check the parameters.
234      */
235     if (    /* --- CODE PAGE --- */
236         (   (CP_ACP != CodePage)
237             && (CP_MACCP != CodePage)
238             && (CP_OEMCP != CodePage)
239             && (CP_SYMBOL != CodePage)
240             && (CP_THREAD_ACP != CodePage)
241             && (CP_UTF7 != CodePage)
242             && (CP_UTF8 != CodePage)
243             && (FALSE == IsInstalledCP (CodePage))
244             )
245         /* --- FLAGS --- */
246         || (dwFlags & ~(/*WC_NO_BEST_FIT_CHARS
247                 |*/ WC_COMPOSITECHECK
248                 | WC_DISCARDNS
249                 | WC_SEPCHARS
250                 | WC_DEFAULTCHAR
251                 )
252             )
253         /* --- INPUT BUFFER --- */
254         || (NULL == lpWideCharStr)
255         )
256     {
257         SetLastError(ERROR_INVALID_PARAMETER);
258         return 0;
259     }
260
261     // for now, make no difference but only convert cut the characters to 7Bit
262     //if (cchWideChar == -1) // assume its a 0-terminated str
263     if (cchWideChar < 0) // assume its a 0-terminated str
264     {           // and determine its length
265 //        for (cchWideChar=0; lpWideCharStr[cchWideChar]!=0; cchWideChar++)
266 //            cchWideChar++;
267         for (cchWideChar = 0; lpWideCharStr[cchWideChar] != 0; cchWideChar++) {
268         }
269         cchWideChar++; // length includes the null terminator
270     }
271
272     // user wants to determine needed space
273     if (cchMultiByte == 0) 
274     {
275         //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
276         return cchWideChar;         // FIXME: determine correct.
277     }
278     // the lpWideCharStr is cchWideChar characters long.
279     for (wi=0, di=0; wi<cchWideChar && di<cchMultiByte; ++wi, ++di)
280     {
281         // Flag and a not displayable char    FIXME
282         /*if( (dwFlags&WC_NO_BEST_FIT_CHARS) && (lpWideCharStr[wi] >127) ) 
283         {
284             lpMultiByteStr[di]=
285             *lpUsedDefaultChar = TRUE;
286
287         }*/
288         // FIXME
289         // just cut off the upper 9 Bit, since vals>=128 mean LeadByte.
290         lpMultiByteStr[di] = lpWideCharStr[wi] & 0x007F;
291     }
292     // has MultiByte exceeded but Wide is still in the string?
293     if (wi < cchWideChar && di >= cchMultiByte)
294     {
295         SetLastError(ERROR_INSUFFICIENT_BUFFER);
296         return 0;
297     }
298     // else return # of bytes wirtten to MBCSbuffer (di)
299     //SetLastError(ERROR_SUCCESS); /* according to wine tests this shouldn't be touched on success.
300     // FIXME: move that elsewhere
301     if (lpUsedDefaultChar != NULL) *lpUsedDefaultChar = FALSE; 
302     return di;
303 }
304
305 /* EOF */