source: trunk/src/kernel32/unicode.cpp@ 1871

Last change on this file since 1871 was 1871, checked in by bird, 26 years ago

Changed some parameters to const.

File size: 11.3 KB
Line 
1/* $Id: unicode.cpp,v 1.16 1999-11-28 23:23:46 bird Exp $ */
2
3/*
4 * Project Odin Software License can be found in LICENSE.TXT
5 * Unicode functions
6 * Copyright 1998 Joel Troster
7 * Copyright 1999 Patrick haller
8 * Copyright 1999 Achim Hasenmueller
9 * Copyright 1999 Christoph Bratschi
10 *
11 * Read comments about the implementation before using these functions
12 * Attention: length values include terminating 0
13 */
14#include <os2win.h>
15#include <winnls.h>
16#include <stdlib.h>
17#include <string.h>
18#include "misc.h"
19#include <unicode.h>
20
21static UconvObject uconv_object = NULL;
22BOOL getUconvObject( void )
23{
24 int rc;
25 BOOL ret;
26 if ( uconv_object )
27 ret = TRUE;
28 else
29 {
30 rc = UniCreateUconvObject( (UniChar*)L"", &uconv_object );
31 if ( rc == ULS_SUCCESS )
32 ret = TRUE;
33 else
34 {
35 uconv_object = NULL; // to make sure
36 return FALSE;
37 }
38 dprintf(("UniCreateUconvObject(%d)\n", rc ));
39 }
40 return ret;
41}
42
43/***********************************************************************
44 * MultiByteToWideChar (KERNEL32.534)
45 *
46 * PARAMS
47 * page [in] Codepage character set to convert from
48 * flags [in] Character mapping flags
49 * src [in] Source string buffer
50 * srclen [in] Length of source string buffer
51 * dst [in] Destination buffer
52 * dstlen [in] Length of destination buffer
53 *
54 * NOTES
55 * The returned length includes the null terminator character.
56 *
57 * RETURNS
58 * Success: If dstlen > 0, number of characters written to destination
59 * buffer. If dstlen == 0, number of characters needed to do
60 * conversion.
61 * Failure: 0. Occurs if not enough space is available.
62 *
63 * ERRORS
64 * ERROR_INSUFFICIENT_BUFFER
65 * ERROR_INVALID_FLAGS (not yet implemented)
66 * ERROR_INVALID_PARAMETER (not yet implemented)
67 *
68 * BUGS
69 * Does not properly handle codepage conversions.
70 * Does not properly handle flags.
71 *
72 */
73INT WINAPI MultiByteToWideChar(UINT page, DWORD flags,
74 LPCSTR src, INT srclen,
75 LPWSTR dst, INT dstlen)
76{
77 int ret;
78
79 if (srclen == -1)
80 srclen = lstrlenA(src)+1;
81 if (!dstlen || !dst)
82 return srclen;
83
84 ret = srclen;
85 while (srclen && dstlen) {
86 *dst = (WCHAR)(unsigned char)*src;
87 dst++; src++;
88 dstlen--; srclen--;
89 }
90 if (!dstlen && srclen) {
91 SetLastError(ERROR_INSUFFICIENT_BUFFER);
92 return 0;
93 }
94 return ret;
95}
96
97/***********************************************************************
98 * WideCharToMultiByte (KERNEL32.727)
99 *
100 * PARAMS
101 * page [in] Codepage character set to convert to
102 * flags [in] Character mapping flags
103 * src [in] Source string buffer
104 * srclen [in] Length of source string buffer
105 * dst [in] Destination buffer
106 * dstlen [in] Length of destination buffer
107 * defchar [in] Default character to use for conversion if no exact
108 * conversion can be made
109 * used [out] Set if default character was used in the conversion
110 *
111 * NOTES
112 * The returned length includes the null terminator character.
113 *
114 * RETURNS
115 * Success: If dstlen > 0, number of characters written to destination
116 * buffer. If dstlen == 0, number of characters needed to do
117 * conversion.
118 * Failure: 0. Occurs if not enough space is available.
119 *
120 * ERRORS
121 * ERROR_INSUFFICIENT_BUFFER
122 * ERROR_INVALID_FLAGS (not yet implemented)
123 *
124 * BUGS
125 * Does not properly handle codepage conversions.
126 * Does not properly handle flags.
127 *
128 */
129INT WIN32API WideCharToMultiByte(UINT page, DWORD flags, LPCWSTR src,
130 INT srclen,LPSTR dst, INT dstlen,
131 LPCSTR defchar, BOOL *used)
132{
133 int count = 0;
134 int eos = 0;
135 int care_for_eos=0;
136 int dont_copy= (dstlen==0);
137
138 if ((!src) || ((!dst) && (!dont_copy)) )
139 { SetLastError(ERROR_INVALID_PARAMETER);
140 return 0;
141 }
142
143 if (page!=GetACP() && page!=CP_OEMCP && page!=CP_ACP)
144 dprintf(("WideCharToMultiByte, Conversion in CP %d not supported\n",page));
145#if 0
146 if (flags)
147 dprintf(("WideCharToMultiByte, flags %lx not supported\n",flags));
148#endif
149 if(used)
150 *used=0;
151 if (srclen == -1)
152 {
153 srclen = lstrlenW(src)+1;
154 care_for_eos=1;
155 }
156 while(srclen && (dont_copy || dstlen))
157 {
158 if(!dont_copy){
159 if(*src<256)
160 *dst = *src;
161 else
162 {
163 /* ??? The WC_DEFAULTCHAR flag only gets used in
164 * combination with the WC_COMPOSITECHECK flag or at
165 * least this is what it seems from using the function
166 * on NT4.0 in combination with reading the documentation.
167 */
168 *dst = defchar ? *defchar : '?';
169 if(used)*used=1;
170 }
171 dstlen--;
172 dst++;
173 }
174 count++;
175 srclen--;
176 if((!*src) && care_for_eos) {
177 eos = 1;
178 break;
179 }
180 src++;
181 }
182 if (dont_copy)
183 return count;
184
185 if (!eos && srclen > 0) {
186 SetLastError(ERROR_INSUFFICIENT_BUFFER);
187 return 0;
188 }
189 return count;
190}
191//******************************************************************************
192//******************************************************************************
193BOOL WIN32API GetCPInfo(UINT uCodePage, CPINFO *lpCPInfo)
194{
195 dprintf(("GetCPInfo (%d), not correctly implemented\n", uCodePage));
196 memset(lpCPInfo, 0, sizeof(CPINFO));
197 lpCPInfo->MaxCharSize = 1;
198 lpCPInfo->DefaultChar[0] = 'a';
199
200 return(TRUE);
201}
202//******************************************************************************
203// unilen: length of astring buffer (including 0 terminator)
204// returns string length
205//******************************************************************************
206int WIN32API UnicodeToAsciiN(LPCWSTR ustring, char *astring, int unilen)
207{
208 int i;
209 int rc;
210 size_t uni_chars_left;
211 size_t out_bytes_left;
212 size_t num_subs;
213 UniChar * in_buf;
214 char * out_buf;
215
216 if (ustring == NULL)
217 {
218 if (astring != NULL && unilen > 0) astring[0] = 0;
219 return 0;
220 }
221
222 if (astring == NULL || unilen <= 0) return 0;
223
224// dprintf(("KERNEL32: UnicodeToAsciiN\n"));
225 if (getUconvObject())
226 {
227 if (unilen == 1)
228 {
229 astring[0] = 0;
230 return 0; //no data
231 }
232
233 uni_chars_left = unilen-1; //elements
234 out_bytes_left = uni_chars_left; //size in bytes == elements
235 in_buf = (UniChar*)ustring;
236 out_buf = astring;
237 rc = UniUconvFromUcs(uconv_object,
238 &in_buf, &uni_chars_left,
239 (void**)&out_buf, &out_bytes_left,
240 &num_subs);
241
242 unilen -= 1+out_bytes_left; //end + left bytes
243 astring[unilen] = 0; //terminate
244
245 return unilen;
246
247// dprintf(("KERNEL32: UnicodeToAsciiN(%d) '%s'\n", rc, astring ));
248 } else
249 {
250 /* idiots unicode conversion :) */
251 for (i = 0; i < unilen-1; i++)
252 {
253 astring[i] = (ustring[i] > 255) ? (char)20 : (char)ustring[i]; //CB: handle invalid characters as space
254 if (ustring[i] == 0) return i; //asta la vista, baby
255 }
256
257 astring[unilen-1] = 0; // @@@PH: 1999/06/09 fix - always terminate string
258
259 return(unilen-1);
260 }
261}
262//******************************************************************************
263// Converts unicode string to ascii string
264// returns length of ascii string
265//******************************************************************************
266int WIN32API UnicodeToAscii(LPCWSTR ustring, char *astring)
267{
268 /* forward to function with len parameter */
269 return UnicodeToAsciiN(ustring, astring, UniStrlen((UniChar*)ustring)+1); //end included
270}
271//******************************************************************************
272// Converts unicode string to ascii string
273// returns pointer to ascii string
274//******************************************************************************
275char * WIN32API UnicodeToAsciiString(LPCWSTR ustring)
276{
277 char *astring;
278
279 if(ustring == NULL) return(NULL);
280
281 astring = (char *)malloc( 1 + UniStrlen((UniChar*)ustring) );
282 UnicodeToAscii( ustring, astring );
283 return(astring);
284}
285//******************************************************************************
286//******************************************************************************
287char * WIN32API UnicodeToAsciiStringN(LPCWSTR ustring, ULONG length)
288{
289 char *astring;
290
291 if(ustring == NULL) return(NULL);
292
293 astring = (char *)malloc( 1 + length );
294 UnicodeToAscii( ustring, astring );
295 return(astring);
296}
297//******************************************************************************
298// Converts ascii string to unicode string
299// returns pointer to unicode string
300//******************************************************************************
301WCHAR * WIN32API AsciiToUnicodeString(const char *astring)
302{
303 WCHAR *ustring;
304
305 if(astring == NULL)
306 return(NULL);
307
308 ustring = (WCHAR *)malloc( 1 + strlen(astring) << 1 );
309 AsciiToUnicode( astring, ustring );
310 return(ustring);
311}
312
313//******************************************************************************
314//SvL: 24-6-'97 - Added
315//******************************************************************************
316void WIN32API FreeAsciiString(char *astring)
317{
318 if( astring )
319 free( astring );
320}
321//******************************************************************************
322// asciilen: max length of unicode buffer (including end 0)
323//******************************************************************************
324void WIN32API AsciiToUnicodeN(const char *ascii, WCHAR *unicode, int asciilen)
325{
326 int rc;
327 int i;
328 size_t uni_chars_left;
329 size_t in_bytes_left;
330 size_t num_subs;
331 UniChar * out_buf;
332 const char * in_buf;
333
334
335 dprintf(("KERNEL32: AsciiToUnicodeN(%s,%08xh)\n",
336 ascii,
337 unicode));
338
339 //CB: no input, set at least terminator
340 if (ascii == NULL)
341 {
342 if (unicode != NULL && asciilen > 0) unicode[0] = 0;
343 return;
344 }
345
346 if (unicode == NULL || asciilen <= 0) return; //nothing to do
347
348// dprintf(("KERNEL32: AsciiToUnicodeN %s\n", ascii));
349 if (getUconvObject())
350 {
351 if (asciilen == 1)
352 {
353 unicode[0] = 0;
354 return;
355 }
356
357 in_buf = ascii;
358 in_bytes_left = asciilen-1; //buffer size in bytes
359 out_buf = (UniChar*)unicode;
360
361 uni_chars_left = in_bytes_left; //elements
362 dprintf(("KERNEL32: AsciiToUnicode %d\n", in_bytes_left));
363
364 rc = UniUconvToUcs( uconv_object,
365 (void**)&in_buf, &in_bytes_left,
366 &out_buf, &uni_chars_left,
367 &num_subs );
368
369 unicode[asciilen-1-in_bytes_left] = 0;
370
371 //if (rc != ULS_SUCCESS && in_bytes_left > 0) //CB: never the case during my tests
372 // dprintf(("KERNEL32: AsciiToUnicode failed, %d bytes left!\n",in_bytes_left));
373
374 } else
375 { //poor man's conversion
376
377 for(i = 0;i < asciilen-1;i++)
378 {
379 unicode[i] = ascii[i];
380 if (ascii[i] == 0) return; //work done
381 }
382
383 unicode[asciilen-1] = 0;
384 }
385}
386//******************************************************************************
387// Copies the full string from ascii to unicode
388//******************************************************************************
389void WIN32API AsciiToUnicode(const char *ascii, WCHAR *unicode)
390{
391 /* achimha for security, strlen might trap if garbage in */
392 /* @@@PH 98/06/07 */
393 if (ascii == NULL)
394 {
395 if (unicode != NULL) unicode[0] = 0; //CB: set at least end
396 return;
397 }
398
399 if (unicode == NULL) return; /* garbage in, garbage out ! */
400
401 /* forward to call with length parameter */
402 AsciiToUnicodeN(ascii, unicode, strlen(ascii)+1); //end included
403}
404
405
406
407
Note: See TracBrowser for help on using the repository browser.