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

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

some updates/minor changes

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