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

Last change on this file since 2007 was 1986, checked in by sandervl, 26 years ago

CB: Only convert the string and not everything in UnicodeToAsciiStringN

File size: 11.5 KB
Line 
1/* $Id: unicode.cpp,v 1.19 1999-12-05 21:11:40 sandervl 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, length;
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
226// length = UniStrlen(ustring)+1;
227// unilen = min(length, unilen);
228
229 if (getUconvObject())
230 {
231 if (unilen == 1)
232 {
233 astring[0] = 0;
234 return 0; //no data
235 }
236
237 uni_chars_left = unilen-1; //elements
238 out_bytes_left = uni_chars_left; //size in bytes == elements
239 in_buf = (UniChar*)ustring;
240 out_buf = astring;
241 rc = UniUconvFromUcs(uconv_object,
242 &in_buf, &uni_chars_left,
243 (void**)&out_buf, &out_bytes_left,
244 &num_subs);
245
246 unilen -= 1+out_bytes_left; //end + left bytes
247 astring[unilen] = 0; //terminate
248
249 return unilen;
250
251// dprintf(("KERNEL32: UnicodeToAsciiN(%d) '%s'\n", rc, astring ));
252 } else
253 {
254 /* idiots unicode conversion :) */
255 for (i = 0; i < unilen-1; i++)
256 {
257 astring[i] = (ustring[i] > 255) ? (char)20 : (char)ustring[i]; //CB: handle invalid characters as space
258 if (ustring[i] == 0) return i; //asta la vista, baby
259 }
260
261 astring[unilen-1] = 0; // @@@PH: 1999/06/09 fix - always terminate string
262
263 return(unilen-1);
264 }
265}
266//******************************************************************************
267// Converts unicode string to ascii string
268// returns length of ascii string
269//******************************************************************************
270int WIN32API UnicodeToAscii(LPCWSTR ustring, char *astring)
271{
272 /* forward to function with len parameter */
273 return UnicodeToAsciiN(ustring, astring, UniStrlen((UniChar*)ustring)+1); //end included
274}
275//******************************************************************************
276// Converts unicode string to ascii string
277// returns pointer to ascii string
278//******************************************************************************
279char * WIN32API UnicodeToAsciiString(LPCWSTR ustring)
280{
281 char *astring;
282
283 if(ustring == NULL) return(NULL);
284
285 astring = (char *)malloc( 1 + UniStrlen((UniChar*)ustring) );
286 UnicodeToAscii( ustring, astring );
287 return(astring);
288}
289//******************************************************************************
290// length = characters to convert
291//******************************************************************************
292char * WIN32API UnicodeToAsciiStringN(LPCWSTR ustring, ULONG length)
293{
294 char *astring;
295
296 if(ustring == NULL) return(NULL);
297
298 astring = (char *)malloc( 1 + length );
299 UnicodeToAsciiN( ustring, astring, length+1 ); //terminating 0 always added
300 return(astring);
301}
302//******************************************************************************
303// Converts ascii string to unicode string
304// returns pointer to unicode string
305//******************************************************************************
306WCHAR * WIN32API AsciiToUnicodeString(const char *astring)
307{
308 WCHAR *ustring;
309
310 if(astring == NULL)
311 return(NULL);
312
313 ustring = (WCHAR *)malloc( 1 + strlen(astring) << 1 );
314 AsciiToUnicode( astring, ustring );
315 return(ustring);
316}
317
318//******************************************************************************
319//SvL: 24-6-'97 - Added
320//******************************************************************************
321void WIN32API FreeAsciiString(char *astring)
322{
323 if( astring )
324 free( astring );
325}
326//******************************************************************************
327// asciilen: max length of unicode buffer (including end 0)
328//******************************************************************************
329void WIN32API AsciiToUnicodeN(const char *ascii, WCHAR *unicode, int asciilen)
330{
331 int rc;
332 int i;
333 size_t uni_chars_left;
334 size_t in_bytes_left;
335 size_t num_subs;
336 UniChar * out_buf;
337 const char * in_buf;
338
339
340 dprintf(("KERNEL32: AsciiToUnicodeN(%s,%08xh)\n",
341 ascii,
342 unicode));
343
344 //CB: no input, set at least terminator
345 if (ascii == NULL)
346 {
347 if (unicode != NULL && asciilen > 0) unicode[0] = 0;
348 return;
349 }
350
351 if (unicode == NULL || asciilen <= 0) return; //nothing to do
352
353// dprintf(("KERNEL32: AsciiToUnicodeN %s\n", ascii));
354 if (getUconvObject())
355 {
356 if (asciilen == 1)
357 {
358 unicode[0] = 0;
359 return;
360 }
361
362 in_buf = ascii;
363 in_bytes_left = asciilen-1; //buffer size in bytes
364 out_buf = (UniChar*)unicode;
365
366 uni_chars_left = in_bytes_left; //elements
367 dprintf(("KERNEL32: AsciiToUnicode %d\n", in_bytes_left));
368
369 rc = UniUconvToUcs( uconv_object,
370 (void**)&in_buf, &in_bytes_left,
371 &out_buf, &uni_chars_left,
372 &num_subs );
373
374 unicode[asciilen-1-in_bytes_left] = 0;
375
376 //if (rc != ULS_SUCCESS && in_bytes_left > 0) //CB: never the case during my tests
377 // dprintf(("KERNEL32: AsciiToUnicode failed, %d bytes left!\n",in_bytes_left));
378
379 } else
380 { //poor man's conversion
381
382 for(i = 0;i < asciilen-1;i++)
383 {
384 unicode[i] = ascii[i];
385 if (ascii[i] == 0) return; //work done
386 }
387
388 unicode[asciilen-1] = 0;
389 }
390}
391//******************************************************************************
392// Copies the full string from ascii to unicode
393//******************************************************************************
394void WIN32API AsciiToUnicode(const char *ascii, WCHAR *unicode)
395{
396 /* achimha for security, strlen might trap if garbage in */
397 /* @@@PH 98/06/07 */
398 if (ascii == NULL)
399 {
400 if (unicode != NULL) unicode[0] = 0; //CB: set at least end
401 return;
402 }
403
404 if (unicode == NULL) return; /* garbage in, garbage out ! */
405
406 /* forward to call with length parameter */
407 AsciiToUnicodeN(ascii, unicode, strlen(ascii)+1); //end included
408}
409
410
411
412
413
Note: See TracBrowser for help on using the repository browser.