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