* Makefile.am: Add LIBICONV to windres.
[deliverable/binutils-gdb.git] / binutils / winduni.c
1 /* winduni.c -- unicode support for the windres program.
2 Copyright 1997, 1998, 2000, 2001, 2003, 2007
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
5 Rewritten by Kai Tietz, Onevision.
6
7 This file is part of GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22 02110-1301, USA. */
23
24 /* This file contains unicode support routines for the windres
25 program. Ideally, we would have generic unicode support which
26 would work on all systems. However, we don't. Instead, on a
27 Windows host, we are prepared to call some Windows routines. This
28 means that we will generate different output on Windows and Unix
29 hosts, but that seems better than not really supporting unicode at
30 all. */
31
32 #include "sysdep.h"
33 #include "bfd.h"
34 #include "libiberty.h" /* for xstrdup */
35 #include "bucomm.h"
36 /* Must be include before windows.h and winnls.h. */
37 #if defined (_WIN32) || defined (__CYGWIN__)
38 #include <windows.h>
39 #include <winnls.h>
40 #endif
41 #include "winduni.h"
42 #include "safe-ctype.h"
43
44 #if HAVE_ICONV_H
45 #include <iconv.h>
46 #endif
47
48 static rc_uint_type wind_WideCharToMultiByte (rc_uint_type, const unichar *, char *, rc_uint_type);
49 static rc_uint_type wind_MultiByteToWideChar (rc_uint_type, const char *, unichar *, rc_uint_type);
50
51 /* Prototypes. */
52 static int unichar_isascii (const unichar *, rc_uint_type);
53
54 #if !defined (_WIN32) && !defined (__CYGWIN__)
55
56 /* Codepages mapped. */
57 static local_iconv_map codepages[] =
58 {
59 { 0, "MS-ANSI" },
60 { 1, "WINDOWS-1252" },
61 { 437, "MS-ANSI" },
62 { 737, "MS-GREEK" },
63 { 775, "WINBALTRIM" },
64 { 850, "MS-ANSI" },
65 { 852, "MS-EE" },
66 { 857, "MS-TURK" },
67 { 862, "CP862" },
68 { 864, "CP864" },
69 { 866, "MS-CYRL" },
70 { 874, "WINDOWS-874" },
71 { 932, "CP932" },
72 { 936, "CP936" },
73 { 949, "CP949" },
74 { 950, "CP950" },
75 { 1250, "WINDOWS-1250" },
76 { 1251, "WINDOWS-1251" },
77 { 1252, "WINDOWS-1252" },
78 { 1253, "WINDOWS-1253" },
79 { 1254, "WINDOWS-1254" },
80 { 1255, "WINDOWS-1255" },
81 { 1256, "WINDOWS-1256" },
82 { 1257, "WINDOWS-1257" },
83 { 1258, "WINDOWS-1258" },
84 { CP_UTF7, "UTF-7" },
85 { CP_UTF8, "UTF-8" },
86 { CP_UTF16, "UTF-16" },
87 { (rc_uint_type) -1, NULL }
88 };
89
90 /* Languages supported. */
91 static const wind_language_t languages[] =
92 {
93 { 0x0000, 437, 1252, "Neutral", "Neutral" },
94 { 0x0401, 864, 1256, "Arabic", "Saudi Arabia" }, { 0x0402, 866, 1251, "Bulgarian", "Bulgaria" },
95 { 0x0403, 850, 1252, "Catalan", "Spain" }, { 0x0404, 950, 950, "Chinese", "Taiwan" },
96 { 0x0405, 852, 1250, "Czech", "Czech Republic" }, { 0x0406, 850, 1252, "Danish", "Denmark" },
97 { 0x0407, 850, 1252, "German", "Germany" }, { 0x0408, 737, 1253, "Greek", "Greece" },
98 { 0x0409, 437, 1252, "English", "United States" }, { 0x040A, 850, 1252, "Spanish - Traditional Sort", "Spain" },
99 { 0x040B, 850, 1252, "Finnish", "Finland" }, { 0x040C, 850, 1252, "French", "France" },
100 { 0x040D, 862, 1255, "Hebrew", "Israel" }, { 0x040E, 852, 1250, "Hungarian", "Hungary" },
101 { 0x040F, 850, 1252, "Icelandic", "Iceland" }, { 0x0410, 850, 1252, "Italian", "Italy" },
102 { 0x0411, 932, 932, "Japanese", "Japan" }, { 0x0412, 949, 949, "Korean", "Korea (south)" },
103 { 0x0413, 850, 1252, "Dutch", "Netherlands" }, { 0x0414, 850, 1252, "Norwegian (Bokmål)", "Norway" },
104 { 0x0415, 852, 1250, "Polish", "Poland" }, { 0x0416, 850, 1252, "Portuguese", "Brazil" },
105 { 0x0418, 852, 1250, "Romanian", "Romania" }, { 0x0419, 866, 1251, "Russian", "Russia" },
106 { 0x041A, 852, 1250, "Croatian", "Croatia" }, { 0x041B, 852, 1250, "Slovak", "Slovakia" },
107 { 0x041C, 852, 1250, "Albanian", "Albania" }, { 0x041D, 850, 1252, "Swedish", "Sweden" },
108 { 0x041E, 874, 874, "Thai", "Thailand" }, { 0x041F, 857, 1254, "Turkish", "Turkey" },
109 { 0x0421, 850, 1252, "Indonesian", "Indonesia" }, { 0x0422, 866, 1251, "Ukrainian", "Ukraine" },
110 { 0x0423, 866, 1251, "Belarusian", "Belarus" }, { 0x0424, 852, 1250, "Slovene", "Slovenia" },
111 { 0x0425, 775, 1257, "Estonian", "Estonia" }, { 0x0426, 775, 1257, "Latvian", "Latvia" },
112 { 0x0427, 775, 1257, "Lithuanian", "Lithuania" },
113 { 0x0429, 864, 1256, "Arabic", "Farsi" }, { 0x042A,1258, 1258, "Vietnamese", "Vietnam" },
114 { 0x042D, 850, 1252, "Basque", "Spain" },
115 { 0x042F, 866, 1251, "Macedonian", "Former Yugoslav Republic of Macedonia" },
116 { 0x0436, 850, 1252, "Afrikaans", "South Africa" },
117 { 0x0438, 850, 1252, "Faroese", "Faroe Islands" },
118 { 0x043C, 437, 1252, "Irish", "Ireland" },
119 { 0x043E, 850, 1252, "Malay", "Malaysia" },
120 { 0x0801, 864, 1256, "Arabic", "Iraq" },
121 { 0x0804, 936, 936, "Chinese (People's republic of China)", "People's republic of China" },
122 { 0x0807, 850, 1252, "German", "Switzerland" },
123 { 0x0809, 850, 1252, "English", "United Kingdom" }, { 0x080A, 850, 1252, "Spanish", "Mexico" },
124 { 0x080C, 850, 1252, "French", "Belgium" },
125 { 0x0810, 850, 1252, "Italian", "Switzerland" },
126 { 0x0813, 850, 1252, "Dutch", "Belgium" }, { 0x0814, 850, 1252, "Norwegian (Nynorsk)", "Norway" },
127 { 0x0816, 850, 1252, "Portuguese", "Portugal" },
128 { 0x081A, 852, 1252, "Serbian (latin)", "Yugoslavia" },
129 { 0x081D, 850, 1252, "Swedish (Finland)", "Finland" },
130 { 0x0C01, 864, 1256, "Arabic", "Egypt" },
131 { 0x0C04, 950, 950, "Chinese", "Hong Kong" },
132 { 0x0C07, 850, 1252, "German", "Austria" },
133 { 0x0C09, 850, 1252, "English", "Australia" }, { 0x0C0A, 850, 1252, "Spanish - International Sort", "Spain" },
134 { 0x0C0C, 850, 1252, "French", "Canada"},
135 { 0x0C1A, 855, 1251, "Serbian (Cyrillic)", "Serbia" },
136 { 0x1001, 864, 1256, "Arabic", "Libya" },
137 { 0x1004, 936, 936, "Chinese", "Singapore" },
138 { 0x1007, 850, 1252, "German", "Luxembourg" },
139 { 0x1009, 850, 1252, "English", "Canada" },
140 { 0x100A, 850, 1252, "Spanish", "Guatemala" },
141 { 0x100C, 850, 1252, "French", "Switzerland" },
142 { 0x1401, 864, 1256, "Arabic", "Algeria" },
143 { 0x1407, 850, 1252, "German", "Liechtenstein" },
144 { 0x1409, 850, 1252, "English", "New Zealand" }, { 0x140A, 850, 1252, "Spanish", "Costa Rica" },
145 { 0x140C, 850, 1252, "French", "Luxembourg" },
146 { 0x1801, 864, 1256, "Arabic", "Morocco" },
147 { 0x1809, 850, 1252, "English", "Ireland" }, { 0x180A, 850, 1252, "Spanish", "Panama" },
148 { 0x180C, 850, 1252, "French", "Monaco" },
149 { 0x1C01, 864, 1256, "Arabic", "Tunisia" },
150 { 0x1C09, 437, 1252, "English", "South Africa" }, { 0x1C0A, 850, 1252, "Spanish", "Dominican Republic" },
151 { 0x2001, 864, 1256, "Arabic", "Oman" },
152 { 0x2009, 850, 1252, "English", "Jamaica" }, { 0x200A, 850, 1252, "Spanish", "Venezuela" },
153 { 0x2401, 864, 1256, "Arabic", "Yemen" },
154 { 0x2409, 850, 1252, "English", "Caribbean" }, { 0x240A, 850, 1252, "Spanish", "Colombia" },
155 { 0x2801, 864, 1256, "Arabic", "Syria" },
156 { 0x2809, 850, 1252, "English", "Belize" }, { 0x280A, 850, 1252, "Spanish", "Peru" },
157 { 0x2C01, 864, 1256, "Arabic", "Jordan" },
158 { 0x2C09, 437, 1252, "English", "Trinidad & Tobago" },{ 0x2C0A, 850, 1252, "Spanish", "Argentina" },
159 { 0x3001, 864, 1256, "Arabic", "Lebanon" },
160 { 0x3009, 437, 1252, "English", "Zimbabwe" }, { 0x300A, 850, 1252, "Spanish", "Ecuador" },
161 { 0x3401, 864, 1256, "Arabic", "Kuwait" },
162 { 0x3409, 437, 1252, "English", "Philippines" }, { 0x340A, 850, 1252, "Spanish", "Chile" },
163 { 0x3801, 864, 1256, "Arabic", "United Arab Emirates" },
164 { 0x380A, 850, 1252, "Spanish", "Uruguay" },
165 { 0x3C01, 864, 1256, "Arabic", "Bahrain" },
166 { 0x3C0A, 850, 1252, "Spanish", "Paraguay" },
167 { 0x4001, 864, 1256, "Arabic", "Qatar" },
168 { 0x400A, 850, 1252, "Spanish", "Bolivia" },
169 { 0x440A, 850, 1252, "Spanish", "El Salvador" },
170 { 0x480A, 850, 1252, "Spanish", "Honduras" },
171 { 0x4C0A, 850, 1252, "Spanish", "Nicaragua" },
172 { 0x500A, 850, 1252, "Spanish", "Puerto Rico" },
173 { (unsigned) -1, 0, 0, NULL, NULL }
174 };
175
176 #endif
177
178 /* Convert an ASCII string to a unicode string. We just copy it,
179 expanding chars to shorts, rather than doing something intelligent. */
180
181 void
182 unicode_from_ascii (rc_uint_type *length, unichar **unicode, const char *ascii)
183 {
184 unicode_from_codepage (length, unicode, ascii, 0 /*CP_ACP*/);
185 }
186
187 /* Convert an unicode string to an ASCII string. We just copy it,
188 shrink shorts to chars, rather than doing something intelligent.
189 Shorts with not within the char range are replaced by '_'. */
190
191 void
192 ascii_from_unicode (rc_uint_type *length, const unichar *unicode, char **ascii)
193 {
194 codepage_from_unicode (length, unicode, ascii, 0/*CP_ACP*/);
195 }
196
197 /* Print the unicode string UNICODE to the file E. LENGTH is the
198 number of characters to print, or -1 if we should print until the
199 end of the string. FIXME: On a Windows host, we should be calling
200 some Windows function, probably WideCharToMultiByte. */
201
202 void
203 unicode_print (FILE *e, const unichar *unicode, rc_uint_type length)
204 {
205 while (1)
206 {
207 unichar ch;
208
209 if (length == 0)
210 return;
211 if ((bfd_signed_vma) length > 0)
212 --length;
213
214 ch = *unicode;
215
216 if (ch == 0 && (bfd_signed_vma) length < 0)
217 return;
218
219 ++unicode;
220
221 if ((ch & 0x7f) == ch)
222 {
223 if (ch == '\\')
224 fputs ("\\\\", e);
225 else if (ch == '"')
226 fputs ("\"\"", e);
227 else if (ISPRINT (ch))
228 putc (ch, e);
229 else
230 {
231 switch (ch)
232 {
233 case ESCAPE_A:
234 fputs ("\\a", e);
235 break;
236
237 case ESCAPE_B:
238 fputs ("\\b", e);
239 break;
240
241 case ESCAPE_F:
242 fputs ("\\f", e);
243 break;
244
245 case ESCAPE_N:
246 fputs ("\\n", e);
247 break;
248
249 case ESCAPE_R:
250 fputs ("\\r", e);
251 break;
252
253 case ESCAPE_T:
254 fputs ("\\t", e);
255 break;
256
257 case ESCAPE_V:
258 fputs ("\\v", e);
259 break;
260
261 default:
262 fprintf (e, "\\%03o", (unsigned int) ch);
263 break;
264 }
265 }
266 }
267 else if ((ch & 0xff) == ch)
268 fprintf (e, "\\%03o", (unsigned int) ch);
269 else
270 fprintf (e, "\\x%x", (unsigned int) ch);
271 }
272 }
273
274 /* Print a unicode string to a file. */
275
276 void
277 ascii_print (FILE *e, const char *s, rc_uint_type length)
278 {
279 while (1)
280 {
281 char ch;
282
283 if (length == 0)
284 return;
285 if ((bfd_signed_vma) length > 0)
286 --length;
287
288 ch = *s;
289
290 if (ch == 0 && (bfd_signed_vma) length < 0)
291 return;
292
293 ++s;
294
295 if ((ch & 0x7f) == ch)
296 {
297 if (ch == '\\')
298 fputs ("\\\\", e);
299 else if (ch == '"')
300 fputs ("\"\"", e);
301 else if (ISPRINT (ch))
302 putc (ch, e);
303 else
304 {
305 switch (ch)
306 {
307 case ESCAPE_A:
308 fputs ("\\a", e);
309 break;
310
311 case ESCAPE_B:
312 fputs ("\\b", e);
313 break;
314
315 case ESCAPE_F:
316 fputs ("\\f", e);
317 break;
318
319 case ESCAPE_N:
320 fputs ("\\n", e);
321 break;
322
323 case ESCAPE_R:
324 fputs ("\\r", e);
325 break;
326
327 case ESCAPE_T:
328 fputs ("\\t", e);
329 break;
330
331 case ESCAPE_V:
332 fputs ("\\v", e);
333 break;
334
335 default:
336 fprintf (e, "\\%03o", (unsigned int) ch);
337 break;
338 }
339 }
340 }
341 else
342 fprintf (e, "\\%03o", (unsigned int) ch & 0xff);
343 }
344 }
345
346 rc_uint_type
347 unichar_len (const unichar *unicode)
348 {
349 rc_uint_type r = 0;
350
351 if (unicode)
352 while (unicode[r] != 0)
353 r++;
354 else
355 --r;
356 return r;
357 }
358
359 unichar *
360 unichar_dup (const unichar *unicode)
361 {
362 unichar *r;
363 int len;
364
365 if (! unicode)
366 return NULL;
367 for (len = 0; unicode[len] != 0; ++len)
368 ;
369 ++len;
370 r = ((unichar *) res_alloc (len * sizeof (unichar)));
371 memcpy (r, unicode, len * sizeof (unichar));
372 return r;
373 }
374
375 unichar *
376 unichar_dup_uppercase (const unichar *u)
377 {
378 unichar *r = unichar_dup (u);
379 int i;
380
381 if (! r)
382 return NULL;
383
384 for (i = 0; r[i] != 0; ++i)
385 {
386 if (r[i] >= 'a' && r[i] <= 'z')
387 r[i] &= 0xdf;
388 }
389 return r;
390 }
391
392 static int
393 unichar_isascii (const unichar *u, rc_uint_type len)
394 {
395 rc_uint_type i;
396
397 if ((bfd_signed_vma) len < 0)
398 {
399 if (u)
400 len = (rc_uint_type) unichar_len (u);
401 else
402 len = 0;
403 }
404
405 for (i = 0; i < len; i++)
406 if ((u[i] & 0xff80) != 0)
407 return 0;
408 return 1;
409 }
410
411 void
412 unicode_print_quoted (FILE *e, const unichar *u, rc_uint_type len)
413 {
414 if (! unichar_isascii (u, len))
415 fputc ('L', e);
416 fputc ('"', e);
417 unicode_print (e, u, len);
418 fputc ('"', e);
419 }
420
421 int
422 unicode_is_valid_codepage (rc_uint_type cp)
423 {
424 if ((cp & 0xffff) != cp)
425 return 0;
426 if (cp == CP_UTF16 || cp == CP_ACP)
427 return 1;
428
429 #if !defined (_WIN32) && !defined (__CYGWIN__)
430 if (! wind_find_codepage_info (cp))
431 return 0;
432 return 1;
433 #else
434 return !! IsValidCodePage ((UINT) cp);
435 #endif
436 }
437
438 #if defined (_WIN32) || defined (__CYGWIN__)
439
440 #define max_cp_string_len 6
441
442 static unsigned int
443 codepage_from_langid (unsigned short langid)
444 {
445 char cp_string [max_cp_string_len];
446 int c;
447
448 memset (cp_string, 0, max_cp_string_len);
449 /* LOCALE_RETURN_NUMBER flag would avoid strtoul conversion,
450 but is unavailable on Win95. */
451 c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
452 LOCALE_IDEFAULTANSICODEPAGE,
453 cp_string, max_cp_string_len);
454 /* If codepage data for an LCID is not installed on users's system,
455 GetLocaleInfo returns an empty string. Fall back to system ANSI
456 default. */
457 if (c == 0)
458 return CP_ACP;
459 return strtoul (cp_string, 0, 10);
460 }
461
462 static unsigned int
463 wincodepage_from_langid (unsigned short langid)
464 {
465 char cp_string [max_cp_string_len];
466 int c;
467
468 memset (cp_string, 0, max_cp_string_len);
469 /* LOCALE_RETURN_NUMBER flag would avoid strtoul conversion,
470 but is unavailable on Win95. */
471 c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
472 LOCALE_IDEFAULTCODEPAGE,
473 cp_string, max_cp_string_len);
474 /* If codepage data for an LCID is not installed on users's system,
475 GetLocaleInfo returns an empty string. Fall back to system ANSI
476 default. */
477 if (c == 0)
478 return CP_OEM;
479 return strtoul (cp_string, 0, 10);
480 }
481
482 static char *
483 lang_from_langid (unsigned short langid)
484 {
485 char cp_string[261];
486 int c;
487
488 memset (cp_string, 0, 261);
489 c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
490 LOCALE_SENGLANGUAGE,
491 cp_string, 260);
492 /* If codepage data for an LCID is not installed on users's system,
493 GetLocaleInfo returns an empty string. Fall back to system ANSI
494 default. */
495 if (c == 0)
496 strcpy (cp_string, "Neutral");
497 return xstrdup (cp_string);
498 }
499
500 static char *
501 country_from_langid (unsigned short langid)
502 {
503 char cp_string[261];
504 int c;
505
506 memset (cp_string, 0, 261);
507 c = GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT),
508 LOCALE_SENGCOUNTRY,
509 cp_string, 260);
510 /* If codepage data for an LCID is not installed on users's system,
511 GetLocaleInfo returns an empty string. Fall back to system ANSI
512 default. */
513 if (c == 0)
514 strcpy (cp_string, "Neutral");
515 return xstrdup (cp_string);
516 }
517
518 #endif
519
520 const wind_language_t *
521 wind_find_language_by_id (unsigned id)
522 {
523 #if !defined (_WIN32) && !defined (__CYGWIN__)
524 int i;
525
526 if (! id)
527 return NULL;
528 for (i = 0; languages[i].id != (unsigned) -1 && languages[i].id != id; i++)
529 ;
530 if (languages[i].id == id)
531 return &languages[i];
532 return NULL;
533 #else
534 static wind_language_t wl;
535
536 wl.id = id;
537 wl.doscp = codepage_from_langid ((unsigned short) id);
538 wl.wincp = wincodepage_from_langid ((unsigned short) id);
539 wl.name = lang_from_langid ((unsigned short) id);
540 wl.country = country_from_langid ((unsigned short) id);
541
542 return & wl;
543 #endif
544 }
545
546 const local_iconv_map *
547 wind_find_codepage_info (unsigned cp)
548 {
549 #if !defined (_WIN32) && !defined (__CYGWIN__)
550 int i;
551
552 for (i = 0; codepages[i].codepage != (rc_uint_type) -1 && codepages[i].codepage != cp; i++)
553 ;
554 if (codepages[i].codepage == (rc_uint_type) -1)
555 return NULL;
556 return &codepages[i];
557 #else
558 static local_iconv_map lim;
559 if (!unicode_is_valid_codepage (cp))
560 return NULL;
561 lim.codepage = cp;
562 lim.iconv_name = "";
563 return & lim;
564 #endif
565 }
566
567 /* Convert an Codepage string to a unicode string. */
568
569 void
570 unicode_from_codepage (rc_uint_type *length, unichar **u, const char *src, rc_uint_type cp)
571 {
572 rc_uint_type len;
573
574 len = wind_MultiByteToWideChar (cp, src, NULL, 0);
575 if (len)
576 {
577 *u = ((unichar *) res_alloc (len));
578 wind_MultiByteToWideChar (cp, src, *u, len);
579 }
580 /* Discount the trailing '/0'. If MultiByteToWideChar failed,
581 this will set *length to -1. */
582 len -= sizeof (unichar);
583
584 if (length != NULL)
585 *length = len / sizeof (unichar);
586 }
587
588 /* Convert an unicode string to an codepage string. */
589
590 void
591 codepage_from_unicode (rc_uint_type *length, const unichar *unicode, char **ascii, rc_uint_type cp)
592 {
593 rc_uint_type len;
594
595 len = wind_WideCharToMultiByte (cp, unicode, NULL, 0);
596 if (len)
597 {
598 *ascii = (char *) res_alloc (len * sizeof (char));
599 wind_WideCharToMultiByte (cp, unicode, *ascii, len);
600 }
601 /* Discount the trailing '/0'. If MultiByteToWideChar failed,
602 this will set *length to -1. */
603 len--;
604
605 if (length != NULL)
606 *length = len;
607 }
608
609 #ifdef HAVE_ICONV_H
610 static int
611 iconv_onechar (iconv_t cd, const char *s, char *d, int d_len, const char **n_s, char **n_d)
612 {
613 int i;
614
615 for (i = 1; i <= 32; i++)
616 {
617 char *tmp_d = d;
618 const char *tmp_s = s;
619 size_t ret;
620 size_t s_left = (size_t) i;
621 size_t d_left = (size_t) d_len;
622
623 ret = iconv (cd, & tmp_s, & s_left, & tmp_d, & d_left);
624
625 if (ret != (size_t) -1)
626 {
627 *n_s = tmp_s;
628 *n_d = tmp_d;
629 return 0;
630 }
631 }
632
633 return 1;
634 }
635
636 static const char *
637 wind_iconv_cp (rc_uint_type cp)
638 {
639 const local_iconv_map *lim = wind_find_codepage_info (cp);
640
641 if (!lim)
642 return NULL;
643 return lim->iconv_name;
644 }
645 #endif /* HAVE_ICONV_H */
646
647 static rc_uint_type
648 wind_MultiByteToWideChar (rc_uint_type cp, const char *mb,
649 unichar *u, rc_uint_type u_len)
650 {
651 rc_uint_type ret = 0;
652
653 #if defined (_WIN32) || defined (__CYGWIN__)
654 ret = (rc_uint_type) MultiByteToWideChar (cp, MB_PRECOMPOSED,
655 mb, -1, u, u_len);
656 /* Convert to bytes. */
657 ret *= sizeof (unichar);
658
659 #elif defined (HAVE_ICONV_H)
660 int first = 1;
661 char tmp[32];
662 char *p_tmp;
663 const char *iconv_name = wind_iconv_cp (cp);
664
665 if (!mb || !iconv_name)
666 return 0;
667 iconv_t cd = iconv_open ("UTF-16", iconv_name);
668
669 while (1)
670 {
671 int iret;
672 const char *n_mb;
673 char *n_tmp;
674
675 p_tmp = tmp;
676 iret = iconv_onechar (cd, (const char *) mb, p_tmp, 32, & n_mb, & n_tmp);
677 if (first)
678 {
679 first = 0;
680 continue;
681 }
682 if (!iret)
683 {
684 size_t l_tmp = (size_t) (n_tmp - p_tmp);
685
686 if (u)
687 {
688 if ((size_t) u_len < l_tmp)
689 break;
690 memcpy (u, tmp, l_tmp);
691 u += l_tmp/2;
692 u_len -= l_tmp;
693 }
694 ret += l_tmp;
695 }
696 else
697 break;
698 if (tmp[0] == 0 && tmp[1] == 0)
699 break;
700 mb = n_mb;
701 }
702 iconv_close (cd);
703 #else
704 if (cp)
705 ret = 0;
706 ret = strlen (mb) + 1;
707 ret *= sizeof (unichar);
708 if (u != NULL && u_len != 0)
709 {
710 do
711 {
712 *u++ = ((unichar) *mb) & 0xff;
713 --u_len; mb++;
714 }
715 while (u_len != 0 && mb[-1] != 0);
716 }
717 if (u != NULL && u_len != 0)
718 *u = 0;
719 #endif
720 return ret;
721 }
722
723 static rc_uint_type
724 wind_WideCharToMultiByte (rc_uint_type cp, const unichar *u, char *mb, rc_uint_type mb_len)
725 {
726 rc_uint_type ret = 0;
727 #if defined (_WIN32) || defined (__CYGWIN__)
728 WINBOOL used_def = FALSE;
729
730 ret = (rc_uint_type) WideCharToMultiByte (cp, 0, u, -1, mb, mb_len,
731 NULL, & used_def);
732 #elif defined (HAVE_ICONV_H)
733 int first = 1;
734 char tmp[32];
735 char *p_tmp;
736 const char *iconv_name = wind_iconv_cp (cp);
737
738 if (!u || !iconv_name)
739 return 0;
740 iconv_t cd = iconv_open (iconv_name, "UTF-16");
741
742 while (1)
743 {
744 int iret;
745 const char *n_u;
746 char *n_tmp;
747
748 p_tmp = tmp;
749 iret = iconv_onechar (cd, (const char *) u, p_tmp, 32, &n_u, & n_tmp);
750 if (first)
751 {
752 first = 0;
753 continue;
754 }
755 if (!iret)
756 {
757 size_t l_tmp = (size_t) (n_tmp - p_tmp);
758
759 if (mb)
760 {
761 if ((size_t) mb_len < l_tmp)
762 break;
763 memcpy (mb, tmp, l_tmp);
764 mb += l_tmp;
765 mb_len -= l_tmp;
766 }
767 ret += l_tmp;
768 }
769 else
770 break;
771 if (u[0] == 0)
772 break;
773 u = (const unichar *) n_u;
774 }
775 iconv_close (cd);
776 #else
777 if (cp)
778 ret = 0;
779
780 while (u[ret] != 0)
781 ++ret;
782
783 ++ret;
784
785 if (mb)
786 {
787 while (*u != 0 && mb_len != 0)
788 {
789 if (u[0] == (u[0] & 0x7f))
790 *mb++ = (char) u[0];
791 else
792 *mb++ = '_';
793 ++u; --mb_len;
794 }
795 if (mb_len != 0)
796 *mb = 0;
797 }
798 #endif
799 return ret;
800 }
This page took 0.056774 seconds and 5 git commands to generate.